Visual-C++-实现数字化图像的分割

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Visual C++ 实现数字化图像的分割

一、前言

用计算机进行数字图像处理的目的有两个,一是产生更适合人类视觉观察和识别的图像,二是希望计算机能够自动进行识别和理解图像。无论是为了何种目的,图像处理的关键一步是对包含有大量各式各样景物信息的图像进行分解。分解的最终结果就是图像被分成一些具有各种特征的最小成分,这些成分就称为图像的基元。产生这些基元的过程就是图像分割的过程。图像分割作为图像处理领域中极为重要的内容之一,是实现图像分析与理解的基础。从概念上来说,所谓图像分割就是按照一定的原则将一幅图像或景物分为若干个部分或子集的过程。目前图像处理系统中我们只能得到二维图像信息,因此只能进行图像分割而不是景物分割(景物是三维信息);图像分割也可以理解为将图像中有意义的特征区域或者需要应用的特征区域提取出来,这些特征区域可以是像素的灰度值、物体轮廓曲线、纹理特性等,也可以是空间频谱或直方图特征等。。在图像中用来表示某一物体的区域,其特征都是相近或相同的,但是不同物体的区域之间,特征就会急剧变化。目前已经提出的图像分割方法很多,从分割依据的角度来看,图像的分割方法可以分为相似性分割和非连续性分割。相似性分割就是将具有同一灰度级或相同组织结构的像素聚集在一起,形成图像的不同区域;非连续性分割就是首先检测局部不连续性,然后将它们连接在一起形成边界,这些边界将图像分成不同的区域。由于不同种类的图像,不同的应用场合,需要提取的图像特征是不同的,当然对应的图像特征提取方法也就不同,因此并不存在一种普遍适应的最优方法。

图像分割方法又可分为结构分割方法和非结构分割方法两大类。结构分割方法是根据图像的局部区域象素的特征来实现图像分割,如阈值分割、区域生长、边缘检测、纹理分析等,这些方法假定事先知道这些区域的特性,或者在处理过程中能够求得这些特性,从而能够寻找各种形态或研究各像素群。非结构分割法包括统计模式识别、神经网络方法或其它利用景物的先验知识实现的方法等等。这些内容由于专业性很强,就不在本文讨论内容中了,有兴趣的读者可以参考图像处理的专业书籍。总之,图像分割可以分为图像的边缘提取和图像的二值化二部分内容,下面我们首先来讨论一下各种常用的图像边缘提取的方法。

二、图像边缘检测

数字图像的边缘检测是图像分割、目标区域的识别、区域形状提取等图像分析领域十分重要的基础,是图像识别中提取图像特征的一个重要属性,图像理解和分析的第一步往往就是边缘检测,目前它以成为机器视觉研究领域最活跃的课题之一,在工程应用中占有十分重要的地位。物体的边缘是以图像的局部特征不连续的形式出现的,也就是指图像局部亮度变化最显著的部分,例如灰度值的突变、颜色的突变、纹理结构的突变等,同时物体的边缘也是不同区域的分界处。图像边缘有方向和幅度两个特性,通常沿边缘的走向灰度变化平缓,垂直于边缘走向的像素灰度变换剧烈,根据灰度变化的特点,可分为阶跃型、房顶型和凸缘型,如图一所示,这些变化对应图像中不同的景物。需要读者注意的是,实际分析中图像要复杂的多,图像边缘的灰度变化情况并不仅限于上述标准情况。

(a)阶跃型(b) 房顶型(c) 凸缘型

图一边缘灰度变换的几种类型

由于边缘是图像上灰度变化最剧烈的地方,传统的边缘检测就是利用了这个特点,对图像各个像素点进行微分或求二阶微分来确定边缘像素点。一阶微分图像的峰值处对应着图像的边缘点;二阶微分图像的过零点处对应着图像的边缘点。根据数字图像的特点,处理图像过程中常采用差分来代替导数运算,对于图像的简单一阶导数运算,由于具有固定的方向性,只能检测特定方向的边缘,所以不具有普遍性。为了克服一阶导数的缺点,我们

