横浜国立大学理工学部建築都市環境系学科卒
一級鉄筋技能士
機械学習を学んでいるとDeepLearningを使った画像のAIをよく見かけると思います。
この記事では、画像のデータや画像処理について解説していきます。
目次
画像データの仕組みとは?
デジカメ、スマフォと今では大量の画像が毎日撮られています。
この画像データがどういったデータの集まりかご存知でしょうか?
画像は画素(ピクセル)の集まり
下記の猫の画像を拡大するとどのように見えるでしょう?
目の周りの赤枠の箇所を拡大してみましょう。
色のついた四角が見えますね。この□一つ一つを「画素」「ピクセル」と言います。
画像が滑らかに見えるのは、ピクセルの数が多いからです。
画像は高さ、幅があるデータである
画像は幅、奥行き、RGBの3チャンネル、の立方体のデータ構造
画像が幅と高さのデータを持っていることが分かりましたが、各ピクセルの色はどのように表されるのでしょうか?
色は3元色の赤、緑、青のRGB(Red Green Blue)で表されます。
なので、1つのピクセルに3つのデータ(3チャンネル)必要ということになります。
RGBそれぞれ0-255の値で表現されます。
0なら色はつかず、255なら色がつきます。
R:G:B=0:0:0は黒色ですし、R:G:B=255:255:255は白色になります。
画像は高さ、幅、奥行き3チャンネル、の立方体のデータになる
画像処理について
画像は高さ、幅、3chの0-255のデータを持っていることがわかりました。
このデータを処理して、色々なエフェクトで画像を変換したり、顔や目鼻口の位置を取得したりすることを画像処理と言います。
スマフォで色々な盛れる顔に変換できるのも画像処理の組み合わせがなせる技です。
画像処理で一般的に使われるライブラリはOpenCV
画像処理で一般的に使われるライブラリはOpenCVというライブラリです。
インストールは下記でできます。
1 |
pip install opencv-python |
下記の画像を読み込んでみます。
画像処理でよく使われるlenaさんです。
imreadメソッドで、lena.pngファイルを読み込んで、shapeでデータの形を確認します。
imreadメソッドとは、ローカルの画像ファイルをPythonファイルから読み込む際に用いるメソッドです。
1 2 3 |
import cv2 img = cv2.imread('lena.png') img.shape |
1 |
(512, 512, 3) |
高さ:幅:奥行き=512:512:3
なのがわかります。
次に、一番左上の座標のRGBの値を確認してみましょう。
高さ=0、幅=0の座標のデータを見ます。左上が必ず(0, 0)になります。
1 |
img[0,0] |
1 |
array([121, 133, 222], dtype=uint8) |
R:G:B = 121:133:222であることがわかります。
次に画像を表示してみましょう。
1 2 |
import matplotlib.pyplot as plt plt.imshow(img) |
色がおかしなことになっています。
これはOpneCVはRGBではなく、BGRの順に読み込むためです。
下記コードで、RGBに修正できます。
1 2 |
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img_rgb) |
色が元の画像と同じもので表示されたはずです。
色々な画像処理 モノクロ、平均化、エッジ検出
画像が読み込めたので、色々画像処理をかけてみましょう。
モノクロ
まず、モノクロ画像に変換します。
1 2 3 4 5 6 |
# BGR を GRAYに変換 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # img_grayのデータの形確認 print(img_gray.shape) # cmap="gray"でグレーで表示 plt.imshow(img_gray, cmap = "gray") |
モノクロに変わりました。
合わせて、img_grayのデータの形を確認していますが、3次元目がなくなり、2次元データになっています。
これは、モノクロデータには色データがいらないので、0-255の黒か白で表されるからです。
平均化
次は平均化という処理で、平均化フィルタとも呼ばれます。
他にも中央値のメジアンフィルタなどもあります。
初めての方はどういう風に画像が変わるかわからないかもしれませんが、少しボヤッとした画像になります。
1 2 3 |
# 7, 7 マトリックスで平均化 img_rgb = cv2.blur(img_rgb,(7,7)) plt.imshow(img_rgb) |
これはボヤッとした画像を作りたいのではなく、画像のノイズをこれで取り除くことができます。
blurメソッドには(7, 7)を渡していますが、これは7×7の箱を平均化処理に使うという意味です。
エッジ検出
次は、画像のエッジを検出します。
エッジ検出にはCanny法と呼ばれる方法を使ってみます。
1 2 |
img_edges = cv2.Canny(img_rgb,50,100) plt.imshow(img_edges, cmap='gray') |
CannyメソッドのminVal: 50やmaxVal :100でエッジの検出加減を調整しています。
詳しくは下記ドキュメント参考ください。
フィルタ処理
OpenCVでは簡単に色々な画像処理を試すことができました。
DeepLearningで使うのはフィルタ処理なので、フィルタ処理について詳しくみていきましょう。
フィルタは単純に3×3や5×5の箱を動かしながら、計算をしています。
今回は平均化フィルタの処理を実装していきましょう。
フィルタ処理の計算方法
計算には、フィルタと画像が必要になります。
右の画像の数値はimg_grayデータから参考として引っ張ってきました。
1 |
img_gray[100:107,100:107] |
計算は、以下の手順です。
- 3×3のフィルタと画像の左上(赤枠箇所)の3×3部分を掛け算して、平均
- 平均した値は新しい画像として保持
- フィルタを1つずらす
上記をひたすら、繰り返して、平均化画像を作ります。
参考までに、左上の計算は、99 = (98*1 + 98*1 + 98*1 + 107*1 + 98*1 + 98*1 + 94*1 + 94*1 + 102*1)/9になります。
フィルタの1の値を部分的に0や0.5などにしたり、平均ではなく最大値、最小値、中央値などを取ることでフィルタ処理される結果が変わります。
また、上記例では1つずつフィルタをずらして計算しますが、DeepLearningでは2つずつずらす場合もあります。
実装
3×3のフィルタを、先ほどモノクロに変換したimg_grayを対象に実装してみましょう。
まず、平均化した画像の配列とフィルタを定義します。
1 2 3 4 5 |
import numpy as np # 新しい画像の配列 全て0の値 img_new = np.zeros([img_gray.shape[0]-2, img_gray.shape[1]-2]) # フィルタ 全て1の値 img_filter = np.ones([3, 3]) |
後は、先ほどの手順通りに実装していきましょう。
xとyの座標をずらしながら、平均を算出しています。
1 2 3 4 5 6 7 8 9 10 11 |
# 座標を1つずつずらしながら、平均値を算出 for x in range(1,img_gray.shape[1]-1): for y in range(1,img_gray.shape[0]-1): # 画像をフィルタサイズで取得 img_temp = img_gray[y-1:y+2, x-1:x+2] # フィルタ*画像の合計値 sum_val = np.sum(img_filter * img_temp) # 平均 avg_val = sum_val / (img_filter.shape[1]*img_filter.shape[0]) # 新しい画像に値を入れる img_new[y-1, x-1] = avg_val |
できた画像を確認します。
1 2 |
print(img_new.shape) plt.imshow(img_new, cmap='gray') |
パッと見分からないですが、計算されています。フィルタサイズを変更して色々試してみてください。
img_newは512×512から510×510になりますが、これは、フィルタサイズによって、画像の端を計算していないためです。
計算する方法場合は、ダミーの値を入れて計算します。
まとめ
画像のフィルタ処理について理解できたでしょうか?
この計算はDeepLearningでも使われますので、しっかり理解しておきましょう。