一杯清酒邀明月
天下本无事,庸人扰之而烦耳。
posts - 3121,comments - 209,views - 578万

  我几乎完全就是照着WIKI百科上的算法实现的,不过是用Matlab而已。使用了两步法进行标记,一步法我还没怎么看。两步法中第二步是比较麻烦的,其中用到了不相交集合的一些理论,尤其是不相交集合森林,我这里的find_set函数就是参考《算法导论》311页的算法写的。如果用c++写,也许需要自己构造数据结构。

  好吧,下面是我理解的算法过程:

  1.首先要确定是标记8邻域连通还是4邻域连通,如果是8邻域连通,就用的模板,如果是4邻域连通,就用的模板。我这里用了是8连通。

  2.用模板变量图像,类似卷积,不过不计算,只比较。比较当前像素和邻域4个或2个像素,如果都不相等,那么标记号加一,并且把这个标记号赋值给另一个标记空间中相同位置的像素,因为不能破坏当前图像的像素。如果有一个相等,那么就把这4个或2个像素中非背景像素中的最小值赋给另一个标记空间相同位置的像素,并且把这4个或2个像素同有相同当前位置像素值的集合取并集(ps:这个真的好难解释--!!)。遍历完会得到标记图像和有标记号那么多个的标记集合。

  3.遍历标记图像,按标记图像的像素值索引标记集合,找到标记集合中代表当前集合最小的值赋值给原图像当前位置的像素(ps:这里最好看《算法导论》或这里)。

  还是看代码吧,运行一下更好:

  main.m

复制代码
 1 clear all;
 2 close all;
 3 clc;
 4 
 5 img=imread('liantong.bmp');
 6 imgn=img>128;
 7 s=uint8(1-imgn);
 8 
 9 %{                      
10 s=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
11    0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0;       %这个矩阵是维基百科中的矩阵
12    0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 0 0;
13    0 0 0 1 1 1 1 0 0 0 1 1 1 1 0 0 0;
14    0 0 1 1 1 1 0 0 0 1 1 1 0 0 1 1 0;
15    0 1 1 1 0 0 1 1 0 0 0 1 1 1 0 0 0;
16    0 0 1 1 0 0 0 0 0 1 1 0 0 0 1 1 0;
17    0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0;
18    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
19 %}
20 imshow(mat2gray(s));
21 [m n]=size(s);
22 tmp=zeros(m,n);
23 label=1;            %第一遍遍历时标记的标签数量
24 for i=2:m
25     for j=2:n-1
26         up_left=s(i-1,j-1);             %原图像当前像素周围四个像素
27         up=s(i-1,j);
28         up_right=s(i-1,j+1);
29         left=s(i,j-1);
30         cur=s(i,j);
31         
32         if cur==1
33             if cur~=up_left && cur~=up &&cur~=up_right &&cur~=left      %当前和四周的都不一样,加新标签
34                 tmp(i,j)=label;
35                 link{label}=[];
36                 label=label+1;
37             else
38                 t=sort([tmp(i,j-1) tmp(i-1,j-1) tmp(i-1,j) tmp(i-1,j+1)]);  %标签图像当前像素周围四个像素并排序         
39                 for k=1:4                   %寻找周围四个像素非零的最小值赋值给标签图像
40                     if t(k)~=0
41                         tmp(i,j)=t(k);
42                         for w=k:4
43                             link{t(w)}=union(t(k:4),link{t(w)});     %设置不相交集合                
44                         end
45                         break;
46                     end
47                 end                  
48             end           
49         end
50         
51     end
52 end
53 
54 for i=1:m
55     for j=1:n
56         if s(i,j) ~=0
57             s(i,j)=find_set(link,tmp(i,j));
58         end
59     end
60 end
61 figure,imshow(mat2gray(s))
复制代码

find_set.m

复制代码
1 function re=find_set(p,i)   %不相交集合寻找代表当前集合的最小值,详见《算法导论》第21章
2     if min(p{i}) ~= i
3         i=find_set(p,min(p{i}));
4     end
5     re=i;
6 end
复制代码

下面是运行的结果:

原图

结果图

效果还不错吧。

posted on   一杯清酒邀明月  阅读(1328)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示