当前位置: 首页 > 知识库问答 >
问题:

Android JNI:将cv::mat转换为jbyteArray

沈飞翔
2023-03-14

我有C/C++源代码(在Windows上运行良好)将输入帧转换为新帧。

>

  • 将byte[]帧从Java转换为JNI jarrayByte

    将jarrayByte转换为Jyte*

    从JByte*创建新的cv::mat原始代码*

    extern "C" JNIEXPORT jbyteArray
    JNICALL
    Java_com_xyz_NativeUtil_convertFrame(JNIEnv *env, jobject obj,
                                                                      jbyteArray yuvFrame) {
    // convert jByteArray to jbyte*
    jbyte* yuvByte = env->GetByteArrayElements(yuvFrame, 0);
    // convert jbyte* to cv::Mat
    cv::Mat frame_original_yuv = cv::Mat(height + height/2, width, CV_8UC1, yuvByte);
    // convert YUV cv::Mat to RGBA cv::Mat
    cv::Mat frame_original_rgba = cv::Mat(height, width, CV_8UC4);
    cv::cvtColor(frame_original_yuv, frame_original_rgba, CV_YUV2RGBA_NV21);
    env->ReleaseByteArrayElements(yuvFrame, yuvByte, 0);
    // convert frame
    cv::Mat frame_converted = convert_frame(frame_original_rgba);
    frame_original_yuv.release();
    
    if (frame_converted .empty()) {
        frame_converted = frame_original_rgba;
    }
    frame_original_rgba.release();
    // convert cv::Mat to jbyteArray
    jbyteArray result = ???
    
    return result;
    

    }

    我的Java代码:

    mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    Image image = reader.acquireLatestImage();
                    if (image == null)
                        return;
    
                    Image.Plane Y = image.getPlanes()[0];
                    Image.Plane U = image.getPlanes()[1];
                    Image.Plane V = image.getPlanes()[2];
    
                    int Yb = Y.getBuffer().remaining();
                    int Ub = U.getBuffer().remaining();
                    int Vb = V.getBuffer().remaining();
    
                    byte[] yuvFrame = new byte[Yb + Ub + Vb];
    
                    Y.getBuffer().get(yuvFrame, 0, Yb);
                    U.getBuffer().get(yuvFrame, Yb, Ub);
                    V.getBuffer().get(yuvFrame, Yb + Ub, Vb);
    
                    image.close();
                }
            }, mBackgroundHandler);
    
  • 共有1个答案

    漆雕唯
    2023-03-14

    假设您希望将本机cv::mat对象传递给Java并将其转换为bitmap

    在这种情况下,最好将其转换为JintArray,因此我将使用它编写一个示例,但您可以轻松地修改该代码以使用JByteArray

    请注意,在该代码中,我假设cv::mat有4个通道(bgra),请相应地更改它。如果您的垫子是灰色的-将R、g、B设置为相同的灰色,将A设置为255。如果您的mat是bgr-将A设置为255。

    jintArray matToBitmapArray(JNIEnv *env, const cv::Mat &image) {
        jintArray resultImage = env->NewIntArray(image.total());
        jint *_data = new jint[image.total()];
        for (int i = 0; i < image.total(); i++) {
            char r = image.data[4 * i + 2];
            char g = image.data[4 * i + 1];
            char b = image.data[4 * i + 0];
            char a = image.data[4 * i + 3];
            _data[i] = (((jint) a << 24) & 0xFF000000) + (((jint) r << 16) & 0x00FF0000) +
                       (((jint) g << 8) & 0x0000FF00) + ((jint) b & 0x000000FF);
        }
        env->SetIntArrayRegion(resultImage, 0, image.total(), _data);
        delete[]_data;
    
        return resultImage;
    }
    
    jintArray matToBitmapArray(JNIEnv *env, const cv::Mat &image) {
        jintArray resultImage = env->NewIntArray(image.total());
        jint *_data = new jint[image.total()];
        for (int i = 0; i < image.total(); i++) {
            char r = image.data[3 * i + 2];
            char g = image.data[3 * i + 1];
            char b = image.data[3 * i + 0];
            char a = (char)255;
            _data[i] = (((jint) a << 24) & 0xFF000000) + (((jint) r << 16) & 0x00FF0000) +
                       (((jint) g << 8) & 0x0000FF00) + ((jint) b & 0x000000FF);
        }
        env->SetIntArrayRegion(resultImage, 0, image.total(), _data);
        delete[]_data;
    
        return resultImage;
    }
    
    jintArray matToBitmapArray(JNIEnv *env, const cv::Mat &image) {
        jintArray resultImage = env->NewIntArray(image.total());
        jint *_data = new jint[image.total()];
        for (int i = 0; i < image.total(); i++) {
            // Note that you can use better gray->rgba conversion
            char r = image.data[i];
            char g = image.data[i];
            char b = image.data[i];
            char a = (char)255;
            _data[i] = (((jint) a << 24) & 0xFF000000) + (((jint) r << 16) & 0x00FF0000) +
                       (((jint) g << 8) & 0x0000FF00) + ((jint) b & 0x000000FF);
        }
        env->SetIntArrayRegion(resultImage, 0, image.total(), _data);
        delete[]_data;
    
        return resultImage;
    }
    
    Bitmap bitmap = Bitmap.createBitmap(ourNativeArray, width, height, Bitmap.Config.ARGB_8888);
    

    编辑

    考虑到您有BGRA4通道映像,以下是如何将其转换为JByteArray

    jbyteArray matToByteArray(JNIEnv *env, const cv::Mat &image) {
        jbyteArray resultImage = env->NewByteArray(image.total() * 4);
        jbyte *_data = new jbyte[image.total() * 4];
        for (int i = 0; i < image.total() * 4; i++) {
            _data[i] = image.data[i];
        }
        env->SetByteArrayRegion(resultImage, 0, image.total() * 4, _data);
        delete[]_data;
    
        return resultImage;
    }
    
     类似资料:
    • 问题内容: 我正在尝试为使用OpenCV中的类的C ++库创建 Python / Cython 包装器。在官方的Python包装器中,所有函数都使用NumPy代替,这非常方便。但是在我自己的包装器中,如何进行这种转换?也就是说,我怎么 创建 的 ? 问题答案: 如kyamagu所建议,您可以使用OpenCV的官方python包装器代码,尤其是and 。 我一直在像您一样处理所有依赖项和生成的头文件

    • 在我的应用程序中,我有一个通过引用接收CV::MAT对象的函数。下面是函数的声明: 这个函数是递归的,在主函数的第一次调用中并不真正需要aaa,所以我只是声明了一个空aaa来将它传递给函数调用。在随后的递归调用中,function生成自己的ch Mat对象。 Main.cpp:75:错误:从“CV::MAT(*)()”类型的临时值初始化“CV::MAT&”类型的非常量引用无效。H:21:错误:在传

    • 问题内容: 如何将a转换为in ? 我正在使用JAVA包装器(不是 JavaCV )。由于我是新手,因此在理解工作方式方面存在一些问题。 我想做这样的事情。(根据Ted W.的回复): 这行不通。只是一张尺寸正确的黑色图片。 问题答案: 我还试图做同样的事情,因为需要将经过处理的图像与两个库结合在一起。而我一直试图做的是把中,而不是RGB值。而且有效!所以我做的是: 1,转换为字节数组 2.然后,

    • 问题内容: 我正在使用Java openCV,并且尝试加载照片并运行与之匹配的模板。模板匹配方法处理Mat对象,因此我需要加载图像并将其转换为Mat。 我这样做的方式是: 这样,我从Android SD卡加载了一张照片,并尝试使用openCV方法bitmapToMat将其转换为Mat对象。问题是在转换时,应用程序崩溃。 这是LogCat: 我不知道我做错了什么,还是只是有问题的openCV。 谢谢

    • 本文向大家介绍如何将OpenCV Mat对象转换为JavaFX WritableImage?,包括了如何将OpenCV Mat对象转换为JavaFX WritableImage?的使用技巧和注意事项,需要的朋友参考一下 如果尝试使用OpenCV imread()方法读取图像,它将返回Mat对象。如果要使用JavaFX窗口显示生成的Mat对象的内容,则需要将Mat对象转换为类javafx.scene

    • 我想把openCV Mat文件转换成GDI+位图图像。我找不到任何关于如何做到这一点的信息?