本周文件交换选择

我们最好的用户反馈

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

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

内容

一份新文件引发了一场思维实验

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

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

弗里曼链码

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

尼古拉斯的实现

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

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

图像处理工具箱

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

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

[B,L] = bwboundaries(I, 8);Contour2 = false(大小(L));ii = 1:数字(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 = calcBoundaries(I) [B, L] = bwboundaries(I, 8);Io = false(size(L));ii = 1:数字(B) thisB = B{ii};第1 = sub2ind(大小(L), thisB (: 1), thisB (:, 2));Io(inds) = 1;结束结束

...我们同样有:

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

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

那更复杂的图像呢?

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

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

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

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

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

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

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

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

我有几个建议

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

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




发布与MATLAB®R2020b

|
  • 打印
  • 发送电子邮件

评论

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