2019-12-12 22:48:37 weixin_44225182 阅读数 122
  • MATLAB图像处理

    介绍MATLAB提供的图像处理功能,包括图像基础知识、图像合成、空间变换、邻域和块处理、局部滤波、正交变换、数学形态学、图像分析、图像增强、图像恢复、图像分割、图像配准和图像三维重建等内容。

    29 人正在学习 去看看 苏金明

一、实验名称

数学形态学应用

二、实验目的

1.熟悉MATLAB软件的使用。
2.掌握数字图像处理中的腐蚀、膨胀定义及操作。
3.掌握图像的开运算、闭运算

三、实验内容

1.在长方形目标物A中,内部有噪声导致的空洞,周围有噪声块。编写MATLAB程序,达到处理后效果:目标本身除了4个角的直角变为圆角外没有变化。
2.利用击中击不中原理,确定所需判断图像在图像中的位置

四、实验仪器与设备

Win10 64位电脑
MATLAB R2017a

五、实验原理

1.腐蚀
    把结构元素B平移a后得到Ba,若Ba包含于X,我们记下这个a点,所有满足上述条件的a点组成的集合称做X被B腐蚀(Erosion)的结果。用公式表示为:E(X)={a| Ba∈X}=XB。原理图如下:
在这里插入图片描述
2.膨胀
    膨胀(dilation)可以看做是腐蚀的对偶运算,其定义是:把结构元素B平移a后得到Ba,若Ba击中X,我们记下这个a点。所有满足上述条件的a点组成的集合称做X被B膨胀的结果。用公式表示为:D(X)={a | Ba↑X}=X B,如图6.13所示。图6.13中X是被处理的对象,B是结构元素,不难知道,对于任意一个在阴影部分的点a,Ba击中X,所以X被B膨胀的结果就是那个阴影部分。阴影部分包括X的所有范围,就象X膨胀了一圈似的,这就是为什么叫膨胀的原因。原理图如下:
在这里插入图片描述
3.击中与击不中原理
    击中击不中变换(HMT)需要两个结构元素B1和B2,合成一个结构元素对B=(B1,B2)一个用于探测图像内部,作为击中部分;另一个用于探测图像外部,作为击不中部分。显然,B1和B2是不应该相连接的,即B1∩B2=Φ。击中击不中变换的数学表达式为:
g(x, y)=hitmiss[f(x, y), B]=erode[f(x, y), B1]AND erode[fc(x, y), B2]
其中,fc(x,y)表示的是f(x,y)的补集。

Hit-miss算法步骤:
击中击不中变换是形态学中用来检测特定形状所处位置的一个基本工具。它的原理就是使用腐蚀;如果要在一幅图像A上找到B形状的目标,我们要做的是:

  1. 建立一个比B大的模板W;使用此模板对图像A进行腐蚀,得到图像假设为Process1;
  2. 用B减去W,从而得到V模板(W-B);使用V模板对图像A的补集进行腐蚀,得到图像假设为Process2
  3. Process1与Process2取交集;得到的结果就是B的位置。这里的位置可能不是B的中心位置,要视W-B时对齐的位置而异; 其实很简单,两次腐蚀,然后交集,结果就出来了。

六、实验过程及代码

1.去除噪声、空洞

A1=imread('noise.png');

C=[0 1 0
   1 1 1
   0 1 0];
A2=imdilate(A1,C);%图像A1被结构元素B膨胀
A3=imdilate(A2,C);
A4=imdilate(A3,C);
A5=imdilate(A4,C);
A6=imdilate(A5,C);
A7=imdilate(A6,C);
A8=imdilate(A7,C);

A9=imerode(A8,C); %腐蚀
A10=imerode(A9,C);
A11=imerode(A10,C);
A12=imerode(A11,C);
A13=imerode(A12,C);
A14=imerode(A13,C);
A15=imerode(A14,C);
A16=imerode(A15,C);
A17=imerode(A16,C);
A18=imerode(A17,C);
A19=imerode(A18,C);
A20=imerode(A19,C);

D=strel('rectangle',[2 2]);
A21=imdilate(A20,C);
A22=imdilate(A21,C);
A23=imdilate(A22,C);
A24=imdilate(A23,C);
A25=imdilate(A24,C);
A26=imdilate(A25,C);
A27=imdilate(A26,C);

imshow(A27);

2.击中与击不中

t=zeros(500,500);

for i=100:200
for j=100:200
t(i,j)=1;
end
end

for i=70:140
for j=370:440
t(i,j)=1;
end
end

for i=300:400
for j=300:480
t(i,j)=1;
end
end

