1

我正在使用 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 并且可以工作,但大小不是)。*

4

2 回答 2

3

yuvMat您的代码构造了一个从一系列unsigned chars中调用的单通道(灰度)图像。当您尝试 - 强制 - 将此单通道图像从 YUV 4:2:0 转换为多通道 RGB 时,OpenCV 库假定每行具有完整 4:4:4 信息的 2/3(1 x height x width对于Y1/2 height x widthfor Uand Veach,而不是3 x height x widthfor a normal YUV),因此目标图像的宽度缩小到原始宽度的 2/3。可以假设从原始图像中读取的数据有一半来自未分配的内存,因为原始图像只有width x height uchars 但2 x width x height uchars 是从内存中读取的!

如果您的uchar缓冲区已经正确格式化为代表 YUV_NV12 (4:2:0 子采样)的一系列字节在width x height每个通道的常规字节中,那么您需要做的就是将您的原始文件构造yuvMat为 aCV_8UC3并且一切顺利。以上假设所有隔行扫描和通道定位都已经在缓冲区中实现。很可能情况并非如此。YUV_NV12 数据带有width x height uchars Y,后跟(1/2) width x (1/2) x height of 2 x uchars 表示UV组合。您可能需要编写自己的阅读器来分别读取Y,U和data 并构造 3 个大小为 s 的V单通道- 填充和通道中的水平和垂直间隙- 然后使用Matwidth x heightUVcv::merge()在使用选项转换该图像YUV之前将这些单通道图像组合成一个 3 通道。注意使用代替。 cv::cvtColor()CV_YUV2BGRBGRRGB

于 2013-07-17T13:53:29.527 回答
0

可能是“作为参数传递的东西”没有足够的数据来填充 720 行。对于某些摄像机,并非所有三个通道都使用相同的位数表示。例如,在 iPhone 上捕捉视频时,三个通道使用 8-4-4 字节而不是 8-8-8。我没有在 OpenCV 中使用过这种类型的相机,但很可能问题就在这里。

于 2013-07-17T01:33:47.193 回答