1

我需要在Matlab中使用一组滤波器来过滤图像。我的第一个尝试是使用一个简单的for循环来反复调用银行中每个过滤器的“imfilter”函数。在Matlab中应用一组图像滤波器

我需要重复这个过程多次为我的应用程序,所以我需要这一步尽可能高效。因此,我想知道是否有任何方法可以将此操作矢量化以加快此过程。为了简化事情,我的所有过滤器内核大小相同(9x9)。

作为我要做的一个例子,我的过滤器设置在一个9x9x32的元素块中,需要将其应用于我的图像。我曾考虑将图像复制到一个块(例如100x100x32),但我不确定是否有办法应用像卷积这样的操作而不使用循环。有没有人有解决这个问题的好方法的建议?

+0

正如这个问题的附录:我意识到,我可能更好地通过滤波在频域而不是在空间域中使用卷积服务。实际上我还没有把它用于测试,但我认为我应该能够对图像进行FFT,对结果进行平铺,然后进行矢量化乘法以应用滤波器组。 – 2011-06-15 18:23:00

回答

0

New答案:使用colfilt()或块过滤样式。 Matlab可以将图像转换为大矩阵,其中每个不同的9x9像素区域是单列(81个元素)。使用im2col()方法。如果你的图像是N乘M,结果矩阵将是81 X(N-8)*(M-8)。

然后,您可以将所有过滤器连接到单个矩阵(每个过滤器都是一行)并将这些巨大的矩阵相乘。这会给你所有过滤器的结果。现在,您必须从结果矩阵中重新构造32个结果图像。使用col2im()方法。 欲了解更多信息类型“DOC colfilt”

此方法效果几乎一样快,MEX文件和犯规进行任何“for”循环

老答案:

你想获得不同的32个结果或过滤器组合的单一结果? 如果这是一个简单的结果比一个简单的方法。 如果您使用线性过滤器(如卷积),则应用过滤器。最后在图像上应用结果滤镜。因此图像将只被卷积一次。 如果您的过滤器是对称的(x和y方向),则不是应用9x9过滤器,而是应用9x1的y方向和1x9的x方向。工作更快一点。 最后,你可以尝试使用Mex文件

+0

我应该澄清一下:我需要为每个滤镜分别输出图像,而不是简单地将所有滤镜应用于图像。 – 2011-06-14 21:29:17

+0

我更新了我的答案。看看里面 – DanielHsH 2011-06-16 07:45:19

+0

谢谢!这只是我正在寻找的那种答案。 – 2011-06-18 20:50:50

2

除了预先分配空间之外,还没有更快的方法来获得确切的解决方案。如果近似值正确,那么你可能能够将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,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 
+0

它看起来像你提供的代码基本上是我已经做的相同的事情,但过滤器存储为单元格阵列而不是3D块。 我想我并不感到震惊,没有更快的方式做这个操作,但我希望我可能会错过一些东西。就目前而言,这个操作占用了我程序中80%的处理时间。 – 2011-06-14 21:06:19