2023年01月30日 更新

ラズパイにOpenCVをインストールして、画像・カメラ表示、文字・図形描画

どうも、クラゲです。

ラズパイでカメラや画像を扱う上で、最も重要なOpenCVというライブラリのインストール方法と具体的な使い方についてご紹介します。

目次

[TOC]

OpenCVとは?

CVとはComputer Visionの略です。OpenCVはインテルが開発しているオープンソースのComputer Vision向けのライブラリで、具体的には、画像処理、画像解析、機械学習などが行えます。

OpenCVをPythonで使うためには cv2 モジュールを import する必要があります。cv22 はバージョンとは関係ないのでご注意ください。OpenCV2でもOpenCV3でもOpenCV4でも、import cv2 です。

OpenCVのバージョン確認

「自分のラズパイにOpenCVがインストールされているのか?」「インストールされているOpenCVのバージョンはいくつなのか?」を確認します。

pythonと打つと対話モードに入るので、>>> の後に import cv2 と入力します。

python
>>> import cv2
>>> 

ここで >>> とだけ出てきた場合はOpenCVがインストールされています。

一方で、ModuleNotFoundError: No module named 'cv2'などと出てきた場合はインストールされていません。この後の項目に進んでOpenCVをインストールしましょう。

バージョン確認は続けて cv2.__version__ と打ち込みます。

python
>>> import cv2
>>> cv2.__version__
'4.6.0'

そうすると '4.6.0' などバージョン表示されます。対話モードを終了するには Ctrl + Z キーを入力してください。

OpenCVをインストール

ラズパイでOpenCVのインストールしようとすると、長い時間待たされた後にエラーになった経験はありませんか? 以下の手順で行えば簡単にすぐインストールできます。

opencv-pythonを活用します。LXTerminalから以下のコマンドを打ちます。

まず必要なライブラリをインストールします

sudo apt install -y libatlas-base-dev


numpyというモジュールのバージョンが低いとエラーになるため、バージョンアップします。

pip install numpy --upgrade


最後にopencv-pythonのバージョンを指定してインストールします。

pip install opencv-python==4.6.0.66

バージョンを指定しない場合は最新バージョンが対象となりますが、エラーになる場合があります。他のバージョンをインストールしたい場合は、こちらを参照してください。

例えば、以下のようなエラー表示が出た場合は、古いバージョンに変えてみましょう

ERROR: Could not build wheels for opencv-python which use PEP 517 and cannot be installed directly

ERROR: Could not build wheels for opencv-python, which is required to install pyproject.toml-based project


ちなみにクラゲの環境は以下の通りです。

  • Raspberry Pi OS 2022-09-22
  • numpy-1.24.1
  • opencv-python 4.6.0.66

画像ファイルの表示

まず表示したい画像をラズパイの実行プログラムと同じディレクトリに用意してください。ファイル名はcat.pngとします。

こちらがコードです。

import cv2

image_file = 'cat.png'
img = cv2.imread(image_file)
cv2.imshow('image', img)

cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.imreadで画像ファイルを読み込みます。また、cv2.imshowで画像を表示します。第一引数は画像表示ウィンドウの名前で、任意の文字列を付けることができます。第二引数にimreadで読み込んだ画像を指定します。

ラズパイ上では、こんな感じで表示されます。画像が表示ウィンドウにフォーカスがあるとき(タイトルバーが濃い色になっているとき)、何かキーを押すとプログラムが終了します。

cv2.waitKey(0)はキーボードが押されるまで処理を待つ関数です。この関数がないと、プログラムが終了してしまうため、画像表示を見ることができません。
cv2.waiKeyは引数の数値だけ処理を待つという関数です。数値の単位はms(ミリセカンド)です。例えば cv2.waitKey(1000)であれば1秒待ちます。ただし、引数が0の場合は特別で、0秒待つという意味ではなく、キーボードが押されるまでずっと処理を待つという意味になります。

最後のcv2.destroyAllWindowsは、全てのウィンドウを閉じるという関数です。実はこの記述は無くても、プログラム終了と同時にウィンドウは閉じられますが、お掃除処理として念のために書いておきましょう。

画像サイズ変更

cv2.resizeを使うと画像サイズを変更できます。
第一引数に入力画像、第二引数に サイズ(width, height)を指定します。
以下のコードは、先程のコードに1行追加しただけです。実行すると画像ウィンドウが400×300のサイズに小さくなって表示されることが確認できます。

import cv2

image_file = 'cat.png'
img = cv2.imread(image_file)
img = cv2.resize(img, (400, 300))
cv2.imshow('image', img)

cv2.waitKey(0)
cv2.destroyAllWindows()

文字列描画

