1

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

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

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

4

2 回答 2

2

Other than pre allocating the space, there is not a faster way to arrive at an exact solution. If approximations are ok, then you might be able to decompose the 32 filters into a set of linear combinations of a smaller number of filters, say eight. See for instance Steerable filters.

http://people.csail.mit.edu/billf/papers/steerpaper91FreemanAdelson.pdf

edit: here is a tool to help apply filters to images.

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
于 2011-06-14T20:10:49.753 回答
0

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

然后您可以将所有过滤器连接到单个矩阵(每个过滤器是一行)并将这些巨大的矩阵相乘。这将为您提供所有过滤器的结果。现在您必须从结果矩阵中重建 32 个结果图像。使用 col2im() 方法。有关更多信息,请键入“doc colfilt”

此方法的运行速度几乎与 mex 文件一样快,并且不需要任何“for”循环

老答案:

您想获得不同的 32 个结果还是过滤器组合的单个结果?如果这是一个单一的结果,那么有一个简单的方法。如果您使用线性过滤器(如卷积),则一个接一个地应用过滤器。最后在图像上应用生成的过滤器。因此图像只会被卷积一次。如果过滤器是对称的(x 和 y 方向),则不要应用 9x9 过滤器,而是在 y 方向上应用 9x1,在 x 方向上应用 1x9。工作得快一点。最后,您可以尝试使用 mex 文件

于 2011-06-14T21:23:20.270 回答