2013-07-17 292 views
1

我使用openCV C++ API,并试图将相机缓冲区(YUV_NV12)转换为RGB格式。然而,我的图像尺寸发生了变化(宽度从720缩小到480),颜色错了(有点紫色/绿色ish)。OpenCV cvtColor()更改我的图像尺寸和错误的颜色

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和多数民众的工作,但规模并不)。*

回答

3

您的代码从一系列unsigned char s中构建一个名为yuvMat的单通道(灰度)图像。当您试图强制将这个单通道图像从YUV 4:2:0转换为多通道RGB时,OpenCV库假定每一行都具有完整4:4:4信息的2/3(对于1 x height x widthY1/2 height x widthUV each,而不是3 x height x width为正常YUV),因此您的目标图像的宽度收缩到原始宽度的2/3。可以认为,从原始图像中读取的一半数据来自未分配的内存,尽管原始图像只有width x height uchar s,但从内存中读取了2 x width x height uchar

如果uchar缓冲器已经正确格式化用于表示YUV_NV12一系列字节的每个信道的常规width x height字节(4:4:2 0子采样),所有需要做的是构造原来的yuvMat作为CV_8UC3和你已准备好出发。上面假定所有的隔行扫描和通道定位已经在缓冲区中实现。但很可能情况并非如此。 YUV_NV12数据与width x height uchar s的Y,其次是(1/2) width x (1/2) x height of 2 x uchar s代表UV合并。你可能需要编写自己的读者分别读取YUV数据,构建3单通道Mat的规模width x height的 - 在这两个UV渠道在水平和垂直填补空白 - 然后使用cv::merge()将这些单通道图像合并到3通道YUV,然后使用cv::cvtColor()使用CV_YUV2BGR选项转换该图像。请注意使用BGR而不是RGB

+0

非常感谢蜜蜂!当我尝试CV_8UC3时,我在0x11d7ba8处调用cvtColor()__generic_memcpy()时会出现段错误。所以你说我应该遍历我的缓冲区的所有像素,并构建一个新的3单通道?为什么选择BGR而不是RGB? – nox

+0

仅供参考,当我调用cvtColor()时(或者当我调用imwrite()时发生崩溃) – nox

+0

在OpenCV中,CV_8U3C图像中的默认颜色顺序是Blue-Green-Red。例如,'cv :: imwrite()'预计彩色图像的BGR排序。段错误可能因各种原因而发生,所以很难弄清楚为什么会出现段错误。有时在发布程序中使用调试库或反之亦然是罪魁祸首。您最好的选择是使用CV_8U单独构建每个通道,将每个通道推入std :: vector ,并使用cv :: merge将矢量合并到单个CV_8UC3图像中。 – Bee

0

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