機械学習、特に深層学習で画像分類や物体検出をするには、画像処理にPythonのライブラリを利用します。
numpy配列を利用することで、画像をただの数字の羅列として扱うことができます。
ビットマップ画像とは
コンピュータ上で扱う画像には2種類ありますが、一般的な拡張子(jpg、png、gif、bmp)の画像ファイルのものは、ビットマップ画像といいます。
画像を画素(ピクセル)を使って表現したもので、格子状に画素を並べた配列情報として扱うことができます。
3行×3列で、9ピクセルの画像を見てみましょう。
画像を画素(ピクセル)を使って表現したもので、格子状に画素を並べた配列情報として扱うことができます。
3行×3列で、9ピクセルの画像を見てみましょう。
この9ピクセルの画像は、 3行×3列のnumpy配列 で作られており、0が黒、1が白を表現しています。
np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]]
画像の種類
画像は使っている色・濃度の違いで、配列情報の取り扱いが変わります。
種類 | 次元 | 諧調 |
バイナリー画像 | 縦×横 | 2諧調(2bit) |
グレースケール画像 | 縦×横 | 256諧調(8bit) |
カラー画像 | 縦×横×RGB | 256諧調(8bit×3) |
バイナリー(二値化)画像
バイナリー画像は、白と黒の2色のみで表現された画像です。
numpy配列では、0と1だけを使用します。
グレースケール画像
グレースケール画像は、白と黒の2色で表現された画像ですが、中間色の灰色を使うことができます。
numpy配列では、0から255まで値を使い、256色を表現できます。
カラー画像
カラー画像は、光の3原色(Red、Green、Blue)の色の強さを組み合わせて表現された画像です。
numpy配列では、Red、Green、Blueのそれぞれを0から255までの値を使いますので、縦と横の2次元と、RGBで3次元の配列になります。
numpy配列の使い方
3行×3列の画像を作ってみます。
使用するライブラリを読み込みます。
import numpy as np import matplotlib.pyplot as plt %matplotlib inline
バイナリー(二値化)画像
3行×3列のnumpy配列を作ります。
0が黒、1が白です。
masu = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]])
masuを画像として表示してみましょう。
plt.imshow(masu, cmap=plt.cm.binary)
白と黒が反転しています。
cmap=plt.cm.binaryは、0が白、1が黒と白黒が逆に割り当てられているためです。
plt.imshow(masu, cmap=plt.cm.binary_r)
cmap=plt.cm.binary _rとして、白黒を反転させて表示すると、図1のようになりました。
ピクセルを書き換えてみます。
masu[:, 0] = 1 # [すべての行, 0列]を1にする masu[:, 1] = 0 # [すべての行, 1列]を0にする masu[:, 2] = 1 # [すべての行, 2列]を1にする
masuは、次のようになりました。
array([[1, 0, 1], [1, 0, 1], [1, 0, 1]])
配列masuを書き換えることで、画像処理ができました。
グレースケール画像
グレースケール画像は、0が黒、255が白となります。
1から254までだんだんと薄くなる灰色を表現し、黒と白を加えて256諧調です。
図1を256諧調にして、3行×3列のnumpy配列を作ります。
masu = np.array([[255, 0, 255], [0, 255, 0], [255, 0, 255]]) plt.imshow(masu, cmap=plt.cm.gray)
cmap=plt.cm.grayは、0が黒、255が白に割り当てられています。
cmap=plt.cm.gray _rとすれば、白黒が反転します。
黒(0)から白(255)まで段階的に変化させてみます。
masu = np.array([[0, 28, 56], [84, 112, 140], [168, 196, 255]]) plt.imshow(masu, cmap=plt.cm.gray)
カラー画像
カラー画像は、各ピクセルが[R, G, B]の色情報をもっています。
・グレースケール – 黒(0)、白(255)
・カラー画像 – 黒([0, 0, 0])、白([255, 255, 255])
numpy配列では、カラー画像の各ピクセルは次のようになります。
masu = np.array([[[255, 255, 255], [0, 0, 0], [255, 255, 255]], [[0, 0, 0], [255, 255, 255], [0, 0, 0]], [[255, 255, 255], [0, 0, 0], [255, 255, 255]]]) plt.imshow(masu)
代表的な色をRGB値で見てみます。
色 | RGB値 |
白 | [255, 255, 255] |
黄色 | [255, 255, 0] |
赤 | [255, 0, 0] |
茶色 | [128, 0, 0] |
水色 | [0, 255, 255] |
青 | [0, 0, 255] |
黄緑 | [0, 255, 0] |
緑 | [0, 128, 0] |
黒 | [0, 0, 0] |
masu = np.array([[[255, 255, 255], [255, 255, 0], [255, 0, 0]], [[128, 0, 0], [0, 255, 255], [0, 0, 255]], [[0, 255, 0], [0, 128, 0], [0, 0, 0]]]) plt.imshow(masu)
画像サイズ
カラー画像は、行(高さ)×列(幅)×色(RGBなら3)の三次元配列です。
グレースケール画像は、 行(高さ)×列(幅)の二次元配列です。
masu.shape
(3, 3, 3)と返ってくれば、3行×3列×3色のカラー画像です。
(3, 3)と返ってくれば、、3行×3列のグレースケール画像です。
複数の画像を1つのデータにまとめる
機械学習で画像を学習させるときは、複数の画像をまとめて、1つのデータとして扱います。
図5と図6の画像を1つにまとめてみましょう。
masu = np.array([[[[255, 255, 255], [0, 0, 0], [255, 255, 255]], [[0, 0, 0], [255, 255, 255], [0, 0, 0]], [[255, 255, 255], [0, 0, 0], [255, 255, 255]]]]) masu = np.append(masu, np.array([[[[255, 255, 255], [255, 255, 0], [255, 0, 0]], [[128, 0, 0], [0, 255, 255], [0, 0, 255]], [[0, 255, 0], [0, 128, 0], [0, 0, 0]]]]), axis=0) masu.shape
(2, 3, 3, 3)と 返ってきたので、2枚×3行×3列×3色として、画像をまとめることができています。
注意する点は、1枚ごとの画像を区別するために、配列の[]が追加しています。
枚数×行(高さ)×列(幅)×色(RGB)の四次元配列です。
画像の表示は、枚数の配列を指定します。
masu[0]、masu[1]を指定して、並べて表示してみます。
# 1枚目 plt.subplot(1,2,1) plt.imshow(masu[0]) # 2枚目 plt.subplot(1,2,2) plt.imshow(masu[1])
データの正規化
機械学習では、データを最小値0、最大値1に変換する正規化という前処理をします。
Min-Max Normalizationなど正規化に使う関数が用意されていますが、画像を正規化するサンプルコードでは単に255で割るだけのケースがあります。
これは、X_trainに入っている画像のすべて値を255で割る処理です。
# サンプルコード # 特徴量の正規化 X_train = X_train / 255
同じように、2**8(2の8乗)-1 → 255 のケースもあります。
# サンプルコード # 特徴量の正規化 X_train = X_train / (2**8-1)
これは、画素が8bitだと、最小値0、最大値は2の8乗で256となることを利用した方法です。
衛星画像など、画素が10bitであると、2**10(2の10乗)-1なので、1023で割ります。
このように正規化した後のデータは画像として表示することができませんが、機械学習では扱いやすいデータとなっています。
畳み込み処理した後のデータを可視化したいときは、8bitの画像なら255を掛けると表示できるようになります。
まとめ
- 画像は3種類あることと、その特徴がわかりました
- 画像をnumpy配列として扱う方法がわかりました
- 機械学習で画像を扱うための、numpyの使い方がわかりました
numpyを利用して生データに直接アクセスすることで、画像処理で実際に行われる操作を見てきました。
OpenCVなど便利で多機能なライブラリがありますが、処理内容を理解するにはnumpyで自作してみることが近道になるのではないでしょうか。