问题描述
我需要使用Matlab中的一组过滤器过滤图像。我的第一次尝试是使用简单的for循环为库中的每个过滤器重复调用\“ imfilter \”函数。
对于我的应用程序,我将需要重复多次此过程,因此,我需要使此步骤尽可能高效。因此,我想知道是否可以通过某种方式对此操作进行矢量处理以加快处理速度。为了简化操作,我所有的过滤器内核都具有相同的大小(9x9)。
作为我要做什么的一个示例,我的滤镜设置在9x9x32元素块中,需要将其应用于我的图像。我曾考虑过将图片复制到一个块中(例如100x100x32),但是我不确定是否有一种方法可以应用诸如卷积之类的操作而无需借助循环。有没有人提出解决此问题的好方法的建议?
解决方法
新答案:使用colfilt()或块过滤样式。 Matlab可以将您的图像转换成大矩阵,其中每个不同的9x9像素区域都是一列(81个元素)。使用im2col()方法进行设置。如果您的图像是N×M,则结果矩阵将是81 X(N-8)*(M-8)。
然后,您可以将所有过滤器连接到单个矩阵(每个过滤器都是一行),然后将这些巨大的矩阵相乘。这将为您提供所有过滤器的结果。现在,您必须从结果矩阵重新构建32个结果图像。使用col2im()方法。
有关更多信息,请输入\'doc colfilt \'
此方法几乎与mex文件一样快,并且不需要任何\'for \'循环
旧答案:
是否要获得不同的32个结果或组合过滤器的单个结果?
如果是令人讨厌的结果,那么有一个简单的方法。
如果使用线性滤波器(如卷积),则将一个滤波器应用于另一个滤波器。最后,将生成的滤镜应用于图像。因此图像将仅卷积一次。
如果您的滤镜是对称的(x和y方向),则不应用9x9滤镜,而是在y方向上应用9x1,在x方向上应用1x9。工作快一点。
最后,您可以尝试使用Mex文件
, 除了预分配空间外,没有更快的方法来获得确切的解决方案。如果近似值合适,则可以将32个过滤器分解为一组较少数量的过滤器(例如8个)的线性组合。例如参见转向过滤器。
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,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,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),2) + 2* amnt(2),\'both\');
end
end
if(length(amnt) == 4)
o = zeros(size(i,1) + amnt(2) + amnt(4),2) + amnt(1) + amnt(3),n) = padarray(padarray(i(:,[amnt(2),amnt(1)],\'pre\'),[amnt(4),amnt(3)],\'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,3));
for n = 1:size(i,3)
o(:,n) = i(t:b,l:r,n);
end