MATLAB,Python,Scilab,Julia比較 第3章 その33【微分フィルタ⑨】

MATLAB,Python,Scilab,Julia比較 第3章 その33【微分フィルタ⑨】 数値計算
MATLAB,Python,Scilab,Julia比較 第3章 その33【微分フィルタ⑨】

バックナンバーはこちら。
https://www.simulationroom999.com/blog/compare-matlabpythonscilabjulia3-backnumber/

はじめに

Sobelフィルタの実験。
今回はPython(NumPy)で実施。

登場人物

博識フクロウのフクさん

指差しフクロウ

イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1

エンジニア歴8年の太郎くん

技術者太郎

イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1

Sobelフィルタ【再掲】

太郎くん
太郎くん

まずは、Sobelフィルタと実験手順を再掲。

Sobelフィルタ

\(
K_{sbl}=
\begin{bmatrix}
1 \\
2 \\
1 \\
\end{bmatrix}
\begin{bmatrix}
-1 & 0 & 1
\end{bmatrix}=
\begin{bmatrix}
-1 & 0 & 1 \\
-2 & 0 & 2 \\
-1 & 0 & 1 \\
\end{bmatrix}
\)

実験手順

  • 画像の読み込み
  • ガウシアンフィルタ用のカーネル用意
  • Sobelフィルタ用のカーネル用意
  • SDTVグレースケール化実施
  • ガウシアンフィルタ実施
  • Sobelフィルタ実施
  • 各Sobelフィルタの結果の合成
  • 画像の書き出し
フクさん
フクさん

これをPython(NumPy)で実現する。

Pythonコード

フクさん
フクさん

Pythonコードはこうなる。

import numpy as np
import cv2

# 畳み込み演算
def convolution2d(img, kernel):
    m, n = kernel.shape # カーネルサイズ取得

    # カーネル中心からみた幅
    dy = int((m-1)/2)  # カーネル上下幅
    dx = int((n-1)/2)  # カーネル左右幅
    
    h, w = img.shape   # イメージサイズ
    out = np.zeros((h, w)) # 出力用イメージ

    # 畳み込み
    for y in range(dy, h - dy):
        for x in range(dx, w - dx):
            out[y][x] = np.sum(img[y-dy:y+dy+1, x-dx:x+dx+1]*kernel)

    return out

def sobel_test():
    # 入力画像の読み込み
    img = cv2.imread("dog.jpg")
    b = img[:,:,0]
    g = img[:,:,1]
    r = img[:,:,2]
    
    # ガウシアンフィルタ用のkernel
    kernel_gauss = np.array([[1/16, 2/16, 1/16],
                             [2/16, 4/16, 2/16],
                             [1/16, 2/16, 1/16]])
    # Sobelフィルタ用のKernel
    kernel_sx = np.array([[-1,  0,  1],
                          [-2,  0,  2],
                          [-1,  0,  1]])
    kernel_sy = kernel_sx.T
    
    # SDTVグレースケール
    gray_sdtv = np.array(0.2990 * r + 0.5870 * g + 0.1140 * b, dtype='uint8')
    
    # ガウシアンフィルタ
    img_g = convolution2d(gray_sdtv, kernel_gauss)
    
    # Sobelフィルタ
    img_sx = convolution2d(img_g, kernel_sx)
    img_sy = convolution2d(img_g, kernel_sy)
    cv2.imwrite("dog_sx.jpg",np.abs(img_sx))
    cv2.imwrite("dog_sy.jpg",np.abs(img_sy))
    
    # 合成
    img_s = np.sqrt( img_sx**2 + img_sy**2 )
    cv2.imwrite("dog_s.jpg",img_s)
    
    return

sobel_test()

処理結果

フクさん
フクさん

処理結果は以下。

Sobleフィルタ(Python)

考察

太郎くん
太郎くん

結果はMATLABと一緒だね。

フクさん
フクさん

特筆するほどの話もほぼ無いな。
油断するとnp.arrayがuint8じゃなくてdoubleになったりするから、
そこらへんが注意点だが、これはSobelフィルタに限った話ではない。

太郎くん
太郎くん

そうか。
imwriteする段階で、uint8になってないとまずいのか。

まとめ

フクさん
フクさん

まとめだよ。

  • Python(NumPy)でSobelフィルタを実施。
    • MATLABと同じ結果が得られた。
  • np.arrayがuint8になっている状態を維持する必要がある。
    • imwrite時にuint8になっていないと期待した出力にならない。

バックナンバーはこちら。

コメント

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