I’d suggest to check what videoio backends are available from the opencv lib running in your python env:
import cv2
print(cv2.getBuildInformation())
and check for Video I/O
such as:
Video I/O:
DC1394: NO
FFMPEG: YES
avcodec: YES (58.54.100)
avformat: YES (58.29.100)
avutil: YES (56.31.100)
swscale: YES (5.5.100)
avresample: YES (4.0.0)
GStreamer: YES (1.16.3)
v4l/v4l2: YES (linux/videodev2.h)
For camera capture, you may use V4L:
# Using V4L2 backend:
cap = cv2.VideoCapture(0, cv2.CAP_V4L)
# or
# cap = cv2.VideoCapture('/dev/video0', cv2.CAP_V4L)
Or gstreamer:
# Using v4l2src plugin that outputs into system memory, you may use RGB format from your camera that you would convert into BGR for opencv:
cap = cv2.VideoCapture("v4l2src device=/dev/video0 ! video/x-raw,format=RGB,width=1280,height=720,framerate=30/1 ! videoconvert ! video/x-raw,format=BGR ! appsink drop=1', cv2.CAP_GSTREAMER)
# As your camera is MIPI with UYVY format, you may also try nvv4l2camerasrc outputting into NVMM memory, use HW convert into BGRx and finally CPU converter for BGR format:
cap = cv2.VideoCapture('nvv4l2camerasrc device=/dev/video0 ! video/x-raw(memory:NVMM),formay=UYVY,width=1280,height=720,framerate=30/1 ! nvvidconv ! video/x-raw,format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink drop=1', cv2.CAP_GSTREAMER)
Also, you may test if the capture did successfully open and check current framing:
if not cap.isOpened():
print('Failed to open camera');
exit(-1)
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = float(cap.get(cv2.CAP_PROP_FPS))
print('camera opened, framing %dx%d@%f fps' % (w,h,fps))
If ok you would be able to run an opencv loop with imshow for displaying result such as:
import cv2
cap = cv2.VideoCapture(0, cv2.CAP_V4L)
if not cap.isOpened():
print('Failed to open camera');
exit(-1)
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = float(cap.get(cv2.CAP_PROP_FPS))
print('camera opened, framing %dx%d@%f fps' % (w,h,fps))
while True:
ret,frame = cap.read()
if not ret:
print('Failed to read from camera')
cap.release()
exit(-3)
cv2.imshow('Test', frame)
cv2.waitKey(1)
cap.release()
Try the available backends for camera capture and when you have one working, try to set up the writer.
Note that the size and framerate of the writer should match the size of the frames you’re pushing into it and the rate you’re pushing these. In your case, you’re pushing 1280x720 frames into a 640x480 writer, that may be wrong.
If your requirement is XVID codec, you may use FFMPEG backend if available:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter("./test.avi", cv2.CAP_FFMPEG, fourcc, fps, (w,h), True)
Or you may use HW encoder for H264 with gstreamer backend:
# BGR frames from opencv are first converted into BGRx with CPU, then resized into 640x480 and converted into NV12 into NVMM memory for HW encoder, and H264 stream is put into AVI container:
out = cv2.VideoWriter("appsrc ! video/x-raw,format=BGR ! queue ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! video/x-raw(memory:NVMM),width=640,height=480 ! nvv4l2h264enc ! h264parse ! avimux ! filesink location=test.avi", cv2.CAP_GSTREAMER, 0, fps, (w,h), True)
# Or:
out = cv2.VideoWriter("appsrc ! video/x-raw,format=BGR ! queue ! videoscale ! video/x-raw,width=640,height=480 ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! video/x-raw(memory:NVMM),format=NV12 ! nvv4l2h264enc ! h264parse ! avimux ! filesink location=test.avi", cv2.CAP_GSTREAMER, 0, fps, (w,h), True)
Again, test if the writer has successfully been created:
if not out.isOpened():
print('Failed to open writer')
cap.release()
exit(-2)
And add the write in the loop (you may remove imshow/waitKey):
import cv2
cap = cv2.VideoCapture(0, cv2.CAP_V4L)
if not cap.isOpened():
print('Failed to open camera');
exit(-1)
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = float(cap.get(cv2.CAP_PROP_FPS))
print('camera opened, framing %dx%d@%f fps' % (w,h,fps))
# Using FFMPEG backend
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter("./test.avi", cv2.CAP_FFMPEG, fourcc, fps, (w,h), True)
# Or using GStreamer backend resizing into 640x480
#out = cv2.VideoWriter("appsrc ! video/x-raw,format=BGR ! queue ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! video/x-raw(memory:NVMM),width=640,height=480 ! nvv4l2h264enc ! h264parse ! avimux ! filesink location=test.avi", cv2.CAP_GSTREAMER, 0, fps, (w,h), True)
#out = cv2.VideoWriter("appsrc ! video/x-raw,format=BGR ! queue ! videoscale ! video/x-raw,width=640,height=480 ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! video/x-raw(memory:NVMM),format=NV12 ! nvv4l2h264enc ! h264parse ! avimux ! filesink location=test.avi", cv2.CAP_GSTREAMER, 0, fps, (w,h), True)
if not out.isOpened():
print('Failed to open writer')
cap.release()
exit(-2)
while True:
ret,frame = cap.read()
if not ret:
print('Failed to read from camera')
out.release()
cap.release()
exit(-3)
out.write(frame)
cv2.imshow('Test', frame)
cv2.waitKey(1)
out.release()
cap.release()