vImage на Mac: невозможно преобразовать из Core Video

Редактировать: Исправлено. Рабочий образец находится по адресу https://github.com/halmueller/vImage-mac-sample.

Я пытаюсь прочитать поток с камеры MacBook Pro Facetime, чтобы обработать ее с помощью инфраструктуры vImage. Я следую примеру в Apple VideoCaptureSample, который написан для iOS.

Я зациклен на создании vImageConverter, который создает буфер изображения, который может использовать vImage. Мой звонок vImageConverter_CreateForCVToCGImageFormat() завершается с ошибкой консоли "недостаточно информации в srcCVFormat для декодирования изображения. 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 возвращает ноль, и я вижу:

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?

1 ответ

Решение

-21601 Код ошибки означает, что в исходном формате CV отсутствует информация о расположении цветов (см. http://dougkerr.net/Pumpkin/articles/Subsampling.pdf чтобы узнать об истории размещения цветов). Вы можете исправить это, явно установив vImageCVImageFormat_SetChromaSiting, Итак, сразу после установки цветового пространства формата и до создания конвертера (т.е. где у вас есть print(cvImageFormat)), добавьте следующее:

        vImageCVImageFormat_SetChromaSiting(cvImageFormat,
                                            kCVImageBufferChromaLocation_Center)

Ура!

Саймон

Таким образом, хотя ответ о вызове установки свойства chorma в формате vImage работает, есть лучший способ сделать это. Просто установите свойство в основном пиксельном буфере видео, а затем, когда вы вызовете 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);

Для дополнительных точек вы также можете установить цветовое пространство ref с помощью kCVImageBufferICCProfileKey и CGColorSpaceCopyICCData() API.

Другие вопросы по тегам