12

少し前に、私はすでにこの質問をしましたが、良い答えも得ました:

このフォーラムを上下に検索してきましたが、本当に必要なものが見つかりませんでした。カメラから生の画像データを取得したい。今まで、そのメソッド captureStillImageAsynchronouslyFromConnection:completionHandler: から imageDataSampleBuffer からデータを取得して、それを NSData オブジェクトに書き込もうとしましたが、うまくいきませんでした。たぶん、私は間違った道を進んでいるのかもしれませんし、単にやり方が間違っているだけかもしれません。私が望んでいないのは、画像が何らかの方法で圧縮されることです。

簡単な方法は、AVCaptureStillImageOutput から jpegStillImageNSDataRepresentation: を使用することですが、私が言ったように、圧縮したくありません。

ありがとう!

カメラからの生画像データ

これでなんとかなると思っていたのですが、「645 PRO」と同じように生の画像データをもっと直接的に取得する必要があることに気付きました。

645 PRO: RAW Redux

そのサイトの写真は、jpeg 圧縮が行われる前に生データを取得していることを示しています。それが私がやりたいことです。私の推測では、変換する必要がありますimageDataSampleBufferが、圧縮なしで完全に変換する方法はありません。「645 PRO」は画像もTIFFで保存するので、少なくとも1つの追加ライブラリを使用していると思います。

写真アプリを作りたいわけではありませんが、写真の特定の機能をチェックできる最高の品質が必要です。

ありがとう!

編集 1: しばらくの間、さまざまな方向を試して検索した後、ステータスの更新を行うことにしました。

このプロジェクトの最終的な目標は、opencv の助けを借りて発生する画像内の特定の機能を確認することです。しかし、アプリが電話でそれを行うことができるようになるまで、私はほとんど圧縮されていない写真を電話から取り出して、コンピューターで分析しようとしています.

したがって、Brad Larson のコードで取得できる「カメラから返された圧縮されていない BGRA バイトを含む NSData インスタンス」を bmp または TIFF ファイルとして保存したいと考えています。コメントで言ったように、これにはopencvを使用してみました(とにかく必要になります)。しかし、私ができる最善のことは、 Computer Vision Talksの関数を使用して 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 - アプローチ

私が試したもう1つのことは、別の投稿で提案されているようにImageMagickを使用することでした。UIImagePNGRepresentationしかし、やのようなものを使わずにそれを行う方法を見つけることができませんでしたUIImageJPEGRepresentation

今のところ、このチュートリアルを使用して 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 ファイルを取得できます。

4

4 に答える 4

17

うわー、そのブログ投稿は特別なものでした。Apple が静止画像から返してくれるサンプル バッファ バイトを取得すると述べているだけの言葉がたくさんあります。彼らのアプローチには特に革新的なものはなく、私はこれを行う多くのカメラ アプリケーションを知っています。

次のようなコードを使用して、AVCaptureStillImageOutput で撮影した写真から返された raw バイトを取得できます。

[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);
}];

これにより、カメラから返された圧縮されていない BGRA バイトを含む NSData インスタンスが得られます。これらをディスクに保存したり、好きなことをしたりできます。本当にバイト自体を処理する必要がある場合は、NSData 作成のオーバーヘッドを回避し、ピクセル バッファーからバイト配列を操作するだけです。

于 2012-07-23T15:19:15.270 に答える
5

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 ファイルを取得します。

于 2012-08-03T12:43:51.850 に答える
2

回答の核心はiOS の Brad からのものです: Get pixel-by-pixel data from camera、主要な要素は Brad の回答から完全に不明です。「キャプチャセッションを構成したら...」に隠されています。

に正しい outputSettings を設定する必要がありますAVCaptureStillImageOutput

たとえば、 に設定kCVPixelBufferPixelFormatTypeKeyするkCVPixelFormatType_420YpCbCr8BiPlanarFullRangeと に YCbCr が与えimageDataSampleBufferられcaptureStillImageAsynchronouslyFromConnection:completionHandler:、これを思いのままに操作できます。

于 2012-07-23T15:37:18.393 に答える