Лапласа Гаусса не разделяется напрямую на два одномерных ядра.Поэтому imfilter
сделает полную свертку, что довольно дорого.Но мы можем вручную разделить его на более простые фильтры.
Лапласа Гаусса определяется как сумма двух производных второго порядка гауссиана:
LoG = d²/dx² G + d²/dy² G
Сам Гауссиан и его производные отделимы .Следовательно, вышеприведенное может быть вычислено с использованием 4 1D свертки, что намного дешевле, чем одиночная 2D свертка, если ядро не очень маленькое (например, если ядро 7x7, нам нужно 49 умножений и сложений на пиксель для 2D ядра, или 4* 7 = 28 умножений и сложений на пиксель для 4-мерных ядер; эта разница увеличивается по мере увеличения ядра).Вычисления будут выглядеть так:
sigma = 3;
cutoff = ceil(3*sigma);
G = fspecial('gaussian',[1,2*cutoff+1],sigma);
d2G = G .* ((-cutoff:cutoff).^2 - sigma^2)/ (sigma^4);
dxx = conv2(d2G,G,img,'same');
dyy = conv2(G,d2G,img,'same');
LoG = dxx + dyy;
Если вы действительно ограничены во времени и не заботитесь о точности, вы можете установить cutoff
в 2*sigma
(для меньшего ядра), но этоне идеально.
Альтернативный, менее точный, состоит в том, чтобы отделить операцию по-разному:
LoG * f = ( d²/dx² G + d²/dy² G ) * f
= ( d²/dx² ? * G + d²/dy² ? * G ) * f
= ( d²/dx^2 ? + d²/dy² ? ) * G * f
(где *
представляет свертку, и del дельта Дирака, сверткаэквивалентно умножению на 1).Оператор d²/dx² ? + d²/dy² ?
на самом деле не существует в дискретном мире, но вы можете принять конечно-разностное приближение, которое приводит к знаменитому ядру Лапласа 3x3:
[ 1 1 1 [ 0 1 0
1 -8 1 or: 1 -4 1
1 1 1 ] 0 1 0 ]
Теперь мы получаем более грубое приближение, ноэто быстрее для вычисления (2 1D свертки и свертка с тривиальным ядром 3x3):
sigma = 3;
cutoff = ceil(3*sigma);
G = fspecial('gaussian',[1,2*cutoff+1],sigma);
tmp = conv2(G,G,img,'same');
h = fspecial('laplacian',0);
LoG = conv2(tmp,h,'same'); % or use imfilter