【Python入門】機械学習の前処理(画像処理のやり方)

To pile images numpy

機械学習、特に深層学習で画像分類や物体検出をするには、画像処理にPythonのライブラリを利用します。
numpy配列を利用することで、画像をただの数字の羅列として扱うことができます。

ビットマップ画像とは

コンピュータ上で扱う画像には2種類ありますが、一般的な拡張子(jpg、png、gif、bmp)の画像ファイルのものは、ビットマップ画像といいます。
画像を画素(ピクセル)を使って表現したもので、格子状に画素を並べた配列情報として扱うことができます。

3行×3列で、9ピクセルの画像を見てみましょう。

画像を画素(ピクセル)を使って表現したもので、格子状に画素を並べた配列情報として扱うことができます。

3行×3列で、9ピクセルの画像を見てみましょう。

3×3
図1: 9ピクセルの画像

この9ピクセルの画像は、 3行×3列のnumpy配列 で作られており、0が黒、1が白を表現しています。

np.array([[1, 0, 1],
          [0, 1, 0],
          [1, 0, 1]]

画像の種類

画像は使っている色・濃度の違いで、配列情報の取り扱いが変わります。

種類次元諧調
バイナリー画像縦×横2諧調(2bit)
グレースケール画像縦×横256諧調(8bit)
カラー画像縦×横×RGB256諧調(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)
図2: 9ピクセルの画像(白黒が反転)

白と黒が反転しています。

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]]) 
図3: 9ピクセルの画像(書き換え後)

配列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) 
3×3
図4: 9ピクセルの画像(256諧調)

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) 
図5: 9ピクセルの画像(黒から白へ)

カラー画像

カラー画像は、各ピクセルが[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)
3×3
図5: 9ピクセルの画像(RGBカラーで白黒)

代表的な色を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)
図6: 9ピクセルの画像(RGBカラー)

画像サイズ

カラー画像は、行(高さ)×列(幅)×色(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])
図7: 9ピクセルの画像(1枚目と2枚目)

データの正規化

機械学習では、データを最小値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で自作してみることが近道になるのではないでしょうか。

関連情報

タイトルとURLをコピーしました