Al configurar el AVCaptureVideoDataOutput que devuelve las imágenes de cámara primas, se puede establecer el formato de las tramas utilizando un código como el siguiente:
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
En este caso se especifica un formato de píxel BGRA (He utilizado este para hacer coincidir un formato de color para una textura OpenGL ES). Cada píxel en ese formato tiene un byte para azul, verde, rojo y alfa, en ese orden. Seguir con esto hace que sea fácil extraer los componentes de color, pero se sacrifica un poco el rendimiento al necesitar hacer la conversión del espacio de color YUV nativo de la cámara.
Otros espacios de color compatibles son kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
y kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
en dispositivos más nuevos y kCVPixelFormatType_422YpCbCr8
en el iPhone 3G. El sufijo VideoRange
o FullRange
simplemente indica si los bytes se devuelven entre 16 - 235 para Y y 16 - 240 para UV o 0 - 255 para cada componente.
Creo que el espacio de color predeterminado utilizado por una instancia de AVCaptureVideoDataOutput es el espacio de color plano YUV 4: 2: 0 (excepto en el iPhone 3G, donde está intercalado YUV 4: 2: 2). Esto significa que hay dos planos de datos de imagen contenidos dentro del cuadro de video, con el plano Y como el primero. Por cada píxel en la imagen resultante, hay un byte para el valor Y en ese píxel.
puede conseguir en estos datos Y primas mediante la aplicación de algo como esto en su delegado de devolución de llamada:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
unsigned char *rawPixelBase = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer);
// Do something with the raw pixels here
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}
A continuación, podría averiguar la ubicación de los datos de la trama para cada coordenada x, y en la imagen y tira del byte que corresponde al componente Y en esa coordenada.
El ejemplo FindMyiCone de Apple de WWDC 2010 (accesible junto con los videos) muestra cómo procesar los datos brutos de BGRA de cada fotograma. También creé una aplicación de muestra, que puede descargar el código para here, que realiza color-based object tracking usando el video en vivo de la cámara del iPhone. Ambos muestran cómo procesar los datos de píxeles en bruto, pero ninguno de estos funciona en el espacio de color YUV.
Ambos Brad Larson y Codo me ayudaron mucho en este problema. Con la combinación de sus respuestas, finalmente pude alcanzar mi objetivo. ¡Muchas gracias, Brad Larson y Codo! – Nihao