imshow(t);%构造原图

m=zeros(100,100);

for i=1:100
for j=1:100
m(i,j)=1;
end
end

figure,imshow(m);%构造m结构元素

n=zeros(120,120);

for i=1:120
for j=1:120
n(i,j)=1;
end
end

for i=10:110
for j=10:110
n(i,j)=0;
end
end

figure,imshow(n);%构造n结构元素 与m交集为空

x1=imerode(t,m);
figure,imshow(x1);%原图被m结构元素腐蚀后
x2=imerode(~t,n);
figure,imshow(x2);%原图补集被n结构元素腐蚀后

x3=x1.*x2;
figure,imshow(x3);%求两张腐蚀后图像的交集

七、实验结果与分析

1.去除噪声、空洞
在这里插入图片描述在这里插入图片描述
图 1 左:原图 右:处理后

2.击中与击不中
在这里插入图片描述在这里插入图片描述
图 2原图(左) 结构元素m(右,纯白色)

在这里插入图片描述在这里插入图片描述

图 3 原图补集(左) n结构元素
在这里插入图片描述在这里插入图片描述
图 4 m对原图腐蚀后(左) n对原图补集腐蚀后(右)

在这里插入图片描述
图 5两腐蚀图求交集

在这里插入图片描述

图 6 最终结果图(红色线圈出的位置就是我们需要找的位置)

八、实验总结及心得体会

    在这次实验中,自己学会了数字图像处理中的腐蚀、膨胀操作,其原理就是利用集合论的知识,对图像进行处理。这利用MATLAB编程的过程中,遇到了一些小困难,主要原因还是对一些函数的不熟悉。在击中与击不中这一块,感触颇多。这一块内容几乎用了半天的时间,才搞懂。这里暴露出的问题时原理理解的不是很深刻,加之MATLAB这里与课本上的例子有点出入,在这里饶了一点弯路。其实还好,在csdn上看别人写的文章,多看几遍,照着例子多看几遍,最后还是明白了。在击中与击不中实验中,我采用的方法是先自己创造出原图、两个结构元素,这样是为了更好的和课本一致,然后稍微改动了一些,感觉课本在讲这块有点错误,课本是从原理角度解释击中与击不中,在MATLAB中,我们则需要取反即可。

更多

获取更多资料、代码,微信公众号:海轰Pro
回复 海轰 即可

2017-10-17 21:48:05 u012679707 阅读数 287
  • MATLAB图像处理

    介绍MATLAB提供的图像处理功能,包括图像基础知识、图像合成、空间变换、邻域和块处理、局部滤波、正交变换、数学形态学、图像分析、图像增强、图像恢复、图像分割、图像配准和图像三维重建等内容。

    29 人正在学习 去看看 苏金明

一、形态学图像处理知识框架



二、二值图像基本形态学运算

2.1 腐蚀

%% 图像放缩  imgErode.m
%{
函数: I1=imerode(I,se);          %图像腐蚀
       se=strel(shape,parameters);%产生结构元素se
函数说明:图像腐蚀
参数说明: I:输入图像
          se:由strel函数返回的自定义或预设的结构元素对象
返回值:腐蚀后目标图像

备注:strel函数中的shape参数,可以为‘square’(正方形)、‘rectangle’(矩形)等
%}

I=imread('erode_dilate.bmp');

se=strel('square',3);%产生边长为3的正方形结构元素
I1=imerode(I,se);   %腐蚀操作


se=strel('square',6);%产生边长为6的正方形结构元素
I2=imerode(I,se);   %腐蚀操作


subplot(2,3,1);
imshow(I);
title('source');

subplot(2,3,2);
imshow(I1);
title('erode_3');

subplot(2,3,3);
imshow(I2);
title('erode_6');


运算结果:



2.2膨胀

%% 图像膨胀  imgdilate.m
%{
函数: I1=imdilate(I,se);          %图像腐蚀
       se=strel(shape,parameters);%产生结构元素se
函数说明:图像膨胀
参数说明: I:输入图像
          se:由strel函数返回的自定义或预设的结构元素对象
返回值:膨胀后图像

备注:strel函数中的shape参数,可以为‘square’(正方形)、‘rectangle’(矩形)等
%}

I=imread('starcraft.bmp');

se=strel('square',3);%产生边长为3的正方形结构元素
I1=imerode(I,se);   %腐蚀操作


se=strel('square',6);%产生边长为6的正方形结构元素
I2=imerode(I,se);   %腐蚀操作


se=strel('square',3);%产生边长为6的正方形结构元素
I3=imdilate(I,se);   %膨胀操作

