将 Android NV21 图像数据缓冲区转换为 OpenCV C++ 的 Mat 对象

9

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

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

where imagebuffer is jbyte*

然而,在输出图像中没有得到预期的图像。 它全部都填充了一些随机的线条等等。 有人知道我应该如何精确地做吗?

3个回答

19

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

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

通常,YUV图像是1通道图像,高度为1.5*height(如果它是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);

完成后,图像全部变成了绿色。如何纠正这个问题? - Waqas Ahmed Ansari
我也遇到了相同的问题(所有灯都是绿色)。你能解决吗? - isra60

0

第一个答案可能不会显示正确的彩色图像。这段代码是我的答案。

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

0
如果您正在使用本地(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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接