見出し画像

【Python】Webカメラで使える解像度・fpsの一覧取得が遅すぎて絶望(→C#で作ったら1秒未満)

【状況】OpenCVで解像度とフレームレートを設定して記録するときに,うっかりそのカメラの仕様にないパラメータ(解像度,fps)を使っている場合,OpenCVが別の有効な数値に置き換えて動作しようとするみたい(それで以前ハマった).そこで,使えるカメラパラメータを事前に調べたいと思いました.
【対処】OpenCVでは,当該カメラで使える解像度,fpsを列挙する機能がないので,設定(set)→取得(get)して調べる方法しかないみたい.網羅的に使えるパラメータを調べようとするも,たった9通り試すのに84秒もかかり絶望した,のメモ.

理想はv4l2-ctl

Linuxだと,v4l2-ctlを使えば,接続しているカメラ全てについて,使用できる解像度とフレームレート,ビデオフォーマットまで一覧が得られるのに.

カメラで使えるパラメータを調べる

OpenCVには,カメラパラメータの列挙する方法がない・・・.いろいろ調べた結果,プリセットを網羅的にやる方法しか見つからない.WindowsのPython,OpenCVだと,こんな力技しかないのかなぁ.

import cv2

# 最初のウェブカメラを使用
device_id = 0

# カメラオブジェクトを作成
cap = cv2.VideoCapture(device_id)

# カメラが正常に開かれたかを確認
if not cap.isOpened():
    print("カメラを開けません")
    exit()

# いくつかの一般的な解像度とフレームレートを設定してみる
resolutions = [(640, 480), (1280, 720), (1920, 1080)]
fps_values = [15, 30, 60]

# 各解像度,fps,ビデオフォーマットに対してループ処理を行う
for resolution in resolutions:
    for fps in fps_values:            
        # 解像度とfpsを設定
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, resolution[0])
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, resolution[1])
        cap.set(cv2.CAP_PROP_FPS, fps)
        
        # 少し待機してカメラが設定に適応するのを待つ
        cv2.waitKey(100)
        
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        actual_fps = int(cap.get(cv2.CAP_PROP_FPS))

        if width == resolution[0] and height == resolution[1] and fps == actual_fps:
            print(f"〇{width}x{height} @ fps: {actual_fps}")
        else:
            print(".")
        
# カメラを解放
cap.release()

出力結果.起動に時間がかかるとはいえ,84秒もかかった・・・.何か間違っているとしか思えず.しかも,記載した数値しか試せないから,やりたいことが十分にできていない.

.
〇640x480 @ fps: 30
.
.
.
.
.
〇1920x1080 @ fps: 30
.
Press any key to continue . . .

結局DirectShow

さんざん調べたけど,網羅的に情報を得るには,結局DirectShowを使ってゴリゴリ書くしかない模様.Pythonで書くのをあきらめてC#で書いたけど,全く楽じゃなかった!やりたい内容の割に長すぎてw(DirectShowLibを使って少しは簡略化できたみたいだけど・・・)

C#で作った結果1秒未満

結果だけ書くと,以下の二つのカメラのパラメータが1秒かからず(!).ついでに解像度の大きい順,fpsの高い順にソートしてみました.
こう並べてみると,MotionJPEGの優秀さが際立つし,内蔵HD WebCamに比べるとロジクールC922のモードの多さが目立ちました.

カメラ名: USB HD Webcam
1920x1080 @ 30.00 fps (MJPG)
1920x1080 @ 3.00 fps (YUY2)
1280x720 @ 30.00 fps (MJPG)
1280x720 @ 8.00 fps (YUY2)
960x540 @ 30.00 fps (MJPG)
960x540 @ 15.00 fps (YUY2)
640x480 @ 30.00 fps (MJPG)
640x480 @ 30.00 fps (YUY2)
640x360 @ 30.00 fps (MJPG)
640x360 @ 30.00 fps (YUY2)
320x240 @ 30.00 fps (MJPG)
320x240 @ 30.00 fps (YUY2)
176x144 @ 30.00 fps (MJPG)
176x144 @ 30.00 fps (YUY2)
160x120 @ 30.00 fps (MJPG)
160x120 @ 30.00 fps (YUY2)
カメラ名: c922 Pro Stream Webcam
2304x1536 @ 2.00 fps (YUY2)
2304x1296 @ 2.00 fps (YUY2)
1920x1080 @ 30.00 fps (MJPG)
1920x1080 @ 5.00 fps (YUY2)
1600x896 @ 30.00 fps (MJPG)
1600x896 @ 7.50 fps (YUY2)
1280x720 @ 30.00 fps (MJPG)
1280x720 @ 10.00 fps (YUY2)
960x720 @ 30.00 fps (MJPG)
960x720 @ 15.00 fps (YUY2)
1024x576 @ 30.00 fps (MJPG)
1024x576 @ 15.00 fps (YUY2)
800x600 @ 30.00 fps (MJPG)
800x600 @ 24.00 fps (YUY2)
864x480 @ 30.00 fps (MJPG)
864x480 @ 24.00 fps (YUY2)
800x448 @ 30.00 fps (YUY2)
800x448 @ 30.00 fps (MJPG)
640x480 @ 30.00 fps (YUY2)
640x480 @ 30.00 fps (MJPG)
640x360 @ 30.00 fps (YUY2)
640x360 @ 30.00 fps (MJPG)
432x240 @ 30.00 fps (YUY2)
432x240 @ 30.00 fps (MJPG)
352x288 @ 30.00 fps (YUY2)
352x288 @ 30.00 fps (MJPG)
320x240 @ 30.00 fps (YUY2)
320x240 @ 30.00 fps (MJPG)
320x180 @ 30.00 fps (YUY2)
320x180 @ 30.00 fps (MJPG)
176x144 @ 30.00 fps (YUY2)
176x144 @ 30.00 fps (MJPG)
160x120 @ 30.00 fps (YUY2)
160x120 @ 30.00 fps (MJPG)
160x90 @ 30.00 fps (YUY2)
160x90 @ 30.00 fps (MJPG)
何かキーを押して終了します...

こんな感じのクラスのリストとして返す仕様にしたので,自分用に使えそうではあります.

    /// <summary>
    /// 保存するカメラパラメータ群
    /// </summary>
    public class CameraParam
    {
        // カメラの解像度の幅(ピクセル単位)
        public int Width { get; set; }

        // カメラの解像度の高さ(ピクセル単位)
        public int Height { get; set; }

        // カメラのフレームレート(1秒あたりのフレーム数)
        public double FrameRate { get; set; }

        // カメラのビデオフォーマット(例: MJPG, YUY2)
        public string Format { get; set; }
    }

もうカメラは嫌だー

この記事が気に入ったらサポートをしてみませんか?