se=strel('square',6);%产生边长为6的正方形结构元素
I4=imdilate(I,se);   %膨胀操作


subplot(2,3,1);
imshow(I);
title('source');

subplot(2,3,2);
imshow(I1);
title('erode_3');

subplot(2,3,3);
imshow(I2);
title('erode_6');

subplot(2,3,4);
imshow(I3);
title('dilate_3');

subplot(2,3,5);
imshow(I4);
title('dilate_6');

运算结果:




2.3开及闭运算

%% 二值图像的开和闭运算  imgOpen_Close.m
%{
函数: I1=imopen(I,se);          %图像开运算(先腐蚀后膨胀)
       I1=imclose(I,se);         %图像闭运算(先膨胀后腐蚀)
函数说明:图像开和闭
参数说明: I:输入图像
          se:由strel函数返回的自定义或预设的结构元素对象
返回值:运算后图像

备注:strel函数中的shape参数,可以为‘square’(正方形)、‘rectangle’(矩形)等
备注:开操作,和先用erode后用dilate效果是一样的
%}

I=imread('erode_dilate.bmp');

se=strel('square',6);%产生边长为3的正方形结构元素
I1=imopen(I,se);   %开操作
I2=imclose(I,se);   %闭操作



subplot(2,3,1);
imshow(I);
title('source');

subplot(2,3,2);
imshow(I1);
title('open');

subplot(2,3,3);
imshow(I2);
title('close');

运算结果:



2014-12-24 17:02:15 TonyShengTan 阅读数 4102
  • MATLAB图像处理

    介绍MATLAB提供的图像处理功能,包括图像基础知识、图像合成、空间变换、邻域和块处理、局部滤波、正交变换、数学形态学、图像分析、图像增强、图像恢复、图像分割、图像配准和图像三维重建等内容。

    29 人正在学习 去看看 苏金明

学习DIP第11天

转载请标明出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意。。。。。。。。

形态学

    数学形态学(Mathematical morphology)是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:二值腐蚀和膨胀 (形态学)、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度等。

    由于二值图像为离散的点集,所以我们将二维离散点定义为栅格,坐标定义为光栅坐标,光栅间的距离为采样间隔。

形态学目

内容迁移至 

http://www.face2ai.com/DIP-3-1-二值图像-形态学处理1-数学形态学/

http://www.tony4ai.com/DIP-3-1-二值图像-形态学处理1-数学形态学/

2017-04-14 20:22:18 u010368556 阅读数 4381
  • MATLAB图像处理

    介绍MATLAB提供的图像处理功能,包括图像基础知识、图像合成、空间变换、邻域和块处理、局部滤波、正交变换、数学形态学、图像分析、图像增强、图像恢复、图像分割、图像配准和图像三维重建等内容。

    29 人正在学习 去看看 苏金明

一、引言
        数学形态学是一门建立在集论基础上的学科,是几何形态学分析和描述的有力工具。数学形态学的历史可回溯到19世纪。1964年法国的Matheron和Serra在积分几何的研究成果上,将数学形态学引入图像处理领域,并研制了基于数学形态学的图像处理系统。1982年出版的专著《Image Analysis andMathematical Morphology》是数学形态学发展的重要里程碑,表明数学形态学在理论上趋于完备及应用上不断深入。数学形态学蓬勃发展,由于其并行快速,易于硬件实现,已引起了人们的广泛关注。目前,数学形态学已在计算机视觉、信号处理与图像分析、模式识别、计算方法与数据处理等方面得到了极为广泛的应用。
        数学形态学可以用来解决抑制噪声、特征提取、边缘检测、图像分割、形状识别、纹理分析、图像恢复与重建、图像压缩等图像处理问题。该文将主要对数学形态学的基本理论及其在图像处理中的应用进行综述。

二、数学形态学的定义和分类
        数学形态学是以形态结构元素为基础对图像进行分析的数学工具。它的基本思想是用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的。数学形态学的应用可以简化图像数据,保持它们基本的形状特征,并除去不相干的结构。数学形态学的基本运算有4个:膨胀、腐蚀、开启和闭合。它们在二值图像中和灰度图像中各有特点。基于这些基本运算还可以推导和组合成各种数学形态学实用算法。

(1)二值形态学
        数学形态学中二值图像的形态变换是一种针对集合的处理过程。其形态算子的实质是表达物体或形状的集合与结构元素间的相互作用,结构元素的形状就决定了这种运算所提取的信号的形状信息。形态学图像处理是在图像中移动一个结构元素,然后将结构元素与下面的二值图像进行交、并等集合运算。
        基本的形态运算是腐蚀和膨胀。
        在形态学中,结构元素是最重要最基本的概念。结构元素在形态变换中的作用相当于信号处理中的“滤波窗口”。用B(x)代表结构元素,对工作空间E中的每一点x,腐蚀和膨胀的定义为:
                                                                 

