
图像细化
精炼技术: 将平面区域简化为图形的结构形状表示方法
骨架: 详细的结构,是目标的重要拓扑描述,并具有广泛的应用范围. 在图像识别或数据压缩中,经常使用细化结构.
例如,在识别字符之前,通常需要对字符进行精炼以找到字符的精炼结构.
细化的作用: 目的是提取图像的骨架,同时保持图像小部分的连通性. 细化处理后的图像有助于突出形状特征并减少冗余信息量.
精炼算法
细化算法: 采用连续去除边界的方法,不会破坏图像的连通性.
通常选择一组结构元素对,并不断循环遍历这些结构对. 如果获得的结果没有改变,则迭代过程终止. 随着迭代的进行,集合会不断完善.
结构对的选择: 仅受不相交的结构元素(不同的结构对)的限制,实际上,我们可以使用相同的结构对,即在重复的迭代细化过程中使用相同的结构对.
满足详细条件:
1. 在细化过程中,应定期缩小图像;

2. 在逐渐缩小图像的过程中,应保持图像的连通性不变.
细化算法过程的详细说明
我们在二值图像上执行骨架提取,即删除不必要的轮廓点,仅保留骨架点. 假设一个像素点,我们将该点定义为p1,其下一个八邻点p2-> p9如下图所示. 该算法考虑p1点邻域的实际情况,以决定是否删除p1点. 假设我们正在处理一个二进制图像,背景为黑色,值为0,要精炼的前景对象的像素值为1.

算法说明如下.
首先将源图像复制到目标图像,然后创建一个临时图像,然后执行以下操作:
1. 将目标图像复制到临时图像,然后扫描一次. 对于不为0的点,如果满足以下四个条件,则删除目标图像中的该点(即将像素设置为0),其中p2,...,p9是像素的灰度值相应的位置(1或0).
a. 2
大于或等于2将确保点p1不是端点或孤立点,因为删除端点和孤立点是不合理的,并且小于或等于6可确保点p1是边界点,不是内在的观点. 当它等于0时,不存在等于1的像素,因此p1是一个孤立点. 当它等于1时,只有1个像素的灰度等于1,因此它是一个端点(注意: 该端点被1个像素包围,并且只能有1个值).

按照
的排列顺序
b. p2-> p9,01个图案的数量为1. 例如,在下图中,p2p3 => 01,p6p7 => 01,因此该像素的01个图案的数量为2.

01个图案的数量为1的原因是为了确保删除当前像素后的连通性. 例如,在下图中,01个图案的数量大于1. 如果删除了当前点p1,则不能保证连通性.

c. P2 * p4 * p6 = 0
d. p4 * p6 * p8 = 0

在第一个子迭代中,仅除去东南边界点,而与西北边界点无关. 请注意,p4和p6出现两次,即其中之一为0,则满足c和d.
2. 接下来,将目标图像再次复制到临时图像,然后扫描一次. 如果不为0的点及其八个邻域满足以下4个条件,则删除目标图像中的点(即将像素设置为0)
a. 2

b. p2->在p9的排列顺序中,01个模式的数量(这里假设二元图的非零值为1)为1.
c. p2 * p4 * p8 = 0
d. p2 * p6 * p8 = 0

第二次迭代是相反的. 它将删除西北边界点. 请注意,p2和p8出现两次,也就是说,如果其中一个为0,则满足c和d.
执行上述两个步骤后,完善算法. 我们可以多次重复上述过程以获得最终的骨架图.
详细的示例编程
1. 首先,对图像进行二值化处理,白色为255,黑色为0.
2. 设置一个3 * 3的Domain S模板.
3. S模板中每个位置的值取决于模板中图像中不同位置的像素. 如果与S模板的某个位置相对应的像素值为白色,则模板上的位置分配为0,否则分配为1.
4. 循环所有前景像素,并将满足以下条件的像素标记为已删除:

5. 循环所有前景像素,并将满足以下条件的像素标记为已删除:
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,否则赋为1 if(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,否则赋为1 if(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; } }
测试结果:


二进制图像粗化处理
通过细化图像的二进制补码,可以获得粗糙化处理.
引用:
图像处理细化算法
C / C ++图像处理(19)------细化算法
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shumachanpin/article-303510-1.html
人家的确是在公海航行
幸福的感觉
再于是