matlab - 如何使用行和列上的 1D 卷积来计算 2D 卷积?

标签 matlab image-processing signal-processing convolution gaussian

我正在寻找一种方法来计算与 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/

相关文章:

matlab - linprog 可以给出 x 的整数值吗?

Python通过水平虚线将图像分割成多 block

python - matplotlib 补丁可以与函数一起使用吗?

signal-processing - 来自加速度计数据的功率谱密度

matlab - 拉格朗日法

arrays - 查找 Array 中所有重复元素的所有索引

image - 使用平均滤波器部分模糊图像

c - 在 OpenCV 中对 cvConvexHull2() 的结果使用 cvApproxPoly()

algorithm - 压缩打乱的整数序列 [0, N)

Python/Scipy 滤波器离散化