用B(x)对E进行腐蚀的结果就是把结构元素B平移后使B包含于E的所有点构成的集合。用B(x)对E进行膨胀的结果就是把结构元素B平移后使B与E的交集非空的点构成的集合。先腐蚀后膨胀的过程称为开运算。它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。先膨胀后腐蚀的过程称为闭运算。它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。
        可见,二值形态膨胀与腐蚀可转化为集合的逻辑运算,算法简单,适于并行处理,且易于硬件实现,适于对二值图像进行图像分割、细化、抽取骨架、边缘提取、形状分析。但是,在不同的应用场合,结构元素的选择及其相应的处理算法是不一样的,对不同的目标图像需设计不同的结构元素和不同的处理算法。结构元素的大小、形状选择合适与否,将直接影响图像的形态运算结果。因此,很多学者结合自己的应用实际,提出了一系列的改进算法。如梁勇提出的用多方位形态学结构元素进行边缘检测算法既具有较好的边缘定位能力,又具有很好的噪声平滑能力。许超提出的以最短线段结构元素构造准圆结构元素或序列结构元素生成准圆结构元素相结合的设计方法,用于骨架的提取,可大大减少形态运算的计算量,并可同时满足尺度、平移及旋转相容性,适于对形状进行分析和描述。

(2)灰度数学形态学
        二值数学形态学可方便地推广到灰度图像空间。只是灰度数学形态学的运算对象不是集合,而是图像函数。以下设f(x,y)是输入图像,b(x,y)是结构元素。用结构元素b对输入图像y进行膨胀和腐蚀运算分别定义为:

                                                                 

对灰度图像的膨胀(或腐蚀)操作有两类效果:
(1)如果结构元素的值都为正的,则输出图像会比输入图像亮(或暗);
(2)根据输入图像中暗(或亮)细节的灰度值以及它们的形状相对于结构元素的关系,它们在运算中或被消减或被除掉。灰度数学形态学中开启和闭合运算的定义与在二值数学形态学中的定义一致。用b对f进行开启和闭合运算的定义为:

  

(3)模糊数学形态学
        将模糊集合理论用于数学形态学就形成了模糊形态学。模糊算子的定义不同,相应的模糊形态运算的定义也不相同。在此,选用Shinba的定义方法。模糊性由结构元素对原图像的适应程度来确定。用有界支撑的模糊结构元素对模糊图像的腐蚀和膨胀运算按它们的隶属函数定义为:

其中,x,yZ2代表空间坐标,ua,ub分别代表图像和结构元素的隶属函数。从(7),(8)式的结果可知,经模糊形态腐蚀膨胀运算后的隶属函数均落在[0,1]的区间内。模糊形态学是传统数学形态学从二值逻辑向模糊逻辑的推广,与传统数学形态学有相似的计算结果和相似的代数特性。模糊形态学重点研究n维空间目标物体的形状特征和形态变换,主要应用于图像处理领域,如模糊增强、模糊边缘检测、模糊分割等。





2017-04-14 20:33:28 u010368556 阅读数 771
  • MATLAB图像处理

    介绍MATLAB提供的图像处理功能,包括图像基础知识、图像合成、空间变换、邻域和块处理、局部滤波、正交变换、数学形态学、图像分析、图像增强、图像恢复、图像分割、图像配准和图像三维重建等内容。

    29 人正在学习 去看看 苏金明

三、数学形态学在图像处理中的主要应用

近年来,数学形态学在图像处理方面得到了日益广泛的应用。下面主要就数学形态学在边缘检测、图像分割、图像细化以及噪声滤除等方面的应用做简要介绍。

(1)边缘检测

边缘检测是大多数图像处理必不可少的一步,提供了物体形状的重要信息。对于二值图像,边缘检测是求一个集合A的边界,记为B(A):

对于灰度图像,边缘检测是求一幅图像的形态学梯度,记为g:

数学形态学运算用于边缘检测,存在着结构元素单一的问题。它对与结构元素同方向的边缘敏感,而与其不同方向的边缘(或噪声)会被平滑掉,即边缘的方向可以由结构元素的形状确定。但如果采用对称的结构元素,又会减弱对图像边缘的方向敏感性。所以在边缘检测中,可以考虑用多方位的形态结构元素,运用不同的结构元素的逻辑组合检测出不同方向的边缘。

