菜鸟教程小白 发表于 2022-12-12 10:06:51

c++ - 将 CMSampleBufferRef 转换为 cv::Mat


                                            <p><p>我正在尝试将 CMSampleBufferRef(作为 iOS 中 AVCaptureVideoDataOutputSampleBufferDelegate 的一部分)转换为 OpenCV Mat,以尝试半实时地稳定输出。</p>

<p>我正在运行一个测试应用程序,紧接着 <a href="https://stackoverflow.com/questions/12355257/open-cv-ios-video-processing" rel="noreferrer noopener nofollow">this</a> ,但在我创建和使用 Mat 时不断遇到问题。</p>

<p><strong>SwiftController </strong></p>

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

<p><strong>OpenCVWrapper</strong></p>

<pre><code>- (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(), ^{
      ];
    });
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}
</code></pre>

<p>在 <code>Mat cur = tmp.clone()</code> 中,我得到一个 <code>EXC_BAD_ACCESS</code></p>

<p>对我在这里做错了什么有什么想法吗?</p>

<p>我试过 bufferWidth 和 CGFloat 和 int,并在 Mat 的构造函数中切换它们,同样的问题。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>改进的解决方案解决了“只有前 30%”的问题:</p>

<pre><code>- (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;
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于c&#43;&#43; - 将 CMSampleBufferRef 转换为 cv::Mat,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/34677890/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/34677890/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: c&#43;&#43; - 将 CMSampleBufferRef 转换为 cv::Mat