OpenCVからWebカメラの「解像度」「FPS」及び、「フォーマット(コーディック)」を設定する方法

2020.05.22

1 はじめに

CX事業本部の平内(SIN)です。

OpenCVでは、USBで接続されたWebカメラを動画入力として扱うことができます。そして、提供されるメソッドで、「解像度」「FPS」及び「フォーマット(コーディック)」の設定及び、取得が可能です。

非常に簡単に利用できますが、想定外な設定となってしまっている例もあり、個人的には、よくやらかすので、自戒を込めてのメモです。

2 環境

動作確認に使用した機材はは、Model 4Bロジクール HD Pro Webcam C920です。

OSは、今年2月の最新版(Raspbian Buster with desktop and recommended software) 2020-02-13-raspbian-buster-full.img です

$ cat /proc/cpuinfo  | grep Revision
Revision    : c03112

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

$ uname -a
Linux raspberrypi 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux

OpenCVは、python3用に4.1.1がインストールされています。

pi@raspberrypi:~ $ python3
Python 3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.1.1'

3 Webカメラの対応諸元

最初に、Webカメラが対応している諸元を確認します。残念ながらOpenCVのメソッドでこれを取得する方法が無いので、v4l2-ctlを使用しています。

pi@raspberrypi:~ $ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture
	[0]: 'YUYV' (YUYV 4:2:2)

・・・(略)・・・

		Size: Discrete 800x448
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)

・・・(略)・・・

	[1]: 'MJPG' (Motion-JPEG, compressed)

・・・(略)・・・

		Size: Discrete 800x448
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.042s (24.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)

・・・(略)・・・

出力を見ると、C920では、下記の2種類のフォーマット(コーディック)に対応している事が分かります。

  • YUYV 4:2:2
  • Motion-JPEG

注:最近のC920は、H.264には対応していないようです。

参考 : SAY GOODBYE TO IN-CAMERA HARDWARE ENCODING

確認しやすいように、上記の出力を一覧しておきます。

フォーマット(CODEC) 解像度 fps
MJPG 1920 x 1080 5, 7.5, 10, 15, 20, 24, 30
MJPG 1600 x 896 5, 7.5, 10, 15, 20, 24, 30
MJPG 1280 x 720 5, 7.5, 10, 15, 20, 24, 30
MJPG 1024 x 576 5, 7.5, 10, 15, 20, 24, 30
MJPG 960 x 720 5, 7.5, 10, 15, 20, 24, 30
MJPG 864 x 480 5, 7.5, 10, 15, 20, 24, 30
MJPG 800 x 600 5, 7.5, 10, 15, 20, 24, 30
MJPG 800 x 448 5, 7.5, 10, 15, 20, 24, 30
MJPG 640 x 480 5, 7.5, 10, 15, 20, 24, 30
MJPG 640 x 360 5, 7.5, 10, 15, 20, 24, 30
MJPG 432 x 240 5, 7.5, 10, 15, 20, 24, 30
MJPG 320 x 240 5, 7.5, 10, 15, 20, 24, 30
MJPG 320 x 180 5, 7.5, 10, 15, 20, 24, 30
MJPG 352 x 288 5, 7.5, 10, 15, 20, 24, 30
MJPG 176 x 144 5, 7.5, 10, 15, 20, 24, 30
MJPG 160 x 120 5, 7.5, 10, 15, 20, 24, 30
MJPG 160 x 90 5, 7.5, 10, 15, 20, 24, 30
YUYV 2304 x 1536 2
YUYV 2304 x 1296 2
YUYV 1920 x 1080 5
YUYV 1600 x 896 5, 7.5
YUYV 1280 x 720 5, 7.5, 10
YUYV 1024 x 576 5, 7.5, 10, 15
YUYV 960 x 720 5, 7.5, 10, 15
YUYV 800 x 600 5, 7.5, 10, 15, 20, 24
YUYV 864 x 480 5, 7.5, 10, 15, 20, 24, 30
YUYV 800 x 448 5, 7.5, 10, 15, 20, 24, 30
YUYV 640 x 480 5, 7.5, 10, 15, 20, 24, 30
YUYV 640 x 360 5, 7.5, 10, 15, 20, 24, 30
YUYV 432 x 240 5, 7.5, 10, 15, 20, 24, 30
YUYV 352 x 288 5, 7.5, 10, 15, 20, 24, 30
YUYV 320 x 240 5, 7.5, 10, 15, 20, 24, 30
YUYV 320 x 180 5, 7.5, 10, 15, 20, 24, 30
YUYV 176 x 144 5, 7.5, 10, 15, 20, 24, 30
YUYV 160 x 120 5, 7.5, 10, 15, 20, 24, 30
YUYV 160 x 90 5, 7.5, 10, 15, 20, 24, 30

