我已经实现了一个启动摄像头的Android应用程序,并使用JNI接口将所有预览缓冲区发送到本机组件。由于预览数据是NV21图像格式,我需要从中创建一个cv :: Mat实例。我搜索了它并找到了以下解决方案:
cv::Mat _yuv(height, width, CV_8UC1, (uchar *) imagebuffer);
where imagebuffer is jbyte*
但是,请勿在输出图像中获得预期的图像。这些都充满了一些随机的线条等。有谁知道我到底能做到什么?
答案 0 :(得分:16)
您需要将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);
答案 1 :(得分: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);
答案 2 :(得分: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