高效地将 BufferedImage 转换为 IplImage

发布于 2024-12-27 16:48:14 字数 1190 浏览 0 评论 0原文

我正在尝试有效地将 BufferedImage 转换为 IplImage...您能给我有关 jni 部分的任何提示吗?

现在我执行以下步骤:

我从 BufferedImage 获取 rgb,然后将它们发送到 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;}

真的很慢...谢谢您的帮助!

I'm trying to do efficiently convert a BufferedImage to an IplImage... could you give me any hint about the jni part?

Right now I do these steps:

I get the rgbs from the BufferedImage and I send them to the jni code where I do the following:

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;}};

and

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;}

But that is really slow... thank you for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒中人 2025-01-03 16:48:14

对于 JavaCV

IplImage.createFrom(aBufferedImage)

编辑:您的代码速度缓慢有几个原因。 BufferedImage 类是在 NIO 缓冲区流行之前设计的,因此它使用标准 Java 数组作为后备缓冲区。 Java 数组无法(安全)直接从 JNI 访问,因此默认情况下,通过调用 GetIntArrayElements() 的方式,内存会被临时分配,数组数据会被复制到新分配的内存中,而 ReleaseIntArrayElements() 也会复制回数据到数组中,并释放临时分配的内存。您还可以在每次调用时分配一个新的 IplImage,并在将所有内容从临时缓冲区复制到临时 IplImage 时制作另一个副本。简而言之,您的代码在堆上分配内存两次并复制数据三次。达到预期效果的推荐方法是使用直接 NIO 缓冲区从 Java 内部仅复制一次数据。您可以通过查看 JavaCV 源代码的相关部分来检查它的样子,即 IplImage.copyFrom(BufferedImage):

http://code.google.com/p/javacv/source/browse/trunk/javacv/src/com/googlecode/javacv/cpp/opencv_core.java#881

它分支为有很多特殊情况,但基本上它会循环所有像素以生成副本。添加几个线程在多个内核上并行循环也可以进一步提高性能...

从 Java 复制数据后,如果需要,您可以直接从本机代码使用它。

With JavaCV:

IplImage.createFrom(aBufferedImage)

EDIT: There are a couple of reasons why your code is slow. The BufferedImage class was designed before NIO buffers came into fashion, so it uses standard Java arrays as backing buffer. Java arrays cannot be (safely) accessed directly from JNI, so by default, with the way you call GetIntArrayElements(), memory gets temporarily allocated and the array data gets copied into that new allocated memory, while ReleaseIntArrayElements() also copies back the data into the array, and frees the temporary allocated memory. And you also allocate a new IplImage on every call and make another copy when copying everything from that temporary buffer to the temporary IplImage. In a nutshell, your code allocates memory twice on the heap and copies the data three times. The recommended way to achieve the desired effect is instead to copy the data only once from inside Java, using direct NIO buffers. You can check what this looks like by peering into the relevant portion of the JavaCV's source code, namely IplImage.copyFrom(BufferedImage):

http://code.google.com/p/javacv/source/browse/trunk/javacv/src/com/googlecode/javacv/cpp/opencv_core.java#881

It branches into a lot of special cases, but basically it loops over all pixels to produce the copy. Adding a couple of threads to loop in parallel on multiple cores could also improve performance further...

After copying the data from Java, you may then use it directly from your native code if desired.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文