OpenCV 画像の畳み込み演算(動画あり)

AI
OpenCV 畳み込み

画像のある場所からエッジやコーナなどを抽出するには、空間フィルタリングを行います。
空間フィルタリングとは、ある特定の画素とその周辺の画素の値から、何らかの計算を行って出力する処理のことです。
空間フィルタリングのことをフィルタと呼ぶ場合も多いです。

スポンサーリンク

畳み込みについて

空間フィルタリングを数式で計算する方法として、畳み込み(convolution)があります。
畳み込みの手法はディープニューラルネットワークでもCNNの技術として活用される重要な考え方です。
今回は畳み込みの考え方と計算方法を学習します。

畳み込み演算の方法

畳みこみ演算を行うには、まずカーネル(フィルタ)を用意します。
例えば3行3列の行列を用意して、その値には目的に応じた値を設定します。

画像全体を平滑化したい場合は、3行3列の行列の要素は全て1/9にします。
このフィルタを画像のある部分に対応させて、画像が本来持っている値とフィルタの値を行列積で計算します。

得られた値は3行3列の行列の中央部分の値にします。
そのことで画像の平滑化が行われます。

具体的には上図右側のグリッド内の赤い部分の値は、 I(x, y) = a*r + b*s + c*t + d*u + e*v + f*w + g*x + h*y + i*z となります。
このように画像に対してカーネルを対応させて行列積を求めることで、カーネルの値に従ったフィルタがかかる仕組みです。

畳み込み演算をPythonで確認

畳み込み演算をPython で確認します。
まずは、平滑化を行うカーネルを水平方向のもを作成し、x軸方向だけ画素がある状態つまり、一本線を描いて畳み込み演算を行います。

x軸方向の画素をNampy配列で用意して、[0.3, 0.3, 0.3]のカーネルを適用した例

X = np.array([[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]],dtype=float)
print(X.shape)

plt.figure(figsize=(10, 5), dpi=72)
plt.subplot(1,2,1); plt.imshow(X, cmap='gray')
plt.show()

# カーネル
W1 = np.array([[0.3, 0.3, 0.3]])

# 畳み込み
C1 = np.copy(X)
for i in range(3,13,1):
  C1[0,i-2] = np.dot(X[0,i-3:i],W1[0,:])

plt.figure(figsize=(10, 5), dpi=72)
plt.subplot(1,2,2); plt.imshow(C1, cmap='gray')
plt.show()
print(C1)

結果
最初の画像は画素値が0は黒、画素値1は白で描かれた線です。

次に、カーネルを適用した方は黒からグレーそして白その後グレーになった後黒となだらかになりました。

それぞれの画素とカーネルの計算は次の図のようになります。

OpenCvの関数を使った畳み込み演算

今度は写真にカーネル(フィルタ)をかけて平滑化します。
写真の表示はcolaboratory対応のため、matplotlibを使った表示です。

OpenCVでは、画像とカーネルの畳み込みの計算は filter2D 関数を使います。

filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
src:画像データ
ddepth:出力画像のbit深度。負の値を入力することで、入力画像と同じものを指定できる
kernel:フィルター

*bit深度:ビット深度とは色数のことです。例えば、1ビットだと0,1の2種類の値を表せるので2色表現できます。8ビットだと0〜255で256色の表現ができます。

畳み込み演算で平滑化する例

img_bgr =cv2.imread('mika2.jpg',0)

kernel = np.ones((3,3)) / 9.0
img_kel = cv2.filter2D(img,-1,kernel)

plt.figure(figsize=(12, 12), dpi=72)
plt.subplot(1,2,1);plt.imshow(img);plt.title('Normal')
plt.subplot(1,2,2);plt.imshow(img_kel);plt.title('Smoothing')
plt.show()

結果

カーネルの値を変更すると様々なフィルタをかけることができます。
フィルタはOpenCVでは便利な関数が複数用意してあります。(別途紹介予定)

訂正:動画では写真をグレースケールで読み込んだ後に、RGB変換していますが、その際のコードのBGR2RGBをGRAY2RGBに訂正する必要があります。この処理は必ず必要なものではありません。グレースケールのままフィルタを使用することができます。

img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # 訂正前
img = cv2.cvtColor(img_bgr, cv2.COLOR_GRAY2RGB)  # 訂正後

尚、ここで紹介するコードとダウンロード用のサンプルはカラーの状態でフィルタをかけたものにしています。

参考になった書籍

OpenCVというよりも、画像認識の理論面が幅広く数式を使って説明されています。画像分析を自分のものにしたい場合に最適です。

Pythonサンプルのダウンロード

ここでダウンロードする「oencv_conv1.ipynb」ファイルは、このPython動画で使用したものです。
動画では写真をグレースケールで読み込みましたが、このサンプルはカラー(RGB)で変換したものを使用しています。

oencv_conv1.ipynb

OpenCV動画一覧

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