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

処理結果は以下。

考察

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

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

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

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

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

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

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

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