定义了图像的梯度为梯度算子为,它是图像处理中最常用的一阶微分算法,式子中表示图像的灰度值,图像梯度的最重要性质是梯度的方向是在图像灰度最大变化率上,它恰好可以放映出图像边缘上的灰度变化。

图像边缘提取的常用梯度算子有Robert算子、Sobel算子、Prewitt算子、Krisch算子等。下面以边缘检测Sobel算子为例来讲述数字图像处理中边缘检测的实现:

对于数字图像,可以用一阶差分代替一阶微分;

△xf(x,y)=f(x,y)-f(x-1,y);

△yf(x,y)=f(x,y)-f(x,y-1);

求梯度时对于平方和运算及开方运算,可以用两个分量的绝对值之和表示,即:

Sobel梯度算子是先做成加权平均,再微分,然后求梯度,即:

△xf(x,y)= f(x-1,y+1) + 2f(x,y+1) + f(x+1,y+1)- f(x-1,y-1) - 2f(x,y-1) - f(x+1,y-1);

△yf(x,y)= f(x-1,y-1) + 2f(x-1,y) + f(x-1,y+1)- f(x+1,y-1) - 2f(x+1,y) - f(x+1,y+1);

G[f(x,y)]=|△xf(x,y)|+|△yf(x,y)|;

上述各式中的像素之间的关系见图二

图二 Sober算子中各个像素点的关系图

我在视图类中定义了响应菜单命令的边缘检测Sobel算子实现灰度图像边缘检测的函数(图像数据的获取可以参见我在天极网上发表的的相关文章):

void CDibView::OnMENUSobel()

{

CClientDC pDC(this);

HDC hDC=pDC.GetSafeHdc();//获取当前设备上下文的句柄;

SetStretchBltMode(hDC,COLORONCOLOR);

HANDLE data1handle;

LPDIBHDRTMAPINFOHEADER lpDIBHdr;

CDibDoc *pDoc=GetDocument();

HDIB hdib;

unsigned char *lpDIBBits;

unsigned char *data;

hdib=pDoc->m_hDIB;//得到图象数据;

lpDIBHdr=(LPDIBHDRTMAPINFOHEADER)GlobalLock((HGLOBAL)hdib);

lpDIBBits= lpDIBHdr +* (LPDWORD)lpDIBHdr + 256*sizeof(RGBQUAD);

//得到指向位图像素值的指针;

data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpDIBHdr->biWidth*8)*lpDIBHdr->biHeight); //申请存放处理后的像素值的缓冲区

data=(unsigned char*)GlobalLock((HGLOBAL)data1handle);

AfxGetApp()->BeginWaitCursor();

int i,j,buf,buf1,buf2;

for( j=0; jbiHeight; j++)//以下循环求(x,y)位置的灰度值

for( i=0; ibiWidth; i++)

{

if(((i-1)>=0)&&((i+1)biWidth)&&((j-1)>=0)&&((j+1)biHeight))

{//对于图像四周边界处的向素点不处理

buf1=(int)*(lpDIBBits+(i+1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j-1))

+2*(int)*(lpDIBBits+(i+1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j))

+(int)(int)*(lpDIBBits+(i+1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j+1));

buf1=buf1-(int)(int)*(lpDIBBits+(i-1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j-1))

-2*(int)(int)*(lpDIBBits+(i-1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j))

-(int)(int)*(lpDIBBits+(i-1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j+1));

//以上是对图像进行水平(x)方向的加权微分

buf2=(int)(int)*(lpDIBBits+(i-1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j+1))

+2*(int)(int)*(lpDIBBits+(i)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j+1))

+(int)(int)*(lpDIBBits+(i+1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j+1));

buf2=buf2-(int)(int)*(lpDIBBits+(i-1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j-1))

-2*(int)(int)*(lpDIBBits+(i)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j-1))

-(int)(int)*(lpDIBBits+(i+1)*WIDTHBYTES(lpDIBHdr->biWidth*8)+(j-1));

//以上是对图像进行垂直(y)方向加权微分

buf=abs(buf1)+abs(buf2);//求梯度

if(buf>255) buf=255;

if(buf<0)buf=0;

相关文档
最新文档