梁勇等人构造了8个方向的多方位形态学结构元素,应用基本形态运算,得到8个方向的边缘检测结果,再把这些结果进行归一化运算、加权求和,得到最终的图像边缘。该算法在保持图像细节特征和平滑边缘等方面,取得了较好的效果。

                              原图:                                                边界提取:

边缘检测源代码:

/********************************************************************
形态学基本操作采用二值图像 
***********************************************************************/
#include<cv.h>
#include <highgui.h>
int main(){
	IplImage * image,*image2,*image3;
	image = cvLoadImage("E:\\image\\mapleleaf.tif", 0);
	cvNamedWindow("image",1);
	cvShowImage("image",image);
	

	/*边界提取*/
   image2 = cvCreateImage(cvSize(image->width, image->height),image->depth ,1);
    image3 = cvCreateImage(cvSize(image->width, image->height),image->depth ,1);
   int  i , j ;
   int left,right, up , down;
   int n = 2;//窗口大小为5*5
   int r,s,flag;
   unsigned char * ptr, *dst;
   for (i = 0 ; i< image->height; i++)
   {
	   for (j = 0 ; j< image->width; j++)
	   {
		   //窗口设定
           left = j - n;
		   right = j +n;
		   up = i -n;
		   down = i+n;
		   //窗口出界处理
		   if(left< 0){left = 0;}
		   if(right >= image->width){right = image->width-1;}
		   if(up< 0){up =0;}
		   if(down >= image->height){down = image->height -1;}

		   //腐蚀处理
		   dst = (unsigned char *)image2->imageData + image2->widthStep*i + j;
		   flag = 1;
		   for (r = up;r <= down;r++)
		   {
			   for (s = left ; s<= right; s++)
			   {
				  ptr = (unsigned char *)image->imageData + r*image->widthStep + s;

				  if(*ptr != 255){
						flag = 0;
				  }
			   }
		   }
		   if (flag == 1)
		   {
			   *dst = 255;
		   }
		   else{
			   *dst = 0;
		   }

	   }
   }
   cvSub(image,image2,image3,0);
   cvNamedWindow("image3",1);
   cvShowImage("image3",image3);
   cvSaveImage("mapleleafboard.bmp", image3);
   cvWaitKey(0);
	cvReleaseImage(&image);
	cvReleaseImage(&image2);
	cvReleaseImage(&image3);
	cvDestroyAllWindows();
	return 0 ;
}


(2)图像分割

      基于数学形态学的图像分割算法是利用数学形态学变换,把复杂目标X分割成一系列互不相交的简单子集X1,X2,…,XN,即:

       对目标X的分割过程可按下面的方法完成:首先求出X的最大内接“圆”X1,然后将X1从X中减去,再求X-X1的最大内接“圆”X2,…,依此类推,直到最后得到的集合为空集为止。下面以二值图像为例,介绍用数学形态学方法求解子集X1,X2,…,XN的过程。

     设B为结构元素,B可以是圆、三角形、正方形等简单的几何基元,那么“简单”形状集合Xi可以用下面的公式来定义:

      式中ni为一整数,用上式定义Xi分割目标,有时会产生分割过程不唯一的现象。为此可采用下面公式来定义简单集合Xi:

      其中Li为一个点或一条线,当Li为点时,则与(12)式定义等价。(13)式定义的简单形状Xi可由niB沿线Li移动而产生。即将“产生器”niB的中心沿“脊骨”Li移动产生。如果niB为圆,则得到的Xi称Blum带。它具有一些特殊的性质,如Xi的边界是光滑的,Xi的最大圆与其边界相切,Xi的脊骨与产生器都是唯一的等等。

      有了简单形状集合Xi的定义,则目标X可按下面方法分割。首先按式(14)求出X的最大内切结构元素Xi:

      数学形态学用于图像分割的缺点是对边界噪声敏感。为了改善这一问题,刘志敏等人提出了基于图像最大内切圆的数学形态学形状描述图像分割算法和基于目标最小闭包结构元素的数学形态学形状描述图像分割算法,并使用该算法对二值图像进行了分割,取得了较好的效果。邓世伟等人提出一种基于数学形态学的深度图像分割算法。作者首先利用形态学算子获得分别含有阶跃边缘与屋脊边缘的凸脊和凹谷图像,然后利用控制区域生长过程得到最终的分割结果。与传统方法相比,该方法速度快,抗噪性能好。

