高斯拉普拉斯算子的更快方法

Hoj*_*olf 3 optimization matlab filtering image-processing laplacianofgaussian

我目前正在优化代码以提高图像处理效率。我的第一个问题是,由于vision.VideoFileReaderstep地方花了很长时间才能打开每一帧。我通过将灰度图像压缩为1 RGB帧中的3帧来加快代码速度。这样,我可以使用加载1个RGB帧,vid.step()并导入3帧准备进行处理。

现在,我的代码在高斯的拉普拉斯算子(LoG)过滤上运行缓慢。我读到可以使用该函数imfilter执行LoG,但这似乎是下一个速率限制步骤。

进一步阅读后,看来imfilter速度不是最佳选择。显然,MATLAB引入了LoG函数,但它是在R2016b中引入的,不幸的是我正在使用R2016a。

有没有一种方法可以加快速度,imfilter或者有更好的功能可以用来执行LoG过滤?

我应该打电话给python来加快这个过程吗?

在此处输入图片说明

码:

Hei = gh.Video.reader.info.VideoSize(2);
Wid = gh.Video.reader.info.VideoSize(1);

Log_filter = fspecial('log', filterdot, thresh); % fspecial creat predefined filter.Return a filter.
    % 25X25 Gaussian filter with SD =25 is created.

tic
ii = 1;

bkgd = zeros(Hei,Wid,3);
bkgd(:,:,1) = gh.Bkgd;
bkgd(:,:,2) = gh.Bkgd;
bkgd(:,:,3) = gh.Bkgd;

bkgdmod = reshape(bkgd,720,[]);

while ~isDone(gh.Video.reader)
    frame = gh.readFrame();
    img_temp = double(frame);

    img_temp2 = reshape(img_temp,720,[]);
    subbk = img_temp2 - bkgdmod;

    img_LOG = imfilter(subbk, Log_filter, 'symmetric', 'conv');

    img_LOG =  imbinarize(img_LOG,.002);
    [~, centroids, ~] = gh.Video.blobAnalyser.step(img_LOG);

    toc
end
Run Code Online (Sandbox Code Playgroud)

Cri*_*ngo 5

高斯Laplace不能直接分为两个1D内核。因此,imfilter将进行完整的卷积,这是相当昂贵的。但是我们可以手动将其分离为更简单的过滤器。


高斯的拉普拉斯定义为高斯的两个二阶导数之和:

LoG = d²/dx² G + d²/dy² G
Run Code Online (Sandbox Code Playgroud)

高斯本身及其派生词是可分离的。因此,可以使用4个1D卷积来计算以上内容,这比单个2D卷积便宜得多,除非内核非常小(例如,如果内核为7x7,则2D内核每个像素需要49个乘法和加法运算,或者4 *对于4个1D内核,每个像素* 7 = 28乘法和加法;随着内核的变大,此差异会增大)。计算结果为:

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;
Run Code Online (Sandbox Code Playgroud)

如果您确实时间有限,并且不关心精度,则可以设置cutoff2*sigma(对于较小的内核),但这并不理想。


一种不太精确的替代方法是以不同的方式分离操作:

LoG * f = ( d²/dx² G + d²/dy² G ) * f
        = ( d²/dx²  * G + d²/dy²  * G ) * f
        = ( d²/dx^2  + d²/dy²  ) * G * f
Run Code Online (Sandbox Code Playgroud)

(其中*表示卷积,以及狄拉克增量,等于卷积乘以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 ]
Run Code Online (Sandbox Code Playgroud)

现在我们得到了更粗略的近似值,但是计算起来更快(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
Run Code Online (Sandbox Code Playgroud)

  • @ Hojo.Timberwolf GPU需要大量时间来发送内存并从GPU收集内存。如果您可以堆叠一些图像,则将它们发送到GPU一起处理它们并收集结果,将可以提高速度。 (2认同)