跟踪图像中二值区域的边界
布雷特本周的精选是弗里曼链码,通过尼古拉斯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要处理的人。我将我想看到弗里曼的算法在您的工作中被引用,我想看到“帮助”评论充实一点,以帮助您的文件的用户。最后,如果你们能把“轮廓”列入你们的产出清单,那将是有益的。(尽管这对任何人来说都很容易修改。)尽管如此,真的是扎实的工作:发人深省,非常赞赏!
一如既往,我欢迎你的想法和评论.
- 类别:
- 选择
评论
如欲留言,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。