Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios YUV-NV12视频缓冲区的连续性&x27;s-y平面和uv平面_Ios_Opencv_Video Processing_Yuv_Cvpixelbuffer - Fatal编程技术网

Ios YUV-NV12视频缓冲区的连续性&x27;s-y平面和uv平面

Ios YUV-NV12视频缓冲区的连续性&x27;s-y平面和uv平面,ios,opencv,video-processing,yuv,cvpixelbuffer,Ios,Opencv,Video Processing,Yuv,Cvpixelbuffer,我有一个(CMSampleBufferRef)imageBuffer,它是yuv_nv12(4:2:0)的类型 现在我运行以下代码,发现结果令人困惑 UInt8 *baseSRC = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); UInt8 *yBaseSRC = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); UInt8 *uvBaseSRC = (UInt8 *)

我有一个
(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看起来像这样:


最终找到了解决方案,基本上解决方案是分配一块新内存,将y平面数据和uv平面数据连接起来。然后将其转换为cvmat即可

以下是代码片段:

UInt8 *newBase = (UInt8 *)malloc(landscapeWidth*landscapeHeight*1.5);
memcpy(newBase, yBaseSRC, landscapeWidth*landscapeHeight);
memcpy(newBase+landscapeWidth*landscapeHeight, uvBaseSRC, landscapeWidth*landscapeHeight*0.5);
Mat nv12Mat(landscapeHeight*1.5,landscapeWidth,CV_8UC1,(unsigned char *)newBase);

CVPixelBuffers是不透明类型,我可以推断您找到的增量是属于CVPixelBuffer数据类型的数据。由于数据类型没有文档记录,而且苹果提供了提取所需数据的API,因此我不会对数据的组织方式做出假设。至于opencv垫,为什么使用高度为(高度*1.5)。你应该只传递“height”。@blackirishman因为“height”是y平面的高度,uv平面的高度等于“height/2.0”,所以缓冲区的总大小应该是“widthheight+widthheight/2.0”,这与“width*height*1.5”的含义相同。当你第一次写这篇文章时,你是在创建y平面的一个垫子,对吗?您对CVPixelBufferGetWidthOfPlane和CVPixelBufferGetHeightOfPlane的调用为您提供了应该输入到垫子中的宽度和高度。@blackirishman否,我正在创建一个包含所有平面(包括y、u、v)的垫子。绿色数据必须是CVPixelBuffer中的任何平面。delta除以高度是10.66,这看起来像你刚刚发布的图像中的10个像素。