图像细化原理

news/2024/11/27 8:31:15/

1. 图像细化原理

Zhang-Suen 算法原理
Zhang-Suen 算法每运行一次, 需要遍历所有的不为0的像素。在对每个像素(P1)进行删除或保留的判断时,我们需要关注其周围的8个邻居像素(P2, P3, P4, P5, P6, P7, P8)的值。其中 P2 到 P8 的顺序是算法规定,用于后面判断。

在这里插入图片描述

1.1.1. 算法的每次运行需要进行`两个子阶段`, 满足某个阶段的全部要求,才能将`P1`像素待置零。最后执行完把待置零的像素全部置零。在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.2. 细化算法过程详解

我们对一副二值图像进行骨架提取,就是删除不需要的轮廓点,只保留其骨架点。假设一个像素点,我们定义该点为p1,则它的八邻域点p2->p9位置如下图所示,该算法考虑p1点邻域的实际情况,以便决定是否删除p1点。假设我们处理的为二值图像,背景为黑色,值为0,要细化的前景物体像素值为1。

在这里插入图片描述

算法的描述如下。

首先复制源图像到目地图像,然后建立一个临时图像,接着执行下面操作:

  1. 把目地图像复制给临时图像,对临时图像进行一次扫描,对于不为0的点,如果满足以下四个条件,则在目地图像中删除该点(就是设置该像素为0),这里p2,…,p9是对应位置的像素灰度值(其为1或者0)。

    a:2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

大于等于2会保证p1点不是端点或孤立点,因为删除端点和孤立点是不合理的,小于等于6保证p1点是一个边界点,而不是一个内部点。等于0时候,周围没有等于1的像素,所以p1为孤立点,等于1的时候,周围只有1个灰度等于1的像素,所以是端点(注:端点是周围有且只能有1个值为1的像素)。

在这里插入图片描述

b:p2->p9的排列顺序中,0->1模式的数量为1,比如下面的图中,有p2->p3 => 0->1, p6->p7=>0->1,所以该像素0->1模式的数量为2。

在这里插入图片描述

之所以要01模式数量为1,是要保证删除当前像素点后的连通性。比如下面的图中,0->1模式数量大于1,如果删除当前点p1,则连通性不能保证。
在这里插入图片描述

c: P2*p4*p6 = 0
d: p4*p6*p8 = 0
在这里插入图片描述

在第一次子迭代中,只是移去东南的边界点,而不考虑西北的边界点,注意p4,p6出现了2次,就是说它们有一个为0,则c,d就满足。

  1. 接下来,把目地图像再次复制到临时图像,接着对临时图像进行一次扫描,如果不为0的点它的八邻域满足以下4个条件,则在目地图像中删除该点(就是设置该像素为0)

    a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

    b. p2->p9的排列顺序中,01模式的数量(这里假设二值图非零值为1)为1。

    c. p2p4p8 = 0

    d. p2p6p8 = 0
    在这里插入图片描述

第二次迭代则相反,会移去西北的边界点,注意p2,p8出现了2次,就是说它们有一个为0,则c,d就满足。

执行完上面两个步骤后,就完成了一次细化算法,我们可以多次迭代执行上述过程,得到最终的骨架图。

1.2.1. 细化实例编程

1.首先对图像进行二值化,白色为255,黑色为0。
2.设置一个3*3的领域S模板。
3.S模板中各个位置上的取值取决于模板所对应图像中不同位置的像素,如果S模板某一个位置上所对应的像素值为白,模板上该位置赋为0,否则赋为1。
4.循环所有的前景像素点,对符合如下条件的像素点标记为删除:

2 ≤ N(p1) ≤ 6——N(p1)表示跟P1相邻的8个像素点中,为前景像素点的个数
S(P1) = 1——S(P1)表示将p2-p9-p2之间按序前后分别成对值为0、1的个数
P2 * P4 * P6 = 0
P4 * P6 * P8 = 0
5.循环所有的前景像素点,对符合如下条件的像素点标记为删除:

