开发者

Applying a bank of image filters in Matlab

I need to filter an image using a bank of filters in Matlab. My first attempt was to use a开发者_如何转开发 simple for loop to repeatedly call the "imfilter" function for each filter in the bank.

I will need to repeat this process many times for my application, so I need to this step to be as efficient as possible. Therefore, I was wondering if there was any way this operation could be vectorized to speed up the process. In an effort to simplify things, all of my filter kernels are the same size (9x9).

As an example of what I am going for, my filters are set up in a 9x9x32 element block, which needs to be applied to my image. I thought about replicating the image into a block (e.g. 100x100x32), but I'm not sure if there's a way to apply an operation like convolution without resorting to loops. Does anyone have suggestions for a good way of tackling this problem?


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


New Answer: Use colfilt() or block filtering style. Matlab can transform your image into large matrix where each distinct 9x9 pixel area is a single column (81 elements). Make it using im2col() method. If your image is N by M the result matrix would be 81 X (N-8)*(M-8).

Then you can concatenate all your filters to single matrix (each filter is a row) and multiply those huge matrices. This will give you the result of all filters. Now you have to reconstruct back 32 result images from the result matrix. use col2im() method. For more information type 'doc colfilt'

This method works almost as fast as mex file and doesnt require any 'for' loop

Old answer:

Do you want to get different 32 results or single result for combination of filters? If it is a sungle result than there is an easy way. If you use linear filters (like convolutions) then apply filters one on another. Finally apply the resulting filter on the image. Thus image will be convolved only once. If you filters are symmetric (x and y direction) then instead of applying the 9x9 filter apply 9x1 on y direction and 1x9 on x direction. Works a bit faster. Finally, you can try using Mex file

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