4 OpenCV

続いてOpenCVでWebカメラを利用する場合の一般的なコードです。cap.set()で解像度やFPSを指定し、cap.get()で設定された内容を確認しています。

CAP_PROP_FOURCCでフォーマットを明示的に設定した例は少ないのですが、カメラが予期しないモードで動作していて、解像度等の設定に失敗する事があるので注意が必要です。

なお、CAP_PROP_FOURCCの戻り値は、文字列として取得するためにデコードする必要があります
参考:https://github.com/opencv/opencv/blob/master/samples/python/video_v4l2.py

デバイスの変更などで、想定していないモードで動作している可能性もありますので、プログラムの中で、解像度やFPSに依存したコードを書く場合は、cap.get()で取得した値を使用する方が安全だと思います。

# -*- coding: utf-8 -*-
import cv2

# Webカメラ
DEVICE_ID = 0 

WIDTH = 800
HEIGHT = 600
FPS = 24

def decode_fourcc(v):
        v = int(v)
        return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)])

def main():
    cap = cv2.VideoCapture (DEVICE_ID)

    # フォーマット・解像度・FPSの設定
    #cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M','J','P','G'))
    cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y','U','Y','V'))
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
    cap.set(cv2.CAP_PROP_FPS, FPS)

    # フォーマット・解像度・FPSの取得
    fourcc = decode_fourcc(cap.get(cv2.CAP_PROP_FOURCC))
    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    fps = cap.get(cv2.CAP_PROP_FPS)
    print("fourcc:{} fps:{} width:{} height:{}".format(fourcc, fps, width, height))

    while True:
        
        # カメラ画像取得
        _, frame = cap.read()
        if(frame is None):
            continue

        # 画像表示
        cv2.imshow('frame', frame)
        
        # キュー入力判定(1msの待機)
        # waitKeyがないと、imshow()は表示できない
        # 'q'をタイプされたらループから抜ける
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    # VideoCaptureオブジェクト破棄
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
	main()

5 失敗例

よくやってしまう失敗例を紹介させて下さい。

(1) フォーマット間違い

MJPGのつもりで、800 ✕ 600 30FPSを設定したつもりが、動作モードがYUYVになっていて失敗している状況です。 YUYVの場合、800 ✕ 600 の最高FPSは、24ですので、30を設定すると24で初期化されます。

WIDTH = 800
HEIGHT = 600
FPS = 30

fourcc:YUYV fps:24.0 width:800.0 height:600.0

(2) フォーマット間違い

YUYVの最高解像度である 2304 ✕ 1536 2FPSを設定したつもりが、動作モードがMJPGになっていて想定外の解像度・FPSになっている状況です。(この場合、MJPGの最高解像度になっている)

WIDTH = 2304
HEIGHT = 1536
FPS = 2

fourcc:MJPG fps:5.0 width:1920.0 height:1080.0

(3) 指定間違い

1920 ✕ 1080 30FPSを設定したつもりが、HIGHTとWIDTHを間違えて、想定外の解像度・FPSになっている状況です。完全な凡ミスですが、結構やってしまいます。

HEIGHT = 1920
WIDTH = 1080
FPS = 30

fourcc:MJPG fps:30.0 width:960.0 height:720.0

6 最後に

今回は、OpenCVで「解像度」「FPS」及び「フォーマット(コーディック)」を設定する要領について確認してみました。 想定外の動作をしないように、設定されている状態を常に確認しながら作業することが重要だと思います。(すいません、自分自身への戒めです)