2

を参照してくださいEDIT奇妙な行動ガウス画像をぼかす大きな半径/標準偏差を使用して

詳細に。

interesting implementationが見つかりましたが、誰かが既に尋ねていますhow to code that kind of algorithm。だからそれはビジネスではありません。

さらに私はGIMPのように与えられた半径の標準偏差を計算するには、次の式を使用のことを行います

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

私のアルゴリズムは何の問題もなく、半径の小さい値(例えば3,5,7)のために働く(あなたその違いを少なくとも見ることはできません)。私は21の半径で画像をぼかすしようとすると、出力は次のようである:明らかに

Matlab´s/GIMP´s result

imgaussfilt(A,sigma)出力GIMP's/MATLAB'sに比べ

My result

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

画像の境界線は無視されます。私はその問題を認識しています。しかし、出力画像に「奇妙なピクセルストライプ」のの由来を理解できません。完全性の理由から

は、ここではソースコードは次のとおりです。

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)); 

EDIT:完全を期すために

と他人を助けるために:私はerfan's修正を適用しました。結果は今よりはるかに良くなりますが、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)); 

結果: The implemented algorithm

GIMP's結果: GIMP

完全に質問に答えるという点で、同じ質問を他の人を助けるために私は、違いの起源を尋ねることが有用かもしれないと思います。

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

答えて

1

hは、表示されたの水平および垂直ストライプの責任を負います。

h

物事を右にするために、あなたは正しい半径にhを切り捨てることができます:あなたは、次のプロットに見られ、その境界は、この対称性を破るように、角度の対称性とhを定義しているが

truncated 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. 

ここは私のテストです。私の画像:

enter image description here

注:出力修飾関数の後

enter image description here

:あなたgaussianBlurSepTest(半径= 35)後

enter image description here

取得する少し暗い。問題がある場合は、stdDeviationを再正規化したり、meshgridを広げることができます。

+0

私は間違いを今理解しています。ありがとうございました!それが私の仕事です!私はその答えを刻んだものとしてマークします。 完全性と他の人を助けるために、私はそれとは別にアルゴリズムを改善する方法を尋ねると便利だと思います。私の編集を参照してください。 –

+0

私はあなたのメッシュのサイズを増やすことで(ひいては 'h 'の範囲を広げて)、はるかに良い結果が得られると信じています。しかし、はるかに多くの計算時間のコスト。 meshgridの範囲を2倍にして試してみてください。 – erfan

0

私は犯人がconv2命令であり、あなたのイメージの種類がuint8uint16ですので、あなたのイメージをフィルタリングしているとき、それはあなたがfloatdoubleタイプを使用する必要があり、だと思います。 フィルタサイズが非常に大きいので、ピクセル上に係数ウィンドウを適用した結果、8ビットまたは16ビットの整数範囲(255または65535)を超えます。私は以下のようにuint8に戻ってそれを投げ、あなたのフィルタを適用する前に、フィルタの適用後のdoubleにあなたのイメージをキャストしようとすることをお勧め:

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

幸運を。

+0

ありがとうございました!残念ながら、あなたの提案は決して出力画像に影響しません。 –