2011-03-03 16 views
3

私はOpenCVで何らかのリアルタイム画像検出を行うiPhoneアプリを書いています。 OpenCVが理解しているIplImageにカメラからCMSampleBufferRefイメージ(AVFoundationのAVCaptureVideoDataOutputSampleBufferDelegateを使用しています)を変換する最良の方法は何ですか?変換はリアルタイムで実行できるほど速くする必要があります。CMSampleBufferRefを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]; 
} 

ありがとうございます。

答えて

12

このサンプルコードはCMSampleBufferのポインタを管理するために、Appleのサンプルに基づいています。

- (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; 
} 

電話のカメラバッファはBGRAであるので、あなたは、4チャネルIplImageへを作成する必要があります。

私の経験上、この変換はリアルタイムアプリケーションで実行するのに十分速いですが、もちろんOpenCVを使用すると時間がかかることがあります。

+0

これがうまく機能し、640×480の画像の変換時間は0.00020秒であるプラスマイナス0.00004 @cduck – cduck

+0

4.私のiPhone上:はい、私は3GSでもこのソリューションで30fpsを達成しました。 –

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; 

}

関連する問題