2015-01-13 4 views
0

Есть ли способ принять фильтры нижних частот и высоких частот в следующем коде и объединить их в одно ядро ​​и применить одну функцию conv2()?Комбинируйте свернутый фильтр в matlab

примечание: длина (lfilter) = 21, длина (hfilter) = 81.

, что мы в основном делаем на последнем этапе говорит, чтобы удалить крупные объекты из изображения (после того, как уже удаление очень маленькие объекты с гауссовским размытием).

properties (Constant) 
    minStar = 2; % min star radius 
    maxStar = 8; % max star radius 
    threshold = 12; 
end 

function filter2(this) 
     normalize = @(x) x/sum(x); 
     lfilter = normalize(exp(-((-ceil(5*this.minStar):ceil(5*this.minStar))/(2*this.minStar)).^2)); 
     hfilter = normalize(exp(-((-ceil(5*this.maxStar):ceil(5*this.maxStar))/(2*this.maxStar)).^2)); 
     this.low = conv2(lfilter',lfilter,this.raw,'same'); 
     this.high = conv2(hfilter',hfilter,this.raw,'same'); 
     this.filtered = this.low - this.high; 
     this.foreground = this.filtered > this.threshold; 
    end 

ответ

1

Я только что получил ответ на форумах matlab. http://www.mathworks.com/matlabcentral/answers/169713-combine-convolution-filters-bandpass-into-a-single-kernel

Суть в том, что вы должны использовать прокладку для заполнения обеих сторон более короткого фильтра, а затем вы можете просто комбинировать векторы.

Convolution - это линейная операция, поэтому да, вы можете объединить две операции фильтрации в одну. Просто сделайте фильтры одинакового размера и добавьте/вычтите их. Например:

lfilter = normalize(exp(-((-ceil(5*minStar):ceil(5*minmax))/(2*this.minStar)).^2)); 
hfilter = normalize(exp(-((-ceil(5*maxStar):ceil(5*minmax))/(2*this.maxStar)).^2)); 
padlength = (length(hfilter) - length(lfilter))/2; 
lfilter = padarray(lfilter, [0 padlength]); 
lhfilter = lfilter - hfilter; 
this.filtered = conv2(lhfilter',lhfilter,this.raw,'same'); 
+0

Хорошая точка о том, что они линейные. :) – eigenchris

3

Поскольку оператор свертки ассоциативно:

conv(a, conv(b,c)) == conv(conv(a,b), c) 

вы должны быть в состоянии объединить два ядра в один раз, сворачивая их друг с другом.


В вашем случае что-то вроде этого должно работать:

new_kernel = conv2(lfilter',lfilter, conv2(hfilter',hfilter), 'same'); 

свертка является коммутативной, а поэтому порядок, в котором вы выполняете извилины не имеет значения.

EDIT: как я объясняю ниже, способ выполнения четырьмя 1D свертками метода афера оказывается быстрее, чем одна двумерная свертка.

+0

Я искал объединение фильтров в одно ядро. Чтобы уменьшить количество сверток (мне нужно перенести это в конечном итоге на графический процессор) –

+0

Я вижу. Использование многих 1D-фильтров, а не большого 2D-фильтра, кажется лучшей идеей. Предполагая, что у всех 1D-фильтров есть векторы с компонентами 'N', а изображение -' M' на пикселях 'M', ваш исходный метод потребует умножения' 4 * N * M * M'. Mine действительно потребует 'N * N * M * M', если мы предположим, что новое ядро ​​объединено в' N' на 'N'. – eigenchris

+0

Да, я хочу, чтобы ядро ​​разгладилось, gpu любит, это. Просто отправил ответ, который у меня есть. –

Смежные вопросы