Mac 上的 vImage:无法从 Core Video 转换

vImage on the Mac: unable to convert from Core Video

编辑: 已修复。工作示例位于 https://github.com/halmueller/vImage-mac-sample.

我正在尝试读取 MacBook Pro 的 Facetime 摄像头的提要,以使用 vImage 框架对其进行处理。我正在按照 Apple VideoCaptureSample 中的示例进行操作,该示例是为 iOS 编写的。

我对创建 vImageConverter 挂断了,它创建了一个 vImage 可以使用的图像缓冲区。我对 vImageConverter_CreateForCVToCGImageFormat() 的调用失败,控制台错误 "insufficient information in srcCVFormat to decode image. vImageCVImageFormatError = -21601"。

相同的调用适用于 iOS。但是图像格式在 iOS 和 macOS 上是不同的。在 iOS 上,vImageConverter 构造函数能够推断出格式信息,但在 macOS 上,它不能。

这是我的设置代码:

func displayEqualizedPixelBuffer(pixelBuffer: CVPixelBuffer) {
    var error = kvImageNoError

    if converter == nil {
        let cvImageFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer).takeRetainedValue()
        let deviceRGBSpace = CGColorSpaceCreateDeviceRGB()
        let dcip3SolorSpace = CGColorSpace(name: CGColorSpace.dcip3)
        vImageCVImageFormat_SetColorSpace(cvImageFormat,
                                          deviceRGBSpace)
        print(cvImageFormat)

        if let unmanagedConverter = vImageConverter_CreateForCVToCGImageFormat(
            cvImageFormat,
            &cgImageFormat,
            nil,
            vImage_Flags(kvImagePrintDiagnosticsToConsole),
            &error) {

            guard error == kvImageNoError else {
                return
            }

            converter = unmanagedConverter.takeRetainedValue()
        } else {
            return
        }
    }

当我在 iOS 上 运行 时,我在控制台中看到:

vImageCVFormatRef 0x101e12210:
type: '420f'
matrix: 
    0.29899999499321 0.58700001239777 0.11400000005960
    -0.16873589158058 -0.33126410841942 0.50000000000000
    0.50000000000000 -0.41868758201599 -0.08131241053343
chroma location: <RGB Base colorspace missing>
RGB base colorspace: =Bo

不过,在 macOS 上,对 vImageConverter_CreateForCVToCGImageFormat returns 的调用为零,我看到:

vImageCVFormatRef 0x10133a270:
type: '2vuy'
matrix: 
    0.29899999499321 0.58700001239777 0.11400000005960
    -0.16873589158058 -0.33126410841942 0.50000000000000
    0.50000000000000 -0.41868758201599 -0.08131241053343
chroma location: <RGB Base colorspace missing>
RGB base colorspace: Рü

2018-03-13... kvImagePrintDiagnosticsToConsole: vImageConverter_CreateForCVToCGImageFormat error: 
insufficient information in srcCVFormat to decode image. vImageCVImageFormatError = -21601

请注意图像类型(4 个字母代码)不同,RGB 基本色彩空间也是如此。我试过 Mac 使用 dcip3ColorSpace 而不是 deviceRGB,结果是一样的。

创建这个 vImageConverter 我缺少什么?

-21601 错误代码表示源 CV 格式缺少色度定位信息(有关色度定位的漂亮背景,请参阅 http://dougkerr.net/Pumpkin/articles/Subsampling.pdf)。您可以通过使用 vImageCVImageFormat_SetChromaSiting 显式设置来解决此问题。因此,在设置格式的颜色 space 之后,在创建转换器之前(即你有 print(cvImageFormat) 的地方),立即添加以下内容:

        vImageCVImageFormat_SetChromaSiting(cvImageFormat,
                                            kCVImageBufferChromaLocation_Center)

干杯!

西蒙

因此,虽然关于在 vImage 格式上调用设置 chorma 属性 的答案确实有效,但有更好的方法可以做到这一点。只需在核心视频像素缓冲区上设置 属性,然后当您调用 vImageCVImageFormat_CreateWithCVPixelBuffer() 时它就会正常工作,如下所示:

NSDictionary *pbAttachments = @{
  (__bridge NSString*)kCVImageBufferChromaLocationTopFieldKey:(__bridge NSString*)kCVImageBufferChromaLocation_Center,
  (__bridge NSString*)kCVImageBufferAlphaChannelIsOpaque: (id)kCFBooleanTrue,
};

CVBufferRef pixelBuffer = cvPixelBuffer;
CVBufferSetAttachments(pixelBuffer, (__bridge CFDictionaryRef)pbAttachments, kCVAttachmentMode_ShouldPropagate);

为了加分,您还可以使用 kCVImageBufferICCProfileKey 和 CGColorSpaceCopyICCData() 设置颜色空间参考 API。