画像のある場所からエッジやコーナなどを抽出するには、空間フィルタリングを行います。
空間フィルタリングとは、ある特定の画素とその周辺の画素の値から、何らかの計算を行って出力する処理のことです。
空間フィルタリングのことをフィルタと呼ぶ場合も多いです。
畳み込みについて
空間フィルタリングを数式で計算する方法として、畳み込み(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 関数を使います。
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)で変換したものを使用しています。
コメントを投稿するにはログインしてください。