数字图像处理实验报告.docx
- 文档编号:8606980
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:9
- 大小:23.83KB
数字图像处理实验报告.docx
《数字图像处理实验报告.docx》由会员分享,可在线阅读,更多相关《数字图像处理实验报告.docx(9页珍藏版)》请在冰豆网上搜索。
数字图像处理实验报告
数字图像处理实验报告
数字图像处理实验报告11.实验内容:
主要是图像几何变换的编程,包括图像读取、重写、图像翻译、图像镜像、图像转置、缩放、旋转变换等。
具体要求如下:
1.编程实现图像翻译,要求翻译后的图像大小保持不变;
2.编程实现镜像;
3.编程实现图像转置;
4.实现图像缩放的编程需要双线性插值和最近邻插值。
现在,比较两种方法的缩放效果。
5.编程以任意角度旋转图像需要双线性插值和最近邻插值。
值,并比较两种方法的旋转效果。
二.实验的目的和意义:
本实验旨在让学生熟悉和掌握图像处理编程环境,掌握图像平移、镜像、换位、旋转等几何变换方法,通过编程实现图像文件的读写操作和图像平移、镜像、换位、旋转等几何变换的程序实现。
三.实验原理和主要框架:
3.1实验中使用的编程环境:
VisualC++(简称VC)是微软公司提供的基于C/C++的应用集成开发工具。
VC拥有丰富的功能和大量的扩展库,可以有效地创建高性能的Windows应用和Web应用。
VC除了提供高效的C/C++编译器外,还提供了大量可重用的类和组件,包括著名的微软基础类库(MFC)和活动模板类库(ATL),是软件开发人员不可多得的开发工具。
VC丰富的功能和大量的扩展库,类的复用特性及其对函数库和DLL库的支持,可以使程序更加模块化,通过向导程序大大简化了库资源的使用和应用程序的开发。
因为VC有明显的优势,所以我选择它作为数字图像几何变换的开发工具。
在本程序的开发过程中,VC的核心知识、消息映射机制、对话控制编程等都得到了生动的体现和灵活的应用。
3.2实验对象:
256色BMP(BITMAP)格式图像。
位图的文件结构:
组成图:
BITMAPFILEHEADER。
位图文件头
(仅用于BMP文件)bftype="BM"bfsizebfreserved1。
bfReserved2
bfOffBits
biSize
biWidth
BIH八十八
双翼飞机
biBitCount
双压缩
biSizeImage
比克斯佩尔斯特计
泌乳素计
bicclrused
双重要
单色DIB有2个条目。
16色DIB有16个条目或更少。
256色DIB有256个条目或更少。
真正的DIB没有调色板。
每个条目的长度为4字节(32位)。
像素按每行和每列的顺序排列。
每行的字节数必须是4的整数。
位图标题调色板DIB像素DIB图像数据。
1.BMP文件组成。
BMP文件由文件头、位图头、颜色信息和图形数据组成。
2.BMP文件头。
BMP头数据结构包含BMP文件类型(必须是BMP)、文件大小(以字节为单位)、位图文件保留字(必须是0)和位图开始位置(相对于位图)。
文件头的偏移量指示)和其他信息。
3.位图标题。
BMP表头数据用来说明尺寸(宽度、高度等。
)的位图以像素为单位。
以字节为单位,以每米像素为单位的水平和垂直分辨率)、目标设备的级别、每个像素所需的位数以及位图压缩类型(必须为0)。
4.颜色表。
颜色表用于描述位图中的颜色。
它有几个条目,每个条目都是一个RGBQUAD。
类型,它定义一种颜色,包括蓝色、红色和绿色的亮度(值范围为0-255)。
位图标题和颜色表构成位图信息。
5.位图数据。
位图数据记录位图的每个像素值,记录顺序在扫描行从左到右。
线条是从下往上的。
Windows规定一条扫描线占用的字节数必须是4的倍数(即与单位一样长),不足的字节用0填充。
3.3位图显示:
①一般显示方法:
1.申请内存空存储位图文件。
2.位图文件被读入应用内存空。
3.在函数中,创建用于显示的位图,使用函数创建兼容的DC,并使用函数选择用于显示和删除的位图。
然而,上述方法的缺点是:
1)显示速度慢;2)内存占用大;3)位图缩小显示时,图形失真大(可通过安装字体平滑软件解决);4)在低色位设备(如256显示模式)上显示高色位图形(如真彩色)严重失真。
②BMP位图缩放显示:
使用视频功能显示位图,内存少,速度快,还可以淡化图形。
淡化是一种图形算法,可用于在支持比图像更少颜色的设备上显示彩色图像。
BMP位图的显示方法如下:
1.打开视频功能,通常放在构造函数中。
2.申请内存空存储位图文件。
3.位图文件被读入应用的内存空。
4.在函数中显示位图。
5.关闭视频功能,通常放在析构函数中。
上述方法的优点是:
1)显示速度快;2)占用内存少;3)放大缩小时图形失真小,4)在低色位数设备上显示高色位数图形时失真小;5)直接处理位图数据可以制作简单的动画。
3.4程序中使用的访问功能。
Windows支持一些重要的DIB访问函数,但是这些函数还没有封装在MFC中。
这些功能主要包括:
1.SetDIBitsToDevice功能:
该功能可以直接在显示器或打印机上显示DIB。
不缩放处理时。
2.拉伸DIB功能:
该功能可以在显示器和打印机上缩放显示DIB。
Getdibits函数:
返回函数使用应用内存从GDI位图构造DIB。
通过这个功能,
可以控制DIB的格式,指定每个像素颜色的位数,指定是否压缩。
4.CreateDIBitmap函数:
通过这个函数,可以从DIB创建GDI位图。
5.CreateDIBSection函数:
这个函数可以创建一个特殊的DIB,叫做DIB项,然后返回。
一个GDI位图句柄。
6.LoadImage函数:
这个函数可以直接从磁盘文件中读取位图,并返回一个DIB。
把手。
7.drawdibraw功能:
Windows提供了一个窗口视频(VFW)组件,VisualC++支持。
组件中的DrawDibDraw函数。
VFW是一个可以取代伸缩位的函数。
它的主要优点是可以使用抖动颜色,提高DIB显示的速度。
它的缺点是VFW代码必须连接到流程。
3.5图像的几何变换。
图像的几何变换通常包括图像平移、镜像变换、图像转置、图像缩放和图像旋转等。
数字图像处理实验报告2一、实验的目的和意义。
实验目的:
本实验旨在通过用VC等高级语言编写一些数字图像处理的基本算法程序,使学生巩固和掌握图像处理技术的基本技能,提高动手能力,并通过实际编程了解图像处理软件实现的基本原理。
为学生进一步学习数字摄影测量、遥感和地理信息系统等专业课程,应用图像处理解决实际问题打下基础。
二、实验原理和方法。
(1)从原始格式到BMP格式的转换:
Raw格式:
Raw格式文件是由数字图像组成的二维矩阵,其中像素以行号和列号的顺序存储在文件中。
这种文件只包含图像像素数据,没有标题。
因此,在读取图像时,需要根据文件大小计算图像中包含的行数和列数,或者提前知道图像大小(矩阵大小)。
原始文件按照图像从上到下和从左到右的顺序存储。
BMP格式:
BMP文件数据区按照图像上下到上、左列到右列的顺序存储在数据区。
BMP文件由文件头、信息头、颜色表和数据区组成。
要将Raw文件转换为BMP文件,首先为BMP文件申请四部分内存:
文件头、位图信息头、颜色表和图像数据,然后根据输入值、Raw文件信息和BMP文件信息计算这四部分的值,赋值后写入BMP文件。
(2)灰度图像的线性拉伸:
灰度变化是一种点运算,将原始图像各像素的灰度值线性变化后变为灰度。
灰度线性变换是指根据线性灰度变换函数对图像中所有点的灰度进行变换。
灰度变换方程如下:
这个方程是线性的。
其中参数是输入图像像素的灰度值,参数是输出图像的灰度值。
灰度值。
设原始图像的灰度范围为[a,b],变化后的范围为[a',b'],则:
fA=(b'-a')/(b-a)
fB=-(b'-a')/(b-a)*a+a'
如果计算值大于255,让它等于255,如果小于0,让它等于0。
(3)局部处理(3*3高通滤波,3*3低通滤波):
在局部处理中,当处理一个像素时,使用与该像素相邻的一组像素来获得经过某种变换后的处理图像中某一点的像素值。
目标像素的邻域一般是由像素组成的二维矩阵,像素的大小为奇数,目标像素位于矩阵的中心,即目标像素是区域的中心像素。
处理后,目标像素的值是通过特定算法计算的结果。
其实都是卷积实现的。
卷积通常用矩阵表示。
将矩阵的中心与一个像素对齐,将矩阵中的值与对应的像素相乘,然后将所有乘积相加,得到中心像素的灰度值。
边界像素不被处理,并保持原始灰度值。
如果计算出的像素灰度值超过[0~255],将接近属于该范围的最近像素值。
低通滤波的3*3算子如表1所示。
3*3高通滤波的算子如表2所示。
表格1
1/9
1/9
1/9
1/9
1/9
1/9
1/9
1/9
1/9
表格2
-1
-1
-1
-1
九
-1
-1
-1
-1
(4)图像几何处理(图像平移、图像缩放):
至于图像平移,如果平移量为(tx,ty),原始图像中像素的坐标为(x0,y0),则改变后的坐标为(x1,y1),x1=x0+tx,y1=y0+ty。
平移只需要改变像素的灰度值,不需要改变位图头和调色板内容。
对于图像缩放,假设放大倍数为比值,缩放变换矩阵为:
页眉中新图像的宽度和高度分别以水平和垂直比例成为原始宽度和高度的乘积,图像大小成为新宽度(变成4的整数倍)和新高度的乘积。
(5)灰度图像的中值滤波:
中值滤波也是一种局部处理,对窗口中的像素进行排序,将中值赋给模板中心的像素,所以窗口中的数字一般是基数。
我用的中值滤波窗口是十字准线的9号窗口。
(6)灰度图像边缘检测:
边缘检测有三种算子:
罗伯茨、普雷维特和索贝尔。
三个算子都做一阶差分。
每个像素的梯度值由算子计算,水平梯度的绝对值和垂直梯度的绝对值相加。
如果梯度值大于某个阈值,则其灰度值被指定为255,否则被指定为0。
(7)图像旋转:
图像旋转一般是以图像的中心为中心顺时针旋转,利用图像的四个角得到图像的旋转尺寸。
首先计算原始图像四个角点在以图像中心为原点的坐标系中的坐标值,根据旋转矩阵计算旋转后的坐标值,根据四个角点的新坐标值计算最大宽度和高度作为新图像的宽度和高度值,根据计算值修改位图头,申请新的内存,存储旋转后图像的灰度值。
旋转矩阵如下:
它还需要原始图像中每个像素的坐标。
首先将新图像的坐标系平移到图像中心,逆时针旋转,然后平移到屏幕左上角,再将原始图像对应的坐标值赋给新图像。
(8)图像二值化:
判断分析:
假设图像的灰度区间为[0,L-1],选择一个阈值T,将图像的像素分成两组。
最大值对应的t是判断分析方法的分割阈值。
搜索阈值后,将灰度值小于阈值的像素赋0,其他赋1,修改文件头和调色板,申请新内存。
(9)图像直方图:
计算每个灰度值的频率和像素总数。
将频率除以总数作为频率,灰度值作为横坐标,频率作为纵坐标。
三、实验过程和步骤。
首先,构建一个基于MFC的多文档项目,将视图基类改为滚动视图,并用自己的学号命名。
我用的是书中给出的CDib类,它有获取BMP宽度和高度的函数、指向位图头的指针和指向图像数据的指针。
所以我在Document类(doc类)中定义了一个CDib类的对象,在打开和保存文件的时候用这个对象调用CDib中读取和存储文件的函数,可以用这个对象的两个指针对打开的图像进行各种操作。
1.1。
原始格式到BMP格式的转换:
首先,为RawToBMP创建一个对话框,并添加四个编辑框(一个用于打开文件的路径,一个用于保存文件的路径,另外两个)、两个按钮以及默认的确认和取消按钮。
使用类向导插入这个对话框类,并为前两个编辑框定义两个CString变量,用于存储打开和保存文件的路径。
同时,为两个浏览按钮添加一个消息响应函数,在消息函数中创建一个CFileDialog对象,并使用该对象的函数为前两个编辑框的成员变量分配两个路径值。
然后为OK键添加一个消息响应函数,分别定义BMP格式文件的前三个数据变量,计算每个变量的值,使用一个CFile对象获取Raw图像的数据,使用另一个CFile对象将数据存储在输入路径的文件中,CFile对象的Read函数会自动创建一个文件。
然后在菜单上新建一个菜单,在菜单中添加一个消息响应函数,在其消息响应函数中创建一个RowToBMP对话框。
这样,点击菜单后会弹出一个对话框。
按下OK键后,即可读取Raw文件并存储BMP文件,从而完成整个消息周期。
2.灰度图像的线性拉伸;
创建一个对话框输入更改后的灰度值,为对话框的两个编辑框定义成员变量,给文档类添加处理函数,根据对话框的输入值计算fA和fB,做一个循环,从0到255的灰度值计算拉伸后的灰度值(超限情况下特殊处理),并以这个值的索引存储在数组中,然后使用文档类中定义的CDib类的成员变量m_DIB获取当前。
查找数组中每个像素变化后的灰度值到图像数据部分的指针m_DIB.m_pBits,并将这个值赋给指针m_pBits指向的内存。
刷新视图。
然后在菜单中添加一个线性拉伸的菜单,在菜单的ID中添加一个消息响应函数,在这个函数中创建一个对话框,调用文档类的线性拉伸函数,将对话框的两个成员变量传递给这个函数。
3.局部治疗:
在文档类中添加低通滤波和高通滤波的成员函数,使用m_DIB对象中的指针m_pBits指向函数中的图像数据部分,先申请一个新的内存来存储原始图像的灰度值,然后定义9个BYTE指针,使用双嵌套循环每次指向复制图像对应的模板中的9个数字。
然后根据模板中的数值计算中心像素的灰度值,判断是否超出范围。
如果超出范围,做相应的处理,否则直接将此值赋给m_pBits中对应的中心像素。
然后循环刷新视图。
增加一个菜单进行本地处理,为菜单设置一个消息响应函数,在菜单消息响应函数中调用document类的函数,完成m_DIB的处理。
4.图像几何变换:
建立平移对话框,定义两个成员变量,分别存储输入的水平位移和垂直位移。
在文档类中添加一个翻译函数,申请一个新的内存来复制原始图像的信息,并设置。
外环变量I作为纵坐标,内环变量j作为横坐标。
通过双循环,获取原始图像中每个像素的坐标(i0,j0),并将复制图像中(i0,j0)对应的像素的灰度值赋给m_DIB.m_pBits指针中的图像。
如果在原始图像中找不到该像素,请将其设置为背景色。
刷新视图。
在菜单中增加一个图像翻译菜单,在菜单中增加一个消息响应函数,在这个函数中创建一个翻译对话框,调用文档类的翻译函数,将对话框的成员变量传递给这个函数。
建立一个缩放对话框类,为此类定义两个成员变量,并存储输入的水平缩放因子和垂直缩放因子。
然后在文档类中添加一个缩放函数,使用m_DIB.m_pBMI(指向位图头的指针)修改位图头中的宽度、高度和图像大小。
计算新图像的大小,并申请新内存来存储新图像。
和平移函数一样,计算原始图像中每个像素的坐标,i0=I/pratio,j0=j/VRatio,pratio和VRatio分别是水平比例因子和垂直比例因子。
将原始图像中对应坐标的灰度值赋给新内存,然后将m_DIB.m_pBits(指向图像数据的指针)指向新内存刷新视图。
5.中值滤波:
向文档类添加两个成员函数。
一个用于对传入指针的内容进行排序,另一个用于中值滤波。
还需要申请一个新的内存来复制原始图像的信息,有双重嵌套循环,不需要处理边界像素。
对于每个像素,使用一个大小为9字节的数组来存储复制的图像窗口中的像素值,然后将数组的第一个地址传递给排序函数,中间的值被分配给当前图像窗口中心的像素。
排序功能我用的是快速排序法。
向菜单中添加中值滤波菜单项,向其添加消息响应函数,并调用文档类的中值滤波函数。
6.边缘检测:
文档类中定义了三个函数,分别是Roberts,Prewit和Sobel算子处理函数。
处理时先申请新内存拷贝原始图像信息,不处理边界像素。
对于每个像素值,计算其在复制图像中的渐变。
判断,如果梯度值大于150(这是我自己的决定),将灰度值赋值为255,否则设置为零。
在菜单中增加一个边缘检测菜单,将属性设置为弹出,增加三个下一级菜单,分别是Roberts,Prewit,Sobel。
每个菜单的消息响应函数在文档类中调用自己的处理函数。
7.图像旋转:
创建一个对话框来输入旋转角度并将成员函数添加到文档类中。
首先将角度转换为弧度值。
计算原始图像四个角的坐标和新图像四个角的坐标。
根据新图像四个角点的坐标,选择横坐标差较大的两个对角点的宽度和纵坐标差较大的两个对角点的高度。
根据计算的高度和宽度修改文件头,并申请内存来存储新图像。
计算原始图像中每个像素的坐标,得到其灰度值,并写入新的内存。
将m_DIB.m_pBits指向新内存。
刷新视图。
添加图像旋转菜单,在菜单响应函数中创建对话框,在文档类中调用旋转函数,将对话框中得到的角度传递给旋转函数。
8.图像二值化:
给文档类增加一个成员函数,根据后代的图像和阈值返回组间方差和组内方差的比值。
然后加入一个成员函数进行二值化。
在函数中:
计算新BMP文件的大小,申请新的内存,存储整个BMP文件的新信息。
将位图头中的biBitCount设置为1,调色板数组只有两个元素,下标0的三个灰度值全部为0,下标1的三个灰度值全部为255。
将上述函数返回的最大值从最大灰度值搜索到最小灰度值作为阈值。
对于每个像素,如果其原始灰度值小于阈值,则指定1,否则指定0。
将m_DIB、m_pBits指向新内存的图像数据部分,将m_DIB.m_pBMI指向位图头。
9.图像直方图:
在文档类中添加一个int指针成员变量m_pGray,在构造函数中将指针赋给空,在文档类中定义一个函数,统计每个灰度值出现的频率,申请一个内存,存储在这个内存中,然后将m_pGray指向它。
创建一个对话框来绘制直方图,添加一个图片控件,调用控件中的文档类成员变量,并绘制直方图。
添加滚动条确定阈值,为滚动条添加消息响应函数,根据滚动条的值进行二值化。
在菜单中添加直方图菜单,添加消息响应函数,在响应函数中创建直方图对话框对象。
最后因为开始项目的时候没有把菜单设计好,做的有点乱,所以在View中增加了WM_CONTEXTMENU消息响应函数,并在函数体中实现了带有CMenu类的弹出菜单。
四.结果分析与评价。
(1)从1)Raw格式转换为BMP格式:
效果如图1所示。
1图表
老师说转换后期用一个循环会降低效率,但其实只要宽度是4的整数倍,后期循环就做不了。
所以我觉得这个算法的效率还可以。
(2)线性变化:
输入线性变化范围为10~20,效果如图2所示。
图表2
使用线性查找表后,这个算法的效率应该会高很多,但是我的算法是线性表从0变为255后的值。
实际上,如果图片的灰度范围较小,已经做了很多无用的计算,之前已经搜索过原始图像的最大和最小灰度值,所以线性表的生成周期只能从最小灰度达到最大灰度。
另外,在我设计的算法中,如果最大值和最小值颠倒,程序会自动交换它们的值,这样做可能会增加一些东西。
(3)低通滤波:
效果见图3。
图表3
取8个邻域的平均值,效果不是很好。
高通滤波:
效果如图4所示。
图表4
基本上我觉得优势还是突出的。
中值滤波:
效果见图5。
图表5
我对这个中值滤波器的效果相当满意。
因为排序,我不得不调用其他函数。
我用了快速排序,用了9个十字窗口,所以速度比25个窗口快。
平滑效果还可以。
(4)边缘检测:
罗伯茨算子:
效果如图6所示。
图表6
Prewit运算符:
效果如图7所示。
图表7
索贝尔算子:
效果如图8所示。
图表8
由于Prewit算子和Sobel算子都使用了8个数字,所以效果更好。
相比之下,Sobel算子对这张图的效果更好,这应该是因为给了4个邻域更多的权重。
然而,后两种算法也需要更多的计算。
(5)图像翻译:
效果见图9。
图表9
此图像的翻译量相对较大,因此裁剪后的图像也显得不真实。
主要原因是我的图像大小和坐标没有变化,所以我只显示原始图像坐标内的翻译图像。
事实上,我可以改变图像的大小,为了节省计算,我可以让循环变量I和J从一个新的值开始计算,前面的都是给定的背景颜色。
图像缩放:
水平比例为0.4,垂直比例为0.5,效果如图10所示。
图表10。
在此基础上旋转:
效果如图11所示。
图表11。
这些算法的主要计算是在for循环中,所以如果我们想优化算法,我们必须简化循环中的计算。
但是我的想法和书上的差不多,还没有优化。
也许,这个优化算法需要看很多别人做的好程序,才能自己学习。
(6)二值化(判断分析法):
效果见图12。
图表12。
其实我用直方图的最佳阈值应该在100左右,但是我的程序的阈值好像小了一点,所以效果不是很好。
我在计算组间方差和组内方差的时候,调用了一个函数来求阈值,但是这里的计算可能还是有些问题。
而且在我的函数中,我需要调用这个函数256次,而且由于计算机是按照字节来处理数据的,所以在写入图像数据时,我需要将每8个数据写入一个数组,然后通过计算得到字节类型值,这使得我的算法效率低下。
最后我觉得用比特运算会更快,但是之前的问题我还没有想到更好的解决方法。
(7)直方图:
效果见图13。
这个图像中的像素太多了。
如果我没看错的话,量化不是很好。
图表13。
动词(verb的缩写)实验总结和经验。
这次实验我学到的最大的一点就是,终于有了MFC编程的概念。
虽然我在VC++考试中的成绩还算不错,但是里面的很多东西,没有我自己的编程是永远无法真正理解的。
比如封装,这次CDib的便利性很好地利用了类的封装。
另外,比如MFC是基于消息响应机制,这就决定了应该使用鼠标或者菜单响应功能来实现功能,而用C语言编写程序时,则完全基于主功能的线程。
另外,我也学会了调试的真谛。
以前,我们只知道那些按钮是干什么用的。
调试的真正目的是检查程序计算的值是否符合我们自己的算法,这样我们就可以快速方便地找出自己的错误。
自学也是一个重要方面。
其实现在用MSDN也不是很难,不应该被英语打击。
现在,因为我们熟悉一些专有名词,读MSDN更容易。
万一我们不懂功能,也可以利用网络找到很多功能用法的解释。
刚开始的时候看了位图并显示出来,但是真的不知道从哪里开始,就按照实验书敲了敲前面部分,但是慢慢明白了代码的意思。
所以后来基本都是我自己做的,但是算法基本和书上的一样。
但是我自己编辑的时候没有注意很多细节。
比如我自己编辑的时候没有注意这个问题。
结果,犯了很多错误。
有些事情是由函数调用引起的,有些是由于不等式符号两边的数据匹配问题,有些是由于指针的移动。
直到这个时候,我才真正明白为什么实验书里的程序里有那么多强制类型转换。
虽然书中很多东西并不完美,但我只是学会了编程。
正如老师所说,算法的效率非常重要。
提高算法效率,一是简化计算(必须说这需要数学基础),二是避免多次重复计算。
在参考书中的程序中,为了避免这样的重复计算(尤其是在循环中),有些数字会被计算为常数,只要这个常数以后加上,效率就高得多。
另外,对于很多错误,我的程序做得并不好。
比如不打开8位图像,我的程序不会提示错误,正常结束,但可能会出错。
所以,这是我应该从其他节目中学到的。
最后,我自己菜单的布局也很乱。
应该从一开始就布局。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数字图像 处理 实验 报告
