我正在读取NVidia TX2上GStreamer管道中的摄像机。我希望输出经过h264编码并写入文件。接下来,我想在OpenCV中使用这些帧以进行进一步处理。
为此,我使用gst-launch创建了以下管道:
gst-launch-1.0 nvcamerasrc sensor-id=0 ! \
'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1280,
format=(string)I420, framerate=(fraction)30/1' ! tee name=t \
t. ! queue! omxh264enc ! 'video/x-h264, stream-format=(string)byte-stream' ! \
h264parse ! qtmux ! \
filesink location=test.mov \
t. ! queue! nvvidconv ! video/x-raw ! xvimagesink -e
这一切正常,并且此管道没有问题。它在屏幕上显示帧(这部分将在OpenCV中由appsink代替),并创建可以播放的电影文件。
请注意命令末尾的“ -e”。要停止录制,请按ctrl-C。如果我省略“ -e”,则会得到无法播放的损坏的Moviefile。在检查gst-launch-1.0手册页时,这也很有意义,因为它专门提到了这种情况。
否,当我在Python中将其转换为OpenCV时,我得到了:
import cv2
pipeline = ("nvcamerasrc sensor-id=0 ! "
"video/x-raw(memory:NVMM), width=(int)640, height=(int)360, format=(string)I420, framerate=(fraction)30/1 ! tee name=t "
"t. ! queue! omxh264enc ! video/x-h264, stream-format=(string)byte-stream ! "
"h264parse ! qtmux ! "
"filesink location=test.mov "
"t. ! queue! nvvidconv ! video/x-raw, format=(string)BGRx ! "
"videoconvert ! video/x-raw, format=(string)BGR ! appsink")
vc1 = cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)
while(True):
_, vc1_f = vc1.read()
cv2.imshow('vc1', vc1_f)
if not cv2.waitKey(1) == -1:
break
vc1.release()
cv2.destroyAllWindows()
这也可以正常运行,没有任何错误,唯一发生的是我退出时最终得到了损坏的电影文件。与在gst启动版本中省略“ -e”选项时完全相同。
在所有这些中,我意识到我有点滥用VideoCapture,因为通常这不用于写入文件,而只是用于通过appsink元素将帧放入OpenCV中。但是,在这里,它还用于通过使用gstreamer管道直接写入文件。
我当然可以创建一个单独的管道:
"appsrc ! videoconvert ! omxh264enc ! h264parse ! qtmux ! filesink location=test.mov "
并通过使用VideoWriter将OpenCV中获得的帧反馈到其中(我对此进行了测试并且可以正常工作),但是这会产生一些开销,因此我宁愿不必这样做并保持其清洁并坚持下去我的一个VideoCapture管道。
所以基本上我的问题是:我想在这里做什么吗?还是我只是滥用VideoCapture?即是否有与VideoCapture的gst-launch“ -e”选项等效的Python OpenCV,因为VideoCapture :: release()不能完成这项工作。
谢谢!
编辑
找不到合适的解决方案(OpenCV论坛confirmed不存在),但决定只保存H264流,将混合保留在管道之外,然后分别使用ffmpeg进行。 H264流不关心不干净的关机。