MATLAB、Python、Scilab、Julia比較ページはこちら
https://www.simulationroom999.com/blog/comparison-of-matlab-python-scilab/
はじめに
の、
MATLAB,Python,Scilab,Julia比較 第3章 その21【ガウシアンフィルタ⑦】
を書き直したもの。
畳み込み演算のガウシアンフィルタの話になる。
今回はMATLABで実施してみる。
使用する畳み込みカーネルと画像
今回からは、実際にガウシアンカーネルを試していく。
まずはMATLABから。
使用する畳み込みカーネルと画像を再掲する。
畳み込みカーネル
\(
\displaystyle K_{3\times3}=\frac{1}{16}
\begin{bmatrix}
1 & 2 & 1 \\
2 & 4 & 2 \\
1 & 2 & 1 \\
\end{bmatrix}
\)
画像
MATLABコード
MATLABコードは以下になる。
convolution2d.m
function out = convolution2d(img, kernel)
[m, n] = size(kernel); % カーネルサイズ取得
% カーネル中心からみた幅
dy = int64(fix((m-1)/2)); % カーネル上下幅
dx = int64(fix((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( sum( double(img(y-dy:y+dy, x-dx:x+dx)).*kernel ) );
end
end
end
gaussian_test.m
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 = zeros(h, w, c, 'uint8');
% ガウシアンフィルタ
tic
img_gauss(:,:,1) = convolution2d(img(:,:,1), kernel_gauss);
img_gauss(:,:,2) = convolution2d(img(:,:,2), kernel_gauss);
img_gauss(:,:,3) = convolution2d(img(:,:,3), kernel_gauss);
toc
imwrite(img_gauss,'dog_gaussian.jpg');
end
処理結果
そして処理結果。
考察
画像が変化したかは、ぱっと見わかりにくい。
並べて見ると、一応平滑化感じはある。
元々、それほどノイズが乗っている画像でもないので、人間の目で見た際の変化は少ないことはやむを得ない。
畳み込み演算用の関数はconvolution2dになる。
out(y, x) = sum( sum( double(img(y-dy:y+dy, x-dx:x+dx)).*kernel ) );
の部分が一回の畳み込み演算。
MATLABのsumは列方向、行方向のそれぞれの総和が取れるが、一括で全体の総和が取れないため、2回実施している。
MATLAB R2018b以降であれば、sum(A,’all’)のような指定の仕方がで行列全体の総和が取れる。
ここでは、どのversionでも動くように2回のsumをする方式を採用している。
あとは、行列をベクトルに変換して、内積として処理させることもできるが、
行列の形状は変えず、アダマール積と総和の組み合わせで実現している。
アダマール積は演算子が「.*」になる。
この点は注意が必要。
あとはRGB 3chをそれぞれ抽出して、ガウス分布カーネルと一緒に畳み込み演算関数に渡してる。
そのため、同じような処理を3回実施している。
まとめ
- MATLABでガウシアンフィルタを実施。
- 畳み込み演算は関数化。
- MATLABのsumは行と列のそれぞれの総和しか計算できない。(version依存)
- RGB 3chに対して同じ処理を実施している。
MATLAB、Python、Scilab、Julia比較ページはこちら
コメント