【问题标题】:opencv C++ create Mat object from android NV21 image data bufferopencv C++ 从 android NV21 图像数据缓冲区创建 Mat 对象
【发布时间】:2014-04-17 01:18:54
【问题描述】:

我已经实现了一个 android 应用程序,它启动相机并使用 JNI 接口将所有预览缓冲区发送到本机组件。由于预览数据是 NV21 图像格式,我需要从中创建一个 cv::Mat 实例。我搜索它并找到了以下解决方案:

cv::Mat _yuv(height, width, CV_8UC1, (uchar *) imagebuffer);

where imagebuffer is jbyte*

但是,不要在输出图像中得到预期的图像。里面全是一些随机的线条等等。有谁知道我到底是怎么做到的?

【问题讨论】:

    标签: android c++ opencv


    【解决方案1】:

    您需要将 YUV 图像转换为 RGBA 图像。

    cv::Mat _yuv(height+height/2, width, CV_8UC1, (uchar *)imagebuffer);
    cv::cvtColor(_yuv, _yuv, CV_YUV2RGBA_NV21);
    

    通常,YUV 图像是带有1.5*height 的 1 通道图像(如果是 RGB 或灰度图像)。

    或者您可以创建一个新的 Mat 并将 jint 数组传递给本机函数并使用该数组来设置位图的像素。

    jint *_out = env->GetIntArrayElements(out, 0);     
    
    cv::Mat _yuv(height + height/2, width, CV_8UC1, (uchar*)imagebuffer);
    cv::Mat _rgba(height, width, CV_8UC4, (uchar *)_out);
    
    cv::cvtColor(_yuv, _rgba, CV_YUV2RGBA_NV21);
    
    env->ReleaseIntArrayElements(out, _out, 0);
    

    在 Java 中,

    bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    pixels = new int[width * height];
    
    native_function(height, width, bytedata, pixels);
    
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    

    【讨论】:

    • 这样做之后,图像全是绿色的。如何纠正这个问题?
    • 我也有同样的问题(全绿)你能解决这个问题吗?
    【解决方案2】:

    第一个答案可能无法作为正确的彩色图像。这段代码就是我的答案。

        cv::Mat yuv(height+height/2, width, CV_8UC1,(uchar *)nv21ImageBuffer);
        cv::Mat converted(height, width, CV_8UC3);
        cv::cvtColor(yuv, converted, CV_YUV2BGR_NV21);
        cv::imwrite("anywhere/colorImage.jpg",converted);
    

    【讨论】:

      【解决方案3】:

      如果您使用的是本机 (C++) NDK camera2 API(版本 24 及更高版本)。您可以使用以下方法:

      #define YUV_IMG_HEIGHT      (1280)
      #define YUV_IMG_WIDTH       (720)
      
      void ndk_yuv_to_rgb_image()
      {
                uint8_t *yPixel = nullptr;
                uint8_t *uPixel = nullptr;
                uint8_t *vPixel = nullptr;
      
                int32_t yLen = 0;
                int32_t uLen = 0;
                int32_t vLen = 0;
      
                cv::Mat _yuv_rgb_img, _yuv_gray_img;
      
                AImage_getPlaneData(yuv_image, 0, &yPixel, &yLen);
                AImage_getPlaneData(yuv_image, 1, &uPixel, &uLen);
                AImage_getPlaneData(yuv_image, 2, &vPixel, &vLen);
      
                uint8_t * data = new uint8_t[yLen + vLen + uLen];
                memcpy(data, yPixel, yLen);
                memcpy(data+yLen, vPixel, vLen);
                memcpy(data+yLen+vLen, uPixel, uLen);
      
                cv::Mat mYUV = cv::Mat(YUV_IMG_HEIGHT * 1.5, YUV_IMG_WIDTH, CV_8UC1, data);
      
                cv::cvtColor(mYUV, _yuv_rgb_img, CV_YUV2RGB_NV21, 3);
      }
      

      如需完整的 C++ NDK Camera2 API,请查看我的 git repo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-08
        • 1970-01-01
        • 1970-01-01
        • 2013-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多