如何在Jetson Nano上使用Python cv2.VideoWriter加速视频录制

huangapple go评论127阅读模式
英文:

How to speed up Video Recording with Python cv2.VideoWriter on Jetson Nano

问题

以下是您要翻译的部分:

"I am trying to do video recording on Jetson Nano. I found that when the cv2.VideoWriter using write() the program becomes slow. How can I speed up the cv2.VideoWriter? Maybe use Gstreamer or GPU or nvidia-component can speed up the FPS.

My Code:

import os
import time
import cv2

width = 2560
height = 1440
framerate = 30
video_path = 'fps_test.mp4';

gs_pipeline = f"v4l2src device=/dev/video0 io-mode=2 " \
              f"! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG " \
              f"! nvv4l2decoder mjpeg=1 " \
              f"! nvvidconv flip-method=4  " \
              f"! video/x-raw, format=BGRx " \
              f"! videoconvert " \
              f"! video/x-raw, format=BGR " \
              f"! appsink drop=1"

gs_pipeline = gs_pipeline
print(f"gst-launch-1.0 {gs_pipeline}\n")

v_cap = v_writer = None

...

Console:
```python
FPS = 0.000
FPS = 2.438
FPS = 3.606
FPS = 2.805
FPS = 2.741
FPS = 3.265
FPS = 3.603
FPS = 3.524
FPS = 3.290

如果您需要进一步的帮助,请随时提出。

英文:

I am trying to do video recording on Jetson Nano. I found that when the cv2.VideoWriter using write() the program becomes slow. How can I speed up the cv2.VideoWriter? Maybe use Gstreamer or GPU or nvidia-component can speed up the FPS.

My Code:

import os
import time
import cv2

width = 2560
height = 1440
framerate = 30
video_path = 'fps_test.mp4'

gs_pipeline = f"v4l2src device=/dev/video0 io-mode=2 " \
              f"! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG " \
              f"! nvv4l2decoder mjpeg=1 " \
              f"! nvvidconv flip-method=4  " \
              f"! video/x-raw, format=BGRx " \
              f"! videoconvert " \
              f"! video/x-raw, format=BGR " \
              f"! appsink drop=1"

gs_pipeline = gs_pipeline
print(f"gst-launch-1.0 {gs_pipeline}\n")

v_cap = v_writer = None


def main():
    global v_cap, v_writer
    codec = cv2.VideoWriter_fourcc(*'mp4v')
    v_writer = cv2.VideoWriter(video_path, codec, 20, (width, height))
    v_cap = cv2.VideoCapture(gs_pipeline, cv2.CAP_GSTREAMER)

    prev_frame_fetched_time = 0
    while v_cap.isOpened():
        ret_val, frame = v_cap.read()
        if not ret_val:
            break

        v_writer.write(frame)

        curr_frame_fetched_time = time.time()
        curr_fps = 1 / (curr_frame_fetched_time - prev_frame_fetched_time)
        prev_frame_fetched_time = curr_frame_fetched_time

        print(f"FPS = {curr_fps:.3f}")

    v_cap.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:  # If CTRL+C is pressed, exit cleanly:
        pass
    finally:
        v_cap.release()
        cv2.destroyAllWindows()
        if os.path.exists(video_path):
            os.remove(video_path)

Console:

FPS = 0.000
FPS = 2.438
FPS = 3.606
FPS = 2.805
FPS = 2.741
FPS = 3.265
FPS = 3.603
FPS = 3.524
FPS = 3.290

答案1

得分: 1

你可以首先尝试使用纯GStreamer录制,使用以下命令:

gst-launch-1.0 -ev v4l2src device=/dev/video0 io-mode=2 ! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG ! nvv4l2decoder mjpeg=1 ! nvvidconv flip-method=2 ! nvv4l2h264enc ! h264parse ! qtmux ! filesink location={video_path}

如果这个方法有效,你可以尝试将其拆分为OpenCV的VideoCapture和VideoWriter,假设你正在处理BGR帧:

v_cap_str = f"v4l2src device=/dev/video0 io-mode=2 " \
            f"! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG " \
            f"! nvv4l2decoder mjpeg=1 " \
            f"! nvvidconv flip-method=2 ! video/x-raw,format=BGRx " \
            f"! videoconvert ! video/x-raw,format=BGR " \
            f"! queue ! appsink drop=1 "
v_cap = cv2.VideoCapture(v_cap_str, cv2.CAP_GSTREAMER)

以及VideoWriter:

v_wrt_str = f"appsrc ! video/x-raw, format=BGR ! queue " \
            f"! videoconvert ! video/x-raw,format=BGRx " \
            f"! nvvidconv ! video/x-raw(memory:NVMM),format=NV12 " \
            f"! nvv4l2h264enc " \
            f"! h264parse " \
            f"! qtmux " \
            f"! filesink location={video_path}"
v_wrt = cv2.VideoWriter(v_wrt_str, cv2.CAP_GSTREAMER, 0, {framerate as float}, ({width as int}, {height as int}))

确保捕获和写入两者都已打开,然后在循环中从捕获中读取帧并将其推送到写入器中。

英文:

You may first try a pure gstreamer recording with:

gst-launch-1.0 -ev v4l2src device=/dev/video0 io-mode=2 ! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG ! nvv4l2decoder mjpeg=1 ! nvvidconv flip-method=2 ! nvv4l2h264enc ! h264parse ! qtmux ! filesink location={video_path}

If this works, you may try to split into opencv VideoCapture and VideoWriter, assuming you're processing BGR frames:

v_cap_str = f"v4l2src device=/dev/video0 io-mode=2 " \
f"! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG " \
f"! nvv4l2decoder mjpeg=1 " \
f"! nvvidconv flip-method=2 ! video/x-raw,format=BGRx " \
f"! videoconvert ! video/x-raw,format=BGR " \
f"! queue ! appsink drop=1 "
v_cap = cv2.VideoCapture(v_cap_str, cv2.CAP_GSTREAMER)

and VideoWriter:

v_wrt_str = f"appsrc ! video/x-raw, format=BGR ! queue " \
f"! videoconvert ! video/x-raw,format=BGRx " \        
f"! nvvidconv ! video/x-raw(memory:NVMM),format=NV12 " \
f"! nvv4l2h264enc " \
f"! h264parse " \
f"! qtmux " \
f"! filesink location={video_path}"
v_wrt = cv2.VideoWriter(v_wrt_str, cv2.CAP_GSTREAMER, 0, {framerate as float}, ({width as int}, {height as int}))

Check that both capture and writer are opened, then in loop read frames from capture and push these into writer.

答案2

得分: 0

一种可能加速使用cv2.VideoWriter进行视频录制的方法是通过NVIDIA Video Codec SDK利用硬件加速。您可以尝试使用nvv4l2h264enc GStreamer元素与OpenCV的cv2.VideoWriter,使用Jetson Nano上的硬件编码器将视频编码为H.264格式。

import os
import time
import cv2

width = 2560
height = 1440
framerate = 30
video_path = 'fps_test.mp4'

gs_pipeline = f"v4l2src device=/dev/video0 io-mode=2 " \
              f"! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG " \
              f"! nvv4l2decoder mjpeg=1 " \
              f"! nvvidconv flip-method=4  " \
              f"! video/x-raw, format=BGRx " \
              f"! videoconvert " \
              f"! video/x-raw, format=BGR " \
              f"! nvvidconv " \
              f"! 'video/x-raw(memory:NVMM), format=I420' " \
              f"! nvv4l2h264enc " \
              f"! h264parse " \
              f"! mp4mux " \
              f"! filesink location={video_path}"

print(f"gst-launch-1.0 {gs_pipeline}\n")

v_cap = v_writer = None

def main():
    global v_cap, v_writer
    v_cap = cv2.VideoCapture(gs_pipeline, cv2.CAP_GSTREAMER)

    while v_cap.isOpened():
        ret_val, frame = v_cap.read()
        if not ret_val:
            break

        cv2.imshow('frame', frame)
        key = cv2.waitKey(1)

    v_cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass
    finally:
        v_cap.release()
        cv2.destroyAllWindows()
        if os.path.exists(video_path):
            os.remove(video_path)
英文:

One way to potentially speed up the video recording with cv2.VideoWriter is to use hardware acceleration through the NVIDIA Video Codec SDK. You can try using the nvv4l2h264enc GStreamer element with OpenCV's cv2.VideoWriter to encode the video in H.264 format using the hardware encoder on the Jetson Nano.

import os
import time
import cv2
width = 2560
height = 1440
framerate = 30
video_path = 'fps_test.mp4'
gs_pipeline = f"v4l2src device=/dev/video0 io-mode=2 " \
f"! image/jpeg, width={width}, height={height}, framerate={framerate}/1, format=MJPG " \
f"! nvv4l2decoder mjpeg=1 " \
f"! nvvidconv flip-method=4  " \
f"! video/x-raw, format=BGRx " \
f"! videoconvert " \
f"! video/x-raw, format=BGR " \
f"! nvvidconv " \
f"! 'video/x-raw(memory:NVMM), format=I420' " \
f"! nvv4l2h264enc " \
f"! h264parse " \
f"! mp4mux " \
f"! filesink location={video_path}"
print(f"gst-launch-1.0 {gs_pipeline}\n")
v_cap = v_writer = None
def main():
global v_cap, v_writer
v_cap = cv2.VideoCapture(gs_pipeline, cv2.CAP_GSTREAMER)
while v_cap.isOpened():
ret_val, frame = v_cap.read()
if not ret_val:
break
cv2.imshow('frame', frame)
key = cv2.waitKey(1)
v_cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
finally:
v_cap.release()
cv2.destroyAllWindows()
if os.path.exists(video_path):
os.remove(video_path)

答案3

得分: 0

你可以进行多线程操作。因此有一个线程负责获取摄像机帧,另一个线程负责写入帧。由于这两个线程将独立运行,因此不应出现延迟或减速。

英文:

You can multi-threading. So one thread for getting camera frames and another one writing the frames. As both the thread will be running independently there should be no lag/slow down.

huangapple
  • 本文由 发表于 2023年2月18日 03:47:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75488654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定