USBカメラの動画キャプチャ&描画用 Pythonプログラム

AI画像認識も定番ライブラリ OpenCVで簡単制作


画像処理するなら“OpenCV”

画像処理のプログラミングは一見難しそうですが,“OpenCV”というライブラリ(https://opencv.org/)を利用すると,数十行のPython または C++コードで本格的な処理を実現できます.

OpenCVは,画像処理用のさまざまなアルゴリズムを全般的に含んでおり,AI(画像認識など)のような最新処理も試せますし,パソコンだけでなく,ラズベリー・パイのような組み込みマイコン上でも走ります.

USBカメラから動画像をキャプチャして表示するGUIプログラム

USBカメラから動画像をキャプチャし,ウィンドウに表示するGUIを作ってみましょう(図1).


図1 USBカメラから動画像を取り込んでウインドウに表示しているところ

処理の流れ

USBカメラと表示ウィンドウをそれぞれオープンして(利用を宣言して)初期設定したうえで,無限ループ内でカメラからの画像取り込みと表示ウィンドウへの転送を繰り返す,というものです.いずれの操作も,OpenCVが備える関数を呼ぶだけで行えます.


import sys
import time
import numpy as np
import cv2

CAM_WIDTH   = 1280
CAM_HEIGHT  = 960
WINNAME     = 'opencv'

# カメラをオープン
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FOURCC, 
      cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') )
cap.set(cv2.CAP_PROP_FRAME_WIDTH,  CAM_WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, CAM_HEIGHT)

# 表示ウィンドウを作成
cv2.namedWindow(WINNAME, cv2.WINDOW_NORMAL)

ret, frame  = cap.read()

# 画像取り込みと表示の繰り返し
while 1:
    ret, frame  = cap.read()
    cv2.imshow(WINNAME, frame)
    key = cv2.waitKey(1)
    if key > 0:
        break

cap.release()
cv2.destroyWindow(WINNAME)

リスト1 Pythonで記述したソースコード

USBカメラやウィンドウのオープン

リスト1に示すのは,Pythonで記述した実際のコードです.

冒頭でインポートしている“cv2”がOpenCVのことです.

11行目で“cv2.VideoCapture()”を呼び,USBカメラをオープンしています.引数に渡している 0 はUSBカメラの番号です.戻り値の“cap”は,後でカメラを参照するために使います.

この例では,USBカメラを1台しか使っていませんが,引数に指定する番号を変えて,“VideoCapture()”を繰り返し呼ぶことで,複数個のUSBカメラを使えます.ラズベリー・パイでは,図2の方法でカメラ番号を取得できます.

12~14行目は,カメラから取得する映像の解像度やフォーマットの指定です.“Motion JPEG”という圧縮形式を用いています.

17行目が表示用ウィンドウのオープンです.ウィンドウも必要ならば複数枚を開けます.ウィンドウの区別は,ウィンドウの名前(変数“WINNAME”で指定)によって行います.

図2 複数個のUSBカメラを使う場合

メイン・ループ処理

22~27行目の無限ループで,画像取り込みと表示を繰り返しています.

23行目のコード“cap.read()”で,カメラから1フレームぶんの画像データを取得し,変数“frame”に代入します.24行目の“cv2.imshow()”がウィンドウへの画像データ転送です.

単に“cv2.imshow()”を呼ぶだけでは表示は行われません.続けて“cv2.waitKey()”という関数を呼ぶ必要があります.

OpenCVに限らず,GUIプログラミング全般に共通した事項ですが,「(A)ユーザ・プログラム側で描画やキー入力などのリクエストをする → (B)システム側(ライブラリやOS)でリクエストを実際に処理する」という無限ループが,パソコン全体としての処理動作です(イベント・ドリブン処理と呼ばれる).

(A)に該当するのは,リスト1の23行目と24行目です.

25行目の“cv2.waitKey()”呼び出しによって(B)が行われ,初めてウィンドウへの描画が実行されます.なお,“cv2.waitKey()”の戻り値として,その時点で押されていたキーの値が得られるので,それを利用した処理を付け加えることもできます.

露出の調整など,USBカメラ側の初期化が完了していないうちに画像を取り込もうとすると,不正な映像データが来る場合があります(図3).これを回避するためには,メイン・ループに入る前に数フレームほど画像を捨てます.実際,リスト1では,19行目で1フレーム分のデータを捨てています.

図3 メイン・ループに入る前に数フレームほど画像を捨てる

OpenCVは画像処理プログラミングを簡単にしてくれる

以上のように,少しの留意点はありますが,シンプルなコードで画像処理を実現できるのが,OpenCVを利用する最大のメリットです.OpenCVが備える関数に取り込んだカメラ画像(frame)を渡せば,画像加工や画像認識などもすぐに行えます.




(c)2023 Sumio Morioka