【问题标题】:Raw image data from camera like "645 PRO"来自“645 PRO”等相机的原始图像数据
【发布时间】:2012-07-21 16:41:48
【问题描述】:

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

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

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

谢谢!

Raw image data from camera

我以为我可以使用它,但我终于注意到我需要以与“645 PRO”类似的方式更直接地获取原始图像数据。

645 PRO: RAW Redux

该网站上的图片显示他们在任何 jpeg 压缩完成之前获得了原始数据。这就是我想做的。我的猜测是我需要转换imageDataSampleBuffer,但我看不到完全不压缩的方法。 “645 PRO”还将其图片保存在 TIFF 中,因此我认为它至少使用了一个额外的库。

我不想制作照片应用,但我需要最好的质量来检查图片中的某些功能。

谢谢!

编辑 1: 因此,在尝试并在不同的方向搜索了一段时间后,我决定更新状态。

这个项目的最终目标是检查图片中的某些特征,这将在 opencv 的帮助下发生。但在应用程序能够在手机上执行此操作之前,我会尝试从手机中获取大部分未压缩的图片,以便在计算机上对其进行分析。

因此,我想将 Brad Larson 的代码保存为 bmp 或 TIFF 文件的“包含从相机返回的未压缩 BGRA 字节的 NSData 实例”。 正如我在评论中所说,我尝试为此使用 opencv(无论如何都需要它)。但我能做的最好的就是把它变成一个 UIImage 并带有来自Computer Vision Talks 的函数。

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 - 方法

我尝试的另一件事是按照another post 中的建议使用 ImageMagick。 但如果不使用 UIImagePNGRepresentationUIImageJPEGRepresentation 之类的东西,我找不到办法。

现在我正在尝试使用 tutorial 对 libtiff 做一些事情。

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

编辑 2:

我发现了一些东西!而且我必须说我很盲目。

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-Polarisation 之后直接获得大约 30 MB 的 TIFF 文件!

【问题讨论】:

  • 我在大约 10 秒的搜索时间内找到了这个答案:stackoverflow.com/a/10865206/96716
  • 谢谢达斯汀我已经害怕这样的事情了,我只是希望有人能给我一个提示或什么。感谢David H,但我已经看过了,它并没有真正帮助我的情况,或者至少我无法弄清楚如何。但我很感激每一个提示!

标签: ios image opencv camera imagemagick


【解决方案1】:

哇,那篇博文很特别。一大堆词只是说他们从静止图像中获得了 Apple 交给你的样本缓冲区字节。他们的方法没有什么特别创新的地方,而且我知道有很多相机应用程序可以做到这一点。

您可以使用如下代码获取从使用 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 字节。您可以将它们保存到磁盘或对它们做任何您想做的事情。如果你真的需要自己处理字节,我会避免创建 NSData 的开销,只使用像素缓冲区中的字节数组。

【讨论】:

  • 非常感谢您的帮助。很高兴知道我没有走错路。我希望我不会强迫您耐心等待,但是您知道将其更改为位图的简单方法吗?我正在考虑以与另一篇帖子link 类似的方式使用openCV,我只是想知道我是否错过了一种更简单的方法。再次感谢你,我已经为此碰壁了一段时间了。
【解决方案2】:

虽然答案的核心来自iOS: Get pixel-by-pixel data from camera 的布拉德,但布拉德的回复中完全不清楚一个关键要素。它隐藏在“配置捕获会话后...”中。

您需要为您的AVCaptureStillImageOutput 设置正确的输出设置。

例如,将kCVPixelBufferPixelFormatTypeKey 设置为kCVPixelFormatType_420YpCbCr8BiPlanarFullRange 会在captureStillImageAsynchronouslyFromConnection:completionHandler: 中为您提供一个YCbCr imageDataSampleBuffer,然后您可以随意操作它。

【讨论】:

  • 需要注意的一点:kCVPixelBufferPixelFormatTypeKey 是一个 int,因此在添加到字典时必须将其包装在 NSNumber 中。此外,在 ARC 下,您必须手动将实际值转换为 id
【解决方案3】:

我可以用 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 函数。这样我就可以在拜耳过滤器之后直接获得大约 24 MB 的 BMP 文件!

【讨论】:

    【解决方案4】:

    正如@Wildaker 所提到的,要使特定代码起作用,您必须确定相机发送给您的像素格式。如果设置为 32 位 RGBA 格式,来自@thomketler 的代码将起作用。

    这里是来自相机的 YUV 默认代码,使用 OpenCV:

    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 帧。我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      • 1970-01-01
      相关资源
      最近更新 更多