2

編集を参照してください

詳細を理解するために、組み込みアルゴリズムを使用する代わりに、ガウスぼかしアルゴリズムを MATLAB で独自に実装しようとしました。

私は興味深い実装を見つけました.誰かがその種のアルゴリズムをコーディングする方法をすでに尋ねています. だから、それはビジネスではありません。

さらに、次の式を使用して、 GIMPのように指定された半径の標準偏差を計算します。

stdDeviation = sqrt(-(radius^2) / (2*log10(1 / 255)));

私のアルゴリズムは、半径の値が小さい場合 (3、5、7 など) に問題なく動作します (少なくとも違いはわかりません)。半径 21 の画像をぼかしようとすると、出力は次のようになります。

私の結果

GIMP の / MATLAB のimgaussfilt(A,sigma)出力との比較:

Matlab の / GIMP の結果

明らかに、アルゴリズムは同じ (または少なくとも類似した) 出力画像を計算しません。imgaussfilt(A,sigma)それとは別に、GIMP / MATLAB は何をしますか?

画像の境界線は無視できます。私はその問題を認識しています。しかし、出力画像の「奇妙なピクセル ストライプ」の原因がわかりません。

完全を期すために、ソース コードを次に示します。

function y = gaussianBlurSepTest(inputImage)
% radius in pixel; RADIUS MUST BE ODD! 
radius = 21;
% approximate value for standard deviation
stdDeviation = sqrt(-(radius^2) / (2*log10(1 / 255)));

ind = -floor(radius/2):floor(radius/2);
[X, Y] = meshgrid(ind, ind);
h = exp(-(X.^2 + Y.^2) / (2*stdDeviation*stdDeviation));
h = h / sum(h(:));

redChannel = inputImage(:,:,1);
greenChannel = inputImage(:,:,2);
blueChannel = inputImage(:,:,3);

redBlurred = conv2(redChannel, h);
greenBlurred = conv2(greenChannel, h);
blueBlurred = conv2(blueChannel, h);

y = cat(3, uint8(redBlurred), uint8(greenBlurred), uint8(blueBlurred));

編集:

完全を期し、他の人を助けるために: 私は erfan の修正を適用しました。結果ははるかに良くなりましたが、gimp の計算との明らかな違いがまだ見られます。GIMP の結果は「よりスムーズ」に見えます。

実装されたアルゴリズム:

function y = gaussianBlurSepTest(inputImage)
radius = 21;
stdDeviation = sqrt(-(radius^2) / (2*log10(1 / 255)));
ind = -floor(radius/2):floor(radius/2);
[X, Y] = meshgrid(ind, ind);
[~, R] = cart2pol(X, Y);  % Here R is defined
h = exp(-R.^2 / (2*stdDeviation*stdDeviation));
h = h / sum(h(:));
h(R > radius/2) = 0;
h = h / sum(h(:));
redChannel = inputImage(:,:,1);
greenChannel = inputImage(:,:,2);
blueChannel = inputImage(:,:,3);
redBlurred = conv2(redChannel, h);
greenBlurred = conv2(greenChannel, h);
blueBlurred = conv2(blueChannel, h);
y = cat(3, uint8(redBlurred), uint8(greenBlurred), uint8(blueBlurred));

結果: 実装されたアルゴリズム

GIMPの結果: GIMP

質問に完全に答え、同じ質問を持つ他の人を助けるという点で、違いの起源を尋ねることは役立つかもしれないと思います.

ありがとうございました!

4

2 に答える 2

1

h現れた横縞と縦縞の原因です。次のプロットに示すように、角度対称で定義hしましたが、その境界はこの対称性を破っています。

時間

h物事を正しくするために、正しい半径で切り捨てることができます:

切り捨てられたh

あなたの関数に変更を適用したところ、より良い結果が得られるはずです:

function y = gaussianBlurSepTest(inputImage, radius)
stdDeviation = sqrt(-(radius^2) / (2*log10(1 / 255)));
ind = -floor(radius/2):floor(radius/2);
[X, Y] = meshgrid(ind, ind);
[~, R] = cart2pol(X, Y);  % Here R is defined
h = exp(-R.^2 / (2*stdDeviation*stdDeviation));
h = h / sum(h(:));
h(R > radius/2) = 0;  % And here h is truncated. The rest is the same.

これが私のテストです。私のイメージ:

ここに画像の説明を入力

gaussianBlurSepTest(半径 = 35)の後:

ここに画像の説明を入力

変更された関数の後:

ここに画像の説明を入力

注:出力は少し暗くなります。問題がある場合は、メッシュグリッドを再正規化stdDeviationまたは拡大できます。

于 2016-09-06T23:17:41.520 に答える
0

conv2犯人は命令だと思います。それは、画像の種類がuint8oruint16であるためです。画像をフィルタリングするときは、使用floatまたはdouble入力する必要があります。フィルタ サイズが非常に大きいため、ピクセルに係数ウィンドウを適用した結果が 8 ビットまたは 16 ビットの整数範囲 (255 または 65535) を超えています。doubleフィルターを適用する前に画像をキャストし、フィルターを適用した後に画像を次のようにキャストすることをお勧めしuint8ます。

   Output=gaussianBlurSepTest(double(inputImage));
   Output=uint8(Output);

幸運を。

于 2016-09-06T16:54:27.123 に答える