我正在使用以下代码从相机中收集图像数据:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
// Called when a frame arrives
// Should be in BGRA format
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
unsigned char *raw = (unsigned char *)CVPixelBufferGetBaseAddress(imageBuffer);
// Copy memory into allocated buffer
unsigned char *buffer = malloc(sizeof(unsigned char) * bytesPerRow * height);
memcpy(buffer, raw, bytesPerRow * height);
[self processVideoData:buffer width:width height:height bytesPerRow:bytesPerRow];
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}
processVideoData:
方法如下所示:
- (void)processVideoData:(unsigned char *)data width:(size_t)width height:(size_t)height bytesPerRow:(size_t)bytesPerRow
{
dispatch_sync(dispatch_get_main_queue(), ^{
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, data, bytesPerRow * height, NULL);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef image = CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);
// Set layer contents???
UIImage *objcImage = [UIImage imageWithCGImage:image];
self.imageView.image = objcImage;
free(data);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);
CGImageRelease(image);
});
}
没有投诉,没有泄漏,但图像视图中没有任何内容显示它只是保持空白(是的,我已经检查了插座连接)。以前我将bitmapInfo
设置为kCGBitmapByteOrderDefault
,这在设置图像视图的图像属性时导致崩溃,但是图像视图会变暗,这在崩溃之前是有希望的。
我总结说崩溃是由于图像在BGRA而不是BGR,所以我将bitmapInfo
设置为kCGBitmapByteOrderDefault | kCGImageAlphaLast
,这解决了崩溃但没有图像。
我意识到图像看起来很奇怪,因为CGImageRef
期待RGB图像并且我将它传递给BGR但是这应该只会导致由于频道交换而出现奇怪的图像。我还记录了我得到的数据,它似乎是这样的:b:65 g:51 r:42 a:255
,而alpha通道总是如预期的那样。
我很抱歉,如果这很明显,但我无法弄清楚出了什么问题。
答案 0 :(得分:3)
您可以使用此标记组合来实现BGRA
格式:
kCGBitmapByteOrder32Little | kCGImageAlphaSkipFirst
您应该更喜欢使用此解决方案,与OpenCV转换相比,它将是更高效的方式。
以下是将sourcePixelFormat
转换为bitmapInfo
的更常用方法:
sourcePixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer);
bitmapInfo = @{
@(kCVPixelFormatType_32ARGB) : @(kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst),
@(kCVPixelFormatType_32BGRA) : @(kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst),
}[@(sourcePixelFormat)].unsignedIntegerValue;
答案 1 :(得分:0)
事实证明数据格式错误,我没有正确地将其输入CGImageCreate
函数。
数据以BGRA格式输出,因此我将此数据输入IplImage
结构(我使用的是OpenCV v 2.4.9),如下所示:
// Pack IplImage with data
IplImage *img = cvCreateImage(cvSize((int)width, (int)height), 8, 4);
img->imageData = (char *)data;
然后我将其转换为RGB,如下所示:
IplImage *converted = cvCreateImage(cvSize((int)width, (int)height), 8, 3);
cvCvtColor(img, converted, CV_BGRA2RGB);
然后我将转换后的IplImage
中的数据输入到CGImageCreate
函数中,效果很好。