web-dev-qa-db-ja.com

ガボールウェーブレットを画像に適用するにはどうすればよいですか?

これらのガボールフィルターウェーブレットを画像に適用するにはどうすればよいですか?

enter image description here

close all;
clear all;
clc;

% Parameter Setting
R = 128;
C = 128;
Kmax = pi / 2;
f = sqrt( 2 );
Delt = 2 * pi;
Delt2 = Delt * Delt;

% Show the Gabor Wavelets
for v = 0 : 4
    for u = 1 : 8
        GW = GaborWavelet ( R, C, Kmax, f, u, v, Delt2 ); % Create the Gabor wavelets
          figure( 2 );
     subplot( 5, 8, v * 8 + u ),imshow ( real( GW ) ,[]); % Show the real part of Gabor wavelets

    end

    figure ( 3 );
     subplot( 1, 5, v + 1 ),imshow ( abs( GW ),[]); % Show the magnitude of Gabor wavelets

end



function GW = GaborWavelet (R, C, Kmax, f, u, v, Delt2)


k = ( Kmax / ( f ^ v ) ) * exp( 1i * u * pi / 8 );% Wave Vector

kn2 = ( abs( k ) ) ^ 2;

GW = zeros ( R , C );

for m = -R/2 + 1 : R/2

    for n = -C/2 + 1 : C/2

        GW(m+R/2,n+C/2) = ( kn2 / Delt2 ) * exp( -0.5 * kn2 * ( m ^ 2 + n ^ 2 ) / Delt2) * ( exp( 1i * ( real( k ) * m + imag ( k ) * n ) ) - exp ( -0.5 * Delt2 ) );

    end

end

編集:これは私の画像のサイズです

enter image description here

18
vini

ガボールフィルターの一般的な使用法は、いくつかの方向のそれぞれでフィルター応答を計算することです。エッジ検出用。

畳み込み定理 を使用して、画像とフィルターのフーリエ変換の要素ごとの積の逆フーリエ変換を行うことにより、フィルターを画像で畳み込むことができます。基本的な式は次のとおりです。

%# Our image needs to be 2D (grayscale)
if ndims(img) > 2;
    img = rgb2gray(img);
end
%# It is also best if the image has double precision
img = im2double(img);

[m,n] = size(img);
[mf,nf] = size(GW);
GW = padarray(GW,[n-nf m-mf]/2);
GW = ifftshift(GW);
imgf = ifft2( fft2(img) .* GW );

通常、FFT畳み込みは、サイズが20を超えるカーネルに適しています。詳細については、Cの数値レシピをお勧めします。これには、言語に依存しない優れた説明があります。メソッドとその警告の。

カーネルはすでに大きいですが、FFTメソッドを使用すると、そのサイズに関係なくパディングされるため、イメージと同じ大きさにすることができます。 FFTの周期性により、このメソッドは巡回畳み込みを実行します。これは、フィルターが画像の境界線を包み込むことを意味するため、このエッジ効果を排除するには、画像自体もパディングする必要があります。最後に、(少なくとも一般的な実装では)すべてのフィルターに対する合計応答が必要なので、それぞれを画像に順番に適用し、応答を合計する必要があります。通常、3〜6の方向を使用しますが、複数のスケール(異なるカーネルサイズ)でフィルタリングを実行することも一般的であるため、そのコンテキストでは、より多くのフィルターが使用されます。

次のようなコードですべてを行うことができます。

img = im2double(rgb2gray(img)); %# 
[m,n] = size(img); %# Store the original size.

%# It is best if the filter size is odd, so it has a discrete center.
R = 127; C = 127;

%# The minimum amount of padding is just "one side" of the filter.
%# We add 1 if the image size is odd.
%# This assumes the filter size is odd.
pR = (R-1)/2;
pC = (C-1)/2;
if rem(m,2) ~= 0; pR = pR + 1; end;
if rem(n,2) ~= 0; pC = pC + 1; end;
img = padarray(img,[pR pC],'pre'); %# Pad image to handle circular convolution.

GW = {}; %# First, construct the filter bank.
for v = 0 : 4
    for u = 1 : 8
        GW =  [GW {GaborWavelet(R, C, Kmax, f, u, v, Delt2)}];
    end
end

%# Pad all the filters to size of padded image.
%# We made sure padsize will only be even, so we can divide by 2.
padsize = size(img) - [R C];
GW = cellfun( ...
        @(x) padarray(x,padsize/2), ...
        GW, ...
        'UniformOutput',false);

imgFFT = fft2(img); %# Pre-calculate image FFT.

for i=1:length(GW)
    filter = fft2( ifftshift( GW{i} ) ); %# See Numerical Recipes.
    imgfilt{i} = ifft2( imgFFT .* filter ); %# Apply Convolution Theorem.
end

%# Sum the responses to each filter. Do it in the above loop to save some space.
imgS = zeros(m,n);
for i=1:length(imgfilt)
    imgS = imgS + imgfilt{i}(pR+1:end,pC+1:end); %# Just use the valid part.
