《图像处理》实验指导书.docx
《《图像处理》实验指导书.docx》由会员分享,可在线阅读,更多相关《《图像处理》实验指导书.docx(20页珍藏版)》请在冰豆网上搜索。
《图像处理》实验指导书
《图像处理》实验指导书
蔡利梅李剑编
信息与电气工程学院
学生实验守则
一、学生进入实验室必须遵守实验室的规章制度,遵守课堂纪律,保持实验室的安静和整洁,爱护实验室的一切设施。
二、实验课前要认真预习实验指导书,写出实验预习报告,并经教师批阅后方可进行实验。
三、实验课中要遵守操作规程,不要带电连接、更改或拆除线路。
线路接好后,经指导老师检查后,方可接通电源进行实验。
对于软件上机实验,不得随意删改计算机中原有的文件。
四、学生实验前对实验所用仪器设备要了解其操作规程和使用方法,凡因不预习或不按使用方法进行操作而造成仪器设备损坏者,除书面检查外,按学校规定进行赔偿。
五、实验中主意安全,遇到事故应立即关断电源并报告教师检查处理。
六、实验完毕后要做好整理工作,实验数据必须经指导教师签阅后,才能拆除线路,并将仪器、设备、凳子等按规定放好,经同意后方可离开实验室。
七、因故缺课的学生可向实验室申请一次补做机会。
无故缺课或无故迟到(15分钟以上)的不予补做,该次实验无成绩;累计三次者,该实验课以不及格论,并不得参加该门理论课程的考试。
八、实验室仪器设备不能擅自搬动调换,更不能擅自带出实验室。
信息与电气工程学院专业实验中心
二〇〇六年九月
《图像处理》实验一直方图均衡化
一、实验意义及目的
(1)进一步加深对图像直方图均衡化的理解
(2)掌握如何编程实现图像直方图均衡化
二、预备知识
(1)BMP图像格式、直方图均衡化原理
(2)VC6.0编程技术
三、实验原理
1、BMP图像格式
BITMAPFILEHEADER
位图文件头
BITMAPINFOHEADER
位图信息头
RGBQUAD
调色板
DATA
图像数据
(1)位图文件头
typedefstructtagBITMAPFILEHEADER
{
WORDbfType;//文件类型,必是”BM”0x4D42
DWORDbfSize;//指定文件大小(单位:
字节)
WORDbfReserved1;//保留字,不考虑
WORDbfReserved2;//保留字,不考虑
DWORDbfOffBits;//从文件头到位图数据的偏移字节数
}BITMAPFILEHEADER
(2)位图信息头
typedefstructtagBITMAPINFOHEADER
{
DWORDbiSize;//本结构的长度,40个字节
DWORDbiWidth;//图像宽,单位是像素
DWORDbiHeight;//图像高,单位是像素
WORDbiPlanes;//必须是1(位平面)
WORDbiBitCount;//颜色位数,1,4,8,24
DWORDbiCompression;//压缩类型,如//BI_RGB,BI_RLE4
DWORDbiSizeImage;//实际位图数据占用的字节数
DWORDbiXPelsPerMeter;//水平分辨率
DWORDbiYPelsPerMeter;//垂直分辨率
DWORDbiClrUsed;//实际使用的颜色数
DWORDbiClrImportant;//重要的颜色数
}BITMAPINFOHEADER;
(3)调色板单元
typedefstructtagRGBQUAD
{
BYTErgbBlue;//该颜色的蓝色分量
BYTErgbGreen;//该颜色的绿色分量
BYTErgbRed;//该颜色的红色分量
BYTErgbReserved;//保留值,不考虑
}RGBQUAD;
(4)图像数据
Ø图像中的颜色少于或等于256时,数据是颜色在调色板中的索引。
Ø图像为真彩色24位或更多,没有调色板,图像数据直接是每一个像素的颜色值B、G、R。
Ø位图的存储顺序:
从左到右、从下到上;即图像数据中的第一个数是图像的最左下角的像素值。
2、直方图均衡化
(1)原理
采用灰度级r的累计分布函数作为变换函数,把原始的灰度级r变换为s,使得变换后的图像灰度级分布具有均匀概率密度。
(2)步骤
Ø统计原图像的直方图
Ø计算新的灰度级
Ø修正sk为合理的灰度级
Ø计算新的直方图
Ø生成新的图像
四、直方图均衡化实验步骤
1、创建应用程序框架
(1)打开MicrosoftVisualC++运行环境,选择File菜单,单击New,在打开的对话框中,选中Projects页的MFCAppWizard[exe],在Projectname中输入test,设定Project的Location,选定Createnewworkspace,点击OK,进入下一步设置。
(2)在新打开的对话框中,选定Singledocument,单击Next。
(3)在以后的各步中,采用默认设置。
在最后一步,选择Finish。
(4)编译、运行,生成一个简单的Windows界面。
2、实现BMP文件的打开和显示
(1)为“文件/打开”添加基于文档类的消息响应函数
打开菜单View,选择ClassWizard,在打开的对话框中,进入MessageMaps,在Classname中选择CTestDoc类,在ObjectIDs中选择ID_FILE_OPEN,然后选中Messages中的COMMAND,单击右侧的AddFunction菜单,在弹出的小对话框中点击OK,选择了默认的函数名;单击EditCode按钮,则进入TestDoc.cpp编辑函数。
(2)在文档类的头文件中添加相关变量
打开TestDoc.h文件,在其中的一个public下,添加以下变量:
ØBITMAPFILEHEADER*fileheader;
ØBITMAPINFOHEADER*infoheader;
ØCStringFileName;
ØCFilefile;
ØBYTE*BMPData;
ØRGBQUAD*pal;
Øboolflag;
Øintlinebytes;
(3)定义宏定义
在TestDoc.cpp文件中OnFileOpen()函数前定义宏定义,计算存储一行像素需要的字节数:
#defineWIDTHBYTES(x)(((x)+31)/32*4)
(4)编辑函数voidCTestDoc:
:
OnFileOpen(),实现图像文件的打开和数据读取
voidCTestDoc:
:
OnFileOpen()
{
CFileDialogdlg(TRUE,0,0,OFN_HIDEREADONLY,“位图文件|*.bmp|所有文件|*.*||");
if(dlg.DoModal()==IDOK)
{
FileName=dlg.GetPathName();
if(!
file.Open(FileName,CFile:
:
modeRead))return;
fileheader=newBITMAPFILEHEADER[1];
infoheader=newBITMAPINFOHEADER[1];
file.Read(fileheader,14);
if(fileheader->bfType!
=0x4D42)return;
file.Read(infoheader,40);
if(infoheader->biCompression!
=0)return;
linebytes=WIDTHBYTES(infoheader->biBitCount*infoheader->biWidth);
if(infoheader->biBitCount==8)
{
pal=newRGBQUAD[256];
BMPData=newBYTE[linebytes*infoheader->biHeight];
file.Read(pal,256*4);
file.Read(BMPData,linebytes*infoheader->biHeight);
flag=true;
}
elseif(infoheader->biBitCount==24)
{
BMPData=newBYTE[linebytes*infoheader->biHeight];
file.Read(BMPData,linebytes*infoheader->biHeight);
flag=true;
}
elsereturn;
UpdateAllViews(NULL);
}
}
(5)编辑TestView.cpp中的OnDraw()函数,实现图像显示
voidCTestView:
:
OnDraw()
{
CTestDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(pDoc->flag==true)
{
intx,y,p;
unsignedcharr,g,b,pixel;
for(y=0;yinfoheader->biHeight;y++)
{
for(x=0;xinfoheader->biWidth;x++)
{
if(pDoc->infoheader->biBitCount==8)
{
p=x+y*pDoc->linebytes;
pixel=pDoc->BMPData[p];
r=pDoc->pal[pixel].rgbRed;
g=pDoc->pal[pixel].rgbGreen;
b=pDoc->pal[pixel].rgbBlue;
pDC->SetPixel(x,pDoc->infoheader->biHeight-1-y,RGB(r,g,b));
}
elseif(pDoc->infoheader->biBitCount==24)
{
p=x*3+y*pDoc->linebytes;
b=pDoc->BMPData[p];
g=pDoc->BMPData[p+1];
r=pDoc->BMPData[p+2];pDC->SetPixel(x,pDoc->infoheader->biHeight-1-y,RGB(r,g,b));
}
}
}
}
}
3、实现直方图均衡化
(1)修改程序菜单,添加“直方图均衡化”菜单,ID:
ID_HISTBALANCE
(2)创建菜单项“直方图均衡化”基于文档类的消息响应函数OnHistbalance()
(3)编辑OnHistbalance()函数,实现图像的直方图均衡化
voidCTestDoc:
:
OnHistbalance()
{
if(flag==true)
{
if(infoheader->biBitCount==8)
{
unsignedcharpixel;
intx,y,p;
intr[256],s[256];
for(x=0;x<256;x++)
{
r[x]=s[x]=0;
}
for(y=0;ybiHeight;y++)
{
for(x=0;xbiWidth;x++)
{
//统计原图各个灰度出现次数
}
}
//对r累加,求s
for(y=0;ybiHeight;y++)
{
for(x=0;xbiWidth;x++)
{
//在r和s之间建立对应关系,原先像素值为r的像素变为s【r】*255/w/h
}
}
UpdateAllViews(NULL);
}
}
五、实验考核
编制的程序的正确运行(70%)+实验报告(30%)
六、实验报告
实验结束后,撰写实验报告,实验报告主题部分应包括:
算法原理、程序流程、算法各部分主要函数代码以及功能注释、运行结果四部分,每部分占实验报告的10%,按照撰写情况打分。
《图像处理》实验二设定阈值分割
一、实验意义及目的
(1)进一步加深对图像分割的理解
(2)掌握如何编程实现图像分割
二、预备知识
(1)BMP图像格式、图像分割原理
(2)VC6.0编程技术
三、实验原理
1、BMP图像格式
BITMAPFILEHEADER
位图文件头
BITMAPINFOHEADER
位图信息头
RGBQUAD
调色板
DATA
图像数据
2、图像分割
指通过某种方法,使得画面场景中的目标物被分为不同的类别。
通常图像分割的实现方法是,将图像分为“黑”、“白”两类,这两类分别代表了两个不同的对象。
因为结果图像为二值图像,所以通常又称图像分割为图像的二值化处理。
阈值方法是根据图像的灰度值的分布特性确定某个阈值来进行图像分割,是图像分割的基本方法,关键在于分割阈值的确定。
图像阈值分割原理上的计算公式如下:
其中,f(i,j)为原始图像,g(i,j)为结果图像(二值),Th为阈值。
四、设定阈值分割实验步骤
1、打开test应用程序框架
2、修改程序菜单,添加“设定阈值分割”菜单,ID:
ID_THRESH
3、创建菜单项“设定阈值分割”基于文档类的消息响应函数OnThresh()
4、添加设定阈值的对话框IDD_THRESHDLG
(1)在对话框上添加控制按钮:
一个静态文本(用于提示说明)、一个输入文本框(用于输入阈值),修改文本框的名称为IDC_THRESH。
保留两个按钮OK和Cancel不变
(2)创建对话框类CThreshDlg。
(3)给对话框类CThreshDlg添加变量
打开“查看”中的“建立类向导”,选中第二个标签页“MemberVariables”,选中ID为“IDC_THRESH”,点击右侧的添加变量,在弹出的对话框中设置变量名称m_thresh和类型int,设定输入数据的最小值和最大值。
(5)在TestDoc.cpp文件中包含CThreshDlg头文件
在TestDoc.cpp文件开始处添加“#include"ThreshDlg.h"”。
(6)编辑voidCTestDoc:
:
OnThresh()函数
voidCTestDoc:
:
OnThresh()
{
if(flag==true)
{
intthresh;
CThreshDlgdlg;
if(dlg.DoModal()==IDOK)
{
thresh=dlg.m_thresh;
}
elsereturn;
if(infoheader->biBitCount==8)
{
unsignedcharpixel;
intx,y,p;
for(y=0;ybiHeight;y++)
{
for(x=0;xbiWidth;x++)
{
//判断每个像素值大于还是小于阈值并予以分割
}
}
}
UpdateAllViews(NULL);
}
}
五、实验考核
编制的程序的正确运行(70%)+实验报告(30%)
六、实验报告
实验结束后,撰写实验报告,实验报告主题部分应包括:
算法原理、程序流程、算法各部分主要函数代码以及功能注释、运行结果四部分,每部分占实验报告的10%,按照撰写情况打分。
《图像处理》实验三二值图像膨胀、腐蚀
一、实验意义及目的
(1)进一步加深对图像基于数学形态学处理算法的理解
(2)掌握如何编程实现二值图像的膨胀、腐蚀处理
二、预备知识
(1)BMP图像格式、数学形态学处理算法原理、二值图像的膨胀、腐蚀算法
(2)VC6.0编程技术
三、实验原理
1、BMP图像格式
BITMAPFILEHEADER
位图文件头
BITMAPINFOHEADER
位图信息头
RGBQUAD
调色板
DATA
图像数据
2、膨胀原理
(1)定义
X、B是两个集合,X被B膨胀,记为:
,
。
(2)含义
集合B先作关于原点的映射
,然后平移x,形成新的集合
,该集合与集合X相交不为空集时的结构元素参考点的集合。
3、腐蚀原理
(1)定义
X、B是两个集合,X被B腐蚀记为
。
(2)含义
B平移x后仍在集合X内部的参考点集合。
四、设定阈值分割实验步骤
1、打开test应用程序框架
2、修改程序菜单,添加“二值图像处理”下拉菜单,并添加下一级子菜单“膨胀”,ID:
ID_DILATION,添加子菜单“腐蚀”,ID:
ID_EROSION
3、创建菜单项“膨胀”“腐蚀”基于文档类的消息响应函数OnDilation()、OnErosion()
4、添加选择结构元素形状和大小的对话框IDD_NEIGHBORDLG
(1)在对话框上添加控制按钮:
四个单选按钮、分别对应邻域类型1×3、3×1、3×3、5×5,第一个单选按钮选择成组属性。
添加成组静态控制。
(2)创建对话框类CNeighborDlg。
(3)给对话框类CNeighborDlg添加变量
打开“查看”中的“建立类向导”,选中第二个标签页“MemberVariables”,选中ID为“IDC_RADIO1”,点击右侧的添加变量,在弹出的对话框中设置变量名称m_nbtype和类型int。
(5)在TestDoc.cpp文件中包含CNeighborDlg头文件
在TestDoc.cpp文件开始处添加“#include"NeighborDlg.h"”。
(6)编辑voidCTestDoc:
:
OnDilation()函数
voidCTestDoc:
:
OnDilation()
{
if(flag==true)
{
if(bivalue)
{
intnbtype,nbw,nbh,x,y,p,pixel=255;
CNeighborDlgnbdlg;
if(nbdlg.DoModal()==IDOK)
{
nbtype=nbdlg.m_nbtype;
}
else
{
nbtype=0;
}
switch(nbtype)
{
case0:
nbw=1;
nbh=3;
break;
case1:
nbw=3;
nbh=1;
break;
case2:
nbw=3;
nbh=3;
break;
case3:
nbw=5;
nbh=5;
break;
}
BYTE*TempData=newBYTE[linebytes*infoheader->biHeight];
memset(TempData,255,linebytes*infoheader->biHeight);
//开辟临时空间,存放数据
for(y=(nbh-1)/2;ybiHeight-(nbh-1)/2;y++)
{
for(x=(nbw-1)/2;xbiWidth-(nbw-1)/2;x++)
{
for(intm=-(nbh-1)/2;m<(nbh-1)/2+1;m++)
{
for(intn=-(nbw-1)/2;n<(nbw-1)/2+1;n++)
{
//判断当前邻域内是否有黑色点,若有,退出循环;}
}
//若前述判断中发现黑色点,则膨胀后的图像中包含当前点,赋值0给临时存储空间的当前像素点;
}
}
for(y=0;ybiHeight;y++)
{
for(x=0;xbiWidth;x++)
{
//把临时存储空间的数据传给BMPData
}
}
deleteTempData;
}
elseMessageBox(NULL,"notbivalueimage","systeminformation",MB_OK);
UpdateAllViews(NULL);
}
}
(7)编辑voidCTestDoc:
:
OnErosion()函数
voidCTestDoc:
:
OnErosion()
{
if(flag==true)
{
if(bivalue)
{
intnbtype,nbw,nbh,x,y,p,pixel=255;
CNeighborDlgnbdlg;
if(nbdlg.DoModal()==IDOK)
{
nbtype=nbdlg.m_nbtype;
}
else
{
nbtype=0;
}
switch(nbtype)
{
case0:
nbw=1;
nbh=3;
break;
case1:
nbw=3;
nbh=1;
break;
case2:
nbw=3;
nbh=3;
break;
case3:
nbw=5;
nbh=5;
break;
}
BYTE*TempData=newBYTE[linebytes*infoheader->biHeight];
memset(TempData,255,linebytes*infoheader->biHeight);
//开辟临时空间,存放数据
for(y=(nbh-1)/2;ybiHeight-(nbh-1)/2;y++)
{
for(x=(nbw-1)/2;xbiWidth-(nbw-1)/2;x++)
{
for(intm=-(nbh-1)/2;m<(nbh-1)/2+1;m++)
{
for(intn=-(nbw-1)/2;n<(nbw-1)/2+1;n++)
{
//判断当前邻域内是否有白色点,若有,退出循环;}
}
//若有白色点,给临时存储空间中的当前像素点赋255;
}
}
for(y=0;ybiHei