Realizando un video con opencv y ffmpeg. ¿Cómo encontrar el formato de color correcto?

Tengo un progtwig de grabadora de video con webcam creado con python, opencv y ffmpeg

Funciona bien, excepto que el color del video es más azul que la realidad. El problema parece venir del formato de color de las imágenes.

Parece que OpenCv está dando imágenes BGR y ffmpeg + libx264 está esperando YUV420p. He leído que YUV420p corresponde a YCbCr.

opencv no tiene conversión de BGR a YCbCr. Solo tiene una conversión a YCrCb.

He hecho algunas búsquedas e intentado diferentes alternativas para tratar de convertir una imagen opencv a algo que podría estar bien para ffmpeg + libx264. Ninguno está funcionando. En este punto, estoy un poco perdido y agradecería cualquier puntero que pudiera ayudarme a solucionar este problema de color.

Tiene razón, el formato de píxeles predeterminado de OpenCV es BGR .

El formato equivalente en el lado ffmpeg sería BGR24 , por lo que no necesita convertirlo a YUV420p si no lo desea.

Esta publicación muestra cómo usar una aplicación de Python para capturar fotogtwigs de la cámara web y escribir los fotogtwigs en la salida estándar . El propósito es invocar esta aplicación en la línea cmd y canalizar el resultado directamente a la aplicación ffmpeg, que almacena los marcos en el disco. Muy inteligente de hecho!

captura.py :

import cv, sys cap = cv.CaptureFromCAM(0) if not cap: sys.stdout.write("failed CaptureFromCAM") while True : if not cv.GrabFrame(cap) : break frame = cv.RetrieveFrame(cap) sys.stdout.write( frame.tostring() ) 

Y el comando a ejecutar en el shell es:

 python capture.py | ffmpeg -f rawvideo -pix_fmt bgr24 -s 640x480 -r 30 -i - -an -f avi -r 30 foo.avi 

Donde

  • -r da la velocidad de fotogtwigs que sale de la cámara
  • -an dice “no codificar audio”

Probé esta solución en mi Mac OS X con OpenCV 2.4.2.

EDITAR:

En caso de que no haya intentado grabar desde la cámara y usar OpenCV para escribir el video en un archivo mp4 en el disco, aquí vamos:

 import cv, sys cap = cv.CaptureFromCAM(0) # 0 is for /dev/video0 if not cap: sys.stdout.write("!!! Failed CaptureFromCAM") sys.exit(1) frame = cv.RetrieveFrame(cap) if not frame: sys.stdout.write("!!! Failed to retrieve first frame") sys.exit(1) # Unfortunately, the following instruction returns 0 #fps = cv.GetCaptureProperty(cap, cv.CV_CAP_PROP_FPS) fps = 25.0 # so we need to hardcode the FPS print "Recording at: ", fps, " fps" frame_size = cv.GetSize(frame) print "Video size: ", frame_size writer = cv.CreateVideoWriter("out.mp4", cv.CV_FOURCC('F', 'M', 'P', '4'), fps, frame_size, True) if not writer: sys.stdout.write("!!! Error in creating video writer") sys.exit(1) while True : if not cv.GrabFrame(cap) : break frame = cv.RetrieveFrame(cap) cv.WriteFrame(writer, frame) cv.ReleaseVideoWriter(writer) cv.ReleaseCapture(cap) 

He probado esto con Python 2.7 en Mac OS X y OpenCV 2.4.2.

¿Ha intentado cambiar los canales Cb / Cr en OpenCV usando dividir y fusionar ?

Revisé las fórmulas de conversión presentes en: http://en.wikipedia.org/wiki/YCbCr ?

El códec libx264 es capaz de procesar imágenes BGR. No es necesario utilizar ninguna conversión a YCbCr. NO es necesario dar un pix_ftm específico a ffmpeg. Estaba usando RGB y estaba causando el efecto azulado en el video.

La solución fue simplemente usar la imagen original reajustada por la cámara sin ninguna conversión. 🙂

Intenté esto en mi investigación anterior y estaba fallando la aplicación. La solución es copiar el marco devuelto por la cámara.

  frame = opencv.QueryFrame(camera) if not frame: return None, None # RGB : use this one for displaying on the screen im_rgb = opencv.CreateImage(self.size, opencv.IPL_DEPTH_8U, 3) opencv.CvtColor(frame, im_rgb, opencv.CV_BGR2RGB) # BGR : Use this one for the video im_bgr = opencv.CreateImage(self.size, opencv.IPL_DEPTH_8U, 3) opencv.Copy(frame, im_bgr) return im_rgb, im_bgr