【OpenCV×Python】
画像の読み書きと加工 操作まとめ

記事イメージ


(最終更新日:

OpenCVは非常に多様な機能を備えるライブラリです。

本記事では、その中でも機械学習モデル開発などで役に立つ、Pythonによる基礎的な操作を紹介します。

OpenCVとは?

OpenCV(Open Source Computer Vision Library)はインテルにより開発されたオープンソースライブラリです。

画像処理に関する加工から始まり、図形、物体、エッジ検出等の様々な機能が織り込まれており、C++、Java、Pythonなど様々なプラットフォームでAPIが提供されています。

ライセンス

BSDライセンスが適用されます。BSDは、非コピーレフトかつ一定の条件(著作権表示等)の下で商用利用も可能なライセンスです。

参考:opencv/LICENSE(外部リンク)

実行環境へのインストール

通常環境


$ pip install opencv-python

conda環境の場合


$ conda install -c conda-forge opencv

importの指定

Python
import cv2

画像を開く~色彩変換~保存まで

ファイルを開いてnumpy.ndarray型(3次元配列)で取得

opencvでは、画像データはNumpy配列で取り扱いします。

Python
img = cv2.imread('/home/test.jpg')

3px四方に1行1pxずつ赤(R255 G0 B0)・緑(R0 G255 B0)・青(R0 G0 B255)のラインを配置した画像をペイントツールで作成。どのような配列になるか実験してみます。

テスト用の画像を作成。赤緑青を1行ずつ配置しています。3px四方。
テスト用の画像を作成

実際に読み込んでみると、結果は次の通りです。

横・縦・画素の3要素が1pxずつ3次元配列として表現されます。画素順番はBGRになっていることが分かります。

Python
#読み込み
img = cv2.imread('/home/rgb-test.png')
print(img)

#出力結果。BGRの順で1画素ずつ配列として並んでいます。
[[[  0   0 255], [  0   0 255], [  0   0 255]],
 [[  0 255   0], [  0 255   0], [  0 255   0]],
 [[255   0   0], [255   0   0], [255   0   0]]]

開いた画像の変換(グレースケール化、BGR→RGB等)

引き続き↑の3px四方のテスト画像(1行ずつ赤・緑・青を配置)を使用して、変換結果を見ていきます。

変換にはcv2.cvtColorを使用します。第1引数に画像配列、第2引数に変換コードを入れて実行します。

まず、グレースケール変換を行ってみます。カラー読み込みが3次元配列だったのが、2次元配列に変換されます。色情報が消失し、明るさのみの情報となっていることが分かります。

Python
#グレースケールに変換
img = cv2.imread('/home/rgb-test.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(img)

#出力結果
#色情報が消失し、明るさのみの情報(3次元配列→2次元配列)となりました。
[[ 76  76  76]
 [150 150 150]
 [ 29  29  29]]

続いて画素をBGR→RGBに変換します。

OpenCVはBGRがデフォルトですが、他のライブラリはRGBとなっている場合が多いので、組み合わせて使う場合は基本的に変換して使用することになります。

Python
#グレースケールに変換
img = cv2.imread('/home/rgb-test.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print(img)

#出力結果
[[[255   0   0], [255   0   0], [255   0   0]],
 [[  0 255   0], [  0 255   0], [  0 255   0]],
 [[  0   0 255], [  0   0 255], [  0   0 255]]]

その他、cv2.cvtColorの第2引数のコードは多数用意されています。公式ドキュメントをご参照ください。

画像配列を画像ファイルとして保存

cv2.imwrite関数を使用します。BGR形式で保存されるので、RGB配列を保存する場合は事前に変換する必要があります。

尚、戻り値は保存の成否がBool値で返されます。

Python
#保存処理
result = cv2.imwrite('/home/rgb-test-new.png', img)
print(result)

#出力結果。保存成否がBool値で返される。
True

読み込んだ画像を表示する

ウィンドウで画像を表示

ローカル実行環境でウィンドウで画像を表示します。(Google Colaboratoryではこの表示方法は使えません。次のセクションで代替法を解説します。)

Python
cv2.imshow('window-name', img)

表示結果。ウィンドウで開きます。
表示結果

実行環境によっては、cv2.imshowでウィンドウが開いた後フリーズする場合があります。(Windowsなら「応答なし」となりますが、Macでも同様の現象が出ます)

この場合、次のコードのようにcv2.waitKey()を追加で実行することで解決します。画像表示中、キーの応答待ちとするコードです。

Python
cv2.imshow('window-name', img)
cv2.waitKey()

cv2.waitKey関数の有無で表示ができるかどうかが異なった結果。
cv2.waitKey関数の有無で表示ができるかどうかが異なった結果

Google Colaboratoryで画像を表示

Google Colaboratoryでは、imshow関数は使用できません。

代わりに標準出力に画像を表示するcv2_imshow関数を使用することができます。

Python
import cv2
from google.colab.patches import cv2_imshow
img = cv2.imread('2.png')
cv2_imshow(img)

cv2_imshow関数による表示結果。(Google Colaboratoryにて実行)
cv2_imshow関数による表示結果

複数の画像を同時に表示

cv2.hconcat(平行方向に画像を結合)またはcv2.vconcat(垂直方向に画像を結合)で画像を結合することで、複数の画像を同時に表示できます。

Python
import cv2
from google.colab.patches import cv2_imshow
img = cv2.imread('2.png')
img = cv2.hconcat([img, img, img])
cv2_imshow(img)

hconcatで複数画像を水平方向に結合することで、同時表示を実現する。
hconcatで複数画像を水平方向に結合することで、同時表示を実現する

画像の加工(リサイズ、トリミング、回転)

img変数はcv2.imread関数で読み込んだNumpy配列です。

画像のリサイズ

Python
#第2引数にリサイズ後のpxを指定
img = cv2.resize(img, (width, height))

画像のトリミング

Python
#順番に、起点y座標、終点y座標、起点x座標、終点x座標
img = img[y_from:y_to, x_from:x_to]

画像の向きと座標の関係、トリミング処理結果イメージ
画像の向きと座標の関係、トリミング処理結果イメージ

画像を90度・180度回転

cv2.rotate関数を使用します。90度・180度以外の任意の角度の回転については、次のセクションに掲載しています。

Python
#時計回りに90度回転
img = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
#半時計回りに90度回転
img = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
#半時計回りに90度回転
img = cv2.rotate(img, cv2.ROTATE_180)

cv2.rotateの第2引数別の実行結果
cv2.rotateの第2引数別の実行結果

画像を任意の角度で回転

OpenCVに組み込まれているアフィン変換(行列計算に基づく座標変換)の計算ロジックを利用します。

Python
#変換行列を生成。引数は順にcenter(中心座標)、degree(回転角度0~360度)、scale(拡大比率)
matrix = cv2.getRotationMatrix2D((0, 0), 30, 1)

#変換実行。引数は順にsrc(画像配列)、M(変換行列)、dsize(出力画像width,height)、flags(補間方法)
img = cv2.warpAffine(img, matrix, (380, 380), cv2.INTER_LINEAR)

#尚、第4引数の補完方法の候補は次の通り。リサイズの仕上がりの質感に差が出る。
#デフォルトはcv2.INTER_LINEAR。まずデフォルトで試し、画像の性質によってチョイスすればよい。
cv2.INTER_NEAREST #最近傍内挿
cv2.INTER_LINEAR #線型内挿
cv2.INTER_CUBIC #3次畳み込み内挿
cv2.INTER_AREA #ピクセル領域の関係を用いたリサンプリング処理
cv2.INTER_LANCZOS4 #Lanczos内挿

上記コードの変換結果。(x, y)=(0, 0)=画像の左上を中心に、30度回転させた。
上記コードの変換結果

記事筆者へのお問い合わせ、仕事のご依頼

当社では、IT活用をはじめ、業務効率化やM&A、管理会計など幅広い分野でコンサルティング事業・IT開発事業を行っております。

この記事をご覧になり、もし相談してみたい点などがあれば、ぜひ問い合わせフォームまでご連絡ください。

皆様のご投稿をお待ちしております。

記事筆者へ問い合わせする

※ご相談は無料でお受けいたします。
IT活用経営を実現する - 堺財経電算合同会社