VC数字图像处理编程讲座.docx
《VC数字图像处理编程讲座.docx》由会员分享,可在线阅读,更多相关《VC数字图像处理编程讲座.docx(50页珍藏版)》请在冰豆网上搜索。
VC数字图像处理编程讲座
VC数字图像处理编程讲座之一
hhflying发表于2005-6-1010:
50:
00
·VC数字图像处理编程讲座
VC数字图像处理编程讲座之一
前言
数字图像处理技术与理论是计算机应用的一个重要领域,许多工程应用都涉及到图像处理,一直有一个强烈的愿望,想系统的写一个关于数字图像处理的讲座,由于工作学习很忙,时至今日才得以实现。
"图"是物体透射光或反射光的分布,"像"是人的视觉系统对图的接收在大脑中形成的印象或认识。
图像是两者的结合。
人类获取外界信息是靠听觉、视觉、触觉、嗅觉、味觉等,但绝大部分(约80%左右)来自视觉所接收的图像信息。
图像处理就是对图像信息进行加工处理,以满足人的视觉心理和实际应用的需要。
简单的说,依靠计算机对图像进行各种目的的处理我们就称之为数字图像处理。
早期的数字图像处理的目的是以人为对象,为了满足人的视觉效果而改善图像的质量,处理过程中输入的是质量差的图像,输出的是质量好的图像,常用的图像处理方法有图像增强、复原等。
随着计算机技术的发展,有一类图像处理是以机器为对象,处理的目的是使机器能够自动识别目标,这称之为图像的识别,因为这其中要牵涉到一些复杂的模式识别的理论,所以我们后续的讲座只讨论其中最基本的内容。
由于在许多实际应用的编程中往往都要涉及到数字图像处理,涉及到其中的一些算法,这也是许多编程爱好者感兴趣的一个内容,我们这个讲座就是讨论如何利用微软的VisualC++开发工具来实现一些常用的数字图像处理算法,论述了图像处理的理论,同时给出了VC实现的源代码。
本讲座主要的内容分为基础篇、中级篇和高级篇,具体包含的主要内容有:
1.图像文件的格式;
2.图像编程的基础-操作调色板;
3.图像数据的读取、存储和显示、如何获取图像的尺寸等;
4.利用图像来美化界面;
5.图像的基本操作:
图像移动、图像旋转、图像镜像、图像的缩放、图像的剪切板操作;
6.图像显示的各种特技效果;
7.图像的基本处理:
图像的二值化、图像的亮度和对比度的调整、图像的边缘增强、如何得到图像的直方图、图像直方图的修正、图像的平滑、图像的锐化等、图像的伪彩色、彩色图像转换为黑白图像、物体边缘的搜索等等;
8.二值图像的处理:
腐蚀、膨胀、细化、距离变换等;
9.图像分析:
直线、圆、特定物体的识别;
10.JEPG、GIF、PCX等格式文件相关操作;
11.图像文件格式的转换;
12.图像的常用变换:
付利叶变换、DCT变换、沃尔什变换等;
13.AVI视频流的操作;
图像处理技术博大精深,不仅需要有很强的数学功底,还需要熟练掌握一门计算机语言,在当前流行的语言中,我个人觉的VisualC++这个开发平台是图像开发人员的首选工具。
本讲座只是起到抛砖引玉的作用,希望和广大读者共同交流。
VC数字图像处理编程讲座之二
第一节图像的文件格式
要利用计算机对数字化图像进行处理,首先要对图像的文件格式要有清楚的认识,因为我们前面说过,自然界的图像以模拟信号的形式存在,在用计算机进行处理以前,首先要数字化,比如摄像头(CCD)摄取的信号在送往计算机处理前,一般情况下要经过数模转换,这个任务常常由图像采集卡完成,它的输出一般为裸图的形式;如果用户想要生成目标图像文件,必须根据文件的格式做相应的处理。
随着科技的发展,数码像机、数码摄像机已经进入寻常百姓家,我们可以利用这些设备作为图像处理系统的输入设备来为后续的图像处理提供信息源。
无论是什么设备,它总是提供按一定的图像文件格式来提供信息,比较常用的有BMP格式、JPEG格式、GIF格式等等,所以我们在进行图像处理以前,首先要对图像的格式要有清晰的认识,只有在此基础上才可以进行进一步的开发处理。
在讲述图像文件格式前,先对图像作一个简单的分类。
除了最简单的图像外,所有的图像都有颜色,而单色图像则是带有颜色的图像中比较简单的格式,它一般由黑色区域和白色区域组成,可以用一个比特表示一个像素,"1"表示黑色,"0"表示白色,当然也可以倒过来表示,这种图像称之为二值图像。
我们也可以用8个比特(一个字节)表示一个像素,相当于把黑和白等分为256个级别,"0"表示为黑,"255"表示为白,该字节的数值表示相应像素值的灰度值或亮度值,数值越接近"0",对应像素点越黑,相反,则对应像素点越白,此种图像我们一般称之为灰度图像。
单色图像和灰度图像又统称为黑白图像,与之对应存在着彩色图像,这种图像要复杂一些,表示图像时,常用的图像彩色模式有RGB模式、CMYK模式和HIS模式,一般情况下我们只使用RGB模式,R对应红色,G对应绿色,B对应蓝色,它们统称为三基色,这三中色彩的不同搭配,就可以搭配成各种现实中的色彩,此时彩色图像的每一个像素都需要3个样本组成的一组数据表示,其中每个样本用于表示该像素的一个基本颜色。
对于现存的所有的图像文件格式,我们在这里主要介绍BMP图像文件格式,并且文件里的图像数据是未压缩的,因为图像的数字化处理主要是对图像中的各个像素进行相应的处理,而未压缩的BMP图像中的像素数值正好与实际要处理的数字图像相对应,这种格式的文件最合适我们对之进行数字化处理。
请读者记住,压缩过的图像是无法直接进行数字化处理的,如JPEG、GIF等格式的文件,此时首先要对图像文件解压缩,这就要涉及到一些比较复杂的压缩算法。
后续章节中我们将针对特殊的文件格式如何转换为BMP格式的文件问题作专门的论述,经过转换,我们就可以利用得到的未压缩的BMP文件格式进行后续处理。
对于JPEG、GIF等格式,由于涉及到压缩算法,这要求读者掌握一定的信息论方面的知识,如果展开的话,可以写一本书,限于篇幅原因,我们只作一般性的讲解,有兴趣的朋友可以参考相关书籍资料。
一、BMP文件结构
1.BMP文件组成
BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息;位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。
颜色信息包含图像所用到的颜色表,显示图像时需用到这个颜色表来生成调色板,但如果图像为真彩色,既图像的每个像素用24个比特来表示,文件中就没有这一块信息,也就不需要操作调色板。
文件中的数据块表示图像的相应的像素值,需要注意的是:
图像的像素值在文件中的存放顺序为从左到右,从下到上,也就是说,在BMP文件中首先存放的是图像的最后一行像素,最后才存储图像的第一行像素,但对与同一行的像素,则是按照先左边后右边的的顺序存储的;另外一个需要读者朋友关注的细节是:
文件存储图像的每一行像素值时,如果存储该行像素值所占的字节数为4的倍数,则正常存储,否则,需要在后端补0,凑足4的倍数。
2.BMP文件头
BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
其结构定义如下:
typedefstructtagBITMAPFILEHEADER
{
WORDbfType;//位图文件的类型,必须为"BM"
DWORDbfSize;//位图文件的大小,以字节为单位
WORDbfReserved1;//位图文件保留字,必须为0
WORDbfReserved2;//位图文件保留字,必须为0
DWORDbfOffBits;//位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
}BITMAPFILEHEADER;该结构占据14个字节。
3.位图信息头
BMP位图信息头数据用于说明位图的尺寸等信息。
其结构如下:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;//本结构所占用字节数
LONGbiWidth;//位图的宽度,以像素为单位
LONGbiHeight;//位图的高度,以像素为单位
WORDbiPlanes;//目标设备的平面数不清,必须为1
WORDbiBitCount//每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
DWORDbiCompression;//位图压缩类型,必须是0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORDbiSizeImage;//位图的大小,以字节为单位
LONGbiXPelsPerMeter;//位图水平分辨率,每米像素数
LONGbiYPelsPerMeter;//位图垂直分辨率,每米像素数
DWORDbiClrUsed;//位图实际使用的颜色表中的颜色数
DWORDbiClrImportant;//位图显示过程中重要的颜色数
}BITMAPINFOHEADER;该结构占据40个字节。
注意:
对于BMP文件格式,在处理单色图像和真彩色图像的时候,无论图象数据多么庞大,都不对图象数据进行任何压缩处理,一般情况下,如果位图采用压缩格式,那么16色图像采用RLE4压缩算法,256色图像采用RLE8压缩算法。
4.颜色表
颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。
RGBQUAD结构的定义如下:
typedefstructtagRGBQUAD{
BYTErgbBlue;//蓝色的亮度(值范围为0-255)
BYTErgbGreen;//绿色的亮度(值范围为0-255)
BYTErgbRed;//红色的亮度(值范围为0-255)
BYTErgbReserved;//保留,必须为0
}RGBQUAD;
颜色表中RGBQUAD结构数据的个数由BITMAPINFOHEADER中的biBitCount项来确定,当biBitCount=1,4,8时,分别有2,16,256个颜色表项,当biBitCount=24时,图像为真彩色,图像中每个像素的颜色用三个字节表示,分别对应R、G、B值,图像文件没有颜色表项。
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedefstructtagBITMAPINFO{
BITMAPINFOHEADERbmiHeader;//位图信息头
RGBQUADbmiColors[1];//颜色表
}BITMAPINFO;
注意:
RGBQUAD数据结构中,增加了一个保留字段rgbReserved,它不代表任何颜色,必须取固定的值为"0",同时,RGBQUAD结构中定义的颜色值中,红色、绿色和蓝色的排列顺序与一般真彩色图像文件的颜色数据排列顺序恰好相反,既:
若某个位图中的一个像素点的颜色的描述为"00,00,ff,00",则表示该点为红色,而不是蓝色。
5.位图数据
位图数据记录了位图的每一个像素值或该对应像素的颜色表的索引值,图像记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。
这种格式我们又称为Bottom_Up位图,当然与之相对的还有Up_Down形式的位图,它的记录顺序是从上到下的,对于这种形式的位图,也不存在压缩形式。
位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;当biBitCount=4时,2个像素占1个字节;当biBitCount=8时,1个像素占1个字节;当biBitCount=24时,1个像素占3个字节,此时图像为真彩色图像。
当图像不是为真彩色时,图像文件中包含颜色表,位图的数据表示对应像素点在颜色表中相应的索引值,当为真彩色时,每一个像素用三个字节表示图像相应像素点彩色值,每个字节分别对应R、G、B分量的值,这时候图像文件中没有颜色表。
上面我已经讲过了,Windows规定图像文件中一个扫描行所占的字节数必须是4的倍数(即以字为单位),不足的以0填充,图像文件中一个扫描行所占的字节数计算方法:
DataSizePerLine=(biWidth*biBitCount+31)/8;//一个扫描行所占的字节数
位图数据的大小按下式计算(不压缩情况下):
DataSize=DataSizePerLine*biHeight。
上述是BMP文件格式的说明,搞清楚了以上的结构,就可以正确的操作图像文件,对它进行读或写操作了。
二、GIF图像文件格式
GIF图象格式的全称为GraphicsInterchangeFormat,从这个名字可以看出,这种图像格式主要是为了通过网络传输图像而设计的。
GIF文件不支持24位真彩色图像,最多只能存储256色的图像或灰度图像;GIF格式文件也无法存储CMY和HIS模型的图像数据;另外,GIF图像文件的各种数据区域一般没有固定的数据长度和存储顺序,所以为了方便程序寻找数据区,将数据区中的第一个字节作为标志符;最后需要读者注意的是GIF文件存储图像数据是有二种排列顺序:
顺序排列或交叉排列。
交叉排列的方式适合网络传输,这样一来允许用户在不完全掌握图像数据之前,获取当前图像的轮廓数据。
GIF文件格式分为87和89两个版本,对于87这个版本,该文件主要是有五个部分组成,它,们是按顺序出现的:
文件头块、逻辑屏幕描述块、可选择的调色板块、图像数据块、最后是标志文件结束的尾块,该块总是取固定的值3BH。
其中第一和第二两个块用GIF图像文件头结构描述:
GIFHEADER:
{
DBSignature;//该字段占六个字节,为了用于指明图像为GIF格式,前三个字符必须为"GIF",后三字符用于指定是哪个版本,87或89。
DWScreenWidth;//
DWScreenDepth;//占两个字节,以像素为单位表示图像的宽、高
DBGlobalFlagByte;//该字节的各个位用于调色版的描述
DBBackGroundColor;//代表图象的背景颜色的索引
DBAspectRatio;图像的长宽比
}
GIF格式中的调色板有通用调色板和局部调色板之分,因为GIF格式允许一个文件中存储多个图像,因此有这两种调色板,其中通用调色板适于文件中的所有图像,而局部调色板只适用于某一个图像。
格式中的数据区域一般分为四个部分,图像数据识别区域,局部调色板数据,采用压缩算法得到的图象数据区域和结束标志区域。
在GIF89版本中,它包含七个部分,分别是文件头、通用调色板数据、图像数据区和四个补充数据区,它们主要是用于提示程序如何处理图像的。
三、JEPG图像文件
JEPG简称为联合摄影专家小组,作为一种技术,主要用于数字化图像的标准编码,JPEG主要采用有损的压缩编码方式,它比GIF、BMP图像文件要复杂的多,这不是短短的几页篇幅可以将清楚的,万幸的是,我们可以通过一些别的方法将该格式转化为BMP格式。
读者需要知道的是在对JEPG文件格式编码时,通常需要分为以下四步:
颜色转化、DCT变换、量化、编码。
以上介绍了一些常用的图像文件,对比较复杂的格式,如GIF和JEPG,仅仅作了极其浮浅的介绍,后文我们会和它们作进一步的接触。
实际应用中,还有许多图像格式,文章中都没有提到,读者如果需要做进一步的研究,还需要参考一些关于图像格式方面的资料。
VC数字图像处理编程讲座之三
BMP图像的基本操作
上一讲我们主要介绍了图像的格式,其中重点说明了BMP文件的存储格式,同时对JEPG和GIF等常用格式作了简单的介绍。
本节主要讲述如何操作BMP文件,如对其读、写和显示等。
在实现数字图象处理的过程中,主要是通过对图像中的每一个像素点运用各种图像处理算法来达到预期的效果,所以进行图像处理的第一步,也是我们最关心的问题,是如何得到图像中每一个像素点的亮度值;为了观察和验证处理的图像效果,另一个需要解决的问题是如何将处理前后的图像正确的显示出来。
我们这章内容就是解决这些问题。
随着科技的发展,图像处理技术已经渗透到人类生活的各个领域并得到越来越多的应用,但是突出的一个矛盾是图像的格式也是越来越多,目前图像处理所涉及的主要的图像格式就有很多种,如TIF、JEMP、BMP等等,一般情况下,为了处理简单方便,进行数字图像处理所采用的都是BMP格式的图像文件(有时也称为DIB格式的图像文件),并且这种格式的文件是没有压缩的。
我们通过操作这种格式的文件,可以获取正确显示图像所需的调色板信息,图像的尺寸信息,图像中各个像素点的亮度信息等等,有了这些数据,开发人员就可以对图像施加各种处理算法,进行相应的处理。
如果特殊情况下需要处理其它某种格式的图像,如GIF、JEMP等格式的图象文件,可以首先将该格式转换为BMP格式,然后再进行相应的处理。
这一点需要读者清楚。
BMP格式的图像文件又可以分为许多种类,如真彩色位图、256色位图,采用RLE(游程编码)压缩格式的BMP位图等等。
由于在实际的工程应用和图像算法效果验证中经常要处理的是256级并且是没有压缩的BMP灰度图像,例如通过黑白采集卡采集得到的图像就是这种格式,所以我们在整个讲座中范例所处理的文件格式都是BMP灰度图像。
如果读者对这种格式的位图能够作到熟练的操作,那么对于其余形式的BMP位图的操作也不会很困难。
BMP灰度图像作为Windows环境下主要的图像格式之一,以其格式简单,适应性强而倍受欢迎。
正如我们在上一讲中介绍过的那样,这种文件格式就是每一个像素用8bit表示,显示出来的图像是黑白效果,最黑的像素的灰度(也叫作亮度)值为"0",最白的像素的灰度值为"255",整个图像各个像素的灰度值随机的分布在"0"到"255"的区间中,越黑的像素,其灰度值越接近于"0",越白(既越亮)的像素,其灰度值越接近于"255";与此对应的是在该文件类型中的颜色表项的各个RGB分量值是相等的,并且颜色表项的数目是256个。
在进行图像处理时,操作图像中的像素值就要得到图像阵列;经过处理后的图像的像素值需要存储起来;显示图像时要正确实现调色板、得到位图的尺寸信息等。
结合这些问题,下面我们针对性的给出了操作灰度BMP图像时的部分函数实现代码及注释。
一、BMP位图操作
首先我们回顾一下上讲中的重要信息:
BMP位图包括位图文件头结构BITMAPFILEHEADER、位图信息头结构BITMAPINFOHEADER、位图颜色表RGBQUAD和位图像素数据四部分。
处理位图时要根据文件的这些结构得到位图文件大小、位图的宽、高、实现调色板、得到位图像素值等等。
这里要注意的一点是在BMP位图中,位图的每行像素值要填充到一个四字节边界,即位图每行所占的存储长度为四字节的倍数,不足时将多余位用0填充。
有了上述知识,可以开始编写图像处理的程序了,关于在VC的开发平台上如何开发程序的问题这里不再赘述,笔者假定读者都具有一定的VC开发经验。
在开发该图像处理程序的过程中,笔者没有采用面向对象的方法,虽然面向对象的方法可以将数据封装起来,保护类中的数据不受外界的干扰,提高数据的安全性,但是这种安全性是以降低程序的执行效率为代价的,为此,我们充分利用了程序的文档视图结构,在程序中直接使用了一些API函数来操作图像。
在微软的MSDN中有一个名为Diblook的例子,该例子演示了如何操作Dib位图,有兴趣的读者可以参考一下,相信一定会有所收获。
启动VisualC++,生成一个名为Dib的多文档程序,将CDibView类的基类设为CscrollView类,这样作的目的是为了在显示位图时支持滚动条,另外在处理图像应用程序的文档类(CDibDoc.h)中声明如下宏及公有变量:
#defineWIDTHBYTES(bits)(((bits)+31)/32*4)//计算图像每行象素所占的字节数目;
HANDLEm_hDIB;//存放位图数据的句柄;
CPalette*m_palDIB;//指向调色板Cpalette类的指针;
CSizem_sizeDoc;//初始化视图的尺寸,该尺寸为位图的尺寸;
最后将程序的字符串表中的字符串资源IDR_DibTYPE修改为:
"\\nDib\\nDib\\nDibFiles(*.bmp;*.dib)\\n.bmp\\nDib.Document\\nDibDocument"。
这样作的目的是为了在程序文件对话框中可以选择BMP或DIB格式的位图文件。
1、读取灰度BMP位图
可以根据BMP位图文件的结构,操作BMP位图文件并读入图像数据,为此我们充分利用了VC的文档视图结构,重载了文挡类的OnOpenDocument()函数,这样用户就可以在自动生成程序的打开文件对话框中选择所要打开的位图文件,然后程序将自动调用该函数执行读取数据的操作。
该函数的实现代码如下所示:
BOOLCDibDoc:
:
OnOpenDocument(LPCTSTRlpszPathName)
{
LOGPALETTE*pPal;//定义逻辑调色板指针;
pPal=newLOGPALETTE;//初始化该指针;
CFilefile;
CFileExceptionfe;
if(!
file.Open(lpszPathName,CFile:
:
modeRead|CFile:
:
shareDenyWrite,&fe))
{//以"读"的方式打开文件;
AfxMessageBox("图像文件打不开!
");
returnFALSE;
}
DeleteContents();//删除文挡;
BeginWaitCursor();
BITMAPFILEHEADERbmfHeader;//定义位图文件头结构;
LPBITMAPINFOlpbmi;
DWORDdwBitsSize;
HANDLEhDIB;
LPSTRpDIB;//指向位图数据的指针;
BITMAPINFOHEADER*bmhdr;//指向位图信息头结构的指针
dwBitsSize=file.GetLength();//得到文件长度
if(file.Read((LPSTR)&bmfHeader,sizeof(bmfHeader))!
=sizeof(bmfHeader))
returnFALSE;//读取位图文件的文件头结构信息;
if(bmfHeader.bfType!
=0x4d42)//检查该文件是否为BMP格式的文件;
returnFALSE;
hDIB=(HANDLE):
:
GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,dwBitsSize);
//为读取图像文件数据申请缓冲区
if(hDIB==0)
{
returnFALSE;
}
pDIB=(LPSTR):
:
GlobalLock((HGLOBAL)hDIB);
//得到申请的缓冲区的指针;
if(file.ReadHuge(pD