end

%# Look at the result.
imagesc(abs(imgS));

これは基本的に最低限の実装であることに注意してください。周波数分解能を得るために、ゼロの代わりに境界線の複製でパディングするか、ウィンドウ関数を画像に適用するか、パッドサイズを大きくするかを選択できます。これらはそれぞれ、上記で概説した手法の標準的な拡張であり、 Google および Wikipedia を介して調査するのは簡単なはずです。また、事前割り当てなどの基本的なMATLAB最適化を追加していないことにも注意してください。

最後に、フィルターが常に画像よりもはるかに小さい場合は、画像のパディングをスキップすることをお勧めします(つまり、最初のコード例を使用します)。これは、画像にゼロを追加すると、パディングが始まる人工的なエッジ機能が作成されるためです。フィルタが小さい場合、フィルタのパディングのゼロのみが含まれるため、巡回畳み込みからのラップアラウンドは問題を引き起こしません。しかし、フィルターが十分に大きくなるとすぐに、ラップアラウンド効果は深刻になります。大きなフィルターを使用する必要がある場合は、より複雑なパディングスキームを使用するか、画像のエッジをトリミングする必要があります。

16
reve_etrange

ウェーブレットを画像に「適用」するには、通常、ウェーブレットと画像の内積を取得して、そのウェーブレットが画像にどの程度関連しているかを表す大きさの単一の数値を取得します。 128行128列の画像のウェーブレットのフルセット(「正規直交基底」と呼ばれる)がある場合、128 * 128 = 16,384の異なるウェーブレットがあります。ここには40しかありませんが、持っているもので作業します。

ウェーブレット係数を取得するには、画像を撮影します。次のように言います。

t = linspace(-6*pi,6*pi,128);
myImg = sin(t)'*cos(t) + sin(t/3)'*cos(t/3);

そして、これと次のような基底ベクトルGWの1つの内積を取ります。

myCoef = GW(:)'*myImg(:);

私はすべてのウェーブレットを行列GW_ALLに積み上げ、各行が32 GW(:) 'ウェーブレットの1つであり、次のように記述してすべてのウェーブレット係数を一度に計算するのが好きです。

waveletCoefficients = GW_ALL*myImg(:);

これらをstem(abs(waveletCoefficients))でプロットすると、いくつかが他よりも大きいことに気付くでしょう。大きな値は、画像と意志が一致する値です。

最後に、ウェーブレットが直交していると仮定すると(実際にはそうではありませんが、ここではそれほど重要ではありません)、ウェーブレットを使用して画像を再現することはできますが、可能性の合計は32であり、すべてが画像の中心...だから私たちが書くとき

newImage = real(GW_ALL'*waveletCoefficients);

中央には元の画像に似たものが表示されますが、外側には表示されません。

次の結果を得るために、コード(以下)に追加しました。 enter image description here

変更点は次のとおりです。

% function gaborTest()

close all;
clear all;
clc;

% Parameter Setting
R = 128;
C = 128;
Kmax = pi / 2;
f = sqrt( 2 );
Delt = 2 * pi;
Delt2 = Delt * Delt;

% GW_ALL = nan(32, C*R);

% Show the Gabor Wavelets
for v = 0 : 4
    for u = 1 : 8
        GW = GaborWavelet ( R, C, Kmax, f, u, v, Delt2 ); % Create the Gabor wavelets
          figure( 2 );
         subplot( 5, 8, v * 8 + u ),imshow ( real( GW ) ,[]); % Show the real part of Gabor wavelets

         GW_ALL( v*8+u, :) = GW(:);

    end

    figure ( 3 );
     subplot( 1, 5, v + 1 ),imshow ( abs( GW ),[]); % Show the magnitude of Gabor wavelets

end

%% Create an Image:
t = linspace(-6*pi,6*pi,128);
myImg = sin(t)'*cos(t) + sin(t/3)'*cos(t/3);
figure(3333);
clf
subplot(1,3,1);
imagesc(myImg);
title('My Image');
axis image

%% Get the coefficients of the wavelets and plot:
waveletCoefficients = GW_ALL*myImg(:);

subplot(1,3,2);
stem(abs(waveletCoefficients));
title('Wavelet Coefficients')

%% Try and recreate the image from just a few wavelets.
% (we would need C*R wavelets to recreate perfectly)

subplot(1,3,3);
imagesc(reshape(real(GW_ALL'*waveletCoefficients),128,128))
title('My Image Reproduced from Wavelets');
axis image

このアプローチは、ウェーブレット係数を抽出して画像を再現するための基礎を形成します。ガボールウェーブレットは(前述のように)直交ではなく( 参照 )、reve_etrangeで説明されているように畳み込みを使用した特徴抽出に使用される可能性が高くなります。この場合、これを内部ループに追加することを検討してください。

 figure(34);
 subplot(5,8, v * 8 + u );
 imagesc(abs(ifft2((fft2(GW).*fft2(myImg)))));
 axis off
7
Steve