【问题标题】:Capturing a still image from camera in OpenCV Mat format以 OpenCV Mat 格式从相机捕获静止图像
【发布时间】:2014-02-06 14:24:12
【问题描述】:

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

使用以下代码创建静止图像输出:

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

我需要一种基于缓冲区中的像素数据创建 OpenCV Mat 的方法。 我尝试使用从 OpenCV 摄像机类相机 here 获取的此代码创建一个 Mat:

    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 失败。

我知道我可以使用以下代码基于像素数据创建 UIImage:

             UIImage* newImage = [UIImage imageWithData:jpegData];

但我更喜欢直接构造一个 CvMat,就像 OpenCV CvVideoCamera 类中的情况一样,因为我只对在 OpenCV 中处理图像感兴趣,我不想再次花费时间进行转换,也不想冒丢失质量或有方向问题(无论如何,OpenCV 提供的 UIImagetoCV 转换功能导致我内存泄漏并且没有释放内存)。

请告知如何将图像作为 OpenCV Mat 获取。 提前致谢。

【问题讨论】:

    标签: ios opencv avfoundation


    【解决方案1】:

    我找到了解决问题的方法。

    解决办法是:

    通过在 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;
    

    而且你需要使用 pause 方法而不是 stop 方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-09
      • 1970-01-01
      相关资源
      最近更新 更多