Создание видео с opencv и ffmpeg. Как найти правильный цветной формат?
У меня есть программа видеомагнитофона веб-камеры, созданная с помощью python, opencv и ffmpeg
Он работает нормально, за исключением того, что цвет видео более синий, чем реальность. Проблема, похоже, исходит из цветового формата изображений.
Кажется, что OpenCv дает изображения BGR, а ffmpeg + libx264 ожидает YUV420p. Я читал, что YUV420p соответствует YCbCr.
opencv не имеет преобразования из BGR в YCbCr. Он имеет только преобразование в YCrCb.
Я сделал несколько поисков и попробовал разные альтернативы, чтобы попробовать конвертировать opencv-образ в то, что может быть хорошо для ffmpeg + libx264. Никто не работает. На данный момент я немного потерян, и я был бы признателен за любой указатель, который мог бы помочь мне исправить эту проблему цвета.
Ответы
Ответ 1
Вы правы, формат пикселей по умолчанию для OpenCV BGR.
Эквивалентный формат на стороне ffmpeg будет BGR24, поэтому вам не нужно преобразовывать его в YUV420p, если вы этого не хотите.
Этот пост показывает, как использовать приложение python для захвата фреймов с веб-камеры и записи фреймов в stdout. Цель состоит в том, чтобы вызвать это приложение в cmd-строке и передать результат непосредственно в приложение ffmpeg, которое хранит фреймы на диске. Совершенно умный!
capture.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() )
И команда, которая должна быть выполнена в оболочке:
python capture.py | ffmpeg -f rawvideo -pix_fmt bgr24 -s 640x480 -r 30 -i - -an -f avi -r 30 foo.avi
Где
- -r дает частоту кадров, выходящих из камеры.
- -an говорит: "Не кодируйте аудио"
Я протестировал это решение на своей Mac OS X с OpenCV 2.4.2.
EDIT:
Если вы не пытались выполнить запись с камеры и использовать OpenCV для записи видео в файл mp4 на диске, здесь мы идем:
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)
Я тестировал это с помощью Python 2.7 на Mac OS X и OpenCV 2.4.2.
Ответ 2
Вы пытались переключить каналы Cb/Cr в OpenCV, используя split и merge?
Ответ 3
Проверяют формулы преобразования, представленные в: http://en.wikipedia.org/wiki/YCbCr?
Ответ 4
Кодек libx264 способен обрабатывать изображения BGR. Не нужно использовать какое-либо преобразование в YCbCr. НЕТ, чтобы передать spfific pix_ftm в ffmpeg. Я использовал RGB, и это вызывало синеватый эффект на видео.
Решением было просто использовать исходное изображение, настроенное камерой без какого-либо преобразования.:)
Я попробовал это в своем предыдущем исследовании, и это привело к сбою приложения. Решением является копирование кадра, возвращаемого камерой.
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
Ответ 5
Я уже ответил на это здесь. Но моя библиотека VidGear
Python позволяет автоматизировать весь процесс конвейеризации кадров OpenCV в FFmpeg, а также надежно обрабатывает преобразование формата. Вот основной пример 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
Источник: https://github.com/abhiTronix/vidgear/wiki/Compression-Mode:-FFmpeg#2-writegear-classcompression-mode-with-opencv-directly
Вы можете ознакомиться с полным VidGear Docs для более продвинутых приложений и захватывающих функций.
Надеюсь, это поможет!