(3) 形态骨架提取

       形态骨架描述了物体的形状和方向信息。它具有平移不变性、逆扩张性和等幂性等性质,是一种有效的形状描述方法。二值图像A的形态骨架可以通过选定合适的结构元素B,对A进行连续腐蚀和开启运算来求取,设S(A)代表A的骨架,定义为:

       蒋刚毅等人运用数学形态学方法,对交通标志的内核形状提取形态骨架函数,将其作为用于模式匹配的形状特征。A的形态骨架函数SKF(A)表示为:

      SKF(X)中值较大的点对应大的n,并代表了形态骨架的主要成分,即表达了形状的主体结构;而SKF(X)中值较小的点对应小的n,是形态骨架的细节成分,与形状的边缘信息相联系。

      形态骨架函数完整简洁地表达了形态骨架的所有信息,因此,根据形态骨架函数的模式匹配能够实现对不同形状物体的识别。算法具有位移不变性,因而使识别更具稳健性。

                                      原图:                                                             提取骨架:                                                         DNA原图:                                             骨架:


骨架提取原代码:

/************************************************************************/
/* 骨架提取*/
/************************************************************************/
#include<cv.h>
#include <highgui.h>
int main(){
	IplImage* image = cvLoadImage("E:\\image\\bone.tif",0);
	cvNamedWindow("image",1);
	cvNamedWindow("image2",1);
	cvNamedWindow("image3",1);
	cvNamedWindow("image4",1);
	cvNamedWindow("image5",1);
	cvNamedWindow("image6",1);

	cvNamedWindow("result",1);
	cvShowImage("image", image);
	//cvWaitKey(0);
	//当前图片image2  当前被腐蚀后的图片image3 被腐蚀开操作之后的图片 image5 
	//image4 作为开操作的中间值 作差后的图片image6  并之后的图片result  
	IplImage *image2, *image3 , *image4, *image5,*image6,*result;
	image2 = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
	image3 = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
    image5 = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
    image4 = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
	image6 = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
	result = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
	
	//循环标志 flag
	bool flag = true;
	//腐蚀判断标志 flag2
	bool flag2  = true;
	int i,j,r,s;
	unsigned char * ptr,*dst;
	unsigned char B[9] = {255 ,255,255,255,255,255,255,255,255};
	//对result进行赋值 全部为0 
	for (i = 0 ; i< result->height; i++)
	{
		for (j = 0 ; j< result->width ; j++)
		{
			dst = (unsigned char *)(result->imageData + result->widthStep *i +j);
			*dst = 0;
		}
	}
	image2 = cvCloneImage(image);
	cvShowImage("image2", image2);
	//cvWaitKey(0);
	while (flag)
	{
		//flag = false;
		cvShowImage("image2",image2);
		//进行腐蚀操作,开环操作 作差 并
		for (i = 0 ; i< image3->height; i++)
		{
			for (j = 0 ; j< image3->width ; j++)
			{
			dst =  (unsigned char *)(image3->imageData + i*image3->widthStep + j);
				if ((i == 0 )|| (j == 0) ||( i == image->height -1 ) || (j == image->width -1 ))
				{
					*dst = 0;
					//break;
				}
				else{
				flag2 = true;
				for (r = i-1 ; r<= i+1 ; r++)
				{
					for (s = j -1 ; s<= j+1 ; s++)
					{
						ptr  = (unsigned char *)(image2->imageData + r*image2->widthStep + j);
						if(*ptr != 255){
							flag2 =false;
						}
					}
				}
				
				if (flag2)
				{
					*dst = 255;
				}
				else {*dst = 0;}
				}
			}
		}
		cvShowImage("image3",image3);
		

	//开操作 先腐蚀 后膨胀 
		for (i = 0 ; i< image4->height; i++)
		{
			for (j = 0 ; j< image4->width ; j++)
			{
				dst =  (unsigned char *)(image4->imageData + i*image4->widthStep + j);
				if ((i == 0 )|| (j == 0) ||( i == image->height -1 ) || (j == image->width -1 ))
				{
					*dst = 0;
					//break;
				}
				else{
				flag2 = true;
				for (r = i-1 ; r<=  i+1 ; r++)
				{
					for (s = j -1 ; s<= j+1 ; s++)
					{
						ptr  = (unsigned char *)(image3->imageData + r*image3->widthStep + s);
						if(*ptr != 255){
							flag2 =false;
						}
					}
				}
				
				if (flag2)
				{
					*dst = 255;
				}
				else {*dst = 0;}
				}
			}
		}
		cvShowImage("image4",image4);
		//膨胀操作
		for (i = 0 ; i< image5->height; i++)
		{
			for (j = 0 ; j< image5->width ; j++)
			{
				dst =  (unsigned char *)(image5->imageData + i*image5->widthStep + j);
				if ((i == 0 )|| (j == 0) ||( i == image5->height -1 ) || (j == image5->width -1 ))
				{
					*dst = 0;
					//break;
				}
				else{
				flag2 = false;
				for (r = i-1 ; r<= i+1 ; r++)
				{
					for (s = j -1 ; s<= j+1 ; s++)
					{
						ptr  = (unsigned char *)(image4->imageData + r*image4->widthStep + s);
						if(*ptr == 255){
							flag2 = true;
						}
					}
				}
				
				if (flag2)
				{
					*dst = 255;
				}
				else {*dst = 0;}
				}
			}
		}
			cvShowImage("image5",image5);


     //作差
      cvSub(image3,image5,image6,0);
	  //并运算
	  for (i = 0 ; i< result->height; i++)
	  {
		  for (j = 0 ; j< result->width ; j++)
		  {
			  dst = (unsigned char *)(result->imageData + result->widthStep *i +j);
			  ptr = (unsigned char *)(image6->imageData + image6->widthStep *i +j);
			  if (*ptr == 255)
			  {

				  *dst = 255;
			  }
		  }
	  }
	  	cvShowImage("image6",image6);
	  //将腐蚀后的图像复制给当前图像image2
	 image2 =  cvCloneImage(image3);

	  //循环标志判定
	  flag = false;
	  for (i = 0 ; i< image2->height; i++)
	  {
		  for (j = 0 ; j< image2->width ; j++)
		  {
			 
			  ptr = (unsigned char *)(image2->imageData + image2->widthStep *i +j);
			  if (*ptr == 255)
			  {
				  flag = true;
			  }
		  }
	  }
	  cvShowImage("result", result);
	  cvWaitKey(40);
	}
	
	cvShowImage("image2", image2);
	cvShowImage("image3", image3);
	//cvShowImage("image4", image4);
	//cvShowImage("image5", image5);
	//cvShowImage("image6", image6);
	cvShowImage("result",result);
	cvSaveImage("E:\\image\\bonegujia.bmp",result);
	cvWaitKey(0);
	cvReleaseImage(&image);
	cvDestroyAllWindows();
	return 0;
}

