Применение банка фильтров изображений в Matlab - PullRequest
1 голос
/ 15 июня 2011

Мне нужно отфильтровать изображение с помощью банка фильтров в Matlab.Моей первой попыткой было использование простого цикла for для многократного вызова функции «imfilter» для каждого фильтра в банке.

Мне нужно будет повторить этот процесс много раз для моего приложения, поэтому мне нужно, чтобы этот шаг был максимально эффективным.Поэтому мне было интересно, есть ли способ векторизации этой операции для ускорения процесса.В целях упрощения, все мои ядра фильтров имеют одинаковый размер (9x9).

В качестве примера того, что я собираюсь сделать, мои фильтры установлены в блоке элементов 9x9x32, который долженприменить к моему изображению.Я думал о репликации изображения в блок (например, 100x100x32), но я не уверен, есть ли способ применить такую ​​операцию, как свертка, без обращения к циклам.У кого-нибудь есть предложения по хорошему способу решения этой проблемы?

Ответы [ 2 ]

2 голосов
/ 15 июня 2011

Кроме предварительного выделения места, нет более быстрого способа прийти к точному решению. Если аппроксимации в порядке, то вы можете разбить 32 фильтра на набор линейных комбинаций меньшего числа фильтров, скажем, восемь. См. Например, Управляемые фильтры.

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

edit: вот инструмент, помогающий применять фильтры к изображениям.

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 голосов
/ 15 июня 2011

Новый ответ: используйте 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 файл

...