Как преобразовать opencv cv :: Mat в CVPixelBuffer

Я студентка бакалавриата и создаю приложение для iPhone от HumanSeg, используя CoreML. Поскольку моей модели требуется изменение размера и черный отступ на исходных видеокадрах, я не могу полагаться на Vision (который обеспечивает только изменение размера, но без черного заполнения) и должен выполнить преобразовываю себя.

У меня CVPixelBuffer фреймов, и я преобразовал их в cv::Mat, используя следующие коды:

CVPixelBufferLockBaseAddress(pixelBuffer, 0);
int bufferWidth = (int) CVPixelBufferGetWidth(pixelBuffer);
int bufferHeight = (int) CVPixelBufferGetHeight(pixelBuffer);
int bytePerRow = (int) CVPixelBufferGetBytesPerRow(pixelBuffer);
unsigned char *pixel = (unsigned char *) CVPixelBufferGetBaseAddress(pixelBuffer);
Mat image = Mat(bufferHeight, bufferWidth, CV_8UC4, pixel, bytePerRow);
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
/*I'll do my resizing and padding here*/

// How can I implement this function?
convertToCVPixelBuffer(image);

Но теперь, после завершения предварительной обработки, мне нужно преобразовать cv::Mat обратно в CVPixelBuffer скормить его модели CoreML. Как я могу этого добиться? (Или Vision может добиться черной прокладки с помощью каких-то специальных приемов?)

Любая помощь будет оценена по достоинству.


person AXIHIXA    schedule 04.11.2017    source источник


Ответы (2)


Сначала преобразуйте mat в UIImage (или любой другой класс из API iOS), проверьте это вопрос. Затем преобразуйте полученное изображение в CVPixelBuffer, например this.

person Wladek Surala    schedule 09.11.2017
comment
Благодаря вашей помощи, но этот метод слишком медленный и невыносимый для приложения для обработки видео. - person AXIHIXA; 30.11.2017

Пожалуйста, посмотрите код ниже ... Необходимо проверить, делятся ли ширина и высота на 64, иначе мы получим странные результаты из-за BytesPerRow несоответствия с cv::Mat и CVPixelBuffer

CVPixelBufferRef getImageBufferFromMat(cv::Mat matimg) {
    cv::cvtColor(matimg, matimg, CV_BGR2BGRA);
    
    /* Very much required see https://stackoverflow.com/questions/66434552/objective-c-cvmat-to-cvpixelbuffer
     height & width has to be multiple of 64 for better caching
     */
    int widthReminder = matimg.cols % 64, heightReminder = matimg.rows % 64;
    if (widthReminder != 0 || heightReminder != 0) {
        cv::resize(matimg, matimg, cv::Size(matimg.cols + (64 - widthReminder), matimg.rows + (64 - heightReminder)));
    }
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool: YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool: YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             [NSNumber numberWithInt: matimg.cols], kCVPixelBufferWidthKey,
                             [NSNumber numberWithInt: matimg.rows], kCVPixelBufferHeightKey,
                             [NSNumber numberWithInt: matimg.step[0]], kCVPixelBufferBytesPerRowAlignmentKey,
                             nil];
    CVPixelBufferRef imageBuffer;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorMalloc, matimg.cols, matimg.rows, kCVPixelFormatType_32BGRA, (CFDictionaryRef) CFBridgingRetain(options), &imageBuffer) ;
    NSParameterAssert(status == kCVReturnSuccess && imageBuffer != NULL);
    
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    void *base = CVPixelBufferGetBaseAddress(imageBuffer);
    memcpy(base, matimg.data, matimg.total() * matimg.elemSize());
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    
    return imageBuffer;
}
person Abhinava B N    schedule 02.03.2021