バックナンバーはこちら。
https://www.simulationroom999.com/blog/compare-matlabpythonscilabjulia3-backnumber/
はじめに
畳み込み演算のガウシアンフィルタの話。
今回はScilabで実施してみる。
登場人物
博識フクロウのフクさん
![指差しフクロウ](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/指差しフクロウ.png)
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
![技術者太郎](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/技術者01アップ.png)
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
使用する畳み込みカーネルと画像
![太郎くん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/技術者02アップ.png)
まずは畳み込みカーネルと画像の再掲
畳み込みカーネル
\(
\displaystyle K_{3\times3}=\frac{1}{16}
\begin{bmatrix}
1 & 2 & 1 \\
2 & 4 & 2 \\
1 & 2 & 1 \\
\end{bmatrix}
\)
画像
![犬と自転車](https://www.simulationroom999.com/blog/wp-content/uploads/2023/05/02_犬と自転車-1024x768.png)
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/お休みフクロウ.png)
これをScilabで実現する。
Scilabコード
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/指差しフクロウ.png)
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
gaussian_test.sci
function [] = gaussian_test()
img = imread('dog.jpg');
[h, w, c] = size(img);
// ガウシアンフィルタ用のkernel
kernel_gauss = [ 1/16 2/16 1/16;
2/16 4/16 2/16;
1/16 2/16 1/16];
img_gauss = uint8(zeros(h, w, c));
// ガウシアンフィルタ
img_gauss(:,:,1) = convolution2d(img(:,:,1), kernel_gauss);
img_gauss(:,:,2) = convolution2d(img(:,:,2), kernel_gauss);
img_gauss(:,:,3) = convolution2d(img(:,:,3), kernel_gauss);
imwrite(img_gauss,'dog_gaussian.jpg');
endfunction
処理結果
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/指差しフクロウ.png)
処理結果は以下。
![犬と自転車、ガウシアンフィルタ、Scilab](https://www.simulationroom999.com/blog/wp-content/uploads/2023/06/02_dog_gaussianScilab-1024x768.png)
考察
![太郎くん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/技術者01アップ.png)
これはもうMATLAと一緒だなー。
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/お休みフクロウ.png)
まぁ、ほぼコピペなことは認めよう。
![太郎くん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/技術者01アップ.png)
out(y, x) = sum( double(img(y-dy:y+dy, x-dx:x+dx)).*Kernel );
を見ると、sumが一回で済んでるね。
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/指差しフクロウ.png)
sumに関しては、MATLABと挙動が異なり、行列全体の総和になる。
行、列に対しての総和を取りたい場合は、第2引数に1を入れれば列の総和、2を入れれば行の総和になる。
![太郎くん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/「技術者a」20アップ.png)
相変わらず似てるのに、細かい部分で差異が出るんだな・・・。
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/お休みフクロウ.png)
まぁ、こういうのを経験して、ツール、言語の特性を把握していくしかないな。
まとめ
![フクさん](https://www.simulationroom999.com/blog/wp-content/uploads/2020/05/指差しフクロウ.png)
まとめだよ。
- Scilabでガウシアンフィルタを実施。
- 畳み込み演算は関数化。
- Scialbのsumは行列の総和。
- 行、列の総和の場合は第2引数を使用。
- RGB 3chに対して同じ処理を実施。
バックナンバーはこちら。
コメント