【问题标题】:A faster approach to Laplacian of Gaussian一种更快的高斯拉普拉斯算子方法
【发布时间】:2019-05-08 20:12:15
【问题描述】:

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

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

进一步阅读后,imfilter 似乎不是速度的最佳选择。显然 MATLAB 引入了 LoG function,但它是在 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

【问题讨论】:

    标签: matlab image-processing optimization filtering laplacianofgaussian


    【解决方案1】:

    高斯拉普拉斯不能直接分成两个一维核。因此,imfilter 会做一个全卷积,这是相当昂贵的。但我们可以手动将其分离成更简单的过滤器。


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

    LoG = d²/dx² G + d²/dy² G
    

    高斯本身及其衍生物,are separable。因此,上面可以使用 4 个 1D 卷积计算,这比单个 2D 卷积便宜得多,除非内核非常小(例如,如果内核是 7x7,我们需要 49 个 2D 内核每个像素的乘法和加法,或者 4 *7=4 个 1D 内核每像素 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;
    

    如果您真的时间紧迫,并且不关心精度,您可以将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
    

    * 代表卷积,? Dirac delta,卷积相当于乘以 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
    

    【讨论】:

    • 感谢您解释高斯的拉普拉斯以及计算它们的不同方法。在尝试了这些方法之后,我发现imfilter 似乎仍然是我的代码最快的方法。话虽如此,我认为我并没有用我的代码主动计算 LoG,这就是它更快的原因。我将尝试使用gpuArray 来加快处理速度。虽然上次我这样做了,但我最终减慢了处理速度。 :D 我会看到的。再次感谢。
    • @Hojo.Timberwolf GPU 需要相当长的时间来发送内存并从 GPU 收集它。如果您可以堆叠一些图像,将它们发送到 GPU 一起处理并收集结果,您将获得速度提升。
    • @Hojo:我不知道您对filterdot, thresh 使用什么值,但评论说您使用 sigma=25 制作了一个 25x25 过滤器。这确实不是高斯的!其实就是closer to a uniform filter in characteristics。统一过滤器 (fspecial('average') 的计算速度快很多。因此,如果您对过滤器感到满意,请尝试将其替换为统一过滤器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    相关资源
    最近更新 更多