OpenCVでは、画像を表示しているウィンドウに文字や図形を重ね合わせて描画することができます。cv2.putTextは文字列を描画する関数です。引数は以下が指定できます。

出力先画像, 文字列, 位置(X, Y), フォント, フォント倍率, 色(B, G, R), 線の太さ

※位置は、テキストの左下座標が基準

以下は、最初のサンプルコードにcv2.putTextを1行追加した例です。

import cv2

image_file = 'cat.png'
img = cv2.imread(image_file)
cv2.putText(img, "Please Don't Disturb.", (80, 530), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 8)
cv2.imshow('image', img)

cv2.waitKey(0)
cv2.destroyAllWindows()

なお、文字列に日本語を書くと文字化けします。こちらのページに対策があります。

図形描画

cv2.rectangleは長方形を描画する関数です。第1引数は出力先画像、第2引数以降は以下が指定できます。

左上の座標(X, Y), 右下の座標(X, Y), 色(B, G, R), 線の太さ

※線の太さを -1 にすると、長方形の中身が塗りつぶしになります

以下は、最初のサンプルコードにcv2.rectangletを1行追加した例です。

import cv2

image_file = 'cat.png'
img = cv2.imread(image_file)
cv2.rectangle(img, (360, 240), (550, 280), (20, 20, 20), -1)
cv2.imshow('image', img)

cv2.waitKey(0)
cv2.destroyAllWindows()

他にもcv2.lineで直線描画、cv2.circleで円描画、cv2.ellipseで楕円描画などありますので、色々調べてみて下さい。なお、サンプルソースは静止画の例でしたが、カメラ映像にも同様に表示させることができます。

カメラ映像の表示

今までは静止画でしたが、カメラ映像の動画を読み込んで表示します。
ラズパイにUSBカメラを接続してから、以下のコードを実行してみて下さいカメラ映像が動画としてリアルタイムに表示されます。

import cv2

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    cv2.imshow('image', frame)
    key = cv2.waitKey(1)
    if key != -1:
        break

cap.release()
cv2.destroyAllWindows()

上記のコードの解説です。

VideoCapture object取得

cv2.VideoCaptureは引数にデバイス番号を指定して"VideoCapture object"を取得する関数です。
ラズパイに接続されているカメラは1つだけなので、デバイス番号は 0 を指定します。ただし、プログラム終了後にデバイス番号が変わる場合があります。その場合は、抜き差し前後で以下のコマンドを実行することによりデバイス番号を確かめることもできます。

ls /dev/video*

# 実行結果例
# /dev/video0

While Trueによる無限ループ

OpenCVでカメラ映像を取得する手順は、動画として一括読み込み&表示ではなく、カメラ画像1フレーム毎の読み込みと表示を行う必要があります。1コマ読み込んで1コマ表示するということを繰り返すため、無限ループになっています。

画像の読み込みと表示

取得した"VideoCapture object" の cap を使って、cap.readとすることで、カメラからの静止画像を読み込みます。静止画像は2番目の戻り値 frame へ代入されます。1番目の戻り値 ret には正しく静止画像が読み込みできたか否かのブール値(True/False)が入ります。
画像を表示させる手順は画像ファイル表示のときと同じで、cv2.imshowを使います。

キー入力

無限ループのままだとプログラムが終了できないため、キーボード入力があったときに break させループから抜け出します。
今までの静止画像表示のときのように cv.waitKey(0)にしてしまうと、そこで止まって動画にならないため、引数を最小値の 1 に設定しています。当然数値を大きくするとカクカクした映像になります。 キーが押されていないときの cv.waitKeyの戻り値は -1 です。つまり -1 以外のときは、何らかのキーが押されたということになりますので、それを判別して break しています。

VideoCapture object解放

不要になった"VideoCapture object"は、最後にcap.releaseで解放します。

以上カメラ映像表示について説明しましたが、OpenCVによるカメラ映像の読み込みと表示に関しては、ほぼこのコードのまとまりをテンプレートとして使えます。

画像の保存

OpenCVではcv2.imwriteを使うことにより簡単に画像の保存ができます。第一引数に保存ファイル名、第二引数に読み込んだ画像等の変数(今までの例だと imgframe)を指定します。

import cv2

image_file = 'cat.png'
img = cv2.imread(image_file)
cv2.putText(img, "Please Don't Disturb.", (80, 530), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 8)
cv2.imwrite('cat2.png' ,img)

実行するとcat1.pngに文字列を描画したcat2.pngが出来ます。

このように画像に処理を実施(今回の例だと文字描画や図形描画)した後や、カメラ映像の1フレームなどを保存するときに使用します。

以上、「OpenCVで画像・カメラ表示、文字・図形描画」でした!