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

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

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

はじめに

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

登場人物

博識フクロウのフクさん

指差しフクロウ

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

これをScilabで実現する。

Scilabコード

フクさん
フクさん

Scilabコードはこうなる。

convolution2d.sci

function out = convolution2d(img, Kernel)
    [m, n] = size(Kernel);  // カーネルサイズ取得
    
    // カーネル中心からみた幅
    dy = int32((m-1)/2);  // カーネル上下幅
    dx = int32((n-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( double(img(y-dy:y+dy, x-dx:x+dx)).*Kernel );
        end
    end
endfunction

sobel_test.sci

function [] = sobel_test()
    // 入力画像の読み込み
    img = imread('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 = uint8([0.2990 * double(r) ...
                + 0.5870 * double(g) + 0.1140 * double(b) ]);
    
    // ガウシアンフィルタ
    img_g = convolution2d(gray_sdtv, kernel_gauss);
    
    // Sobelフィルタ
    img_sx = convolution2d(img_g, kernel_sx);
    img_sy = convolution2d(img_g, kernel_sy);
    imwrite(uint8(abs(max(min(img_sx,255),-255))),'dog_sx.jpg');
    imwrite(uint8(abs(max(min(img_sy,255),-255))),'dog_sy.jpg');
    
    // 合成
    img_s = uint8(min(sqrt( img_sx.^2 + img_sy.^2 ),255));
    imwrite(img_s,'dog_s.jpg');
endfunction

処理結果

フクさん
フクさん

処理結果は以下になる。

Sobelフィルタ(Scilab)

考察

太郎くん
太郎くん

これもMATLABと同じ結果が得られたってことでよさそうだね。

太郎くん
太郎くん

ただ、Sobelフィルタの合成前のimwriteがすごいことになってるな・・・。

フクさん
フクさん

Scilabの場合、uint8にする際にサチュレーションが利かないっぽいんだよね。
だから、事前に-255~+255の範囲になるようにmin、maxの関数を挟んでいる。

太郎くん
太郎くん

微妙なところで振る舞いが違うんだな・・・。

フクさん
フクさん

まぁ、プログラムを組む際はどっちみち気にすべきところだから、
言うほど手間というほどでもないない。

まとめ

フクさん
フクさん

まとめだよ。

  • ScilabでSobelフィルタを実施。
    • MATLABと同じ結果が得られた。
  • uint8にキャストする際は、事前にmin,maxを使用してサチュレーションをしておく必要がある。

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

コメント

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