我正在寻找一种方法,通过在 Matlab 中使用
conv2
来计算 conv
给出的相同结果。 (我正在用 C 代码进行卷积,我需要比较 Matlab 和我的代码之间的结果)。
我听说只有当核
K
是可分离的(例如高斯核)时,才可以使用 1D 卷积向量乘法来获得与 2D 卷积矩阵乘法相同的结果。此外,通过这种方式,1D-way 比计算 2D-way 快得多。
这里我收集了一些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')
吗?
如果 2-D 核
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
量级的值,因此两个结果在浮点误差范围内是相同的。