将 CMSampleBufferRef 转换为 OpenCV IplImage 的最佳/最快方法是什么?

发布于 2024-10-20 01:56:03 字数 665 浏览 3 评论 0原文

我正在编写一个 iPhone 应用程序,它使用 OpenCV 进行某种实时图像检测。将来自相机的 CMSampleBufferRef 图像(我正在使用 AVFoundation 的 AVCaptureVideoDataOutputSampleBufferDelegate)转换为 OpenCV 可以理解的 IplImage 的最佳方法是什么?转换需要足够快,以便可以实时运行。

- (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
    fromConnection:(AVCaptureConnection *)connection
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  // Convert CMSampleBufferRef into IplImage
  IplImage *openCVImage = ???(sampleBuffer);

  // Do OpenCV computations realtime
  // ...

  [pool release];
} 

提前致谢。

I am writing an iPhone app that does some sort of real-time image detection with OpenCV. What is the best way to convert a CMSampleBufferRef image from the camera (I'm using AVCaptureVideoDataOutputSampleBufferDelegate of AVFoundation) into an IplImage that OpenCV understands? The conversion needs to be fast enough so it can run realtime.

- (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
    fromConnection:(AVCaptureConnection *)connection
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  // Convert CMSampleBufferRef into IplImage
  IplImage *openCVImage = ???(sampleBuffer);

  // Do OpenCV computations realtime
  // ...

  [pool release];
} 

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

淡紫姑娘! 2024-10-27 01:56:03

此示例代码基于 Apple 的示例来管理 CMSampleBuffer 的指针:

- (IplImage *)createIplImageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer {
    IplImage *iplimage = 0;
    if (sampleBuffer) {
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        CVPixelBufferLockBaseAddress(imageBuffer, 0);

        // get information of the image in the buffer
        uint8_t *bufferBaseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
        size_t bufferWidth = CVPixelBufferGetWidth(imageBuffer);
        size_t bufferHeight = CVPixelBufferGetHeight(imageBuffer);

        // create IplImage
        if (bufferBaseAddress) {
            iplimage = cvCreateImage(cvSize(bufferWidth, bufferHeight), IPL_DEPTH_8U, 4);
            iplimage->imageData = (char*)bufferBaseAddress;
        }

        // release memory
        CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    }
    else
        DLog(@"No sampleBuffer!!");

    return iplimage;
}

您需要创建一个 4 通道 IplImage,因为手机的相机缓冲区位于 BGRA 中。

根据我的经验,这种转换速度足够快,可以在实时应用程序中完成,但当然,您添加的任何内容都会花费时间,尤其是使用 OpenCV。

This sample code is based on Apple's sample to manage CMSampleBuffer's pointer:

- (IplImage *)createIplImageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer {
    IplImage *iplimage = 0;
    if (sampleBuffer) {
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        CVPixelBufferLockBaseAddress(imageBuffer, 0);

        // get information of the image in the buffer
        uint8_t *bufferBaseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
        size_t bufferWidth = CVPixelBufferGetWidth(imageBuffer);
        size_t bufferHeight = CVPixelBufferGetHeight(imageBuffer);

        // create IplImage
        if (bufferBaseAddress) {
            iplimage = cvCreateImage(cvSize(bufferWidth, bufferHeight), IPL_DEPTH_8U, 4);
            iplimage->imageData = (char*)bufferBaseAddress;
        }

        // release memory
        CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    }
    else
        DLog(@"No sampleBuffer!!");

    return iplimage;
}

You need to create a 4-channel IplImage because the Phone's camera buffer is in BGRA.

To my experience, this conversion is fast enough to be done in a real-time application, but of course, anything you will add to it will cost time, especially with OpenCV.

过气美图社 2024-10-27 01:56:03

“iplimage->imageData = (char*)bufferBaseAddress;”会导致内存泄漏。

它应该是“memcpy(iplimage->imageData, (char*)bufferBaseAddress, iplimage->imageSize);”

所以完整的代码是:

-(IplImage *)createIplImageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer {
  IplImage *iplimage = 0;

  if (sampleBuffer) {
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer, 0);

    // get information of the image in the buffer
    uint8_t *bufferBaseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
    size_t bufferWidth = CVPixelBufferGetWidth(imageBuffer);
    size_t bufferHeight = CVPixelBufferGetHeight(imageBuffer);

    // create IplImage
    if (bufferBaseAddress) {
        iplimage = cvCreateImage(cvSize(bufferWidth, bufferHeight), IPL_DEPTH_8U, 4);

        //iplimage->imageData = (char*)bufferBaseAddress; 
        memcpy(iplimage->imageData, (char*)bufferBaseAddress, iplimage->imageSize);
    }

    // release memory
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}
else
    DLog(@"No sampleBuffer!!");

return iplimage;

}

"iplimage->imageData = (char*)bufferBaseAddress;" will lead to memory leak.

It should be "memcpy(iplimage->imageData, (char*)bufferBaseAddress, iplimage->imageSize);"

so the complete coded is:

-(IplImage *)createIplImageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer {
  IplImage *iplimage = 0;

  if (sampleBuffer) {
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer, 0);

    // get information of the image in the buffer
    uint8_t *bufferBaseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
    size_t bufferWidth = CVPixelBufferGetWidth(imageBuffer);
    size_t bufferHeight = CVPixelBufferGetHeight(imageBuffer);

    // create IplImage
    if (bufferBaseAddress) {
        iplimage = cvCreateImage(cvSize(bufferWidth, bufferHeight), IPL_DEPTH_8U, 4);

        //iplimage->imageData = (char*)bufferBaseAddress; 
        memcpy(iplimage->imageData, (char*)bufferBaseAddress, iplimage->imageSize);
    }

    // release memory
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}
else
    DLog(@"No sampleBuffer!!");

return iplimage;

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文