我需要在Matlab中使用一组过滤器来过滤图像。我的第一次尝试是使用一个简单的for循环来重复调用bank中每个过滤器的“imfilter”函数。
我需要多次为我的应用重复这个过程,所以我需要这一步尽可能高效。因此,我想知道是否有任何方法可以对此操作进行矢量化以加快该过程。为了简化操作,我的所有过滤器内核都是相同的大小(9x9)。
作为我的目的的一个例子,我的过滤器设置在一个9x9x32元素块中,需要应用于我的图像。我想过将图像复制到一个块(例如100x100x32),但我不确定是否有办法在不使用循环的情况下应用卷积等操作。有没有人建议解决这个问题?
答案 0 :(得分:2)
除了预先分配空间外,没有更快的方法来获得精确的解决方案。如果近似值没问题,那么您可以将32个滤波器分解为一组较少数量的滤波器的线性组合,比如八个。例如,参见可操纵滤波器。
http://people.csail.mit.edu/billf/papers/steerpaper91FreemanAdelson.pdf
编辑:这是一个帮助将过滤器应用于图像的工具。
function FiltIm = ApplyFilterBank(im,filters)
%#function FiltIm = ApplyFilterBank(im,filters)
%#
%#assume im is a single layer image, and filters is a cell array
nFilt = length(filters);
maxsz = 0;
for i = 1:nFilt
maxsz = max(maxsz,max(size(filters{i})));
end
FiltIm = zeros(size(im,1), size(im,2), nFilt);
im = padimage(im,maxsz,'symmetric');
for i = 1:nFilt
FiltIm(:,:,i) = unpadimage(imfilter(im,filters{i}),maxsz);
end
function o = padimage(i,amnt,method)
%#function o = padimage(i,amnt,method)
%#
%#padarray which operates on only the first 2 dimensions of a 3 dimensional
%#image. (of arbitrary number of layers);
%#
%#String values for METHOD
%# 'circular' Pads with circular repetion of elements.
%# 'replicate' Repeats border elements of A.
%# 'symmetric' Pads array with mirror reflections of itself.
%#
%#if(amnt) is length 1, then pad all sides same amount
%#
%#if(amnt) is length 2, then pad y direction amnt(1), and x direction amnt(2)
%#
%#if(amnt) is length 4, then pad sides unequally with order LTRB, left top right bottom
if(nargin < 3)
method = 'replicate';
end
if(length(amnt) == 1)
o = zeros(size(i,1) + 2 * amnt, size(i,2) + 2* amnt, size(i,3));
for n = 1:size(i,3)
o(:,:,n) = padarray(i(:,:,n),[amnt,amnt],method,'both');
end
end
if(length(amnt) == 2)
o = zeros(size(i,1) + 2 * amnt(1), size(i,2) + 2* amnt(2), size(i,3));
for n = 1:size(i,3)
o(:,:,n) = padarray(i(:,:,n),amnt,method,'both');
end
end
if(length(amnt) == 4)
o = zeros(size(i,1) + amnt(2) + amnt(4), size(i,2) + amnt(1) + amnt(3), size(i,3));
for n = 1:size(i,3)
o(:,:,n) = padarray(padarray(i(:,:,n),[amnt(2), amnt(1)],method,'pre'),[amnt(4), amnt(3)],method,'post');
end
end
function o = unpadimage(i,amnt)
%#un does padimage
%#if length(amnt == 1), unpad equal on each side
%#if length(amnt == 2), first amnt is left right, second up down
%#if length(amnt == 4), then [left top right bottom];
switch(length(amnt))
case 1
sx = size(i,2) - 2 * amnt;
sy = size(i,1) - 2 * amnt;
l = amnt + 1;
r = size(i,2) - amnt;
t = amnt + 1;
b = size(i,1) - amnt;
case 2
sx = size(i,2) - 2 * amnt(1);
sy = size(i,1) - 2 * amnt(2);
l = amnt(1) + 1;
r = size(i,2) - amnt(1);
t = amnt(2) + 1;
b = size(i,1) - amnt(2);
case 4
sx = size(i,2) - (amnt(1) + amnt(3));
sy = size(i,1) - (amnt(2) + amnt(4));
l = amnt(1) + 1;
r = size(i,2) - amnt(3);
t = amnt(2) + 1;
b = size(i,1) - amnt(4);
otherwise
error('illegal unpad amount\n');
end
if(any([sx,sy] < 1))
fprintf('unpadimage newsize < 0, returning []\n');
o = [];
return;
end
o = zeros(sy, sx, size(i,3));
for n = 1:size(i,3)
o(:,:,n) = i(t:b,l:r,n);
end
答案 1 :(得分:0)
新答案:使用colfilt()或阻止过滤样式。 Matlab可以将您的图像转换为大矩阵,其中每个不同的9x9像素区域是单个列(81个元素)。使用im2col()方法制作它。如果你的图像是N×M,结果矩阵将是81 X(N-8)*(M-8)。
然后,您可以将所有过滤器连接到单个矩阵(每个过滤器是一行)并将这些巨大的矩阵相乘。这将为您提供所有过滤器的结果。现在,您必须从结果矩阵重建32个结果图像。使用col2im()方法。 有关详情,请输入&#39; doc colfilt&#39;
此方法的工作速度几乎与mex文件一样快,并且不需要任何&#39; for&#39;环
旧答案:
您是否希望获得不同的32个结果或单个结果的过滤器组合? 如果它是一个单一的结果而不是一个简单的方法。 如果使用线性滤波器(如卷积),则将滤波器相互应用。最后在图像上应用生成的滤镜。因此图像只会卷积一次。 如果滤波器是对称的(x和y方向),则应用9x9滤波器而不是应用9x9滤波器,在y方向上应用9x1,在x方向上应用1x9。工作得快一点。 最后,您可以尝试使用Mex文件