PythonでOpenCVとPillowを使って画像を読み込む方法

画像ファイルの読み込み
大きく2つの方法があります。
ひとつは OpenCV を使う方法。もうひとつは Pillow を使う方法です。
順に説明して行きます。
OpenCVを使う場合
OpenCV で画像を読み込むには cv2. imread() を使います。
読み込んだ画像データは ndarray(N-dimensional array の略)型になります。
ndarray 型のデータなら NumPy を使うことができるので高速な画像処理が可能です。
ちなみに、画像処理(image processing)とは、与えられた画像に対して、色や明るさを変えたり、回転、拡大、縮小などの何らかの処理を行って、入力した画像とは異なる画像を出力することです。
例を示します。
まずはソースコードを見てください。
import cv2
img_1 = cv2.imread('./test_photo/hana/001_800px.jpg')
cv2.imshow('img_1', img_1)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imread() で 「001_800px.jpg」という画像ファイルを読み込みます。
その後、cv2.imshow()で画像を出力します。
なお、cv2.waitKey(0) を書かないと画像が一瞬だけ表示されてすぐに消えてしまいます。
出力される画像は例えばこんな感じです。

このとき、img_1 は ndarray 型になっています。
データ型を確認するには以下のように書きます。
import cv2
img_1 = cv2.imread('./test_photo/hana/001_800px.jpg')
print(type(img_1))
実行すると以下が表示されます。
<class 'numpy.ndarray’>
つまり、img_1 は、ndarray 型 になっていることが分かります。
Pillowを使う場合
Pillowで画像を読み込む場合には、Image.open() を使います。
読み込んだ画像データは JpegImageFile というイメージファイルで ndarray 型ではありません。
画像をPillowで読み込んで NumPy で画像処理したいなら ndarray 型に変換する必要があります。
変換は以下のように行います。
from PIL import Image
import numpy as np
img_2 = Image.open('./test_photo/hana/001_800px.jpg')
img_3 = np.asarray(img_2) # 入力画像をndarray型に変換する
cv2.imshow('img_3', img_3)
cv2.waitKey(0)
cv2.destroyAllWindows()
実行すると以下の画像が出力されます。

色が変ですね。
実は、Pillow で読み込んだ画像ファイルの色順番は「RGB」ですが、cv2.imshow() を使って出力すると「BGR」の色順番で出力されます。
このため、青ざめた画像になっています。
色順番を「RGB」のまま出力する方法を紹介します。
色順番を「RGB」のまま出力する方法:その1
from PIL import Image
import numpy as np
img_2 = Image.open('./test_photo/hana/001_800px.jpg')
img_3 = np.asarray(img_2) # 入力画像をndarray型に変換する
img_4 = cv2.cvtColor(img_3, cv2.COLOR_RGB2BGR) # 色をRGBからBGRに変換
cv2.imshow('img_4', img_4)
cv2.waitKey(0)
cv2.destroyAllWindows()
入力画像を ndarray 型に変換した後、cv2.cvtColor() 関数の第二引数(カッコ内で2番目に記載されているもの)を 「cv2.COLOR_RGB2BGR」として色順番を 「RGB」から「BGR」に変換するやり方です。
実行すると以下になります。

色が正常になりました。
色順番を「RGB」のまま出力する方法:その2
from PIL import Image
import numpy as np
img_2 = Image.open('./test_photo/hana/001_800px.jpg')
img_3 = np.asarray(img_2) # 入力画像をndarray型に変換する
img_4 = img_3[:,:,::-1] # 色順番をRGBからBGRに変換する
cv2.imshow('img_4', img_4)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_3 で ndarray 型に変換されているので NumPy が使えます。
img_3の色順番を入れ替える操作を行えばよいので img_4 のように書きます。
これはスライシングという小技です。
[:, :, ::-1] の意味は、[H, W, C](高さ, 幅, チャンネル(RGB))に対して 、高さ方向の全範囲 [:] と幅方向の全範囲 [:] のピクセルに対して、チャンネル(RGB)を逆に(:-1)して(BGR)にしなさいという指示です。
「:」は全範囲を意味し、「:-1」は逆にするを意味します。
簡単な例で言うと、a[:] は a の全範囲、a[::-1] は a の全範囲を逆順にする、という意味です。
上記プログラムを実行すると以下の画像が表示されます。

NumPy の威力。すばらしい。
色順番を「RGB」のまま出力する方法:その3
from PIL import Image
from matplotlib import pyplot as plt
img_2 = Image.open('./test_photo/hana/001_800px.jpg')
plt.imshow(img_2)
plt.show()
matplotlib を使う方法です。
これはグラフを可視化する際によく使われるモジュールです。
matplotlib は、Python上で使われているMATLAB(数値解析ソフトウェア)が持つグラフ描画機能をNumPyに持たせることを目的として作られています。
この方法では、画像を ndarray 型にしなくとも良いし、色順番も「RGB」のままでOKです。
実行すると以下になります。

いままでの画像との違いは目盛りが付いていることです。
先ほども言ったように、グラフを描画する機能を使っているので、単純に実行するとこうなります。
もし目盛りがいらないなら以下のように書きます。
from PIL import Image
from matplotlib import pyplot as plt
img_2 = Image.open('./test_photo/hana/001_800px.jpg')
plt.axis('off')
plt.imshow(img_2)
plt.show()
plt.axis('off’) と書くと目盛りが表示されなくなります。
実行すると以下になります。

目盛りが消えましたね。
ただし、matplotlib を使って画像表示すると画像の周りに余白が付きます。
余白を小さくする方法もありますが、今日はこの辺にしておきます。
最後に、じゃあ実際どの方法が一番良いの?と思うかもしれません。
これはケースバイケースです。
どんなタスクに使うかによって方法も変わってきます。
みなさんの一番使いやすい方法で使っていただければと思います。
ディスカッション
コメント一覧
まだ、コメントがありません