VC编程实现灰度图像与彩色图像的相互转换完整版.docx
- 文档编号:10341106
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:15
- 大小:449.14KB
VC编程实现灰度图像与彩色图像的相互转换完整版.docx
《VC编程实现灰度图像与彩色图像的相互转换完整版.docx》由会员分享,可在线阅读,更多相关《VC编程实现灰度图像与彩色图像的相互转换完整版.docx(15页珍藏版)》请在冰豆网上搜索。
VC编程实现灰度图像与彩色图像的相互转换完整版
VC编程实现灰度图像与彩色图像的相互转换
PhotoShop的图像处理功能很强,其中有一个功能是将灰度图像转换为彩色图像,数字图像处理中,也经常要遇到灰度图像与彩色图像相互转换的问题,如何自己解决这个问题,值得大家探讨,现将我解决这类问题的方法陈述如下:
工程应用中经常要遇到需要把彩色图像到灰度图像的变换的问题,采集卡过来的图像为彩色图像,为加快处理速度,要把彩色图像转换为黑白图象,这个问题比拟好解决,一般情况下彩色图像每个像素用三个字节表示,每个字节对应着R、G、B分量的亮度〔红、绿、蓝〕,转换后的黑白图像的一个像素用一个字节表示该点的灰度值,它的值在0~255之间,数值越大,该点越白,既越亮,越小那么越黑。
转换公式为Gray(i,j)=0.11*R(i,j)+0.59*G(i,j)+0.3*B(i,j),其中Gray(i,j)为转换后的黑白图像在〔i,j〕点处的灰度值,我们可以观察该式,其中绿色所占的比重最大,所以转换时可以直接使用G值作为转换后的灰度。
至于灰度图像转换为彩色图像,技术上称为灰度图像的伪彩色处理,这是一种视觉效果明显而技术又不是很复杂的图像增强技术。
灰度图像中,如果相邻像素点的灰度相差不大,但包含了丰富的信息的话,人眼那么无法从图像中提取相应的信息,因为人眼分辨灰度的能力很差,一般只有几十个数量级,但是人眼对彩色信号的分辨率却很强,这样将黑白图像转换为彩色图像人眼可以提取更多的信息量。
在转换过程中,经常采用的技术是灰度级-彩色变换,意思就是对黑白图像上的每一个像素点,取得该点的灰度值并送入三个通道经过实施不同的变换,产生相应的R、G、B的亮度值,即所求彩色图像对应像素点的彩色值,具体变换公式很多,我采用的是最常用的一种,变换曲线图如下:
上图中,三个图分别代表了三个变换通道,R、G、B指的是变换后对应点的R、G、B分量值,L指的是各个分量的最大值为255,G〔x,y〕为相应点的灰度值。
理论上就这些,下面是我用VC实现的源代码,图一为我的灰度位图,图二为伪彩色处理后的结果图。
我这个实现函数中是如何得到灰度位图的数据的就不多讲了,有兴趣的朋友可参考我在天极网上九月十号发表的?
VC灰度位图处理?
一文,那里应该讲的很清楚了。
需要读者注意的是彩色图像中每个象素中的三个字节分别代表的分量,第一个字节为B,第二个为G值、最后一个为R值,这个顺序不要搞错了。
代码实现如下:
voidCDibView:
:
OnMenuchange()file:
//图像转换实现函数
{
//TODO:
Addyourcommandhandlercodehere
HANDLEdata1handle;
LPBITMAPINFOHEADERlpBi;
BITMAPINFO*m_pBMI;
CDibDoc*pDoc=GetDocument();
HDIBhdib;
unsignedchar*hData;
unsignedchar*data;
hdib=pDoc->GetHDIB();//得到位图数据的句柄,其中包含图像信息头
BeginWaitCursor();
lpBi=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)hdib);
hData=(unsignedchar*)FindDIBBits((LPSTR)lpBi);
m_pBMI=newBITMAPINFO;//生成彩色图像的信息头
m_pBMI->bmiHeader.biBitCount=24;
m_pBMI->bmiHeader.biClrImportant=0;
m_pBMI->bmiHeader.biClrUsed=0;
m_pBMI->bmiHeader.biCompression=BI_RGB;
m_pBMI->bmiHeader.biHeight=lpBi->biHeight;
m_pBMI->bmiHeader.biWidth=lpBi->biWidth;
m_pBMI->bmiHeader.biPlanes=1;
m_pBMI->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
m_pBMI->bmiHeader.biXPelsPerMeter=0;
m_pBMI->bmiHeader.biYPelsPerMeter=0;
m_pBMI->bmiHeader.biSizeImage=WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight*3;
file:
//data=hData;
intR,G,B,i,j;
data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight*3);
file:
//生成存储彩色图象数据的缓冲区
data=(unsignedchar*)GlobalLock((HGLOBAL)data1handle);
for(i=0;ibiHeight;i++)//实现灰度到彩色变换
for(j=0;jbiWidth*8);j++)
{
if(*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)<=64)
{R=0;
G=(int)4*(*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j));
B=255;
}
if(*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)>64
&&*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)<=128)
{R=0;
G=255;
B=(int)4*(128-*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j));
}
if(*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)>128
&&*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)<=192)
{R=(int)4*(*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)-128);
G=255;
B=0;
}
if(*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)>192
&&*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)<=255)
{R=255;
G=(int)4*(255-*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j));
B=0;
}
file:
//将生成的R、G、B分量存入目标缓冲区
*(data+i*WIDTHBYTES(lpBi->biWidth*8)*3+j*3)=B;
*(data+i*WIDTHBYTES(lpBi->biWidth*8)*3+j*3+1)=G;
*(data+i*WIDTHBYTES(lpBi->biWidth*8)*3+j*3+2)=R;
}
GlobalUnlock((HGLOBAL)hdib);
GlobalUnlock(data1handle);
EndWaitCursor();
CClientDCpDC(this);
file:
//显示真彩色图像
StretchDIBits(pDC.GetSafeHdc(),0,0,lpBi->biWidth,lpBi->biHeight,0,0,
lpBi->biWidth,lpBi->biHeight,data,m_pBMI,DIB_RGB_COLORS,
SRCCOPY);
deletem_pBMI;
}
图一
图二
数字图像处理技术博大精深,我真诚的希望和广阔朋友探讨
VisualC++6.0开发灰度位图处理
图像处理技术已经渗透到人类生活的各个领域并得到越来越多的应用,图像处理所涉及的图像格式有很多种,如TIF、JEMP、BMP等等,工程应用中经常要处理256级的灰度BMP图像,如通过黑白采集卡采集得到的图像。
BMP灰度图像作为Windows环境下主要的图像格式之一,以其格式简单,适应性强而倍受欢送。
在进行图像处理时,操作图像中的像素值就要得到图像阵列;经过处理后的图像的像素值存储起来;显示图像时要正确实现调色板,结合这些问题,文章针对性的给出了操作灰度BMP图像时的局部函数实现代码及注释。
一、BMP位图操作
BMP位图包括位图文件头结构BITMAPFILEHEADER、位图信息头结构BITMAPINFOHEADER、位图颜色表RGBQUAD和位图像素数据四局部。
处理位图时要根据文件的这些结构得到位图文件大小、位图的宽、高、实现调色板、得到位图像素值等等。
对于256级灰度图像每个像素用8bit表示颜色的索引值,这里要注意的一点是在BMP位图中,位图的每行像素值要填充到一个四字节边界,即位图每行所占的存储长度为四字节的倍数,缺乏时将多余位用0填充。
在处理图像应用程序的文档类〔CdibDoc.h〕中声明如下宏及公有变量:
#defineWIDTHBYTES(bits)(((bits)+31)/32*4)//计算图像每行象素所占的字节数目
HANDLEm_hDIB;//存放位图数据的句柄
CPalette*m_palDIB;//指向调色板Cpalette类的指针
CSizem_sizeDoc;file:
//初始化视图的尺寸
1、读取灰度BMP位图
根据BMP位图文件的结构,操作BMP位图文件读入数据,重载了文挡类的OnOpenDocument函数如下:
BOOLCDibDoc:
:
OnOpenDocument(LPCTSTRlpszPathName)
{
CFilefile;
CFileExceptionfe;
if(!
file.Open(lpszPathName,CFile:
:
modeRead|CFile:
:
shareDenyWrite,&fe))
{
AfxMessageBox("文件打不开");
returnFALSE;
}//翻开文件
DeleteContents();//删除文挡
BeginWaitCursor();
BITMAPFILEHEADERbmfHeader;//定义位图文件头结构
DWORDdwBitsSize;
HANDLEhDIB;
LPSTRpDIB;
BITMAPINFOHEADER*bmhdr;//指向位图信息头结构的指针
dwBitsSize=file.GetLength();//得到文件长度
if(file.Read((LPSTR)&bmfHeader,sizeof(bmfHeader))!
=
sizeof(bmfHeader))
returnFALSE;
if(bmfHeader.bfType!
=0x4d42)file:
//检查是否为BMP文件
returnFALSE;
hDIB=(HANDLE):
:
GlobalAlloc(GMEM_MOVEABLE|
GMEM_ZEROINIT,dwBitsSize);
file:
//申请缓冲区
if(hDIB==0)
{
returnFALSE;
}
pDIB=(LPSTR):
:
GlobalLock((HGLOBAL)hDIB);
file:
//得到申请的缓冲区的指针
if(file.ReadHuge(pDIB,dwBitsSize-sizeof(BITMAPFILEHEADER))!
=
dwBitsSize-sizeof(BITMAPFILEHEADER))
{
:
:
GlobalUnlock((HGLOBAL)hDIB);
hDIB=NULL;
returnFALSE;
}//读数据,包括位图信息、位图颜色表、图像像素的灰度值
bmhdr=(BITMAPINFOHEADER*)pDIB;//为指向位图信息头结构的指针付值
:
:
GlobalUnlock((HGLOBAL)hDIB);
if((*bmhdr).biBitCount!
=8)file:
//验证是否为8bit位图
returnFALSE;
m_hDIB=hDIB;
InitDIBData();
file:
//自定义函数,根据读入的数据得到位图的宽、高、颜色表
file:
//来得到初始化视的尺寸、生成调色板
EndWaitCursor();
SetPathName(lpszPathName);//设置存储路径
SetModifiedFlag(FALSE);//设置文件修改标志为FALSE
returnTRUE;
}
2、灰度位图数据的存储
为了将图像处理后所得到的像素值保存起来,重载了文档类的OnSaveDocument函数,其具体实现如下:
BOOLCDibDoc:
:
OnSaveDocument(LPCTSTRlpszPathName)
{
CFilefile;
CFileExceptionfe;
BITMAPFILEHEADERbmfHdr;//位图文件头结构
LPBITMAPINFOHEADERlpBI;file:
//指向位图信息结构的指针
DWORDdwDIBSize;
if(!
file.Open(lpszPathName,CFile:
:
modeCreate|
CFile:
:
modeReadWrite|CFile:
:
shareExclusive,&fe))
{
AfxMessageBox("文件打不开");
}//翻开文件
BOOLbSuccess=FALSE;
BeginWaitCursor();
lpBI=(LPBITMAPINFOHEADER):
:
GlobalLock((HGLOBAL)m_hDIB);
if(lpBI==NULL)
returnFALSE;
dwDIBSize=*(LPDWORD)lpBI+256*sizeof(RGBQUAD);
//PartialCalculation
DWORDdwBmBitsSize;//BMP文件信息结构所占的字节数
dwBmBitsSize=WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) *lpBI->biHeight;//存储时位图所有像素所占的总字节数
dwDIBSize+=dwBmBitsSize;
lpBI->biSizeImage=dwBmBitsSize;//位图所有像素所占的总字节数
file:
//以下五句为文件头结构填充值
bmfHdr.bfType=0x4d42;//文件为"BMP"类型
bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER);//文件总长度
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+lpBI->biSize
+256*sizeof(RGBQUAD);
file:
//位图数据距问件头的偏移量
file.Write((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER));//写文件头
file.WriteHuge(lpBI,dwDIBSize);
file:
//将位图信息〔信息头结构、颜色表、像素数据〕写入文件
:
:
GlobalUnlock((HGLOBAL)m_hDIB);
EndWaitCursor();
SetModifiedFlag(FALSE);//backtounmodified
returnTRUE;
}
二、调色板的操作
灰度图像要正确显示,必须实现逻辑调色板和系统调色板,通过在主框架类中处理Windows定义的消息WM_QUERYNEWPALETTE、WM_PALETTECHANGED及视图类中处理自定义消息WM_DOREALIZE〔该消息在主框架窗口定义如下:
#defineWM_REALIZEPAL(WM_USER+100)〕来实现调色板的操作。
voidCMainFrame:
:
OnPaletteChanged(CWnd*pFocusWnd)
{file:
//总实现活动视的调色板
CMDIFrameWnd:
:
OnPaletteChanged(pFocusWnd);
CMDIChildWnd*pMDIChildWnd=MDIGetActive();
if(pMDIChildWnd==NULL)
return
CView*pView=pMDIChildWnd->GetActiveView();
ASSERT(pView!
=NULL);
SendMessageToDescendants(WM_DOREALIZE,(WPARAM)pView->m_hWnd);
file:
//通知所有子窗口系统调色板已改变
}
BOOLCMainFrame:
:
OnQueryNewPalette()//提供实现系统调色板的时机
{
//实现活动视的调色板
CMDIChildWnd*pMDIChildWnd=MDIGetActive();
if(pMDIChildWnd==NULL)
returnFALSE;//noactiveMDIchildframe(nonewpalette)
CView*pView=pMDIChildWnd->GetActiveView();
ASSERT(pView!
=NULL);
file:
//通知活动视图实现系统调色板
pView->SendMessage(WM_DOREALIZE,(WPARAM)pView->m_hWnd);
returnTRUE;
}
LRESULTCDibView:
:
OnDoRealize(WPARAMwParam,LPARAM)//实现系统调色板
{
ASSERT(wParam!
=NULL);
CDibDoc*pDoc=GetDocument();
if(pDoc->m_hDIB==NULL)
return0L;//mustbeanewdocument
CPalette*pPal=pDoc->m_palDIB;
file:
//调色板的颜色表数据在InitDIBData()函数中实现
if(pPal!
=NULL)
{
CMainFrame*pAppFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
ASSERT_KINDOF(CMainFrame,pAppFrame);
CClientDCappDC(pAppFrame);
CPalette*oldPalette=appDC.SelectPalette(pPal,((HWND)wParam)!
=m_hWnd);
file:
//只有活动视才可以设为"FALSE",
//即根据活动视的调色板设为"前景"调色板
if(oldPalette!
=NULL)
{
UINTnColorsChanged=appDC.RealizePalette();//实现系统调色板
if(nColorsChanged>0)
pDoc->UpdateAllViews(NULL);//更新视图
appDC.SelectPalette(oldPalette,TRUE);
file:
//将原系统调色板置为逻辑调色板
}
else
{
TRACE0("\tSelectPalettefailedin
CDibView:
:
OnPaletteChanged\n");
}
}
注:
在调用API函数显示位图时,不要忘记设置逻辑调色板,即"背景"调色板,否那么位图将无法正确显示。
三、图像的数字化处理
通过以上读文件的操作,已经得到图像数据,由于得到的数据包括多余信息,所以在进行数字图像处理时要进一步删除多余信息,只对位图的像素进行操作,以基于模板的高通滤波为例来讲述数字图像处理的实现:
voidCDibView:
:
OnMENUHighPass()
{HANDLEdata1handle;
LPBITMAPINFOHEADERlpBi;
CDibDoc*pDoc=GetDocument();
HDIBhdib;unsignedchar*hData;unsignedchar*data;
hdib=pDoc->GetHDIB();
BeginWaitCursor();
lpBi=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)hdib);
hData=(unsignedchar*)FindDIBBits((LPSTR)lpBi);
pDoc->SetModifiedFlag(TRUE);
data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight);
data=(unsignedchar*)GlobalLock((HGLOBAL)data1handle);
AfxGetApp()->BeginWaitCursor();
inti,j,s,t,ms=1;
intsum=0,sumw=0;
intmask[3][3]={{-1,-1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC 编程 实现 灰度 图像 彩色 相互 转换 完整版