【发布时间】:2016-07-08 19:42:43
【问题描述】:
我有一个(CMSampleBufferRef)imageBuffer,它是 yuv_nv12(4:2:0) 的类型。
现在我运行下面的代码,发现结果很混乱。
UInt8 *baseSRC = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer);
UInt8 *yBaseSRC = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
UInt8 *uvBaseSRC = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 1);
int width = (int)CVPixelBufferGetWidthOfPlane(imageBuffer, 0); //width = 480;
int height = (int)CVPixelBufferGetHeightOfPlane(imageBuffer, 0); //height = 360;
int y_base = yBaseSRC - baseSRC; //y_base = 64;
int uv_y = uvBaseSRC-yBaseSRC; //uv_y = 176640;
int delta = uv_y - width*height; //delta = 3840;
我对这个结果有几个问题。
1:为什么baseSRC 不等于yBaseSRC?
2:为什么yBaseSRC+width*height 不等于uvBaseSRC?理论上,y平面数据后面跟着uv平面数据,没有任何中断,对吧?现在它被大小为 3840 字节的东西打断了,我不明白。
3:我尝试使用以下代码将此示例像素转换为 cvmat,在大多数 iOS 设备上,这可以正常工作,但不适用于 iPhone 4s。在 iPhone 4s 上, 转换后,像素缓冲区的旁边有一些绿线。
Mat nv12Mat(height*1.5,width,CV_8UC1,(unsigned char *)yBaseSRC);
Mat rgbMat;
cvtColor(nv12Mat, rgbMat, CV_YUV2RGB_NV12);
现在 rgbMat 看起来像这样:
【问题讨论】:
-
CVPixelBuffers 是不透明类型,我会推断您找到的增量是 CVPixelBuffer 数据类型的一部分。由于没有记录数据类型并且 Apple 提供了 api 来提取您需要的数据,因此我不会对应该如何组织数据做出假设。至于opencv垫,你为什么使用(高度* 1.5)的高度。你应该只传递“高度”。
-
@blackirishman 因为'height'是y平面的高度,所以uv平面的高度等于'height/2.0',所以缓冲区的总大小应该是'widthheight+ widthheight/2.0',和'width*height*1.5'同义。
-
当你第一次写这篇文章时,你正在创建一个平面的垫子,对吧?您对 CVPixelBufferGetWidthOfPlane 和 CVPixelBufferGetHeightOfPlane 的调用为您提供了应输入到 Mat 中的宽度和高度。
-
@blackirishman 不,我正在创建一个包含所有平面(包括 y、u、v)的 Mat。
-
绿色数据必须是 CVPixelBuffer 中的任何内容。增量除以高度为 10.66,在您刚刚发布的图像中看起来像 10 像素。
标签: ios opencv video-processing yuv cvpixelbuffer