J'ai un programme d'enregistreur vidéo sur la webcam construit avec Python, OpenCV et FFMPEG P>
Cela fonctionne bien, sauf que la couleur de la vidéo est plus bleue que la réalité. Le problème semble provenir du format de couleur des images. p>
Il semble que OpenCV donne des images BGR et FFMPEG + libx264 s'attend à ce que Yuv420P. J'ai lu que Yuv420P correspond à YCBCR. P>
OpenCV n'a aucune conversion de BGR en YCBCR. Il n'a qu'une conversion à YCRCB. P>
J'ai fait des recherches et j'ai essayé différentes alternatives pour essayer de convertir l'image OpenCV en quelque chose qui pourrait être correct pour FFMPEG + libx264. Aucun ne fonctionne. À ce stade, je suis un peu perdu et j'apprécierais n'importe quel pointeur qui pourrait m'aider à réparer ce problème de couleur. P>
5 Réponses :
vérifié les formules de conversion présentes dans: http://en.wikipedia.org/wiki/ycbcrle4/ a>? p>
Merci pour le lien mais je suis un peu perdu entre toutes ces formules. Que recommanderiez-vous afin de le mettre en œuvre?
Vous avez raison, le format de pixel par défaut de OpenCV est BGR strong>. Le format équivalent sur le côté ffmpeg serait BGR24 strong>, de sorte que vous n'avez pas besoin de le convertir en YUV420p si vous ne voulez pas. P> Ce message montre comment utiliser une application python aux cadres de capture de la webcam et écrire les images stdout em>. Le but est d'invoquer cette application sur la cmd ligne et conduite le résultat directement à l'application de ffmpeg, qui stocke les images sur le disque. En effet, très intelligent p> capture.py strong>: p> 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)
Merci pour votre réponse. Je n'avais pas encore le temps de vérifier la solution mais cela a l'air intéressant. J'ai déjà essayé d'utiliser le BGR24 pix_fmt, mais cela ne fonctionne pas avec le codec libx264. Je ne sais pas si j'ai vraiment besoin d'utiliser libx264. J'ai besoin d'une solution multi-plateformes (Windows, Mac, Linux) et, par conséquent, libx264 peut être nécessaire. Je dois vérifier.
Sur Windows LibX264 est le codec par défaut et car l'image a des couleurs erronées car elle n'est pas compatible avec BGR24 pix_fmt
Désolé de demander, mais pourquoi n'utilisez-vous pas OpenCV pour créer le fichier vidéo?
NE PAS OPENCV Utilisez FFMPEG pour créer la vidéo? Serait heureux d'obtenir plus d'informations sur une solution alternative avec OpenCV.
Merci pour le code mais cela ne fonctionne pas: le releasevideoRiter est manquant. J'ai essayé de deler l'écrivain mais ça ne marche pas aussi. Voir Stackoverflow.com/q/5781863/117092
Désolé d'entendre ça, mais Le code a été testé et cela fonctionne B> sur le système que j'ai mentionné. Merci pour le lien, j'ai oublié que j'ai répondu à cette question aussi :)
Je pense que le PB est relatif à la plate-forme Windows. Quoi qu'il en soit, merci pour votre réponse qui est très intéressante. Cela n'a pas résolu mon problème, mais cela (et tout le nombre impressionnant de questions que vous avez répondu à OpenCV) m'a aidé à mieux comprendre comment fonctionner à l'OPENCV et à résoudre mon problème. Ça vaut la prime :)
Je lis à nouveau votre réponse et, en fait, c'était la bonne réponse dès le début. C'était juste ma mise en œuvre qui n'était pas correcte. Cela vaut la peine d'être accepté aussi :)
J'ai essayé différentes conversions. Lequel recommanderiez-vous?
Je vous suggère de simplement échanger les chaînes CB et CR. Dans YCBCR, Y représente la partie "luminance", c'est plus ou moins le niveau de gris. Les informations de couleur sont stockées dans des canaux de 2 "chrominance", CR (comme en chrominance rouge) et CB (chrominance bleu). Comme vous l'avez dit, OpenCV convertit à YCRCB et FFMPEG YUV = YCBCR. Cela + le fait que vos images semblent bleuish me font penser que vous pourriez simplement échanger les canaux de chrominance, cr <-> cb.
Merci. Cela a aidé à trouver la solution. J'ai fait un convertisseur en utilisant Split and Fusion et j'ai réalisé que j'avais une double conversion et que l'utilisation d'une copie était suffisante :)
Le codec libX264 est capable de traiter des images BGR. Pas besoin d'utiliser une conversion à YCBCR. Pas besoin de donner un pix_ftm SPCIFIC à FFMPEG. J'utilisais RGB et cela causait l'effet bleuâtre sur la vidéo.
La solution était simplement d'utiliser l'image d'origine rétablie par la caméra sans aucune conversion. :) P>
J'ai essayé cela dans mon enquête antérieure et que cela écrasait l'application. La solution consiste à copier le cadre renvoyé par la caméra. p>
J'ai déjà répondu à ce ici . Mais mon Vidgear code> strong>
bibliothèque Python # import libraries
from vidgear.gears import WriteGear
import cv2
output_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast"} #define (Codec,CRF,preset) FFmpeg tweak parameters for writer
stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device
writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4'
# infinite loop
while True:
(grabbed, frame) = stream.read()
# read frames
# check if frame empty
if not is grabbed:
#if True break the infinite loop
break
# {do something with frame here}
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# write a modified frame to writer
writer.write(gray)
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
# check for 'q' key-press
if key == ord("q"):
#if 'q' key-pressed break out
break
cv2.destroyAllWindows()
# close output window
stream.release()
# safely close video stream
writer.close()
# safely close writer