iOS с использованием vImage — ускорьте преобразование QCAR YUV в RGB

Я пытаюсь проверить производительность преобразования изображений YUV, созданных Vuforia, и преобразования их в UIImage с помощью вызовов vImage iOS Accelerate Framework. В текущем состоянии кода я просто пытаюсь заставить его работать. Прямо сейчас преобразование дает темное полосатое изображение. Есть ли какие-либо опубликованные подробности о том, как Vuforia изложила формат YUV в своей реализации? Мое первоначальное предположение заключалось в том, что они использовали двухплоскостной формат 420p, который используют устройства iOS. Далее следует соответствующий тестовый код.

UIImage *imageWithQCARCameraImage(const QCAR::Image *cameraImage)
{
    UIImage *image = nil;

    if (cameraImage) {
        QCAR::PIXEL_FORMAT pixelFormat = cameraImage->getFormat();

        CGColorSpaceRef colorSpace = NULL;
        switch (pixelFormat) {
            case QCAR::YUV:
            case QCAR::RGB888:
                colorSpace = CGColorSpaceCreateDeviceRGB();
                break;
            case QCAR::GRAYSCALE:
                colorSpace = CGColorSpaceCreateDeviceGray();
                break;
            case QCAR::RGB565:
            case QCAR::RGBA8888:
            case QCAR::INDEXED:
                std::cerr << "Image format conversion not implemented." << std::endl;
                break;
            case QCAR::UNKNOWN_FORMAT:
                std::cerr << "Image format unknown." << std::endl;
                break;
        }

        int bitsPerComponent = 8;
        int width = cameraImage->getWidth();
        int height = cameraImage->getHeight();
        const void *baseAddress = cameraImage->getPixels();
        size_t totalBytes = QCAR::getBufferSize(width, height, pixelFormat);

        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone;
        CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
        CGImageRef imageRef = NULL;

        if (pixelFormat == QCAR::YUV) {
            int bytesPerPixel = 4;
            uint8_t *sourceDataAddress = (uint8_t *)baseAddress;

            static vImage_Buffer srcYp = {
                .width = static_cast<vImagePixelCount>(width),
                .height = static_cast<vImagePixelCount>(height),
                .data = const_cast<void *>(baseAddress)
            };

            size_t lumaBytes = width * height;
            size_t chromianceBytes = totalBytes - lumaBytes;
            static vImage_Buffer srcCb = {
                .data = static_cast<void *>(sourceDataAddress + lumaBytes)
            };

            static vImage_Buffer srcCr = {
                .data = static_cast<void *>(sourceDataAddress + lumaBytes + (chromianceBytes / 2))
            };

            static vImage_Buffer dest = {
                .width = static_cast<vImagePixelCount>(width),
                .height = static_cast<vImagePixelCount>(height),
                .data = imageData
            };

            //uint8_t permuteMap[] = { 1, 2, 3, 0 };
            vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 0, 128, 255, 255, 255, 1, 255, 0 };
            vImage_YpCbCrToARGB info;

            vImage_Error error;

            error = vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_601_4,
                                                                  &pixelRange,
                                                                  &info,
                                                                  kvImage420Yp8_Cb8_Cr8,
                                                                  kvImageARGB8888,
                                                                  kvImagePrintDiagnosticsToConsole);


            error = vImageConvert_420Yp8_Cb8_Cr8ToARGB8888(&srcYp,
                                                           &srcCb,
                                                           &srcCr,
                                                           &dest,
                                                           &info,
                                                           NULL,
                                                           1,
                                                           kvImageNoFlags);

            vImage_CGImageFormat format =
            {
                .bitsPerComponent = static_cast<uint32_t>(bitsPerComponent),
                .bitsPerPixel = static_cast<uint32_t>(3 * bitsPerComponent),
                .colorSpace = colorSpace,
                .bitmapInfo = bitmapInfo,
                .version = 0,
                .decode = NULL,
                .renderingIntent = renderingIntent
            };

            imageRef = vImageCreateCGImageFromBuffer(&dest,
                                                     &format,
                                                     NULL,
                                                     NULL,
                                                     kvImageNoFlags,
                                                     &error);
            if (error) {
                std::cerr << "Err." << std::endl;
            }
        } else {
            int bitsPerPixel = QCAR::getBitsPerPixel(pixelFormat);
            int bytesPerRow = cameraImage->getStride();
            CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                                      baseAddress,
                                                                      totalBytes,
                                                                      NULL);

           imageRef = CGImageCreate(width,
                                    height,
                                    bitsPerComponent,
                                    bitsPerPixel,
                                    bytesPerRow,
                                    colorSpace,
                                    bitmapInfo,
                                    provider,
                                    NULL,
                                    false,
                                    renderingIntent);
            CGDataProviderRelease(provider);
        }

        if (imageRef != NULL) {
            image = [UIImage imageWithCGImage:imageRef];
            CGImageRelease(imageRef);
        }

        if (colorSpace != NULL) {
            CGColorSpaceRelease(colorSpace);
        }

    }

    return image;
}

person Cameron Lowell Palmer    schedule 07.04.2015    source источник
comment
Любые опубликованные подробности от Qualcomm до сих пор были бесполезны. Но на своих форумах модераторы стараются отвечать на вопросы. Если это хороший вопрос, они ответят только двумя способами: обратитесь к документации или к фактическому ответу. Надеюсь, вы получите ответ, звучит интересно.   -  person Augmented Jacob    schedule 08.04.2015
comment
Спрошу и на форуме, хотя форум у них не очень. То, что я узнал о YUV, говорит мне о том, что их API не предоставляет достаточно подробностей, чтобы вы могли делать что-либо, кроме предположений, поскольку существует множество потенциальных форматов.   -  person Cameron Lowell Palmer    schedule 08.04.2015
comment
Очень очень верно! Qualcomm нужно ускориться.   -  person Augmented Jacob    schedule 09.04.2015
comment
Вам необходимо каждый раз заполнять все четыре поля структуры vImage_Buffer.   -  person Ian Ollmann    schedule 17.04.2015
comment
@IanOllmann, поэтому я сказал только для тестирования. Однако, если вы собираетесь сделать такое заявление о функциональности, было бы полезно, если бы вы предоставили цитату, если вы говорите о производительности, то именно поэтому я сказал, что это было для тестирования. Заставьте это работать, сделайте это правильно, сделайте это быстро. В этой последовательности.   -  person Cameron Lowell Palmer    schedule 19.04.2015
comment
Я - моя собственная цитата по этому поводу. Горящие кусты будут поставляться по мере необходимости.   -  person Ian Ollmann    schedule 20.04.2015
comment
Один горящий куст, пожалуйста.   -  person Cameron Lowell Palmer    schedule 21.04.2015
comment
Ян является каноническим авторитетом во всем, что касается vImage. Когда он требует жертвы, вы находите козла.   -  person Stephen Canon    schedule 21.04.2015
comment
Тем не менее, это не отвечает на основной вопрос, который заключается в следующем... Каков формат кадра Vuforia YUV?   -  person Cameron Lowell Palmer    schedule 21.04.2015


Ответы (1)


person    schedule
comment
отредактируйте свой ответ и добавьте объяснение, как/почему этот код решает проблему (выше кода, а не где-то в комментариях). - person barbsan; 05.12.2018