バックナンバーはこちら。
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
処理結果

処理結果は以下になる。

考察

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

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

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

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

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

まとめだよ。
- ScilabでSobelフィルタを実施。
- MATLABと同じ結果が得られた。
- uint8にキャストする際は、事前にmin,maxを使用してサチュレーションをしておく必要がある。
バックナンバーはこちら。
コメント