画像ファイルとNumPyの配列(Array)との関係を使って画像処理にpillow(PIL)を使った操作は行いました。
Pythonのデータ分析ではNumPy、Pandas、Matplotlibなどのライブラリを使いますが、機械学習の中で画像認証と言ったものも扱われており、画像や動画の処理の扱い方を知っておきたいところです。
画像や動画の処理に特化した外部ライブラリにOpenCVというものあります。ここではPythonとOpenCVを使って基本的な画像処理を学んでいこうと思います。
OpenCVのインストール
MacにOpenCVをインストールしましょう。ここではAnacondaの環境なので、ターミナルからcondaコマンドでインストールします。
下記の記事でOpenCVのインストール方法をまとめています。
なお、OpenCVのインストールでは、かなり苦戦している人が多いようです。それぞれの環境の違いなども影響しているでしょう。私の環境も前のバージョンのanacondaでは何もせずに利用できたのですが、現在はまた新たに環境を整備しないといけません。ネットで検索して自分にあったインストール方法、エラーへの対処法を参考にする必要があるでしょう。
ちなみに、OpenCVのドキュメントはこちらになります。
では、画像処理を行っていきましょう。
Jupyter notebookで画像ファイルを開く
それではOpenCVを使って画像を読み込んでみましょう。pillow(PIL)を使った画像処理は既に行いましたが、同じ画像ファイルを利用して操作してみようと思います。
ライブラリのインポート
jupyter notebookを使って画像処理をする為に、ライブラリをインポートしましょう。
OpenCVをインポートするには、cv2と入力します。
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
合わせて、NumPy、Matplotlibもインポートします。
jupyter notebook上に画像を表示する為に%matplotlib inlineも記述しています。
imread()で画像を読み込む
画像を読み込むにはcv2.imread()を使います。
img = cv2.imread("./images/apples.jpg")
作業ディレクトリにimagesフォルダを作って、画像ファイルのapples.jpgを配置しています。パスを正しく指定してimread()に渡しています。
実行するとこうなります。
(縦長になってしまうので表示の途中で切っています)
画像データのそれぞれの位置のカラーデータが配列として表示されています。
plt.imshow()を使って画像を表示してみます。
plt.imshow(img)
読み込んだ画像データの配列のimgオブジェクトを渡しています。
なぜか青色っぽく画像が表示されてしまいました。
これはOpenCVのcv2.imread()で取得した画像のカラーデータはBGR(青、緑、赤)のデータ配列になっているのに対し、Matplotlibのplt.imshow()で呼び出す場合のカラーデータはRGB(赤、緑、青)のデータ配列として処理している為です。
これをきちんと色合いで表示するにはBGRをRGBに返還して処理する必要があります。
そのためにはcv2.cvtColor()を利用します。
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
cvtColor()にimgを、変換コードのcv2.COLOR_BGR2RGBを使って渡すことでBGRをRGBに返還しています。
表示するとこうなります。
通常のカラーで表示されました。
今度はグレースケールで画像を読み込んでみます。
cv2.imread()で画像を読み込む時に、第2引数にcv2.IMREAD_GRAYSCALEを渡すことでグレーで表示することができます。
img_gray = cv2.imread('./images/apples.jpg', cv2.IMREAD_GRAYSCALE)
plt.imshow(img_gray,cmap='gray')
BGRとRGBの違いからplt.imshow()で表示するとその影響がでるので、cmap=’gray’を指定して表示します。
このimread()の第2引数は1、0、-1の整数値でも指定できますが、次のフラグとそれぞれ対応しています。
- cv2.IMREAD_COLOR (カラー画像として読み込見ます。画像の透明度は無視され、これはデフォルト値として設定されています。)
- cv2.IMREAD_GRAYSCALE (グレースケール画像として読み込みます。)
- cv2.IMREAD_UNCHANGED (アルファチャンネルも含めた画像として読み込見ます。)
画像サイズの変換 – resize()
画像のサイズを変更してみましょう。
まず、画像の形状をshape()を使って調べてみます。
img_rgb.shape
1066行、1600列、つまりheightが1066px、widthが1600px、3カラーチャンネルの画像データになります。
指定のサイズに変換
画像のサイズを変換するにはcv2.resize()を使います。
img =cv2.resize(img_rgb, (1066,200))
plt.imshow(img)
画像ファイルデータを格納してimg_rgbオブジェクトをresize()に渡します。画像サイズをタプルで一緒に渡しています。ここではwidthが1066px、heihtが200pxです。
画像サイズが変換されているのがわかります。
指定の比率で画像サイズを変換
次は元の画像を指定の比率を指定してサイズを変えてみます。
w_ratio = 0.5
h_ratio = 0.5
img_new =cv2.resize(img_rgb, (0, 0), img,w_ratio,h_ratio)
plt.imshow(img_new)
画像の幅と高さをどちらも半分の0.5にします。resize()に元画像を渡し、基準の位置を画像の左上である(0, 0)に起き、比率を指定しています。
表示させてみます。
表示されている画像の目盛りを見ると、画像の大きさが半分になっているのがわかります。
画像の反転 – flip()
次は画像の反転をやってみましょう。
画像を反転させるにはcv2.flip()を使います。
x軸反転(上下反転)
画像を上下反転させるにはx軸で回転させたらいいですね。
img_new = cv2.flip(img_new, 0)
plt.imshow(img_new)
x軸で回転させるには、flip()に画像を渡して、0を指定します。
y軸反転(左右反転)
今度は、上下反転させた画像を左右で反転させてみます。
img_new = cv2.flip(img_new, 1)
plt.imshow(img_new)
左右を反転させるにはy軸で回転させます。flip()に画像を渡して、今度は1を指定します。
xy軸反転
今度は、画像を対角線を軸に反転させてみます。x軸、y軸それぞれ反転させることです。ここでは最初の画像の位置に戻ることになります。
img_new = cv2.flip(img_new, -1)
plt.imshow(img_new)
flip()に画像を渡して、今度は-1を指定します。
画像の保存 – imwrite()
操作した画像を新たに保存してみましょう。新しく画像ファイルに書き込むことになり、imwrite()を使います。
cv2.imwrite('./images/new_apples.jpg', img_new)
imwrite()に保存する場所のパスとファイル名を指定し、元の画像のオブジェクトを渡します。
Trueとかえっきたら画像の保存ができています。指定のパスのディレクトリに、新しく画像ファルができているはずです。ただ、この画像はRGB型ではなくBRG型のカラーで保存されることになるので注意です。そのまま開けば青系の画像になっています。
画像を表示するサイズを調整
resize()などは画像そのものの大きさを変更してしまう訳で、それを保存した場合も画像サイズは変わってしまいます。
そこで、表示のみの大きさを変更することができると便利です。
fig = plt.figure(figsize=(5, 3))
ax = fig.add_subplot(111)
ax.imshow(img_new)
figsizeに図の幅と高さをタプルで指定してfigure()に渡します。そこにadd_subplot()で表示する位置を指定します。(111)は1行1列の1番目という意味で、画像の左上の位置を示しています。(1,1,1)としても同じです。
画像の目盛りはそのままですが、表示が小さくなっているのがわかると思います。この表示の方法はMatplotlibの使い方を確認するといいでしょう。
ターミナルから画像ファイルを別windowで開く
これまでjupyter notebook上に画像を表示してきました。これをnotebook上にではなく別windowで開くこともできるのですが、Macでのjupyter notebook上では動画にエラーがでることが多いようです。具体的には表示した後にカーネルが止まるといった症状です。
ですので、ここではPythonスクリプトファイルにコードを書いて、ターミナルから実行して画像を別windowで開く操作をやってみましょう。
次のコードを試しにjupyter notebookで実行すると、画像を表示した後に止まってしまいます。
import cv2
img = cv2.imread('./images/apples.jpg')
cv2.imshow('APPLES', img)
cv2.waitKey()
imread()で画像を読み込み、imshow()でビューワーのタイトルにAPPLESと示して画像を別windowで表示します。
waitKey()でキー入力を待ち続けますが、何かキーを押すとwindowが閉じて終了します。
jupyter notebookでは止まってしまいますが、テキストエディタで記述してターミナルで実行すればキチンと動作します。
このコードを次のようにもう少し変更してみます。
import cv2
img = cv2.imread('./images/apples.jpg')
while True:
cv2.imshow('APPLES', img)
if cv2.waitKey(1) & 0xFF == 27:
break
cv2.destroyAllWindows()
先ほどのコードと違うところは、while文を使ってTrueの間に画像処理を行っているところです。ここで画像が別窓で開きます。
そしてwaitKey(1)で1ミリ秒待ち、かつEscキーを押したら終了するというif文を入れています。0xFF == 27 は64ビットのPCで[esc]キーを意味しています。[esc]キーを押せば画像表示が終了することになります。ちなみに、0xFF == ord(‘q’) とすると[q]キーを押せば終了するのでquitと意味でよく見られますね。(ASCII制御文字を参照してください)
最後のdestroyAllWindows()で全てのwindowを閉じます。
上記のPythonスクリプトをターミナルからpythonコマンドで実行すると、別窓で画像が表示されるはずです。
最後に
画像や動画の処理に特化した外部ライブラリにOpenCVというものあります。このライブラリをPythonにインポートして画像処理を行うことができます。
OpenCVのMacでの利用は、インストールで躓く人も多いようです。ネットなどで検索して対処法を見つける必要もあるでしょう。
通常、カラーコードはRGBで表されることが多いですが、OpenCVで画像を扱うとBGRで処理されるのでmatplotlibを使って表示をする時は注意が必要です。
jupyter notebookでは、画像表示を別windowで行うとカーネルが止まってしまうことがMacやLinuxなのでは起こることがあるので注意が必要です。その場合はPythonスクリプトのファイルとしてコードを用意し、ターミナルから実行することにしましょう。