我正在寻找一种方法来计算与 conv2
相同的结果将通过使用 conv
给出在 MATLAB 中。 (我正在用 C 代码进行卷积,我需要比较 MATLAB 和我的代码之间的结果。)
我听说使用一维卷积向量乘法可以达到与二维卷积矩阵乘法相同的结果,前提是内核 K
是可分离的,例如高斯核。而且,通过这种方式,1D 方式比计算 2D 方式快得多。
这里我收集了一些Matlab代码:
% Create data
A = randn(10, 10);
% Create gaussian kernel
sigma = 1;
kernel_size = round(6 * sigma);
% Create mesh grid
[x, y] = meshgrid(-kernel_size:kernel_size, -kernel_size:kernel_size);
% Create gaussian 2D kernel
K = 1/(2*pi*sigma^2)*exp(-(x.^2 + y.^2)/(2*sigma^2));
我想知道如何才能达到与 conv2(A, K, 'same')
相同的结果如果我使用conv
仅有的。我应该先做conv(A(i, :); K(i, :), 'same')
对于每一行,然后 conv(A(:, i); K(:, i), 'same')
每列?
最佳答案
如果二维内核 K
可分为行向量 kr
和列向量 kc
,使得 K = kc*kr
,可以更有效地获得 conv2(A, K, 'same')
的结果: conv2(kr, kc, A, 'same')
(或等同于 conv2(kc, kr, A, 'same')
)。
如果只需要使用conv
,则必须将A
的每一行与kr
进行卷积,然后将结果的每一列进行卷积与kc
(或同等的相反顺序)。
因此,在您的示例中:
A = randn(10, 10);
sigma = 1;
kernel_size = round(6 * sigma);
[x, y] = meshgrid(-kernel_size:kernel_size, -kernel_size:kernel_size);
K = 1/(2*pi*sigma^2)*exp(-(x.^2 + y.^2)/(2*sigma^2));
result = conv2(A, K, 'same');
您可以获得相同的结果
x = -kernel_size:kernel_size;
y = x.';
kr = 1/sqrt(2*pi)/sigma * exp(-x.^2/(2*sigma^2));
kc = 1/sqrt(2*pi)/sigma * exp(-y.^2/(2*sigma^2));
result_sep = NaN(size(A));
for r = 1:size(A,1)
result_sep(r,:) = conv(A(r,:), kr, 'same');
end
for c = 1:size(A,1)
result_sep(:,c) = conv(result_sep(:,c), kc, 'same');
end
检查:
max(max(abs(result-result_sep)))
给出的值的顺序为 eps
,因此两个结果在浮点误差范围内是相同的。
关于matlab - 如何使用行和列上的 1D 卷积来计算 2D 卷积?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77719588/