形态学算法对于提取交叉的物体,会产生断裂,一般会在提取之后紧跟连接操作。

                                      原图:                                                                             提取的角点:


 角点提取源代码:采用击中击不中

/********************************************************************
形态学基本操作采用二值图像 形态学方法在边界获取和形状检测中有很多应用 寻找角点
***********************************************************************/
#include<cv.h>
#include <highgui.h>
int main(){
	IplImage * image,*image2,*image3,*image4,*result;
	image = cvLoadImage("E:\\image\\jiaodian.bmp", 0);
	cvNamedWindow("image",1);
	cvShowImage("image",image);


	/*击中击不中变换 寻找角点*/ 
	/************************************************************************/
	/*   最终结果为(79, 85 )和 (129 ,134)两个符合要求的角点  在结果图像中可以看到两个白点*/
	/************************************************************************/
	image2 = cvCreateImage(cvSize(image->width, image->height),image->depth ,1);
	image3 = cvCreateImage(cvSize(image->width, image->height),image->depth ,1);
	image4 = cvCreateImage(cvSize(image->width, image->height),image->depth ,1);
	result = cvCreateImage(cvSize(image->width, image->height),image->depth ,1);

	int  i,j,r,s ;
	unsigned char B1[9] ={ 255,255,255,255,0,0,255,0,0};
	unsigned char B2[9] = {0,0,0,0,255,255,0,255,255 };
	int flag;
//iamge2 是对image进行求补的结果
	unsigned char *ptr, *dst,*ptr2;
	for (i = 0 ; i< image2->height; i++)
	{
		for (j = 0 ; j< image2->width; j++)
		{
			ptr = (unsigned char*)image->imageData + i * image->widthStep+ j;
			dst = (unsigned char*)image2->imageData + i*image2->widthStep + j;
			*dst = 255- (*ptr);

		}
	}

	//对源图像进行腐蚀
	for (i = 0 ; i< image3->height; i++)
	{
		for (j = 0 ; j< image3->width; j++)
		{
			flag = 1;
			dst = (unsigned char*)image3->imageData + i*image3->widthStep +j;
			//边界判断
			if (( i == 0) || (j == 0) || (i == image3->height-1) || (j == image3->width -1 ))
			{
				*dst = 0;
			}
			else{
					for (r = i -1 ; r<= i+1; r++)
					{
						for (s = j-1 ; s <= j +1 ; s++)
						{
							ptr = (unsigned char*)image->imageData + r * image->widthStep+ s;
							if (*ptr != B1[3*(r-i+1) + s-j+1])
							{
							flag = 0;
							break;
							}
						}
					}
					if (flag == 1)
					{
						ptr = (unsigned char*)image->imageData + i * image->widthStep+ j;
						*dst = 255;
					}
					else{
						*dst = 0;
					}

				}

		}
	}

	//显示腐蚀结果

	for (i = 0 ; i< image2->height; i++)
	{
		for (j = 0 ; j< image2->width; j++)
		{
			ptr = (unsigned char*)image->imageData + i * image->widthStep+ j;
			ptr2 = (unsigned char*)image3->imageData + i*image3->widthStep + j;
			if (*ptr2  == 255)
			{
				printf("x, %d  y: %d   %d\n",j, i, *ptr2 - *ptr);
			}
			
		}
	}
	//对补图像进行腐蚀
	for (i = 0 ; i< image4->height; i++)
	{
		for (j = 0 ; j< image4->width; j++)
		{
			flag = 1;
			dst = (unsigned char*)image4->imageData + i*image4->widthStep +j;
			//边界判断
			if (( i == 0) || (j == 0) || (i == image4->height-1) || (j == image4->width -1 ))
			{
				*dst = 0;
			}
			else{
				for (r = i -1 ; r<= i+1; r++)
				{
					for (s = j-1 ; s <= j +1 ; s++)
					{
						ptr = (unsigned char*)image2->imageData + r * image2->widthStep+ s;
						if ((*ptr) != B2[3*(r- i+1) + s-j +1])
						{
							flag = 0;
						}
					}
				}
				if (flag == 1)
				{
					ptr = (unsigned char*)image2->imageData + i * image2->widthStep+ j;
					*dst = 255;
				}
				else{
					*dst = 0;
				}

			}

		}
	}
	//显示腐蚀结果

	for (i = 0 ; i< image4->height; i++)
	{
		for (j = 0 ; j< image4->width; j++)
		{
			ptr = (unsigned char*)image2->imageData + i * image->widthStep+ j;
			ptr2 = (unsigned char*)image4->imageData + i*image3->widthStep + j;
			if (*ptr2  == 255)
			{
				printf("x, %d  y: %d   %d\n",j,i, *ptr2 - *ptr);
			}

		}
	}
	//二者求交集
	for (i = 0 ; i< result->height; i++)
	{
		for (j = 0 ; j< result->width; j++)
		{
			ptr = (unsigned char *)image3->imageData + image3->widthStep * i + j;
			ptr2 = (unsigned char *)image4->imageData + image4->widthStep * i + j;
			dst = (unsigned char *)result->imageData +  result->widthStep*i + j;
			if (((*ptr) == 255) && ((*ptr2) == 255))
			{
				*dst = 255;
				printf("x : %d\n" , j);
				printf("y : %d\n" , i);

			}
			else{
				
				*dst = 0;
			}

		}
	}
	cvNamedWindow("image3",1);
	cvNamedWindow("image4",1);
	cvNamedWindow("result",1);
	cvShowImage("image3",image3);
	cvShowImage("image4",image4);
	cvShowImage("result",result);
	//cvSaveImage("mapleleafboard.bmp", image3);
	cvWaitKey(0);
	cvReleaseImage(&image);
	cvReleaseImage(&image2);
	cvReleaseImage(&image3);
	cvDestroyAllWindows();
	return 0 ;
}

(4)噪声滤除

       对图像中的噪声进行滤除是图像预处理中不可缺少的操作。将开启和闭合运算结合起来可构成形态学噪声滤除器。

      对于二值图像,噪声表现为目标周围的噪声块和目标内部的噪声孔。用结构元素B对集合A进行开启操作,就可以将目标周围的噪声块消除掉;用B对A进行闭合操作,则可以将目标内部的噪声孔消除掉。该方法中,对结构元素的选取相当重要,它应当比所有的噪声孔和噪声块都要大。

      对于灰度图像,滤除噪声就是进行形态学平滑。实际中常用开启运算消除与结构元素相比尺寸较小的亮细节,而保持图像整体灰度值和大的亮区域基本不变;用闭合运算消除与结构元素相比尺寸较小的暗细节,而保持图像整体灰度值和大的暗区域基本不变。将这两种操作综合起来可达到滤除亮区和暗区中各类噪声的效果。同样的,结构元素的选取也是个重要问题。





没有更多推荐了,返回首页