资源描述
实 验 报 告实验课程: 数字图像处理 学生姓名: 涂汉江 学 号: 6100410181 专业班级: 数媒101班 2013年 06月 08日南昌大学实验报告-(1)数据图像显示的Vc程序设计学生姓名: 涂汉江 学 号: 6100410181 专业班级: 数媒101班 实验类型:验证 综合 设计 创新 实验日期: 2013.06.01 实验成绩: 一 实验目的位图图片显示的C语言实现。二 实验要求用C语言编写简单的程序用来打开位图文件。三 实验环境PC机VC6.0四 实验原理 无五 实验代码及结果/主要代码部分void CCOpenImageDoc:OnFileOpen() / TODO: Add your command handler code hereCFileDialog dlg(TRUE,0,0,OFN_HIDEREADONLY, _T(位图文件|*.bmp|所有文件|*.*|);if(dlg.DoModal()=IDOK)FileName=dlg.GetPathName();if(fileheader) delete fileheader;if(infoheader) delete infoheader;if(pal) delete pal;if(BMPData) delete BMPData;if(flag) flag=false;if(!file.Open(FileName,CFile:modeRead)return;fileheader=new BITMAPFILEHEADER1;infoheader=new BITMAPINFOHEADER1;file.Read(fileheader,sizeof(BITMAPFILEHEADER);if(fileheader-bfType!=0x4D42) return;file.Read(infoheader,sizeof(BITMAPINFOHEADER);if(infoheader-biCompression!=0) return;linebytes=WIDTHBYTES(infoheader-biBitCount*infoheader-biWidth);if(infoheader-biBitCount=8)pal=new RGBQUAD256;BMPData=new BYTElinebytes*infoheader-biHeight;file.Read(pal,256*4);file.Read(BMPData,linebytes*infoheader-biHeight);flag=true;else if(infoheader-biBitCount=24)BMPData=new BYTElinebytes*infoheader-biHeight;file.Read(BMPData,linebytes*infoheader-biHeight);flag=true;else return;file.Close();UpdateAllViews(NULL);/结果截图六 实验小结BMP文件格式比一开始做的DAT文件复杂,有一个文件头来记录相关的图片信息,而且文件里图片的存储方式是和正常的扫描顺序相反的,也就是说输出的时候要倒过来输出,所以也需要注意。南昌大学实验报告-(2)直方图均衡化图像增强学生姓名: 涂汉江 学 号: 6100410181 专业班级: 数媒101班实验类型:验证 综合 设计 创新 实验日期: 2013.06.01 实验成绩: 一 实验目的用C语言实现图像的直方图均衡化处理。二 实验要求用C语言实现图像的直方图均衡化处理。三 实验环境PC机VC6.0四 实验原理 图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法。直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而“扩大”前景和背景灰度的差别,以达到增强对比度的目的,这种方法可以利用线性或非线性的方法来实现;直方图均衡化则通过使用累积函数对灰度值进行“调整”以实现对比度的增强。 直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。这种方法通常用来增加许多图像的局部对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。原理: 直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。 直方图均衡化的基本思想是把原始图的直方图变换为均匀分布的形式,这样就增加了象素灰度值的动态范围从而可达到增强图像整体对比度的效果。设原始图像在(x,y)处的灰度为f,而改变后的图像为g,则对图像增强的方法可表述为将在(x,y)处的灰度f映射为g。在灰度直方图均衡化处理中对图像的映射函数可定义为:g = EQ (f),这个映射函数EQ(f)必须满足两个条件(其中L为图像的灰度级数): (1)EQ(f)在0fL-1范围内是一个单值单增函数。这是为了保证增强处理没有打乱原始图像的灰度排列次序,原图各灰度级在变换后仍保持从黑到白(或从白到黑)的排列。 (2)对于0fL-1有0gL-1,这个条件保证了变换前后灰度值动态范围的一致性。 累积分布函数(cumulative distribution function,CDF)即可以满足上述两个条件,并且通过该函数可以完成将原图像f的分布转换成g的均匀分布。此时的直方图均衡化映射函数为:= EQ() = (ni/n) = pf() ,(k=0,1,2,L-1)上述求和区间为0到k,根据该方程可以由源图像的各像素灰度值直接得到直方图均衡化后各像素的灰度值。在实际处理变换时,一般先对原始图像的灰度情况进行统计分析,并计算出原始直方图分布,然后根据计算出的累计直方图分布求出到的灰度映射关系。在重复上述步骤得到源图像所有灰度级到目标图像灰度级的映射关系后,按照这个映射关系对源图像各点像素进行灰度转换,即可完成对源图的直方图均衡化。五 实验代码及结果/主要代码部分void CImageDoc:OnHistogram() / TODO: Add your command handler code hereint x,y;double *MResult;double *MSource;MResult = new double256;MSource = new double256;for(x=0;x256;x+)MResultx = MSourcex = 0.0;/统计直方图for(y = 0; y Height; y+)for(x = 0; x Width; x+) MResultSourcey*Width+x +; for(x=0;x256;x+)for(y=0;yx;y+)MSourcex += MResulty;MSourcex /= Height*Width;/直方图变换for(y = 0; y Height; y+)for(x = 0; x Width; x+)Resulty*Height+x = (char) (255* MSourceSourcey*Height+x);/灰度计算for(y = 0; y Height; y+)for(x = 0; x 空域卷积。滤波器就是建立的一个数学模型,通过这个模型来将图像数据进行能量转化,能量低的就排除掉,噪声就是属于低能量部分。若使用理想滤波器,会在图像中产生振铃现象。采用高斯滤波器的话,系统函数是平滑的,避免了振铃现象。高斯模糊是一种图像滤波器,它使用正态分布(高斯函数)计算模糊模板,并使用该模板与原图像做卷积运算,达到模糊图像的目的。N维空间正态分布方程为:其中,是正态分布的标准差,值越大,图像越模糊(平滑)。r为模糊半径,模糊半径是指模板元素到模板中心的距离。如二维模板大小为m*n,则模板上的元素(x,y)对应的高斯计算公式为:在二维空间中,这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆。分布不为零的像素组成的卷积矩阵与原始图像做变换。每个像素的值都是周围相邻像素值的加权平均。原始像素的值有最大的高斯分布值,所以有最大的权重,相邻像素随着距离原始像素越来越远,其权重也越来越小。这样进行模糊处理比其它的均衡模糊滤波器更高地保留了边缘效果。理论上来讲,图像中每点的分布都不为零,这也就是说每个像素的计算都需要包含整幅图像。在实际应用中,在计算高斯函数的离散近似时,在大概3距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。通常,图像处理程序只需要计算(6+1)*(6+1)的矩阵就可以保证相关像素影响。五 实验代码及结果/主要代码部分void CImageDoc:Gaussfilter(unsigned char *Source, unsigned char *Result,int Height, int Width, int nR) int k=(int)(3);for(int y=0;yHeight;y+)for(int x=0;xWidth;x+)if(xk|yWidth-k-1|yHeight-k-1)Resulty*Width+x=255;elseResulty*Width+x=0;double sum=0; for(int i=-k;ik+1;i+) for(int j=-k;jk+1;j+)sum+=Source(y+i)*Width+x+j*(1/(2*3.14)*pow(2.718,(-1)*(pow(i-1,2)+pow(j-1,2)/2 );Resulty*Width+x=(int)(sum);void CImageDoc:OnGaussfilter() / TODO: Add your command handler code hereGaussfilter(Source, Result, Height, Width,1); for(int y=0;yHeight;y+)for(int x=0;xWidth;x+)PResult3*y*Width+3*x = Resulty*Width+x;PResult3*y*Width+3*x+1 = Resulty*Width+x;PResult3*y*Width+3*x+2 = Resulty*Width+x; UpdateAllViews(NULL);/结果截图六 实验小结高斯滤波实质上是一种信号的滤波器,其用途为信号的平滑处理,数字图像用于后期应用,其噪声是最大的问题,因为误差会累计传递等原因,大多图像处理教材会在很早的时候介绍Gauss滤波器,用于得到信噪比SNR较高的图像(反应真实信号)。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。 南昌大学实验报告-(4)图像的梯度算子边缘提取学生姓名: 涂汉江 学 号: 6100410181 专业班级: 数媒101班 实验类型:验证 综合 设计 创新 实验日期: 2013.06.01 实验成绩: 一 实验目的实现边缘提取。二 实验要求实现边缘提取。三 实验环境PC机VC6.0四 实验原理边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。 这些包括(i)深度上的不连续、(ii)表面方向不连续、(iii)物质属性变化和(iv)场景照明变化。 边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。如果将边缘认为是一定数量点亮度发生变化的地方,那么边缘检测大体上就是计算这个亮度变化的导数。为简化起见,我们可以先在一维空间分析边缘检测。在这个例子中,我们的数据是一行不同点亮度的数据。例如,在下面的1维数据中我们可以直观地说在第4与第5个点之间有一个边界:除非场景中的物体非常简单并且照明条件得到了很好的控制,否则确定一个用来判断两个相邻点之间有多大的亮度变化才算是有边界的阈值,并不是一件容易的事。实际上,这也是为什么边缘检测不是一个微不足道问题的原因之一。检测方法:有许多用于边缘检测的方法, 他们大致可分为两类:基于搜索和基于零交叉。基于搜索的边缘检测方法首先计算边缘强度, 通常用一阶导数表示, 例如梯度模,然后,用计算估计边缘的局部方向, 通常采用梯度的方向,并利用此方向找到局部梯度模的最大值。基于零交叉的方法找到由图像得到的二阶导数的零交叉点来定位边缘。 通常用拉普拉斯算子或非线性微分方程的零交叉点。滤波做为边缘检测的预处理通常是必要的,通常采用高斯滤波。已发表的边缘检测方法应用计算边界强度的度量,这与平滑滤波有本质的不同。 正如许多边缘检测方法依赖于图像梯度的计算,他们用不同种类的滤波器来估计x-方向和y-方向的梯度。计算一阶导数:许多边缘检测操作都是基于亮度的一阶导数这样就得到了原始数据亮度的梯度。使用这个信息我们能够在图像的亮度梯度中搜寻峰值。如果 I(x) 表示点 x 的亮度,I(x) 表示点 x 的一阶导数(亮度梯度),这样我们就会发现: 对于更高性能的图像处理来说,一阶导数能够通过带有掩码的原始数据(1维)卷积计算得到。计算二阶导数:其它一些边缘检测操作是基于亮度的二阶导数。这实质上是亮度梯度的变化率。在理想的连续变化情况下,在二阶导数中检测过零点将得到梯度中的局部最大值。另一方面,二阶导数中的峰值检测是边线检测,只要图像操作使用一个合适的尺度表示。如上所述,边线是双重边缘,这样我们就可以在边线的一边看到一个亮度梯度,而在另一边看到相反的梯度。这样如果图像中有边线出现的话我们就能在亮度梯度上看到非常大的变化。为了找到这些边线,我们可以在图像亮度梯度的二阶导数中寻找过零点。如果 I(x) 表示点 x 的亮度,I(x) 表示点 x 亮度的二阶导数,那么: 同样许多算法也使用卷积掩码快速处理图像数据:步骤:滤波:边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数的计算对噪声很敏感,因此必须使用滤波器来改善与噪声有关的边缘检测器的性能。需要指出,大多数滤波器在降低噪声的同时也导致了边缘强度的损失,因此,增强边缘和降低噪声之间需要折中。增强:增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将邻域(或局部)强度值有显著变化的点突显出来。边缘增强一般是通过计算梯度幅值来完成的。检测:在图像中有许多点的梯度幅值比较大,而这些点在特定的应用领域中并不都是边缘,所以应该用某种方法来确定哪些点是边缘点。最简单的边缘检测判据是梯度幅值阈值判据。定位:如果某一应用场合要求确定边缘位置,则边缘的位置可在子像素分辨率上来估计,边缘的方位也可以被估计出来。在边缘检测算法中,前三个步骤用得十分普遍。这是因为大多数场合下,仅仅需要边缘检测器指出边缘出现在图像某一像素点的附近,而没有必要指出边缘的精确位置或方向。边缘检测的实质是采用某种算法来提取出图像中对象与背景问的交界线。我们将边缘定义为图像中灰度发生急剧变化的区域边界。图像灰度的变化情况可以用图像灰度分布的梯度来反映,因此我们可以用局部图像微分技术来获得边缘检测算子。经典的边缘检测方法,是通过对原始图像中像素的某小邻域构造边缘检测算子来达到检测边缘这一目的的。阈值确定:一旦我们计算出导数之后,下一步要做的就是给出一个阈值来确定哪里是边缘位置。阈值越低,能够检测出的边线越多,结果也就越容易受到图片噪声的影响,并且越容易从图像中挑出不相关的特性。与此相反,一个高的阈值将会遗失细的或者短的线段。一个常用的这种方法是带有滞后作用的阈值选择。这个方法使用不同的阈值去寻找边缘。首先使用一个阈值上限去寻找边线开始的地方。一旦找到了一个开始点,我们在图像上逐点跟踪边缘路径,当大于门槛下限时一直纪录边缘位置,直到数值小于下限之后才停止纪录。这种方法假设边缘是连续的界线,并且我们能够跟踪前面所看到的边缘的模糊部分,而不会将图像中的噪声点标记为边缘。五 实验代码及结果/主要代码部分void CImageDoc:OnGard() / TODO: Add your command handler code hereGrad(Source, Result,Height,Width); for(int y=0;yHeight;y+)for(int x=0;xWidth;x+)PResult3*y*Width+3*x = Resulty*Width+x;PResult3*y*Width+3*x+1 = Resulty*Width+x;PResult3*y*Width+3*x+2 = Resulty*Width+x; UpdateAllViews(NULL);void CImageDoc:Grad(unsigned char *Source, unsigned char *Result, int Height, int Width) unsigned char G;for(int y=0;yHeight;y+)for(int x=0;xWidth;x+)if(x1|yWidth-2|yHeight-2)Resulty*Width+x=0;else G=abs(Sourcey*Width+x-Source(y+1)*Width+(x+1)+abs(Source(y+1)*Width+(x)-Source(y)*Width+(x+1);if(G=3)Resulty*Width+x=G;else Resulty*Width+x=0;/结果截图六 实验小结所谓边缘 ( 或边沿 ) 是指其周围像素灰度有阶跃变化或屋顶变化的那些像素的集合。边缘广泛存在于物体与背景之间、物体与物体之间、基元与基元之间 。因此,它是图像分割所依赖的重要特征。物体的边缘是由灰度不连续性所反映的。经典的边缘提取方法是考察图像的每个像素在某个邻域内灰度的变化,利用边缘临近一阶或二阶方向导数变化规律,用简单的方法检测边缘。这种方法称为边缘检测局部算子法。提取图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。
展开阅读全文