2012-07-06 7 views
5

AVCaptureSessionから画像を取得し、OpenCVで処理してOpenGLでレンダリングする単純なパイプラインを作っています。 RosyWriterに基づいていますが、音声と録音の機能はありません。 OpenCVの処理は、この機能ではCVImageBufferRefからメモリの所有権を取る

- (void)processPixelBuffer: (CVImageBufferRef)pixelBuffer 
{ 
CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
int bufferWidth = CVPixelBufferGetWidth(pixelBuffer); 
int bufferHeight = CVPixelBufferGetHeight(pixelBuffer); 
unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer); 

cv::Mat image = cv::Mat(bufferWidth,bufferHeight,CV_8UC4,pixel); 
//do any processing 
[self setDisplay_matrix:image]; 
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 
} 

のように見え、これまで私は、任意のメモリをコピーしていないと私はそのように維持したいと思います。問題は、pixelBufferがdisplay_imageに含まれるメモリをまだ所有している可能性があることです。処理コードは、新しいメモリを割り当てても割り当てなくても、画像に格納することができます。処理が新しいメモリを割り当てなかった場合は、データが消去されないようにするために、pixelBufferをdisplay_matrixに渡す必要があります。私が記憶の所有権を取る方法はありますか?私はそれがポイントするメモリを破壊することなくpixelBufferを破壊したい。

関連するノートでは、LockBaseAddressとはどういうことがありますか?私がcv :: Mat、CVImageBufferRefのペアを渡していた場合、cv :: Matでデータを変更/使用するたびにベースアドレスをロックする必要がありますか?

+0

こんにちはハンマー、どのようにしてcv :: Mat画像をOpenGL ESにレンダリングしますか?少し早いですがお礼を – lilouch

答えて

0

ベースアドレスデータからコピーせずにデータプロバイダを作成し、このデータプロバイダからUIImageを作成することができます。このイメージを参照している間にバッファの再利用を避けるには、サンプルバッファとロックベースアドレスを保持する必要があります。私はこのプロジェクトhttps://github.com/k06a/UIImage-DecompressAndMap/blob/master/UIImage%2BDecompressAndMap.mからimageFromDataを持って、それを少し採択しました

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    // Retain sample buffer and lock base address 
    CFRetain(sampleBuffer); 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    void *baseAddress = (void *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); 

    UIImage *image = imageFromData(baseAddress, width, height, bytesPerRow, sampleBuffer); 

    // Now you can store this UIImage as long as you want 
} 

UIImage *imageFromData(void *data, size_t width, size_t height, size_t bytesPerRow, CMSampleBufferRef sampleBuffer) 
{ 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGDataProviderRef provider = CGDataProviderCreateWithData((void *)sampleBuffer, data, bytesPerRow * height, munmap_wrapper); 
    CGImageRef inflatedImage = CGImageCreate(width, height, 8, 4*8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, provider, NULL, NO, kCGRenderingIntentDefault); 

    CGColorSpaceRelease(colorSpace); 
    CGDataProviderRelease(provider); 

    UIImage *img = [UIImage imageWithCGImage:inflatedImage scale:scale orientation:UIImageOrientationUp]; 
    CGImageRelease(inflatedImage); 
    return img; 
} 

はまた、提供する必要があります彼らはロックを解除し、このイメージオブジェクトを忘れてしまう時に自動的に解放されなければなりませんunlock_function

void unlock_function(void *info, const void *data, size_t size) 
{ 
    // Unlock base address release sample buffer 
    CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)info; 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 
    CFRelease(sampleBuffer); 
} 
関連する問題