我试图找出执行某种卷积的最佳方法。
我有一个3D矩阵I = [N x M x P]和一个2D矩阵S = [1 x 1 x K x P]。对于我的3D矩阵的每个第p帧(第三维),我想要返回I(:,:,p-K / 2:p + K / 2)和S(1,1,...,p)之间的有效卷积。你有没有办法做到这一点?
事实上,就计算而言,非常接近标准卷积的操作次数,不同之处在于我需要为每一帧更改第二个矩阵......
这是我目前使用的方法:
% I = 3D matrix [N x M x P]
% S = Filter [1 x 1 x K x P] (K is an odd number)
% OUT = Result
[N, M, P] = size(I); % Data size
K = size(S, 3); % Filter length
win = (K-1)/2 ; % Window
OUT = zeros(size(I)); % Pre-allocation
for p = win+1:P-win
OUT(:, :, p) = convn(I(:, :, p-win:p+win), S(1, 1, :, p), 'valid'); % Perform convolution
end
最后我们的操作数量与标准卷积相同,唯一的区别是每个帧的滤波器都不同......
有什么想法吗?
谢谢;)
答案 0 :(得分:0)
因此,您希望将NxMxK子图像与1x1xKx1内核进行卷积,然后仅获取有效部分,即NxM图像。
让我们看一下这个操作的单个(x,y)位置。这个1D卷积,你只保留1个值,相当于子图像和内核的点积:
OUT(x,y,p) = squeeze(I(x,y,p-win:p+win))' * squeeze(S(1,1,:,p))
通过将I的子图像重新整形为(N * M)xK矩阵(K为水平,S为列向量),可以对所有(x,y)进行矢量化。
在所有p中重复此操作最容易实现循环,就像现在一样。另一种方法是创建一个更大的S,其中每列移动一个,这样你就可以在两个矩阵之间做一个点积。但是S的制作也很昂贵,可能也需要一个循环。我不认为避免循环是在MATLAB中再压力了(这些年来它已经变得更快)并且产品本身可能是算法中最昂贵的部分。