Datos de imagen en bruto de la cámara como “645 PRO”

Hace un tiempo, ya hice esta pregunta y también obtuve una buena respuesta:

He estado buscando este foro de arriba a abajo, pero no pude encontrar lo que realmente necesito. Quiero obtener datos de imágenes brutos de la cámara. Hasta ahora intenté sacar los datos de imageDataSampleBuffer de ese método captureStillImageAsynchronouslyFromConnection: completionHandler: y escribirlos en un objeto NSData, pero eso no funcionó. Tal vez estoy en el camino equivocado o tal vez lo estoy haciendo mal. Lo que no quiero es que la imagen se comprima de ninguna manera.

La manera más fácil es usar jpegStillImageNSDataRepresentation: de AVCaptureStillImageOutput, pero como dije, no quiero que se comprima.

¡Gracias!

Datos de imagen en bruto de la cámara

Pensé que podría trabajar con esto, pero finalmente me di cuenta de que necesito obtener datos de imágenes en bruto de forma más directa de la misma manera que en “645 PRO”.

645 PRO: RAW Redux

Las imágenes en ese sitio muestran que obtienen los datos brutos antes de realizar cualquier compresión jpeg. Eso es lo que quiero hacer. Mi suposición es que necesito transformar imageDataSampleBuffer pero no veo una manera de hacerlo completamente sin compresión. “645 PRO” también guarda sus imágenes en TIFF, así que creo que usa al menos una biblioteca adicional.

No quiero hacer una aplicación de fotos, pero necesito la mejor calidad para verificar ciertas características en una imagen.

¡Gracias!

Editar 1: Entonces, después de probar y buscar en diferentes direcciones por un tiempo, decidí dar una actualización de estado.

El objective final de este proyecto es verificar ciertas características en una imagen que sucederá con la ayuda de opencv. Pero hasta que la aplicación pueda hacerlo en el teléfono, estoy tratando de obtener la mayoría de las imágenes sin comprimir del teléfono para analizarlas en la computadora.

Por lo tanto, quiero guardar la “instancia NSData que contiene los bytes BGRA descomprimidos devueltos desde la cámara”. Puedo obtener el código de Brad Larson como archivo bmp o TIFF. Como dije en un comentario, traté de usar opencv para esto (será necesario de todos modos). Pero lo mejor que pude hacer fue convertirlo en un UIImage con una función de 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 – Enfoque

Otra cosa que intenté fue usar ImageMagick como se sugirió en otra publicación . Pero no pude encontrar una manera de hacerlo sin usar algo como UIImagePNGRepresentation o UIImageJPEGRepresentation .

Por ahora estoy tratando de hacer algo con libtiff usando este tutorial .

Tal vez alguien tiene una idea o conoce una forma mucho más sencilla de convertir mi objeto de memoria intermedia en una imagen sin comprimir. Gracias de antemano otra vez!

Editar 2:

¡Encontré algo! Y debo decir que estaba muy ciego.

 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); 

Solo tengo que usar la función de escritura desde opencv. ¡De esta forma obtengo archivos TIFF de alrededor de 30 MB directamente después de la polarización Beyer!

Guau, esa publicación en el blog fue algo especial. Una gran cantidad de palabras para indicar que obtienen los bytes del buffer de muestra que Apple le devuelve de una imagen fija. No hay nada particularmente innovador en su enfoque, y conozco varias aplicaciones de cámara que hacen esto.

Puede obtener los bytes brutos devueltos de una fotografía tomada con un AVCaptureStillImageOutput usando un código como el siguiente:

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

Esto le dará una instancia NSData que contiene los bytes BGRA descomprimidos devueltos por la cámara. Puede guardarlos en el disco o hacer lo que quiera con ellos. Si realmente necesita procesar los bytes, evitaría la sobrecarga de la creación de NSData y simplemente trabajaría con la matriz de bytes del buffer de píxeles.

Podría resolverlo con OpenCV. Gracias a todos los que me ayudaron.

 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); 

Solo tengo que usar la función de escritura desde opencv. ¡De esta manera obtengo archivos BMP alrededor de 24 MB directamente después del filtro bayer!

Si bien el núcleo de la respuesta proviene de Brad en iOS: obtener datos de píxel por píxel desde la cámara , un elemento clave no está del todo claro a partir de la respuesta de Brad. Está oculto en “una vez que haya configurado su sesión de captura …”.

Necesita establecer las configuraciones de salida correctas para su AVCaptureStillImageOutput .

Por ejemplo, establecer kCVPixelBufferPixelFormatTypeKey en kCVPixelFormatType_420YpCbCr8BiPlanarFullRange le dará un YCbCr imageDataSampleBuffer en captureStillImageAsynchronouslyFromConnection:completionHandler: que luego puede manipular al contenido de su corazón.

como @Wildaker mencionó, para que un código específico funcione, debe asegurarse de qué formato de píxeles le está enviando la cámara. El código de @thomketler funcionará si está configurado para el formato RGBA de 32 bits.

Aquí hay un código para el YUV predeterminado de la cámara, usando 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 debe tener el marco BGR completo. Espero que eso ayude.