以OpenCV Mat格式从相机捕捉静止图像

我正在开发一个iOS应用程序,并尝试使用捕获会话从相机获取静态图像快照,但是我无法将其成功转换为OpenCV Mat。

静止图像输出是使用此代码创build的:

- (void)createStillImageOutput; { // setup still image output with jpeg codec self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil]; [self.stillImageOutput setOutputSettings:outputSettings]; [self.captureSession addOutput:self.stillImageOutput]; for (AVCaptureConnection *connection in self.stillImageOutput.connections) { for (AVCaptureInputPort *port in [connection inputPorts]) { if ([port.mediaType isEqual:AVMediaTypeVideo]) { self.videoCaptureConnection = connection; break; } } if (self.videoCaptureConnection) { break; } } NSLog(@"[Camera] still image output created"); } 

然后尝试使用此代码捕获静止图像:

 [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:self.videoCaptureConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { if (error == nil && imageSampleBuffer != NULL) { NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; } 

我需要一种基于缓冲区中的像素数据创buildOpenCV Mat的方法。 我已经尝试使用这个代码,我从OpenCVvideo摄像头类摄像头采取创build一个席子在这里 :

  CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); CVPixelBufferLockBaseAddress(imageBuffer, 0); void* bufferAddress; size_t width; size_t height; size_t bytesPerRow; CGColorSpaceRef colorSpace; CGContextRef context; int format_opencv; OSType format = CVPixelBufferGetPixelFormatType(imageBuffer); if (format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) { format_opencv = CV_8UC1; bufferAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); width = CVPixelBufferGetWidthOfPlane(imageBuffer, 0); height = CVPixelBufferGetHeightOfPlane(imageBuffer, 0); bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0); } else { // expect kCVPixelFormatType_32BGRA format_opencv = CV_8UC4; bufferAddress = CVPixelBufferGetBaseAddress(imageBuffer); width = CVPixelBufferGetWidth(imageBuffer); height = CVPixelBufferGetHeight(imageBuffer); bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); } cv::Mat image(height, width, format_opencv, bufferAddress, bytesPerRow); 

但是无法获得CVPixelBufferGetWidth或CVPixelBufferGetHeight调用中图像的实际高度和宽度,因此Mat创build失败。

我知道我可以使用这个代码创build一个基于像素数据的UIImage:

  UIImage* newImage = [UIImage imageWithData:jpegData]; 

但我更喜欢直接构build一个CvMat,就像OpenCV CvVideoCamera类中的情况一样,因为我只想处理OpenCV中的图像,而且我不想再花时间转换,也不会冒险丢失质量或者遇到问题方向(无论如何,由OpenCV提供的UIImagetoCV转换function正在导致我的内存泄漏,而不是释放内存)。

请告诉我如何获得作为OpenCV垫的图像。 提前致谢。

我find了我的问题的解决scheme。

解决scheme是:

通过在OpenCv相机类中重写此方法:“createVideoPreviewLayer”

它应该是这样的:

 - (void)createVideoPreviewLayer; { self.parentView.layer.sublayers = nil; if (captureVideoPreviewLayer == nil) { captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession]; } if (self.parentView != nil) { captureVideoPreviewLayer.frame = self.parentView.bounds; captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; [self.parentView.layer addSublayer:captureVideoPreviewLayer]; } NSLog(@"[Camera] created AVCaptureVideoPreviewLayer"); } 

你应该添加这行到“createVideoPreviewLayer”方法将解决问题:

 self.parentView.layer.sublayers = nil; 

您需要使用暂停方法而不是停止方法