7

2つの画像を撮影し、関数に頼らずに2DFFTを使用してMatlabでそれらを畳み込みたいと思いconv2ます。ただし、畳み込みのために行列を適切にパディングして準備する方法についてはわかりません。

数学演算は次のとおりです。

A * B = C

上記では、*は畳み込み演算子です(Wikipediaリンク)。

次のMatlabプログラムは、行列をパディングする場合とパディングしない場合の違いを示しています。行列をパディングしないと巡回畳み込みが発生するのではないかと思いますが、エイリアシングなしで線形畳み込みを実行したいと思います。

2つの行列をパディングする場合、 CがAおよびBと同じサイズになるように、畳み込みの出力を切り捨てるにはどうすればよいですか?

A = rgb2gray(im2double(imread('1.png'))); % input A
B = rgb2gray(im2double(imread('2.png'))); % kernel B

figure;
imagesc(A); colormap gray;
title ('A')

figure;
imagesc(B); colormap gray;
title ('B')

[m,n] = size(A);
mm = 2*m - 1;
nn = 2*n - 1;

C = (ifft2(fft2(A,mm,nn).* fft2(B,mm,nn)));

figure;
imagesc(C); colormap gray;
title ('C with padding')

C0 = (ifft2(fft2(A).* fft2(B)));

figure;
imagesc(C0); colormap gray;
title ('C without padding')

プログラムの出力は次のとおりです。

A B C C0

4

2 に答える 2

12

パディングを行わないと、ご指摘のとおり、結果は巡回畳み込みと同等になります。線形畳み込みの場合、2つの画像(2D信号)A * Bを畳み込む場合、完全な出力はサイズになります。Ma+Mb-1 x Na+Nb-1ここでMa x Na, Mb x Nb、画像AとBのサイズはそれぞれです。

期待されるサイズにパディングし、乗算して元に戻すと、を介してifft2、結果の画像の中央部分を保持できます(通常はAとBの最大のものに対応します)。

A = double(imread('cameraman.tif'))./255; % image
B = fspecial('gaussian', [15 15], 2); % some 2D filter function

[m,n] = size(A);
[mb,nb] = size(B); 
% output size 
mm = m + mb - 1;
nn = n + nb - 1;

% pad, multiply and transform back
C = ifft2(fft2(A,mm,nn).* fft2(B,mm,nn));

% padding constants (for output of size == size(A))
padC_m = ceil((mb-1)./2);
padC_n = ceil((nb-1)./2);

% frequency-domain convolution result
D = C(padC_m+1:m+padC_m, padC_n+1:n+padC_n); 
figure; imshow(D,[]);

ここで、上記を使用して空間ドメイン畳み込みを行うことと比較します。conv2D

 % space-domain convolution result
 F = conv2(A,B,'same');
 figure; imshow(F,[]);

結果は視覚的に同じであり、2つの間の合計エラー(丸めによる)は、e-10.

于 2012-09-03T22:40:07.927 に答える
1

conv2()基本的に周波数領域にあるMATLAB関数を作成しました。

function [ mO ] = ImageConvFrequencyDomain( mI, mH, convShape )
% ----------------------------------------------------------------------------------------------- %
% [ mO ] = ImageConvFrequencyDomain( mI, mH, convShape )
% Applies Image Convolution in the Frequency Domain.
% Input:
%   - mI                -   Input Image.
%                           Structure: Matrix.
%                           Type: 'Single' / 'Double' (Single Channel).
%                           Range: (-inf, inf).
%   - mH                -   Filtering Kernel.
%                           Structure: Matrix.
%                           Type: 'Single' / 'Double'.
%                           Range: (-inf, inf).
%   - convShape         -   Convolution Shape.
%                           Sets the convolution shape.
%                           Structure: Scalar.
%                           Type: 'Single' / 'Double'.
%                           Range: {1, 2, 3}.
% Output:
%   - mI                -   Output Image.
%                           Structure: Matrix (Single Channel).
%                           Type: 'Single' / 'Double'.
%                           Range: (-inf, inf).
% References:
%   1.  MATLAB's 'conv2()' - https://www.mathworks.com/help/matlab/ref/conv2.html.
% Remarks:
%   1.  A
% TODO:
%   1.  
%   Release Notes:
%   -   1.0.000     29/04/2021  Royi Avital     RoyiAvital@yahoo.com
%       *   First release version.
% ----------------------------------------------------------------------------------------------- %

CONV_SHAPE_FULL     = 1;
CONV_SHAPE_SAME     = 2;
CONV_SHAPE_VALID    = 3;

numRows     = size(mI, 1);
numCols     = size(mI, 2);

numRowsKernel = size(mH, 1);
numColsKernel = size(mH, 2);

switch(convShape)
    case(CONV_SHAPE_FULL)
        numRowsFft  = numRows + numRowsKernel - 1;
        numColsFft  = numCols + numColsKernel - 1;
        firstRowIdx = 1;
        firstColIdx = 1;
        lastRowIdx  = numRowsFft;
        lastColdIdx = numColsFft;
    case(CONV_SHAPE_SAME)
        numRowsFft  = numRows + numRowsKernel;
        numColsFft  = numCols + numColsKernel;
        firstRowIdx = ceil((numRowsKernel + 1) / 2);
        firstColIdx = ceil((numColsKernel + 1) / 2);
        lastRowIdx  = firstRowIdx + numRows - 1;
        lastColdIdx = firstColIdx + numCols - 1;
    case(CONV_SHAPE_VALID)
        numRowsFft = numRows;
        numColsFft = numCols;
        firstRowIdx = numRowsKernel;
        firstColIdx = numColsKernel;
        % The Kernel when transformed is shifted (Namely its (0, 0) is top
        % left not middle).
        lastRowIdx  = numRowsFft;
        lastColdIdx = numColsFft;
end

mO = ifft2(fft2(mI, numRowsFft, numColsFft) .* fft2(mH, numRowsFft, numColsFft), 'symmetric');
mO = mO(firstRowIdx:lastRowIdx, firstColIdx:lastColdIdx);


end


完全に互換性があり、検証されています。
完全なコードは、StackExchange Signal ProcessingQ74803GitHubリポジトリで入手できます。

于 2021-04-29T12:17:05.670 に答える