【数字图像处理】图像细化处理

图像细化

细化技术:把一个平面区域简化成图的结构形状表示法
骨架:一种细化结构,它是目标的重要拓扑描述,具有非常广泛的应用。在图像识别或数据压缩时,经常用细化结构。
例如:在识别字符之前,往往要先对字符作细化处理,求出字符的细化结构。
细化的作用:目的将图像的骨架提取出来的同时,保持图像细小部分的连通性,对被处理的图像进行细化有助于突出形状特点和减少冗余信息量。

细化算法

细化算法:采取逐次去除边界的方法进行的,不能破化图像的连通性。
通常选择一组结构元素对,不断在这些结构对中循环,如果所得结果不再变化,则终止迭代过程,随着迭代的进行,集合也不断细化。
结构对的选择:仅受结构元素不相交的限制(不同的结构对),事实上,我们可以使用同一个结构对,即在不断重复的迭代细化过程使用同一个结构对。
细化满足的条件:
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的排列顺序中,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出现了2次,就是说它们有一个为0,则c,d就满足。

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

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

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

c. p2*p4*p8 = 0

d. p2*p6*p8 = 0

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

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

细化实例编程

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,否则赋为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;
  }
}

测试结果:

refer:

图像处理细化算法

C/C++ 图像处理(19)------细化算法

原文地址:https://www.cnblogs.com/-wenli/p/11743999.html

时间: 2024-08-08 21:35:19

【数字图像处理】图像细化处理的相关文章

数字图像处理——图像的几何变换

数字图像处理--图像的几何变换 几何变换不改变像素值,而是改变像素所在的位置. 它包括两个独立的算法: 空间变换算法 插值算法 分类 从图像类型上 二维图像 三维图像 从三维到二维平面投影变换 从变换的性质 基本变换:平移,比例缩放,旋转,镜像,错切 复合变换 图像的平移 在同一坐标系下,设\(P_0(x_0,y_0)\) ,经过水平偏移量\(\triangle x\) ,垂直偏移量\(\triangle y\),得到平移之后的坐标: \[ \begin{cases} x = x_0 + \tr

数字图像处理学习笔记之一 DIP绪论与MATLAB基础

写在前面的话 数字图像处理系列的学习笔记是作者结合上海大学计算机学院<数字图像处理>课程的学习所做的笔记,使用参考书籍为<冈萨雷斯数字图像处理(第二版)(MATLAB版)>,同时学习过程中会参考网络学习资源.对于数字图像处理的学习不可能仅仅依靠作者所写的这一系列笔记,而是需要花时间和精力学习,本文只可作参考和交流之用.由于涉及此学科不久,在学习过程中难免存在错误,请读者不吝赐教. 数字图像处理绪论 数字图像处理(DIP)的研究目标和处理对象: DIP的研究目标是获取信息,处理对象是

数字图像处理 第三版 第一章笔记

1. 数字图像和数字图像处理 图像可定义为一个函数,其自变量是坐标,因变量是灰度值. 当自变量和因变量全是离散值时,则称该图像是数字图像. 数字图像由有限数量的元素组成,这些元素成为像素,每个像素都有特定的位置和灰度值. 数字图像处理是指借助数字计算机来处理数字图像. 从图像处理到计算机视觉是一个连续的统一体. 典型地,将统一体分为三种计算处理,即初级.中级和高级. (1)低级处理涉及初级操作,如降噪.增强.锐化.输入输出都是图像. (2)中级处理涉及诸多任务,如分割.分类和识别等.输入为图像,

【数字图像处理】七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行讲解,主要通过MFC单文档视图实现显示BMP图像增强处理,包括图像普通平滑.高斯平滑.不同算子的图像锐化知识.希望该篇文章对你有所帮助,尤其是初学者和学习图像处理的学生. [数字图像处理]一.MFC详解显示BMP格式图片 [数字图像处理]二.MFC单文档分割窗口显示图片 [数字图像处理]三.MFC实现图像灰度.采样和量化功能详解 [数字图像处理]四.MFC对话框绘制灰度直方图 [数字图像

数字图像处理 CImage类的使用与封装(jpg png gif tif bmp等格式图像的加载、数据读写、保存等功能)

引入CImage类的原因 原有的CBitmap 类只能处理BMP格式的图片,非常受限.而CImage可以处理JPGE.GIF.BMP.PNG等多种格式图片,扩展了图片处理功能且能与CBitmap 进行转换( 因为所载入的位图句柄都是HBITMAP,所以可相互转换),因此引入CImage类进行图像处理. CImage类简介 CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG.GIF.BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换. CImage提供增强型的

【数字图像处理】五.MFC图像点运算之灰度线性变化、灰度非线性变化、阈值化和均衡化处理具体解释

本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行解说.主要通过MFC单文档视图实现显示BMP图片点运算处理.包含图像灰度线性变换.灰度非线性变换.图像阈值化处理.图像均衡化处理等知识,并结合前一篇论文灰度直方图进行展示 .同一时候文章比較具体基础,希望该篇文章对你有所帮助,尤其是刚開始学习的人和学习图像处理的学生. [数字图像处理]一.MFC具体解释显示BMP格式图片 [数字图像处理]二.MFC单文档切割窗体显示图片 [数字图像处理]

数字图像处理之python篇四:图像中的像素访问

前面的一些例子中,我们都是利用Image.open()来打开一幅图像,然后直接对这个PIL对象进行操作.如果只是简单的操作还可以,但是如果操作稍微复杂一些,就比较吃力了.因此,通常我们加载完图片后,都是把图片转换成矩阵来进行更加复杂的操作. python中利用numpy库和scipy库来进行各种数据操作和科学计算.我们可以通过pip来直接安装这两个库 pip install numpy pip install scipy 以后,只要是在python中进行数字图像处理,我们都需要导入这些包: fr

【数字图像处理】六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解

本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行讲解,主要通过MFC单文档视图实现显示BMP图片空间几何变换,包括图像平移.图形旋转.图像反转倒置镜像和图像缩放的知识.同时文章比较详细基础,没有采用GDI+获取矩阵,而是通过读取BMP图片信息头和矩阵像素实现变换,希望该篇文章对你有所帮助,尤其是初学者和学习图像处理的学生. [数字图像处理]一.MFC详解显示BMP格式图片 [数字图像处理]二.MFC单文档分割窗口显示图片 [数字图像处

【数字图像处理之(二)】图像的分类

在计算机中,按照颜色和灰度的多少可以将图像分为灰度图像.二值图像.索引图像和RGB图像四种基本类型.在计算机中,通常是以数组(或矩阵)的形式储存图像的. 灰度图像: 灰度图像矩阵元素的取值范围通常为[0,255].因此其数据类型一般为8位无符号整数的[uint8],这就是人们经常提到的256灰度图像."0"表示纯黑色,"255"表示纯白色,中间的数字从小到大表示由黑到白的过渡色. 然而,在某些领域(例如医学成像),要求提供超出[uint8]的动态范围:会采用[uin