簡體   English   中英

將 CMSampleBufferRef 轉換為 cv::Mat

[英]Convert CMSampleBufferRef to cv::Mat

我正在嘗試將 CMSampleBufferRef(作為 iOS 中 AVCaptureVideoDataOutputSampleBufferDelegate 的一部分)轉換為 OpenCV Mat,以嘗試半實時穩定輸出。

我跑在下面的那一刻測試應用這個,但一直收到當我創建和使用墊的問題。

迅捷控制器

let wrapper : OpenCVWrapper = OpenCVWrapper()
...
func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
    self.wrapper.processBuffer(sampleBuffer, self.previewMat)
}

OpenCVWrapper

- (void)processBuffer:(CMSampleBufferRef)buffer :(UIImageView*)previewMat {
    // Convert current buffer to Mat
    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(buffer);
    CVPixelBufferLockBaseAddress( pixelBuffer, 0);

    CGFloat bufferWidth = CVPixelBufferGetWidth(pixelBuffer);
    CGFloat bufferHeight = CVPixelBufferGetHeight(pixelBuffer);

    unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer);

    Mat tmp(bufferWidth, bufferHeight, CV_8UC4, pixel);
    Mat cur = tmp.clone();

    dispatch_async(dispatch_get_main_queue(), ^{
        [previewMat setImage:[UIImage imageWithCVMat:cur]];
    });
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}

Mat cur = tmp.clone()我得到一個EXC_BAD_ACCESS

對我在這里做錯了什么有任何想法嗎?

我試過 bufferWidth 和 CGFloat 和 int,並在 Mat 的構造函數中切換它們,同樣的問題。

改進了解決“僅前 30%”問題的解決方案:

- (cv::Mat)matFromBuffer:(CMSampleBufferRef)buffer {
    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(buffer);
    CVPixelBufferLockBaseAddress( pixelBuffer, 0 );

    //Processing here
    int bufferWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
    int bufferHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
    unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer);

    //put buffer in open cv, no memory copied
    cv::Mat mat = cv::Mat(bufferHeight,bufferWidth,CV_8UC4,pixel,CVPixelBufferGetBytesPerRow(pixelBuffer));

    //End processing
    CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );

    cv::Mat matGray;
    cvtColor(mat, matGray, CV_BGR2GRAY);

    return matGray;
}

也許這會奏效:

- (void)processBuffer:(CMSampleBufferRef)buffer :(UIImageView*)previewMat {
{
    CVImageBufferRef imgBuf = CMSampleBufferGetImageBuffer(buffer);

    // lock the buffer
    CVPixelBufferLockBaseAddress(imgBuf, 0);

    // get the address to the image data
    void *imgBufAddr = CVPixelBufferGetBaseAddressOfPlane(imgBuf, 0);

    // get image properties
    int w = (int)CVPixelBufferGetWidth(imgBuf);
    int h = (int)CVPixelBufferGetHeight(imgBuf);

    // create the cv mat
    cv::Mat image;
    image.create(h, w, CV_8UC4);
    // memcpy(image.data, imgBufAddr, w * h); copies only 25% of the image
    memcpy(image.data, imgBufAddr, w * h* 4); // copies all pixels

    // unlock again
    CVPixelBufferUnlockBaseAddress(imgBuf, 0);

    dispatch_async(dispatch_get_main_queue(), ^{
        [previewMat setImage:[UIImage imageWithCVMat:image]];
    });
}

圖像類型不相等,您需要嘗試執行某種操作

cvtColor(image, image_copy, CV_BGRA2BGR);

嘗試使用其他類型的 CV_BGRA2BGR

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM