当前位置: 首页 > 知识库问答 >
问题:

将CVImageBuffer转换为YUV420对象

宇文迪
2023-03-14

我想保持YUV420格式的流视频从相机,以避免在转换到灰度的惩罚,但我也想保留彩色分量。最终的目标是用像OpenCV这样的计算机视觉库进行处理。虽然我最终可能会选择BGRA,但我仍然希望能够用YUV测试一个工作解决方案。那么如何将像素格式为KCVPixelFormattype_420YPCBCR8BiplanarFullRange的CVImageBuffer转换为单个内存块呢?

拒绝的解决方案:

    null

共有1个答案

柳晔
2023-03-14

这将把数据填充到包含字节的NSObject中,具体取决于指定的像素格式。我继续,并提供了能力,以检测和malloc内存的BGRA或YUV像素格式。所以这个解决方案非常适合测试这两者。

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVImageBufferRef videoImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    CVPixelBufferLockBaseAddress(videoImageBuffer, 0);

    void *baseAddress = NULL;
    NSUInteger totalBytes = 0;
    size_t width = CVPixelBufferGetWidth(videoImageBuffer);
    size_t height = 0;
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoImageBuffer);
    OSType pixelFormat = CVPixelBufferGetPixelFormatType(videoImageBuffer);
    if (pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
        pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
        size_t planeCount = CVPixelBufferGetPlaneCount(videoImageBuffer);
        baseAddress = CVPixelBufferGetBaseAddressOfPlane(videoImageBuffer, 0);

        for (int plane = 0; plane < planeCount; plane++) {
            size_t planeHeight = CVPixelBufferGetHeightOfPlane(videoImageBuffer, plane);
            size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(videoImageBuffer, plane);
            height += planeHeight;
            totalBytes += (int)planeHeight * (int)bytesPerRow;
        }
    } else if (pixelFormat == kCVPixelFormatType_32BGRA) {
        baseAddress = CVPixelBufferGetBaseAddress(videoImageBuffer);
        height = CVPixelBufferGetHeight(videoImageBuffer);
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoImageBuffer);
        totalBytes += (int)height * (int)bytesPerRow;
    }

    // Doesn't have to be an NSData object
    NSData *rawPixelData = [NSData dataWithBytes:baseAddress length:totalBytes];

    // Just a plain-ol-NSObject with the following properties
    NTNUVideoFrame *videoFrame = [[NTNUVideoFrame alloc] init];
    videoFrame.width = width;
    videoFrame.height = height;
    videoFrame.bytesPerRow = bytesPerRow;
    videoFrame.pixelFormat = pixelFormat; 
    // Alternatively if you switch rawPixelData to void *
    // videoFrame.rawPixelData = baseAddress;
    videoFrame.rawPixelData = rawPixelData;
    [self.delegate didUpdateVideoFrame:videoFrame];

    CVPixelBufferUnlockBaseAddress(videoImageBuffer, 0);
}

您需要记住的唯一一件事是,如果您计划切换线程,或者dispatch_async并且不使用nsdata,则需要mallocmemcpy基址。一旦解锁基址,像素数据将不再有效。

void *rawPixelData = malloc(totalBytes);
memcpy(rawPixelData, baseAddress, totalBytes);

此时您需要考虑在完成时调用该内存块的free的问题。

 类似资料:
  • 问题内容: 我有一个JSON对象,我将其转换为并在此处进行一些处理。稍后,我想转换相同的缓冲区数据以转换为有效的JSON对象。 我正在研究Node V6.9.1 下面是我尝试过的代码,但是当我转换回JSON却无法打开该对象时遇到了。 所以我尝试使用检查方式打印整个对象 如果我尝试像数组一样读取它 我也尝试解析它抛出 我需要将其视为我创建的真实对象(我的意思是像上面声明的那样)。 请帮忙.. 问题答

  • 我正试图将下面的json转换成java bean,需要你的帮助 Sort.json 我的豆子看起来像 我的测试课是 我看到的错误是 请建议:

  • 问题内容: 我正在将struts2用于Action,将jquery用于UI … 我想知道如何将Map对象转换为JSON对象并将其发送回UI, 现在可以在JSP页面中将其打印为普通的Java Map对象: 但我希望它是这样的: 我将如何实现这一目标…? 问题答案: 尝试Gson: 不过,我不建议将这种代码放入JSP。诸如此类的事情应该存在于Servlet或Action类之类的控制器中。 您还绝对不希

  • 问题内容: 我对服务进行了调用,并将响应存储在中。但是,我试图将其转换为类对象并得到错误。这是我的代码: 响应如下所示: 这是该类的样子: 但是我得到了错误: 我究竟做错了什么? 编辑1: 这是从答案中使用gson的尝试: 但是我得到了错误: 问题答案: 找出问题所在。需要提取jsonobject而不是获取字符串。这是解决此问题的行:

  • 我需要将实体对象转换为json。我把 到 servlet 配置文件,因此 Spring 可以自动将对象转换为 json 格式。但Spring没有这样做。我还在项目中添加了杰克逊罐子。 控制器方法 小组学生 } 在浏览器中,我发现我有 406 错误和错误窗口错误[对象对象]。 如果有人知道问题出在哪里,我会很高兴得到帮助。 谢谢。

  • 问题内容: 转换的最佳方法是什么: 至: 问题答案: ECMAScript 6引入了易于填充的内容: 该方法用于将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 数组的自身属性不会被复制,因为它无法枚举。 另外,您可以使用ES6 传播语法来达到相同的结果: