OpenCV入門

OpenCVライブラリの基礎知識,およびPythonによるカメラ画像の取得と表示の実装を学ぶ。

【学習内容の構成】

  1. OpenCV:コンピュータビジョンと機械学習のライブラリ
  2. カメラ操作:cv2.VideoCaptureによる画像取得とcv2.imshowによる表示
  3. 配列:画像データを表現する要素の並び(次元と形)
  4. BGR成分:画像のB,G,R各成分の個別表示

スライド資料:[PDF], [パワーポイント]

YouTube動画:https://youtu.be/0JOdLablP7Y

【サイト内の関連ページ】

OpenCV サンプル Python プログラム: 別ページで説明。

目次

【実行にあたっての前提】

本資料のプログラムは,Windows上でテキストエディタ等に保存した.pyファイルを,コマンドプロンプトからpython ファイル名.pyの形式で実行することを想定する。JupyterなどのノートブックやIDLEの対話環境では,cv2.imshowによるウィンドウ表示が正しく動作しないことがあるため,スクリプトとして実行する。

表示と操作について,次の点に注意する。

1. OpenCVとは

OpenCV(Open Source Computer Vision Library)は,コンピュータビジョン(画像認識や画像処理)と機械学習のためのオープンソースライブラリである。2500以上のアルゴリズムを提供し,画像処理および認識のタスクに対応する。

1.1 OpenCVの主な機能

OpenCVが提供する主な機能には以下のようなものがある。各項目は抽象度が異なり,大きな分野(例:3次元モデルの抽出)と具体的な応用(例:赤目の除去)が混在している。

1.2 ライセンスと対応環境

OpenCVはApache 2 License(バージョン4.5.0以降。それ以前は3-clause BSD License)で提供されており,商用利用を含めて使用できる。

対応プログラミング言語は以下の通りである。

対応するオペレーティングシステムおよびプラットフォームは以下の通りである。本資料ではWindowsでの利用を前提とする。

1.3 学習リソース

OpenCVを学習するための主な公式リソースは以下の通りである。

2. インストールと動作環境

本資料のプログラム例を実行するには,OpenCVとNumPyが必要である。インストールはPythonのパッケージ管理ツールpipで行う。Windowsのコマンドプロンプトで以下を実行する。

pip install opencv-python numpy

opencv-pythonはNumPyを依存パッケージとして自動的にインストールするため,numpyの明示的な指定は省略できる場合がある。NumPyはOpenCVが画像を配列として扱うための基盤ライブラリである。

2.1 GPUとCPUについて

pipでインストールされるopencv-pythonは,CPUで動作するビルドである。本資料で扱うカメラ画像の取得・表示・成分分解は,GPUの有無にかかわらずCPUのみで動作する。GPU搭載機・CPUのみの機のいずれでも,同じプログラムを実行できる。

3. カメラ画像を取得して表示するプログラム

OpenCVを使用してカメラから画像を取得し,表示するプログラム例を示す。読み出したフレームは配列として格納される。配列の構造については第4章で説明する。

3.1 カメラから1枚の画像を取得して表示するプログラム

import cv2

# カメラオブジェクトを生成(WindowsではCAP_DSHOWを指定する)
v = cv2.VideoCapture(0, cv2.CAP_DSHOW)

# フレームを読み出す
ret, f = v.read()

# 画像を表示する
cv2.imshow("Camera", f)

# キー入力を待つ
cv2.waitKey(0)

# カメラを解放する
v.release()

# ウィンドウを閉じる
cv2.destroyAllWindows()

このプログラムの処理の流れは以下の通りである。

  1. cv2.VideoCapture(0, cv2.CAP_DSHOW)でカメラオブジェクトvを生成する。第1引数の0はデフォルトカメラを指定する。第2引数のcv2.CAP_DSHOWは,Windowsでカメラを扱うためのバックエンド(DirectShow)の指定である。Windowsの既定のバックエンドではカメラの起動に数秒かかることがあり,cv2.CAP_DSHOWを指定すると起動が速くなる。
  2. v.read()でカメラからフレームを読み出す。戻り値は読み出しの成功を示すフラグretとフレームデータfである。
  3. cv2.imshow()で画像をウィンドウに表示する。
  4. cv2.waitKey(0)でキー入力があるまで待機する。引数0は無制限の待機を意味する。この関数はキー入力の受け取りに加えてウィンドウの描画も担うため,cv2.imshow()と組み合わせて呼ぶ。
  5. v.release()でカメラを解放する。
  6. cv2.destroyAllWindows()で表示中のすべてのウィンドウを閉じる。

4. 画像データを表す配列の構造

OpenCVで扱う画像データは配列として表現される。配列の概念は画像処理の基礎となる。

4.1 配列の基礎

配列は要素の並びである。各要素には添字(インデックス)が付き,添字は0から始まる。

例えば1次元配列[8 5 4 1 3]では,各要素の添字は以下のようになる。

4.2 配列の次元

配列には次元という概念がある。Pythonでは配列を以下のように表示する。

画像データは2次元配列(グレースケール画像)または3次元配列(カラー画像)として表現される。グレースケール画像とは,色を持たず明るさ(輝度)のみで表す画像であり,各ピクセルが1つの値を持つ1チャンネルの2次元配列となる。カラー画像は各ピクセルが複数の色成分を持つため3次元配列となる。

4.3 配列の形と次元の取得

Pythonでは配列の内容,形,次元数を以下のように取得できる。

import cv2

# カメラオブジェクトを生成(WindowsではCAP_DSHOWを指定する)
v = cv2.VideoCapture(0, cv2.CAP_DSHOW)

# フレームを読み出す
ret, f = v.read()

# 配列の内容を表示する
print(f)

# 配列の形を表示する(例: (480, 640, 3))
print(f.shape)

# 配列の次元数を表示する(例: 3)
print(f.ndim)

# カメラを解放する
v.release()

この例では,カメラから取得した画像fは3次元配列である。f.shape(480, 640, 3)のような形を返し,高さ480ピクセル,幅640ピクセル,3つの色成分を持つことを意味する。f.ndimは次元数を返し,この場合は3となる。

5. 画像のB, G, Rの3成分

カラー画像は,B(青),G(緑),R(赤)の3つの色成分から構成される。OpenCVでは画像データは3次元配列として表現され,各ピクセルの色情報はこの3成分の組み合わせで表される。OpenCVの色成分の並び順は,一般的なRGBではなくBGR(青,緑,赤)である。

5.1 画像データの構造

OpenCVで取得したカラー画像は,以下の構造を持つ3次元配列である。

配列の添字を用いて特定の色成分にアクセスできる。色成分がBGR順である点は,他ライブラリと連携する際に影響する。例えばRGB順を前提とするライブラリ(matplotlib等)にOpenCVの画像をそのまま渡すと,青と赤が入れ替わり色が反転して表示される。この場合はcv2.cvtColor(f, cv2.COLOR_BGR2RGB)で並び順を変換してから渡す。

5.2 各色成分の表示

以下のプログラム例では,カメラから取得した画像全体と各色成分を個別に表示する。

import cv2

# カメラオブジェクトを生成(WindowsではCAP_DSHOWを指定する)
v = cv2.VideoCapture(0, cv2.CAP_DSHOW)

# フレームを読み出す
ret, f = v.read()

# 画像全体を表示する
cv2.imshow("All", f)

# B成分を表示する
cv2.imshow("B", f[:, :, 0])

# G成分を表示する
cv2.imshow("G", f[:, :, 1])

# R成分を表示する
cv2.imshow("R", f[:, :, 2])

# キー入力を待つ
cv2.waitKey(0)

# カメラを解放する
v.release()

# ウィンドウを閉じる
cv2.destroyAllWindows()

配列のスライス表記f[:, :, 0]f[:, :, 1]f[:, :, 2]は,それぞれB成分,G成分,R成分を取り出す。:は「すべて」を意味し,f[:, :, 0]は「すべての行,すべての列における第3次元のインデックス0の要素」すなわちB成分を取得する。各成分は1チャンネルの2次元配列となるため,グレースケール画像(明るさのみの画像)として表示される。

6. カメラ映像をリアルタイムで表示するプログラム

カメラからの映像を連続的に表示するには,フレームを繰り返し読み出して表示する。

6.1 ビデオ表示のプログラム例

import cv2

# カメラオブジェクトを生成(WindowsではCAP_DSHOWを指定する)
v = cv2.VideoCapture(0, cv2.CAP_DSHOW)

while True:
    # フレームを読み出す
    ret, f = v.read()

    # 画像を表示する
    cv2.imshow("Video", f)

    # 1ミリ秒待ち、ESCキーが押されたらループを抜ける
    if cv2.waitKey(1) == 27:
        break

# カメラを解放する
v.release()

# ウィンドウを閉じる
cv2.destroyAllWindows()

このプログラムの処理の流れは以下の通りである。

  1. while Trueで処理を繰り返す。
  2. ループ内でv.read()により各フレームを読み出す。
  3. cv2.imshow()で読み出したフレームを表示する。
  4. cv2.waitKey(1)で1ミリ秒待機する。この待機はウィンドウの描画とキー入力の受け取りに必要である。
  5. cv2.waitKey(1)の戻り値が27(ESCキーのコード)のとき,ループを抜けて処理を終了する。
  6. v.release()でカメラを解放し,cv2.destroyAllWindows()でウィンドウを閉じる。

連続的にフレームを取得・表示することで,動画として表示される。

7. 演習

7.1 演習1.カメラ画像の取得と表示

テーマ: カメラから1枚の画像を取得し,ウィンドウに表示する。

手順:

  1. 第3章のプログラム例を.pyファイルとして保存する。
  2. コマンドプロンプトでpython ファイル名.pyを実行する。
  3. ウィンドウに表示された画像を確認し,任意のキーを押してウィンドウを閉じる。

ヒント: ウィンドウが表示されない場合,cv2.imshowの後にcv2.waitKeyが記述されているか確認する。カメラ番号0で取得できない場合,1や2に変更する。

考察ポイント: 表示された画像の色合いや明るさを確認する。画像が表示されるまでにかかる時間を観察する。

7.2 演習2.配列の形と次元の確認

テーマ: 取得した画像が配列として持つ形と次元数を確認する。

手順:

  1. 第4章4.3のプログラム例を.pyファイルとして保存する。
  2. コマンドプロンプトでpython ファイル名.pyを実行する。
  3. 表示されたf.shapef.ndimの値を記録する。

ヒント: f.shapeは3つの数値の組で表示される。3つの数値はそれぞれ高さ,幅,色成分の数に対応する。

考察ポイント: f.shapeの3番目の値が何を表すか,第3次元の意味(色成分)と対応づける。使用するカメラによって高さと幅の値がどう変わるかを確認する。

7.3 演習3.B, G, R成分の個別表示

テーマ: カラー画像をB,G,Rの3成分に分け,個別に表示して比較する。

手順:

  1. 第5章5.2のプログラム例を.pyファイルとして保存する。
  2. コマンドプロンプトでpython ファイル名.pyを実行する。
  3. 4つのウィンドウ(全体,B,G,R)を見比べ,任意のキーを押してウィンドウを閉じる。

ヒント: 各成分のウィンドウはグレースケール(明るさのみ)で表示される。明るく表示される部分は,その色成分の値が大きい領域である。

考察ポイント: 赤い物体をカメラに映したとき,どの成分のウィンドウで明るく表示されるかを確認する。各成分の明暗の違いと,元のカラー画像の色との対応を読み取る。

7.4 演習4.カメラ映像のリアルタイム表示

テーマ: カメラ映像を連続的に表示し,ESCキーで終了する。

手順:

  1. 第6章6.1のプログラム例を.pyファイルとして保存する。
  2. コマンドプロンプトでpython ファイル名.pyを実行する。
  3. 映像を確認し,ESCキーを押して終了する。

ヒント: 映像が更新されない場合,ループ内にcv2.waitKey(1)が記述されているか確認する。

考察ポイント: 1枚だけ表示する演習1との違いを確認する。cv2.waitKeyの引数を1から大きい値に変えると,映像の更新がどう変わるかを観察する。

8. その他のコンピュータビジョンライブラリ

OpenCV以外にも,コンピュータビジョンに関連するライブラリがある。用途に応じて使い分ける。いずれもPythonからpipでインストールでき,Windows上で動作する。

8.1 コンピュータビジョンに関わるライブラリ類(補足)

これらのライブラリは特定のタスクに特化した機能を提供し,OpenCVと組み合わせて使用されることもある。