LoginSignup
19
15

More than 3 years have passed since last update.

OpenCVからカメラの解像度を切り替える

Last updated at Posted at 2020-05-30

はじめに

在宅勤務がはじまって、WEBカメラの価格が高騰しました。
この期間に買ったへなちょこカメラでopenCVでキャプチャするときの解像度とフレームレートの変更に苦労したのでまとめておきます。

やったこと

Jetsonで、openCVを用いるときに、WEBカメラのコーデックを変えようとしたらCAP_PROP_FOURCCのsetでunhandled propertyといわれたので、v4l2srcを入力、appsinkを出力にgstreamerを利用して、これをvideoCaptureの引数文字列として指定することで、カメラのコーデックと解像度を変更しました。

OpenCVでのフレームレート変更

通常は
【Python】OpenCVでWebカメラのフレームサイズ、FPS設定にあるように

解像度変更
cap=videoCapture(0)
video_input.set(cv2.CAP_PROP_FPS, 30) 
video_input.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
video_input.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) 

とかやると解像度の変更ができます。
このとき、変更先の解像度とFPSはカメラでサポートされているものである必要があり、このリストはv4l2-ctlコマンドなどで取得できます。以下は今回の対象のへなちょこカメラの出力です。

XavierNX:~/docker/darknet/work$ v4l2-ctl -d /dev/video1 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'MJPG' (compressed)
    Name        : Motion-JPEG
        Size: Discrete 1920x1080
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 1280x720
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 320x180
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 1920x1080
            Interval: Discrete 0.033s (30.000 fps)

    Index       : 1
    Type        : Video Capture
    Pixel Format: 'YUYV'
    Name        : YUYV 4:2:2
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 640x360
            Interval: Discrete 0.033s (30.000 fps)

XavierNX:~/docker/darknet/work$ 

v4l2-ctlがなければ、apt install v4l-utilsでインストールが可能です。

問題点

  • 問題点1:OpenCVがYUYVでカメラをオープンしようとする
    上記の出力例だと、OPENCVは、YUYVの1個目(1個目かどうかは自信ないです)の640x360-30FPSでオープンしようとすることにあります。 この挙動を変更し、MJPG形式にカメラを切り替えない限り、このへなちょこカメラでは640x360以外の解像度が設定できません。
  • 問題点2:VideoCapturePropertiesではCAP_PROP_FOURCC でフォーマット変更ができることになっていますが、やってみるとunhandled propertyとなりJetson上では変更できません。

問題点2について

OpenCVのカメラ読み込みを高速化し、遅延時間も短くするなどを参照すると

解像度変更
import cv2

cap=cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'));
video_input.set(cv2.CAP_PROP_FPS, 30) 
video_input.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
video_input.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) 

while True:
    ret, frame_read = cap.read()
    cv2.imshow('Read',frame_read )
    cv2.waitKey(30)
cap.release()

ってやると動く気がします。
しかしなぜか、やってみるとJETSON上では

[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (1184) setProperty OpenCV | GStreamer warning: GStreamer: unhandled property

っていわれ、MJPGに切り替えることができません。
実際にOpenCV4.11のgitのCAP_gstreamer.cppを見ると set関数ではCAP_PROP_FORCCは定義されておらずunhandled propertyにおちるようにかかれている気がします。
MACとかでやると動くのでvideoCapture でVIDEOデバイスをあけるときの実装が別のコードを利用するような気もしますが、Jetsonでの動作はコード上は As designedな動作に見えます。

解決策

この道をすすむことはあきらめ、v4l2srcとappsinkをgstreamerで指定することで、コーデック解像度、FPSの変更を行いました。

解像度変更v4l2src
import cv2

src = 'v4l2src device=/dev/video1 ! image/jpeg,width=1280, height=720, framerate=(fraction)30/1 !jpegdec !videoconvert ! appsink'

cap=cv2.VideoCapture(src)
while(cap.isOpened()):
    ret, frame_read = cap.read()

    cv2.imshow('Read',frame_read )
    cv2.waitKey(30)
cap.release()

~             

他にもgstreamerのvideoinput部分を書き換えるといろいろできて楽しそうです。
v4l2srcのドキュメント
とか、gst-launch-1.0にのせるパラメータで検索するといろいろ出てきます。

19
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
15