Исходные данные изображения с камеры типа "645 PRO"
Некоторое время назад я уже задавал этот вопрос, и у меня также был хороший ответ:
Я искал этот форум вверх и вниз, но я не мог найти то, что я очень нужно. Я хочу получить необработанные данные изображения с камеры. До сих пор Я попытался извлечь данные из imageDataSampleBuffer из этого метод captureStillImageAsynchronouslyFromConnection: completeHandler: и записать его в объект NSData, но это не сработало. Может быть, я нахожусь неправильный трек или, может быть, я просто делаю это неправильно. Я не хочу, чтобы для сжатия изображения каким-либо образом.
Простым способом является использование jpegStillImageNSDataRepresentation: from AVCaptureStillImageOutput, но, как я уже сказал, я не хочу, чтобы это было сжатый.
Спасибо!
Исходные данные изображения с камеры
Я думал, что смогу с этим справиться, но я, наконец, заметил, что мне нужно получить данные необработанного изображения более точно так же, как это сделано в "645 PRO".
645 PRO: RAW Redux
Изображения на этом сайте показывают, что они получают необработанные данные перед выполнением любого jpeg-сжатия. Это то, что я хочу сделать. Я предполагаю, что мне нужно преобразовать imageDataSampleBuffer
, но я не вижу способа сделать это полностью без сжатия.
"645 PRO" также сохраняет свои снимки в TIFF, поэтому я думаю, что он использует хотя бы одну дополнительную библиотеку.
Я не хочу делать фотоприложение, но мне нужно лучшее качество, которое я могу проверить для некоторых функций на картинке.
Спасибо!
Изменить 1:
Поэтому после попытки и поиска в разных направлениях какое-то время я решил дать обновление статуса.
Конечной целью этого проекта является проверка определенных функций на картинке, которая будет происходить с помощью opencv. Но пока приложение не сможет сделать это по телефону, я пытаюсь получить в основном несжатые картинки из телефона, чтобы проанализировать их на компьютере.
Поэтому я хочу сохранить "экземпляр NSData, содержащий несжатые байты BGRA, возвращенные с камеры". Я могу получить код Брэда Ларсона в формате BMP или TIFF.
Как я уже сказал в комментарии, я попытался использовать opencv для этого (в любом случае это будет необходимо). Но лучшее, что я мог сделать, это превратить его в 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 - Подход
Еще одна вещь, которую я пробовал, - использовать 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);
Мне просто нужно использовать функцию imwrite из opencv. Таким образом, я получаю файлы TIFF около 30 МБ непосредственно после поляризации бейера!
Ответы
Ответ 1
Я мог бы решить это с помощью 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);
Мне просто нужно использовать функцию imwrite из opencv. Таким образом, я получаю BMP файлы около 24 МБ непосредственно после фильтра bayer!
Ответ 2
Ничего себе, это сообщение в блоге было чем-то особенным. Множество слов, чтобы просто указать, что они получают байты выборки, которые 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 и просто работал с массивом байтов из буфера пикселей.
Ответ 3
В то время как ядро ответа приходит от Брэда в iOS: Получайте пиксельные данные с камеры, ключевой элемент полностью неясен из ответа Брэда. Он скрыт в "после настройки вашего сеанса захвата...".
Вам нужно установить правильные выходные настройки для AVCaptureStillImageOutput
.
Например, установка kCVPixelBufferPixelFormatTypeKey
в kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
даст вам YCbCr imageDataSampleBuffer
в captureStillImageAsynchronouslyFromConnection:completionHandler:
, который затем вы можете манипулировать своим сердечным содержимым.
Ответ 4
как упоминал @Wildaker, для конкретного кода для работы вы должны быть уверены, какой формат пикселя отправляет камера. Код из @thomketler будет работать, если он настроен для 32-битного формата RGBA.
Вот код для 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. Надеюсь, что это поможет.