数 字 图 像 处 理 上 机 指 导.docx
《数 字 图 像 处 理 上 机 指 导.docx》由会员分享,可在线阅读,更多相关《数 字 图 像 处 理 上 机 指 导.docx(16页珍藏版)》请在冰豆网上搜索。
数字图像处理上机指导
VC++数字图像处理上机指导
(试用版)
桂进斌编著
适用专业:
电子信息相关专业
2011年3月
实验一、VC6.0下bmp位图的读取与显示
实验目的:
掌握windowsBMP格式位图文件的基本格式。
会使用VC++读取图像数据并显示。
实验内容:
1、在VC6.0环境下,生成MFC应用程序框架。
2、在已生成的应用程序中,加BMP位图读取与显示的代码,从已有文件中读取bmp格式文件并在视图中显示。
实验原理及步骤:
基本知识:
BMP位图文件格式
BMP位图文件中主要由4部分内容组成:
1、文件头BITMAPFILEHEADER为一STRUCTURE:
typedefstructtagBITMAPFILEHEADER{
WORDbfType;//文件类型,必须为“BM”或0x424d
DWORDbfSize;//文件大小
WORDbfReserved1;//保留
WORDbfReserved2;//保留
DWORDbfOffBits;//从文件头到实际位图数据的偏移字节数
}BITMAPFILEHEADER,FAR*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
2、位图信息头BITMAPINFOHEADER,定义如下:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;//structuresize
LONGbiWidth;//imagewidth
LONGbiHeight;//imageheight
WORDbiPlanes;//valueis1
WORDbiBitCount;//colorbits
DWORDbiCompression;//compressionornot
DWORDbiSizeImage;//Imagesize=width*height(其中width必须为4的倍数。
LONGbiXPelsPerMeter;//
LONGbiYPelsPerMeter;
DWORDbiClrUsed;//
DWORDbiClrImportant;
}BITMAPINFOHEADER,FAR*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
3、调色板
typedefstructtagRGBQUAD{
BYTErgbBlue;
BYTErgbGreen;
BYTErgbRed;
BYTErgbReserved;
}RGBQUAD;用于存放图像的颜色。
4、图像的实际数据。
对于2色图,用1位表示像素的值。
对于16色图,用4位表示像素的值。
对于256色图,一个字节刚好表示1个像素。
对于用到调色板的位图,图像数据就是该像素颜色在调色板中索引值,对于真彩色,不用调色板,三个字节的数据分别代表图像的B、G、R。
1、生成一名为dip的基于MFC的应用程序框架:
选择file菜单new选项,在打开的窗口中选择project选项,选中MFCAppWizard(exe)。
并在projectname输入dip,选择存放project的位置。
如下图所示。
选择ok,进入下一步。
选择singledocument,并在最后CdipView类的基类中选择CscrollView,使应用程序视图具有滚动条。
具体过程可参阅VC++6.0上机指导。
2、在应用程序中加入具体的函数和变量。
(1)在CdipView.h中加入如入变量:
public:
intm_x;
HBITMAPm_Bmp;
LPVOIDm_ColorList;
LPBYTEm_Image;
LPBITMAPINFOHEADERm_DibHead;
enumallocate{None,crtallocate,heapallocate};
allocatem_nBmpallocate;
allocatem_nImageallocate;
DWORDm_ImageSize;
intm_nPalette;
HANDLEm_hFile;
HANDLEm_hMap;
LPVOIDm_lpvFile;
HPALETTEm_hPalette;
HGLOBALm_hGlob;
利用ClassWizard向CdipView类中加入如下成员函数。
voidzftjh(unsignedchar*lpDib,longlWidth,longlHeight);
voidSetPaletteSize(intnBitCount);
voidClear();
BOOLReadFile(CFile*pFile);
BOOLSetPalette();
BOOLGetPalette();
BOOLDibToDC(CDC*pDC,CSizesize);
BOOLMemToDib(LPVOIDlmem);
CSizeGetDibSize();
并在具体的函数实现其功能,具体代码见附录1。
(2)利用资源编辑器,在主菜单中添加消息响应函数OnFileOpen(),并加入入下代码:
CFileDialogfiledlg(TRUE,"bmp","*.bmp");
if(filedlg.DoModal()!
=IDOK)
return;
CFilemyfile;
myfile.Open(filedlg.GetPathName(),CFile:
:
modeRead);
if(ReadFile(&myfile)==TRUE)
Invalidate();
SetPalette();
附录1:
读取bmp位图的函数代码。
CSizeCDipView:
:
GetDibSize()
{
if(m_DibHead==NULL)
returnCSize(0,0);
returnCSize((int)m_DibHead->biWidth,(int)m_DibHead->biHeight);
}
BOOLCDipView:
:
MemToDib(LPVOIDlmem)
{
Clear();
m_DibHead=(LPBITMAPINFOHEADER)lmem;
SetPaletteSize(m_DibHead->biBitCount);
m_Image=(LPBYTE)m_ColorList+sizeof(RGBQUAD)*m_nPalette;
GetPalette();
returnTRUE;
}
BOOLCDipView:
:
DibToDC(CDC*pDC,CSizesize)
{
if(m_DibHead==NULL)
returnFALSE;
if(m_hPalette!
=NULL)
{
HDChdc=pDC->GetSafeHdc();
:
:
SelectPalette(hdc,m_hPalette,TRUE);
}
pDC->SetStretchBltMode(COLORONCOLOR);
:
:
StretchDIBits(pDC->GetSafeHdc(),0,0,size.cx,size.cy,
0,0,m_DibHead->biWidth,m_DibHead->biHeight,
m_Image,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,
SRCCOPY);
returnTRUE;
}
BOOLCDipView:
:
GetPalette()
{
if(m_nPalette==0)
returnFALSE;
if(m_hPalette!
=NULL)
:
:
DeleteObject(m_hPalette);
LPLOGPALETTEpTempPalette=(LPLOGPALETTE)newchar[2*sizeof(WORD)+
m_nPalette*sizeof(PALETTEENTRY)];
pTempPalette->palVersion=0x30;
pTempPalette->palNumEntries=m_nPalette;
LPRGBQUADpRGBQuad=(LPRGBQUAD)m_ColorList;
for(inti=0;i{
pTempPalette->palPalEntry[i].peRed=pRGBQuad->rgbRed;
pTempPalette->palPalEntry[i].peGreen=pRGBQuad->rgbGreen;
pTempPalette->palPalEntry[i].peBlue=pRGBQuad->rgbBlue;
pTempPalette->palPalEntry[i].peFlags=0;
pRGBQuad++;
}
m_hPalette=:
:
CreatePalette(pTempPalette);
deletepTempPalette;
returnTRUE;
}
BOOLCDipView:
:
SetPalette()
{
if(m_nPalette!
=0)
returnFALSE;
CClientDCdc(this);
CDC*pDC=&dc;
m_hPalette=:
:
CreateHalftonePalette(pDC->GetSafeHdc());
returnTRUE;
}
BOOLCDipView:
:
ReadFile(CFile*pFile)
{
intnCount,nSize;
BITMAPFILEHEADERbmfh;
Clear();
try{
nCount=pFile->Read((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
if(nCount!
=sizeof(BITMAPFILEHEADER)){
thrownewCException;
}
if(bmfh.bfType!
=0x4d42){
thrownewCException;
}
nSize=bmfh.bfOffBits-sizeof(BITMAPFILEHEADER);
m_DibHead=(LPBITMAPINFOHEADER)newchar[nSize];
m_nBmpallocate=m_nImageallocate=crtallocate;
nCount=pFile->Read(m_DibHead,nSize);
SetPaletteSize(m_DibHead->biBitCount);
GetPalette();
m_Image=(LPBYTE)newchar[m_ImageSize];
nCount=pFile->Read(m_Image,m_ImageSize);
}
catch(CException*tmpc){
AfxMessageBox("文件读取错误");
tmpc->Delete();
returnFALSE;
}
returnTRUE;
}
voidCDipView:
:
Clear()
{
if(m_hFile==NULL)return;
:
:
UnmapViewOfFile(m_lpvFile);
:
:
CloseHandle(m_hMap);
:
:
CloseHandle(m_hFile);
m_hFile=NULL;
if(m_nBmpallocate==crtallocate){
delete[]m_DibHead;
}
elseif(m_nBmpallocate==heapallocate){
:
:
GlobalUnlock(m_hGlob);
:
:
GlobalFree(m_hGlob);
}
if(m_nImageallocate==crtallocate)delete[]m_Image;
if(m_hPalette!
=NULL):
:
DeleteObject(m_hPalette);
if(m_Bmp!
=NULL):
:
DeleteObject(m_Bmp);
m_nBmpallocate=m_nImageallocate=None;
m_hGlob=NULL;
m_DibHead=NULL;
m_Image=NULL;
m_ColorList=NULL;
m_nPalette=0;
m_ImageSize=0;
m_lpvFile=NULL;
m_hMap=NULL;
m_hFile=NULL;
m_Bmp=NULL;
m_hPalette=NULL;
}
voidCDipView:
:
SetPaletteSize(intnBitCount)
{
if(m_DibHead->biSize!
=sizeof(BITMAPINFOHEADER)){
thrownewCException;
}
m_ImageSize=m_DibHead->biSizeImage;
if(m_ImageSize==0){
DWORDdwBytes=((DWORD)m_DibHead->biWidth*
m_DibHead->biBitCount)/32;
if(((DWORD)m_DibHead->biWidth*m_DibHead->biBitCount)%32)
{
dwBytes++;
}
dwBytes*=4;
m_ImageSize=dwBytes*m_DibHead->biHeight;
}
m_ColorList=(LPBYTE)m_DibHead+sizeof(BITMAPINFOHEADER);
if((m_DibHead==NULL)||(m_DibHead->biClrUsed==0)){
switch(nBitCount){
case1:
m_nPalette=2;
break;
case4:
m_nPalette=16;
break;
case8:
m_nPalette=256;
break;
case16:
case24:
case32:
m_nPalette=0;
break;
default:
ASSERT(FALSE);
}
}
else{
m_nPalette=m_DibHead->biClrUsed;
}
ASSERT((m_nPalette>=0)&&(m_nPalette<=256));
}
作业与思考:
分析上述代码,说明每一部分的功能。
实验二、bmp位图的二值化与反色
实验目的:
理解图像的象素操作。
理解二值化与反色的本质。
实验内容及步骤:
1、根据实验一的结果,VC6.0开发环境下的资源编辑器中,在主菜单下添加一名为“点运算”的菜单。
并添加两个分别名为“二值化”与“反色”的子菜单项。
分别给它们名为“IDM_ERZH”、“IDM_FANCE”的ID。
2、打开classwizard,分别为下述两菜单项加入相应的消息映射函数。
3、在函数体中加入二值化和反色的实现代码。
4、在两函数体最后加入更新视图的函数:
Invalidate。
思考与练习:
1、说明影响二值化效果的参数是什么?
2、说明反色的原理是什么?
实验二、直方图编程
实验目的:
深入理解直方图的概念,学习VC++对话框中图形绘制的基本方法及步骤。
实验步骤:
1、在点运算的主菜单中添加一名为直方图的菜单资源,命名资源ID为IDM_ZFT 。
2、利用类向导添加相应消息响应函数。
3、展开Resource选项中Dialog项,右键单击该项,选择InsertDialog项,添加一对话框资源,并命名为IDD_ZFT_DIALOG。
4、编辑对话框资源,添加一PICTURE控件,两个button控件,并分别设置相应的ID号(一个为ID_OK,一个为ID_CANCEL)并加入相应的消息响应函数。
5、在ID_OK的消息响应函数中加入直方图的绘制代码,见附1。
6、编译运行。
作业与思考:
写出在对话框中绘图的基本步骤。
实验三、直方图均衡化实现图像增强
实验目的:
掌握直方图均衡化的原理。
掌握直方图均衡化实现图像增强的实现方法。
实验原理:
见课本第四章。
实验内容及步骤:
利用直方图均衡化实现图像增强。
1、在资源编辑器中添加一菜单项,给定一ID号。
用于表示直方图增强的选项。
2、利用类向导添加相应的消息响映函数。
在函数体中加入下述代码。
if(m_DibHead->biBitCount!
=8)
{
MessageBox("当前版本仅支持256色位图的操作!
","系统提示!
",MB_ICONINFORMATION|MB_OK);
return;
}
zftjh(m_Image,m_DibHead->biWidth,m_DibHead->biHeight);
Invalidate();
其中函数zftjh的实现代码如下:
zftjh(unsignedchar*lpDib,longlWidth,longlHeight)
{
unsignedchar*lpsrc;
longlresult(0);
longi,j;
unsignedcharbMap[256];
longlCount[256];
for(i=0;i<256;i++)
lCount[i]=0;
for(i=0;ifor(j=0;j{
lpsrc=lpDib+i*lWidth+j;
lCount[*lpsrc]++;
}
for(i=0;i<256;i++)
{
lresult=0;
for(j=0;j<=i;j++)
lresult+=lCount[j];
bMap[i]=(lresult*255)/lHeight/lWidth;
}
for(i=0;ifor(j=0;j{
lpsrc=lpDib+i*lWidth+j;
*lpsrc=bMap[*lpsrc];
}
}
3、编译、运行。
查看结果。
思考与作业:
1、提交上机报告,要求说明实验的原理及具体的实现过程。
2、试说明为什么直方图均衡能实现图像的增强。
实验四、图像的平滑与锐化
实验目的:
掌握图像平滑与锐化的基本原理。
用C++编程实现图像的平滑与锐化。
实验内容:
1、选择一种平滑方式对图像进行平滑操作。
2、选择一种锐化方法对图像进行锐化操作。
3、分析图像的平滑与锐化的作用是什么。
4、试分析各种方法的特点。
实验步骤:
1、在主菜单中添加图像增强的菜单项,并添加相应的图像平滑与图像锐化两个子菜单项。
2、利用类向导添加相应的消息响应函数。
实现图像的平滑与锐化操作。
3、打开一幅图像,先进行平滑,然后再进行锐化操作。
观察图像的变化情况。
思考与作业:
1、提交上机报告,要求说明图像平滑与锐化的原理。
2、说明各种平滑方法对图像的操作结果有什么不同?
3、说明哪一种锐化方法最好?
为什么?
实验五、图像的无约束复原
实验目的:
掌握图像无约束复原的原理及应用。
实验内容及步骤:
1、对一幅图像加入运动因素,模拟图像由于运动产生模糊的图像。
2、对上述的模糊图像进行复原。
比较复原的图像与原图像。
实验步骤:
1、在主菜单中加入图像复原菜单项,并添加两子菜单项,分别为“模糊”和“复原”。
并赋以相应的ID号。
2、利用类向导加入相应的消息响应函数。
并完成两个函数代码的编写。
3、观察结果,比较复原后的图像与没有模糊时的图像。
思考与作业:
1、提交上机报告,具体要求同前。
2、举例说明图像复原的应用。
实验六、图像的频域处理(低通、高通)
实验目的:
理解图像傅立叶变换,掌握二维FFT函数的调用方法。
理解图像频谱的物理意义。
实验内容及步骤:
1、在菜单中添加一选项,然后建立消息映射函数,在函数中调用一维傅立叶变换函数,实现二维傅立叶变换,并计算图像的频谱。
2、在菜单中添加一选项实现低通滤波。
3、在菜单中添加一选项实现高通滤波。