【问题标题】:What is the best/fastest way to convert CMSampleBufferRef to OpenCV IplImage?将 CMSampleBufferRef 转换为 OpenCV IplImage 的最佳/最快方法是什么?
【发布时间】:2011-03-03 03:05:42
【问题描述】:

我正在编写一个使用 OpenCV 进行某种实时图像检测的 iPhone 应用程序。将相机中的 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];
} 

提前致谢。

【问题讨论】:

    标签: iphone opencv real-time avfoundation


    【解决方案1】:

    此示例代码基于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,因为 Phone 的相机缓冲区位于 BGRA 中。

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

    【讨论】:

    • 这很好用,在我的 iPhone 4 上,640x480 图像的转换时间为 0.00020 秒正负 0.00004。
    • @cduck:是的,我用这个解决方案达到了 30 fps,即使在 3GS 上也是如此。
    【解决方案2】:

    "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;
    

    }

    【讨论】:

      猜你喜欢
      • 2016-05-29
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      相关资源
      最近更新 更多