2 ≤ N(p1) ≤ 6——N(p1)表示跟P1相邻的8个像素点中,为前景像素点的个数
S(P1) = 1——S(P1)表示将p2-p9-p2之间按序前后分别成对值为0、1的个数
P2 * P4 * P8 = 0
P2 * P6 * P8 = 0
6.如果没有满足的点,则结束细化过程。

下面:

Image_Use为目标图像:高120,长180,处理时不考虑边界(四边)

                   
//背景为黑色,值为0,要细化的前景物体像素值为1。
int temp[3][3];
int count = 0,flinsh_flag = 0;
while(1){flinsh_flag = 0;for(int i = 1;i<120-1;i++){for(int j = 1;j<180-1;j++)    {if(Image_Use[i][j] == 255) continue;//第一步初始化模板memset(temp, 0, sizeof(temp));count = 0;//第二步根据模板所对应的像素点,对模板进行赋值//如果S模板某一个位置上所对应的像素值为白,模板上该位置赋为0,否则赋为1if(Image_Use[i][j-1] == 0) temp[1][0] = 1;if(Image_Use[i][j+1] == 0) temp[1][2] = 1;if(Image_Use[i-1][j-1] == 0) temp[0][0] = 1;if(Image_Use[i-1][j+1] == 0) temp[0][2] = 1;if(Image_Use[i-1][j] == 0) temp[0][1] = 1;if(Image_Use[i+1][j-1] == 0) temp[2][0] = 1;if(Image_Use[i+1][j+1] == 0) temp[2][2] = 1;if(Image_Use[i+1][j] == 0) temp[2][1] = 1;    //for(int x = 0;x<3;x++)for(int y = 0;y<3;y++){      if(x == 1 && y == 1) continue;if(temp[x][y] == 1)count ++;}if(count>=2&&count<=6){ int ap = 0;if (temp[0][1] == 0 && temp[0][2] == 1) ++ap;if (temp[0][2] == 0 && temp[1][2] == 1) ++ap;if (temp[1][2] == 0 && temp[2][2] == 1) ++ap;if (temp[2][2] == 0 && temp[2][1] == 1) ++ap;if (temp[2][1] == 0 && temp[2][0] == 1) ++ap;if (temp[2][0] == 0 && temp[1][0] == 1) ++ap;if (temp[1][0] == 0 && temp[0][0] == 1) ++ap;if (temp[0][0] == 0 && temp[0][1] == 1) ++ap;if(ap == 1&&((temp[0][1]*temp[1][2]*temp[2][1])== 0)&&((temp[1][2]*temp[2][1]*temp[1][0])== 0)){Image_Use[i][j] = 255;flinsh_flag ++;}}}
}if(flinsh_flag == 0) {break;}flinsh_flag = 0;for(int i = 1;i<120-1;i++){for(int j = 1;j<180-1;j++)    {if(Image_Use[i][j] == 255) continue;//第一步初始化模板memset(temp, 0, sizeof(temp));count = 0;//第二步根据模板所对应的像素点,对模板进行赋值//如果S模板某一个位置上所对应的像素值为白,模板上该位置赋为0,否则赋为1if(Image_Use[i][j-1] == 0) temp[1][0] = 1;if(Image_Use[i][j+1] == 0) temp[1][2] = 1;if(Image_Use[i-1][j-1] == 0) temp[0][0] = 1;if(Image_Use[i-1][j+1] == 0) temp[0][2] = 1;if(Image_Use[i-1][j] == 0) temp[0][1] = 1;if(Image_Use[i+1][j-1] == 0) temp[2][0] = 1;if(Image_Use[i+1][j+1] == 0) temp[2][2] = 1;if(Image_Use[i+1][j] == 0) temp[2][1] = 1;    //for(int x = 0;x<3;x++)for(int y = 0;y<3;y++){       if(x == 1 && y == 1) continue;if(temp[x][y] == 1)count ++;}if(count>=2&&count<=6){    int ap = 0;if (temp[0][1] == 0 && temp[0][2] == 1) ++ap;if (temp[0][2] == 0 && temp[1][2] == 1) ++ap;if (temp[1][2] == 0 && temp[2][2] == 1) ++ap;if (temp[2][2] == 0 && temp[2][1] == 1) ++ap;if (temp[2][1] == 0 && temp[2][0] == 1) ++ap;if (temp[2][0] == 0 && temp[1][0] == 1) ++ap;if (temp[1][0] == 0 && temp[0][0] == 1) ++ap;if (temp[0][0] == 0 && temp[0][1] == 1) ++ap;if(ap == 1&&((temp[0][1]*temp[1][2]*temp[1][0])== 0)&&((temp[0][1]*temp[2][1]*temp[1][0]) == 0)){Image_Use[i][j] = 255;flinsh_flag++;}}}}if(flinsh_flag == 0){ break;}
}


http://www.ppmy.cn/news/431302.html

相关文章

英语中如何表达各行各业

前言 &#x1f3e0;个人主页&#xff1a;我是沐风晓月 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是沐风晓月&#xff0c;阿里云社区博客专家 &#x1f609;&#x1f609; &#x1f495; 座右铭&#xff1a; 先努力成长自己&#xff0c;再帮助更多的人,一起加油进…

手机UC浏览器下载的视频m3u8格式如何转换为mp4

在某浏览器下载的m3u8文件如何转换成mp4问价相信许多老伙伴都很苦恼吧&#xff0c;今天教你一个简单易懂的方法。 不废话&#xff0c;直接来硬货 下载手机QQ浏览器 里面有m3u8直接转化为mp4文件的插件&#xff0c;&#xff08;在QQ浏览器里面–文件–视频-- 找到你要转换的视…

java uc_UC浏览器Java通用版本uc Java通用版本java通用版本浏览器uc7

陈祖母开始脱下男人的湿衣服&#xff0c;但经过几次尝试&#xff0c;她仍然无法用旧骨头帮她&#xff0c;也无法帮助男人。 此刻&#xff0c;陈宝珠率领一名中年男子返回。 uc浏览器java通用版本uc java通用版本java通用浏览器uc7.5 java通用版本这个中年人Chen奶奶很自然地意识…

linux下播放wma格式,智能手机什么软件能用播放wma格式的音乐

你们知道wma和mp3哪个音质好么&#xff1f;微软为了让wma有更好的网络可传播性&#xff0c;所以在128KBPS以下时&#xff0c;同密度的MP3都不能超越WMA的音质。但是128仿佛是wma的一个门槛&#xff0c;一但超过这个质率它就无法像MP3那样发挥接近CD的高保真音质了。所以总言而之…

辨别 利用AAC转成无损格式音乐 的假无损

我们都知道,网络上无损音乐很多,假无损也很多. 如果是MP3转成无损,很好鉴别. 但是,自从出现了一个叫做AAC的东西... 很多网上鉴别是否是CD音质的软件都几乎无法鉴别这首歌是CD音质,还是利用AAC转成无损音乐的假无损 D 也欢迎各位提出意见与建议~ ) 于是 今天就花了大功夫来测试…

【AirPlay2】AirPlay升级后的FLAC和ALAC无损音乐格式究竟是什么?

前言:我最近在弄苹果的airplay项目,发现airplay2对比airplay多了音质方面的增强。AAC和MP3接触过,但对FLAC和ALAC完全不了解,整理学习资料汇总成如下信息: AirPlay2 在2017年推出,在前一代AirPlay的基础上加入了Apple自家智慧家庭平台HomeKit的整合,主要在音乐版块增加…

Android的UC的flash插件下载,uc浏览器flash不支持解决方法详解

uc浏览器flash不支持解决方法详解 Adobe Flash Player是Android系统的一项重要功能&#xff0c;这款Android软件可以让自己的Android手机访问基于Flash制作的视频、游戏、互动媒体、网络应用程序等网站功能。Flash Player将实现一个完整的Web浏览体验。遇到uc浏览器flash不支持…

防UC浏览器,夸克浏览器转码,应对UC浏览器、夸克浏览器转码,UC浏览器、夸克浏览器转码解决办法

小说站防UC浏览器&#xff0c;夸克浏览器转码&#xff0c;应对UC浏览器、夸克浏览器转码&#xff0c;UC浏览器、夸克浏览器转码解决办法 看到一个小说站是这样防UC、夸克转码的&#xff0c;他的下一章 href 是空的“ <a id"next" href"">下一章<…