这是我的第一个问题,我认为这是解决这个问题的最佳社区。
我正在开发一个与图像处理相关的java应用程序,并尝试使用jna使用cviptools库(用c/c++编写)的函数,但这是我第一次使用此方法。
当我试图执行一个小测试来检查我是否能够执行c函数rst_不变量时,我得到了以下错误:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:497)
at com.sun.jna.Function.invoke(Function.java:441)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy2.rst_invariant(Unknown Source)
at aplicacion.Main.main(Main.java:75)
... 11 more
Exception running application aplicacion.Main
显然,这个错误与内存管理有关,但我没有足够的知识和经验来检测它。我认为问题可能与c数据类型和我使用的java类之间的无效关系有关,但我不确定。
我附上了原始c函数的代码、结构和我尝试过的Map。
每一个改进代码的建议都是受欢迎的。如果您需要其他信息,请告诉我:d
非常感谢你!!!
rst_不变量.c
double* rst_invariant(Image* label_image, int r, int c) {
int** image; /* 2-d matrix data pointer */
int y, /* Índice de fila */
x, /* Índice de columna */
p, q, i, j, label;
double* ptr;
double moment[2][2], /* zeroth moment and first moment */
moment1[4][4], /* central moment */
moment2[4][4]; /* normalization of central moment */
unsigned int rows, /* Número de filas en la imagen */
cols; /* Número de columnas en la imagen */
rows = getNoOfRows_Image(label_image);
cols = getNoOfCols_Image(label_image);
ptr = (double*)malloc(7 * sizeof(double));
printf("hola\n");
for (i = 0; i < 7; i++) ptr[i] = 0.0;
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++) moment[i][j] = 0.0;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
moment1[i][j] = 0.0;
moment2[i][j] = 0.0;
}
/*
Compara el valor del píxel de la ubicación (y,x)
con el valor del umbral. Si es más grande que
el umbral escribe 255 en la localización, si no escribe 0
*/
image = (int**)getData_Image(label_image, 0);
label = image[r][c];
for (p = 0; p <= 1; p++) {
for (q = 0; q <= 1; q++) {
for (y = 1; y < rows; y++) {
for (x = 1; x < cols; x++) {
if (image[y][x] == label) {
moment[p][q] = moment[p][q] + pow(x, p) * pow(y, q) * 1; /* Para imágenes binarias, considera patrones binarios. Donde f(x, y) = 1 or 0, aquí 1 es blanco, 0 es negro */
}
}
}
}
}
for (p = 0; p <= 3; p++) {
for (q = 0; q <= 3; q++) {
for (y = 1; y < rows; y++) {
for (x = 1; x < cols; x++) {
if (image[y][x] == label) {
moment1[p][q] = moment1[p][q] + pow((x - (moment[1][0] / moment[0][0])), p) * pow((y - (moment[0][1] / moment[0][0])), q) * 1; /* Para imágenes binarias, considera patrones binarios. Donde f(x, y) = 1 or 0, aquí 1 es blanco, 0 es negro */
}
}
}
}
}
for (p = 0; p < 4; p++) {
for (q = 0; q < 4; q++) {
if ((p + q) == 2 || (p + q) == 3) {
moment2[p][q] = moment1[p][q] / pow(moment1[0][0], ((p + q) * 0.5) + 1);
}
}
}
ptr[0] = moment2[2][0] + moment2[0][2];
ptr[1] = (moment2[2][0] - moment2[0][2]) * (moment2[2][0] - moment2[0][2]) + 4 * (moment2[1][1]) * (moment2[1][1]);
ptr[2] =
(moment2[3][0] - 3 * moment2[1][2]) * (moment2[3][0] - 3 * moment2[1][2]) + (3 * moment2[2][1] - moment2[0][3]) * (3 * moment2[2][1] - moment2[0][3]);
ptr[3] =
(moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) + (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3]);
ptr[4] =
(moment2[3][0] - 3 * moment2[1][2]) * (moment2[3][0] + moment2[1][2]) * ((moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - 3 * (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3])) + (3 * moment2[2][1] - moment2[0][3]) * (moment2[2][1] + moment2[0][3]) * (3 * (moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3]));
ptr[5] =
(moment2[2][0] - moment2[0][2]) * ((moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3])) + 4 * (moment2[1][1]) * (moment2[3][0] + moment2[1][2]) * (moment2[2][1] + moment2[0][3]);
ptr[6] =
(3 * moment2[2][1] - moment2[0][3]) * (moment2[3][0] + moment2[1][2]) * ((moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - 3 * (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3])) - (moment2[3][0] - 3 * moment2[1][2]) * (moment2[2][1] + moment2[0][3]) * (3 * (moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3]));
return ptr;
}
图像结构
typedef struct {
int image_format;
int color_space;
int bands;
MATRIX**image_ptr;
} IMAGE;
# define bandP image_ptr
typedef IMAGE Image;
矩阵结构
typedef struct {
int data_type;
int data_format;
unsigned int rows;
unsigned int cols;
char**rptr;
char**iptr;
} MATRIX;
typedef MATRIX Matrix;
java中的图像结构Map
@Structure.FieldOrder({ "data_type", "color_space", "bands", "image_ptr" })
public class Image extends Structure {
public int data_type; // enum se mapea como int
public int color_space; // enum se mapea como int
public int bands;
public Matrix image_ptr; // MATRIX**(doble puntero a struct)
public Image() {
super();
}
public Image(Matrix image_ptr) {
super();
// Valores por defecto, quizás se puedan eliminar
this.data_type = 0;
this.color_space = 0;
this.bands = 0;
this.image_ptr = image_ptr;
}
java中的矩阵结构Map
@FieldOrder({ "data_type", "data_format", "rows", "cols", "rptr", "iptr" })
public class Matrix extends Structure {
public int data_type;
public int data_format;
public int rows;
public int cols;
public Pointer rptr;
public Pointer iptr;
// CONSTRUCTOR
public Matrix() {
super();
}
public Matrix (int imagenMatriz[][], int columnas, int filas) {
super();
// Valores por defecto, quizás se puedan eliminar
this.data_type = 0;
this.data_format = 0;
// Filas y columnas
this.rows = filas;
this.cols = columnas;
// Asignación de memoria para la matriz
this.rptr = new Memory(this.rows * 8); // Creamos vector de Pointer con tamanho = alto de la imagen (número de filas). Cada puntero ocupa 8 bytes.
for(int i = 0; i < this.rows; i++) {
Pointer fila = new Memory(this.cols * Integer.BYTES);
this.rptr.setPointer(i * 8, fila);
for(int j = 0; j < this.cols; j++) {
this.rptr.getPointer(i * 8).setInt(j * Integer.BYTES, imagenMatriz[j][i]); //Comentar y revisar esto, creo que está OK
}
}
// Probablemente, eliminable, de momento lo dejamos así
this.iptr = new Memory(8);
}
java中的接口定义
public interface I_CVIPTools extends Library {
I_CVIPTools INSTANCE = (I_CVIPTools) Native.load("rst_invariant", I_CVIPTools.class);
public Pointer rst_invariant(Image label_image, int r, int c);
}
我试图执行的测试(我在最后一行中得到错误)
Matrix test_matrix = new Matrix(test.getMatriz(), test.getColumnas(), test.getFilas());
System.out.println("Píxel (702, 242) = " + test_matrix.getPixel(702, 242));
Image test_image = new Image(test_matrix);
Pointer vector = new Memory(7 * Double.BYTES);
vector = I_CVIPTools.INSTANCE.rst_invariant(test_image, 242, 702);
1条答案
按热度按时间i1icjdpr1#
Map结构时要理解的关键点是它们何时被值和引用使用。
默认情况下,未装饰的结构是
ByReference
在方法/函数参数中使用时,以及ByValue
在结构内部使用时。如果需要以默认方式以外的方式使用它,则需要专门使用适当的接口。这个
Image
结构包含此本机元素:在jna中,这只是一个指针,或者
ByReference
结构。您错误地将其Map为内联ByValue
(默认情况下)结构:这就是导致当前“无效内存访问”错误的原因。你正在填充
Image
使用来自您的Matrix
结构。但是本机代码处理Image
struct看到两个整数data_type
及data_format
并试图将它们解释为指向结构数据所在位置的指针。你不拥有被指向的记忆。我看不到全部
Matrix
Map在您的问题中,但您需要包括ByReference
间接寻址级别之一的标记。此外,由于有两种间接方式,您需要实际传递
PointerByReference
给你Image
结构,因此您将使用以下内容替换当前Map:要填充该值,请执行以下操作: