本周文件交换精选

我们最好的用户提交

跟踪图像中二值区域的边界

布雷特本周的精选是弗里曼链码,通过尼古拉斯Douillet

内容

一个新文件提示了一个思维实验

我以前从未这样做过,但我决定写一个刚刚上线的文件今天(当我写这篇文章的时候)!看到尼古拉斯提交的这张图片,我很兴奋:

说实话,我从来没听说过《弗里曼链密码》但我听说过很多在图像处理的基础上,跟踪二值区域的边界通常会派上用场——有选项总是一件好事。我并不陌生尼古拉斯的工作;他的65篇文件交换贡献已经被下载了数千次,并获得了几次5星评级。那里有很多好东西,甚至一个函数我有点害怕跑。(阅读“概述”,你就会明白了。)

弗里曼链码

像我通常做的那样,从维基百科开始(我喜欢并经常支持维基百科,尽管我孩子的老师不允许他们使用这个资源),我做了一点万博1manbetx阅读弗里曼链密码.它本质上是一种二值图像的边界跟踪压缩算法。

尼古拉斯的实现

Nicolas对Freeman算法的实现没有任何MathWorks的工具箱依赖性;它在核心MATLAB中运行。所以如果你有图像处理工具箱(IPT),你需要跟踪一个单独的二进制区域,没有孔,这个功能工作得很漂亮:

% ('gear.jpg'是尼古拉斯与他的条目共享的一个文件。)I = imread(“gear.jpg”);I = imbinalize (I);[Code, row_idx0, col_idx0] = Freeman_chain_code(I, false);注意:第二个输入参数是触发可视化的“verbose”标志%的输出。(我在这里抑制了可视化,因为输出如上所示。)

图像处理工具箱

这就是更有趣的地方。当然,有一种IPT等效的方法可以生成相同的信息——所以我想做一个快速比较:

使用图像处理工具箱功能:

[B,L] = bwbounds (I, 8);Contour2 = false(size(L));ii = 1:numel(B) thisB = B{ii};第1 = sub2ind(大小(L), thisB (: 1), thisB (:, 2));Contour2(inds) = 1;结束imshow (Contour2)标题(“使用bwboundaries”

的界限相同的。(事实上,很容易证实,至少在这种情况下,他们事实上,两者是一样的。)

与时间相比如何?

我建议时间当你想准确地计算函数运行的时间时:

fcn = @() Freeman_chain_code(I, false);t_Freeman = timeit(fcn);

定义一个函数来捕获IPT功能:

函数Io = calcborders (I) [B, L] = bwborders (I, 8);Io = false(size(L));ii = 1:numel(B) thisB = B{ii};第1 = sub2ind(大小(L), thisB (: 1), thisB (:, 2));Io(inds) = 1;结束结束

...我们同样有:

fcn = @() calcborders (I);t_IPT = timeit(fcn);
> >流(\nIPT: %0.5f sec\n', t_Freeman, t_IPT) Freeman: 0.00024秒;IPT: 0.00090秒

它们都非常快。令人惊讶的是,对于这张特定的图像,Freeman边界检测甚至比Toolbox功能还要快。(它还没有被验证到bwboundaries是。)

更复杂的图像呢?

现在让我们把情况弄得稍微复杂一点。假设我们有一个二值图像包含多个感兴趣区域(roi):

I = imread(“coins.png”);I = imfill(imbinalize (I),“黑洞”);Freeman_chain_code(我,真的);

有趣的…弗里曼链码只返回一个单一的轮廓线——第一个检测到的区域(在MATLAB意义上)。

此外,即使你有一个单一的区域——但该区域有一个或多个孔(即,如果欧拉数的图像小于1)时,尼古拉斯的函数只会捕获那个地区的轮廓!

I = false(300);I(150, 150) = true;I = bwdist(I);I = I > 15 & I < 50;
[~, ~, ~, Contour] = Freeman_chain_code_modified(I, false);
Contour2 = calcborders (I);次要情节(2,2,1:2);imshow (I)标题(“原始”) subplot(2,2,3)弗里曼的) subplot(2,2,4)“bwbounaries”

我擅自修改了Nicolas的代码以适应多个区域。(在此过程中,我使用了IPT的一些功能!)在修改后的版本中,我将整个过程包装在一个while循环中,并在处理后将每个ROI中的像素设置为0。我还添加了“轮廓”输出参数,因为我发现它通常是边界跟踪工作流中最有用的方面。)最后:

[Code, a, b, Contour] = Freeman_chain_code_modified(I, true);

但是,即使代码现在可以容纳多个roi,它仍然不能像我需要的那样在包含漏洞的roi上工作。而且,修改后的Freeman代码现在是好几倍bwboundaries的方法。

以下是几点建议

尼古拉斯,谢谢你的投稿,也谢谢你的许多其他作品!您的代码实现得很好,而且非常有用——特别是对于那些无法访问图像处理工具箱和有简单roi要处理的人。我我想看到弗里曼的算法在您的工作中被引用,我想看到“帮助”评论充实一点,以帮助您的文件的用户。最后,如果你们能把“轮廓”列入你们的产出清单,那将是有益的。(尽管这对任何人来说都很容易修改。)尽管如此,真的是扎实的工作:发人深省,非常赞赏!

一如既往,我欢迎你的想法和评论




发布与MATLAB®R2020b

|
  • 打印
  • 发送电子邮件

评论

如欲留言,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。