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

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

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

はじめに

Sobelフィルタの実験。
今回はJuliaで実施。

登場人物

博識フクロウのフクさん

指差しフクロウ

イラスト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フィルタの結果の合成
  • 画像の書き出し
フクさん
フクさん

これをJuliaで実現する。

Juliaコード

フクさん
フクさん

Juliaコードはこうなる。

using Images

# 畳み込み演算
function convolution2d(img, kernel)
    (n, m) = size(kernel); # カーネルサイズ取得
    
    # カーネル中心からみた幅
    dy = Int64((n-1)/2);  # カーネル上下幅
    dx = Int64((m-1)/2);  # カーネル左右幅
    
    (h, w) = size(img);   # イメージサイズ
    out = zeros(h, w);    # 出力用イメージ
    
    # 畳み込み
    for y = dy+1:(h - dy)
        for x = dx+1:(w-dx)
            out[y, x] = sum( img[y-dy:y+dy, x-dx:x+dx].*kernel );
        end
    end
    return out;
end

function sobel_test()
    # 入力画像の読み込み
    img = channelview(load("dog.jpg"));
    r = img[1,:,:];
    g = img[2,:,:];
    b = img[3,:,:];
    
    # ガウシアンフィルタ用のkernel
    kernel_gauss = [ 1/16  2/16  1/16; 
                     2/16  4/16  2/16; 
                     1/16  2/16  1/16];
    # Sobelフィルタ用のKernel
    kernel_sx = [-1  0  1;
                 -2  0  2;
                 -1  0  1];
    kernel_sy = kernel_sx';
    
    # SDTVグレースケール
    gray_sdtv = 0.2990 * r + 0.5870 * g + 0.1140 * b;

    # ガウシアンフィルタ
    img_g = convolution2d(gray_sdtv, kernel_gauss);

    # Sobelフィルタ
    img_sx = convolution2d(img_g, kernel_sx);
    img_sy = convolution2d(img_g, kernel_sy);
    save("dog_sx_j.jpg",colorview(Gray,max.(min.(abs.(img_sx),1),0)));
    save("dog_sy_j.jpg",colorview(Gray,max.(min.(abs.(img_sy),1),0)));
    
    # 合成
    img_s = sqrt.( img_sx.^2 + img_sy.^2 );
    save("dog_s_j.jpg",colorview(Gray, min.(abs.(img_s),1)));
    
    return;
end

sobel_test();

処理結果

フクさん
フクさん

処理結果は以下。

Sobelフィルタ(Julia)

考察

太郎くん
太郎くん

これもMATLABの結果と一緒だな。

太郎くん
太郎くん

コードもまぁ基本的には一緒っぽいが・・・。

太郎くん
太郎くん

あ、そうか!
Juliaの場合、256階調的な表現じゃなくて、0~1に正規化されてるのか?!

フクさん
フクさん

そうそう。
ここがちょっと混乱を誘う。

太郎くん
太郎くん

あと、Scilabの時みたいに、min,maxでサチュレーションしているのか。

フクさん
フクさん

Juliaの場合、画像書き出し時にオーバーフロー、アンダーフローが発生すると、実行時エラーが起きるからね。
事前に再度0~1で正規化を保証しておく必要がある。

太郎くん
太郎くん

まぁ、そこはちゃんとしておいた方が良いよねー。

まとめ

フクさん
フクさん

まとめだよ。

  • JuliaでSobelフィルタを実施。
    • MATLABと同じ結果が得られた。
    • コード上の演算はほぼMATLABと一緒
  • 画像が0~1で正規化されている点に注意。
    画像書き出し時にも再度正規化しておくと良い。

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

コメント

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