我正在尝试有效地将BufferedImage转换为IplImage ...你能否给我一些关于jni部分的提示?
现在我执行以下步骤:
我从BufferedImage获取rgbs并将它们发送到jni代码,我执行以下操作:
IplImage* getIplImageFromIntArray(JNIEnv* env, jintArray array_data,
jint width, jint height) {
int *pixels = env->GetIntArrayElements(array_data, 0);
if (pixels == 0) {
return 0;
}
IplImage *image = loadPixels(pixels, width, height);
env->ReleaseIntArrayElements(array_data, pixels, 0);
if (image == 0) {
return 0;
}
return image;}};
和
IplImage* loadPixels(int* pixels, int width, int height) {
int x, y;
IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
unsigned char* base = (unsigned char*) (img->imageData);
unsigned char* ptr;
for (y = 0; y < height; y++) {
ptr = base + y * img->widthStep;
for (x = 0; x < width; x++) {
// blue
ptr[3 * x] = pixels[x + y * width] & 0xFF;
// green
ptr[3 * x + 1] = pixels[x + y * width] >> 8 & 0xFF;
// blue
ptr[3 * x + 2] = pixels[x + y * width] >> 16 & 0xFF;
}
}
return img;}
但那真的很慢......谢谢你的帮助!
答案 0 :(得分:1)
使用JavaCV:
IplImage.createFrom(aBufferedImage)
编辑:您的代码速度慢的原因有很多。 BufferedImage类是在NIO缓冲区开始之前设计的,因此它使用标准Java数组作为后备缓冲区。无法(安全地)直接从JNI访问Java数组,因此默认情况下,通过调用GetIntArrayElements()的方式,临时分配内存并将数组数据复制到新分配的内存中,而ReleaseIntArrayElements()也会复制数据进入数组,并释放临时分配的内存。并且您还在每次调用时分配一个新的IplImage,并在将所有内容从该临时缓冲区复制到临时IplImage时创建另一个副本。简而言之,您的代码在堆上分配两次内存并将数据复制三次。实现所需效果的推荐方法是使用直接NIO缓冲区从Java内部复制数据一次。您可以通过查看JavaCV源代码的相关部分来检查它的外观,即IplImage.copyFrom(BufferedImage):
它分支到很多特殊情况,但基本上它遍历所有像素以产生副本。添加几个线程以在多个内核上并行循环也可以进一步提高性能......
从Java复制数据后,您可以根据需要直接从本机代码中使用它。