【问题标题】:convert CMSampleBufferRef to UIImage将 CMSampleBufferRef 转换为 UIImage
【发布时间】:2013-01-01 06:41:01
【问题描述】:

我正在使用 AVCaptureSession 捕获视频。 但我想将捕获的图像转换为 UIImage。

我在网上找到了一些代码:

- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
{

    NSLog(@"imageFromSampleBuffer: called");
    // Get a CMSampleBuffer's Core Video image buffer for the media data
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    // Lock the base address of the pixel buffer
    CVPixelBufferLockBaseAddress(imageBuffer, 0);

    // Get the number of bytes per row for the pixel buffer
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);

    // Get the number of bytes per row for the pixel buffer
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    // Get the pixel buffer width and height
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);

    // Create a device-dependent RGB color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // Create a bitmap graphics context with the sample buffer data
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
                                                 bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    // Create a Quartz image from the pixel data in the bitmap graphics context
    CGImageRef quartzImage = CGBitmapContextCreateImage(context);
    // Unlock the pixel buffer
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);


    // Free up the context and color space
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    // Create an image object from the Quartz image
    UIImage *image = [UIImage imageWithCGImage:quartzImage];

    // Release the Quartz image
    CGImageRelease(quartzImage);

    return (image);
}

但我遇到了一些错误:

Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 2560 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst.
Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGBitmapContextCreateImage: invalid context 0x0
2013-01-17 17:39:25.896 ThinkOutsideTheBox[2363:907] image <UIImage: 0x1d553f00>
Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGContextDrawImage: invalid context 0x0
Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGBitmapContextGetData: invalid context 0x0

编辑: 我还使用 UIImage 来获取 rgb 颜色:

-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{

    UIImage* image = [self imageFromSampleBuffer:sampleBuffer];
    unsigned char* pixels = [image rgbaPixels];
    double totalLuminance = 0.0;
    for(int p=0;p<image.size.width*image.size.height*4;p+=4)
    {
        totalLuminance += pixels[p]*0.299 + pixels[p+1]*0.587 + pixels[p+2]*0.114;
    }
    totalLuminance /= (image.size.width*image.size.height);
    totalLuminance /= 255.0;
    NSLog(@"totalLuminance %f",totalLuminance);

}

【问题讨论】:

  • 根据警告,当您收到上述错误时,widthheightbytesPerRow 值的值是多少?听起来您的图像缓冲区在您尝试使用它之前已被释放(可能是由于处理是在单独的线程上完成的)。
  • 另外,您确定要捕获 RGB 样本吗?其他类型更紧凑,因此 bytesPerRow 小于适合 RGB 缓冲区宽度的值。
  • 如果在其中添加NSLog(@"Pixel format: 0x%x", CVPixelBufferGetPixelFormatType(imageBuffer));,会得到什么日志输出?
  • @PeterHosey NSLog:像素格式:0x34323076
  • 那是'420v',也就是kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange。您的缓冲区内容不是 RGB 像素;它们在the documentation for that pixel format constant 中进行了描述。尝试使用此数据创建 RGB、ARGB 或 RGBA 上下文将不起作用。

标签: ios core-graphics avfoundation


【解决方案1】:

您最好将set the capture video data output's videoSettings 设置为specifies the pixel format you want 的字典,您需要将其设置为CGBitmapContext 可以处理的RGB 变化。

文档有a list of all of the pixel formats that Core Video can process。 CGBitmapContext 仅支持其中的一小部分。您在 Internet 上找到的代码所期望的格式是 kCVPixelFormatType_32BGRA,但这可能是为 Mac 编写的——在 iOS 设备上,kCVPixelFormatType_32ARGB(大端)可能更快。尝试它们,在设备上,然后比较帧速率。

【讨论】:

  • iOS 似乎不支持kCVPixelFormatType_32ARGB。AVCaptureOutput.h 获取支持的格式列表。此平台上可用的像素格式类型为 (420v,420f,BGRA)。
  • @demon 所以如果 BGRA 是可用格式之一,那么匹配的密钥将是 kCVPixelFormatType_32BGRA,并且该密钥将用于捕获 PNG?
  • @Crashalot 首先,您的视频必须包含 Alpha 通道,否则毫无意义。
  • @demon 是的理解,但你是说使用 kCVPixelFormatType_32BGRA 而不是 kCVPixelFormatType_32ARGB?
【解决方案2】:

你可以试试这个代码。

-(UIImage *) screenshotOfVideoStream:(CMSampleBufferRef)samImageBuff
  {
       CVImageBufferRef imageBuffer =  
         CMSampleBufferGetImageBuffer(samImageBuff);
       CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
       CIContext *temporaryContext = [CIContext contextWithOptions:nil];
       CGImageRef videoImage = [temporaryContext
                         createCGImage:ciImage
                         fromRect:CGRectMake(0, 0,
                         CVPixelBufferGetWidth(imageBuffer),
                         CVPixelBufferGetHeight(imageBuffer))];

       UIImage *image = [[UIImage alloc] initWithCGImage:videoImage];
       CGImageRelease(videoImage);
      return image;
}

它对我有用。

【讨论】:

  • 就我而言,imageBuffer 为零。
【解决方案3】:

如果有人像我一样期待 jpeg 图像,Apple 提供了简单的 API:

[AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:photoSampleBuffer];

和:

[AVCapturePhotoOutput JPEGPhotoDataRepresentationForJPEGSampleBuffer:photoSampleBuffer previewPhotoSampleBuffer:previewPhotoSampleBuffer]

【讨论】:

    猜你喜欢
    • 2013-05-04
    • 2013-10-19
    • 2016-04-13
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多