我正在使用openCV C ++ API,我正在尝试将相机缓冲区(YUV_NV12)转换为RGB格式。但是,我的图像尺寸发生了变化(宽度从720缩小到480),颜色错误(有点紫色/绿色)。
unsigned char* myYUVBufferPointer = (something passed as argument)
int myYUVBufferHeight = 1280
int myYUVBufferWidth = 720
cv::Mat yuvMat(myYUVBufferHeight, myYUVBufferWidth, CV_8U, myYUVBufferPointer);
cv::Mat rgbMat;
cv::cvtColor(yuvMat, rgbMat, CV_YUV2RGB_NV12);
cv::imwrite("path/to/my/image.jpg",rgbMat);
有什么想法吗? *(我更感兴趣的是尺寸变化而不是颜色,因为我最终将它转换为CV_YUV2GRAY_NV12,那可行,但尺寸不大)。*
答案 0 :(得分:3)
您的代码构造了一系列yuvMat
中名为unsigned char
的单通道(灰度)图像。当您尝试 - 强制 - 将此单通道图像从YUV 4:2:0转换为多通道RGB时,OpenCV库假定每行有2/3的完整4:4:4信息({{ 1}}用于1 x height x width
和Y
用于1/2 height x width
和U
每个,而不是V
用于普通3 x height x width
因此你的宽度目标图像缩小到原始宽度的2/3。可以假设从原始图像读取的一半数据来自未分配的内存,因为原始图像只有YUV
s但从内存中读取width x height uchar
!
如果您的2 x width x height uchar
缓冲区已经针对每个通道的传统uchar
字节中表示YUV_NV12(4:2:0子采样)的一系列字节进行了正确格式化,那么您需要做的就是构建原来的width x height
为yuvMat
,你很高兴。以上假设所有隔行扫描和通道定位已在缓冲区中实现。最可能的情况并非如此。 YUV_NV12数据随CV_8UC3
的{{1}}一起提供,后跟代表width x height uchar
的{{1}}组合。您可能需要编写自己的阅读器以分别阅读Y
,(1/2) width x (1/2) x height of 2 x uchar
和UV
数据,并构建3个大小为Y
的单通道U
- 填写V
和Mat
频道中的水平和垂直间隙 - 然后使用width x height
将这些单频道图像合并到3频道U
之前使用V
使用cv::merge()
选项转换该图片。请注意使用YUV
代替cv::cvtColor()
。
答案 1 :(得分:0)
可能是“作为参数传递的东西”没有足够的数据来填充720行。对于一些摄像机,并非所有三个通道都使用相同的位数来表示。例如,在iPhone上捕获视频时,三个通道使用8-4-4字节而不是8-8-8。我没有在OpenCV上使用过这种类型的相机,但问题很可能就在这里。