来自相机的原始图像数据,如“645 PRO”

前一段我已经问过这个问题了,我也得到了很好的回答:

我一直在search这个论坛,但我找不到我真正需要的东西。 我想从相机获取原始图像数据。 直到现在,我试图从该方法captureStillImageAsynchronouslyFromConnection:completionHandler:中获取数据的imageDataSampleBuffer:并将其写入到一个NSData对象,但是这并不起作用。 也许我在错误的轨道上,或者我只是做错了。 我不想要的是以任何方式压缩图像。

简单的方法是使用jpegStillImageNSDataRepresentation:从AVCaptureStillImageOutput,但就像我说我不希望它被压缩。

谢谢!

来自相机的原始图像数据

我以为我可以用这个工作,但我终于注意到,我需要像在“645 PRO”中那样直接获取原始图像数据。

645 PRO:RAW Redux

该网站上的图片显示,他们得到原始数据之前,任何JPEG压缩完成。 那是我想要做的。 我的猜测是,我需要转换imageDataSampleBuffer但我没有看到一种方式来完成没有压缩。 “645专业”还保存在TIFF的图片,所以我认为它至less使用一个额外的库。

我不想做一个照片应用程序,但我需要最好的质量来检查图片中的某些function。

谢谢!

编辑1:所以在尝试和search不同的方向一段时间后,我决定给一个状态更新。

这个项目的最终目标是在opencv的帮助下检查图片中的某些特征。 但直到应用程序能够在手机上做到这一点,我试图从电话中获得大部分未压缩的图片,以分析他们在电脑上。

因此,我想保存“NSData实例包含从相机返回的未压缩的BGRA字节”我可以得到Brad Larson的代码作为bmp或TIFF文件。 正如我在评论中所说的,我尝试过使用opencv(无论如何都需要)。 但是我能做的最好的就是把它变成一个具有计算机视觉会谈function的UIImage。

 void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress); UIImage *testImag = [UIImage imageWithMat:frame andImageOrientation:UIImageOrientationUp]; //imageWithMat... being the function from Computer Vision Talks which I can post if someone wants to see it 

ImageMagick – 方法

我尝试的另一件事是在另一篇文章中build议使用ImageMagick。 但是我找不到一种方法来做到这一点,而不使用像UIImagePNGRepresentationUIImageJPEGRepresentation

现在我正在尝试使用本教程来处理libtiff。

也许有人有一个想法或知道一个更简单的方法来将我的缓冲区对象转换为一个未压缩的图片。 再次感谢!

编辑2:

我find了一些东西 我必须说我很盲目。

 void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"ocv%d.TIFF", picNum]]; const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding]; const cv::string newPaths = (const cv::string)cPath; cv::imwrite(newPaths, frame); 

我只需要使用opencv的imwrite函数。 通过这种方式,我可以在beyer-Polarization之后直接获得大约30MB的TIFF文件!

哇,那个博客文章是特别的。 大量的单词只是表示他们获得了苹果从静止图像中取回的样本缓冲区字节。 他们的方法没有什么特别的创新,我知道一些相机应用程序这样做。

您可以使用以下代码获取从使用AVCaptureStillImageOutput拍摄的照片返回的原始字节:

 [photoOutput captureStillImageAsynchronouslyFromConnection:[[photoOutput connections] objectAtIndex:0] completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) { CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(imageSampleBuffer); CVPixelBufferLockBaseAddress(cameraFrame, 0); GLubyte *rawImageBytes = CVPixelBufferGetBaseAddress(cameraFrame); size_t bytesPerRow = CVPixelBufferGetBytesPerRow(cameraFrame); NSData *dataForRawBytes = [NSData dataWithBytes:rawImageBytes length:bytesPerRow * CVPixelBufferGetHeight(cameraFrame)]; // Do whatever with your bytes CVPixelBufferUnlockBaseAddress(cameraFrame, 0); }]; 

这会给你一个NSData实例,包含从摄像机返回的未压缩的BGRA字节。 您可以将这些保存到磁盘或做任何你想要的。 如果你真的需要自己处理字节,我会避免创buildNSData的开销,只是像素缓冲区的字节数组。

我可以用OpenCV解决它。 感谢所有帮助过我的人

 void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"ocv%d.BMP", picNum]]; const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding]; const cv::string newPaths = (const cv::string)cPath; cv::imwrite(newPaths, frame); 

我只需要使用opencv的imwrite函数。 这样,我可以在拜耳filter后直接获得24 MB左右的BMP文件!

虽然答案的核心来自于iOS的布拉德:从相机获取逐像素的数据 ,关键因素完全不清楚从布拉德的答复。 它隐藏在“一旦你有捕获会话configuration…”。

您需要为您的AVCaptureStillImageOutput设置正确的outputSettings。

例如,将kCVPixelBufferPixelFormatTypeKey设置为kCVPixelFormatType_420YpCbCr8BiPlanarFullRange会在captureStillImageAsynchronouslyFromConnection:completionHandler:为您提供一个YCbCr imageDataSampleBuffer ,然后您可以操纵该内容。

就像@Wildaker提到的那样,对于一个特定的代码来说,你必须确定摄像机发送给你的像素格式。 如果设置为32位RGBA格式,则@thomketler中的代码将可以正常工作。

下面是使用OpenCV从摄像机YUV默认的代码:

 cv::Mat convertImage(CMSampleBufferRef sampleBuffer) { CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(sampleBuffer); CVPixelBufferLockBaseAddress(cameraFrame, 0); int w = (int)CVPixelBufferGetWidth(cameraFrame); int h = (int)CVPixelBufferGetHeight(cameraFrame); void *baseAddress = CVPixelBufferGetBaseAddressOfPlane(cameraFrame, 0); cv::Mat img_buffer(h+h/2, w, CV_8UC1, (uchar *)baseAddress); cv::Mat cam_frame; cv::cvtColor(img_buffer, cam_frame, cv::COLOR_YUV2BGR_NV21); cam_frame = cam_frame.t(); //End processing CVPixelBufferUnlockBaseAddress( cameraFrame, 0 ); return cam_frame; } 

cam_frame应该有完整的BGR帧。 我希望有帮助。