//////////////////////////////////直方图对话框构造函数; ZFT::ZFT(CWnd* pParent /*=NULL*/) : CDialog(ZFT::IDD, pParent)//ZFT为定义的用来显示直方图的对话框类; { Width=Height=0;//对话框初始化阶段设置图像的宽和高为"0"; } ////////////////////////对话框重画函数; void ZFT::OnPaint() { CRect rect;//矩形区域对象; CWnd *pWnd;//得到图片框的窗口指针; pWnd=GetDlgItem(IDC_Graphic);//得到ZFT对话框内的"Frame"控件的指针; file://(IDC_Graphic为放置在对话框上的一个"Picture"控件,并讲类型设置为"Frame")。 pWnd->GetClientRect(&rect);//得到"Frame"控件窗口的"视"区域; int i; CPaintDC dc(pWnd);//得到"Frame"控件的设备上下文; file://画直方图的x、y轴; dc.MoveTo(0,rect.Height()); dc.LineTo(rect.Width(),rect.Height()); dc.MoveTo(0,rect.Height()); dc.LineTo(0,0); file://画直方图,num[]是"ZFT"的内部数组变量,存放的是图像各个灰度级出现的概率;该数组的各个分量在 显示具体图像的直方图时设置; for(i=0;i<256;i++)//根据图像上的各个灰度级出现的概率,在坐标上对应的画出一根直线,从而各个表示各灰度级出现概率的直线构成了图像的直方图; { dc.MoveTo(i+1,rect.Height()); dc.LineTo (i+1,(rect.Height()-rect.Height()*num[i]*30)); file://此处num分量乘以"30"是为了放大个灰度级上对应的出现概率直线,增强显示效果; } } //////////////////////////////////////////////////////// void ZFT::OnMouseMove(UINT nFlags, CPoint point) {//OnMouseMove函数处理鼠标消息,显示当前鼠标所在直方图上的灰度值等信息; CWnd *pWnd,*pWndText;//定义两个窗口对象; CPoint point1;//定义个一个点对象; point1=point;//存放当前鼠标的位置信息; CRect rect;//矩形对象; CString string ;//字符串对象; pWnd=GetDlgItem(IDC_Graphic);//得到显示直方图的框架窗口对象指针; pWndText=GetDlgItem(IDC_NUM);//得到指向文本框对象(IDC_NUM)窗口的指针; pWnd->GetWindowRect(&rect);//获取pWnd窗口对象窗口区域位置; file://屏幕坐标转换为客户区坐标; ScreenToClient(&rect); file://判断当前鼠标是否指在直方图内; if(rect.PtInRect (point)) { int x=point1.x-rect.left; file://当前鼠标位置减去区域的起始位置恰好为当前鼠标所指位置所表示的灰度级; string.Format("%d",x); file://显示当前位置对应的图像的灰度级; pWndText->SetWindowText((LPCTSTR)string); } CDialog::OnMouseMove(nFlags, point); } //////////////////////////////////////// void CDibView::OnImagehorgm() file://在程序的"视"类对象内处理显示图像直方图的函数; { CDibDoc *pDoc=GetDocument(); HDIB hdib; hdib=pDoc->GetHDIB(); BITMAPINFOHEADER *lpDIBHdr;//位图信息头结构指针; BYTE *lpDIBBits;//指向位图像素灰度值的指针; lpDIBHdr=( BITMAPINFOHEADER *)GlobalLock(hdib);//得到图像的位图头信息 lpDIBBits=(BYTE*)lpDIBHdr+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD); file://获取图像像素值 ZFT dialog;//直方图对话框模板对象; int i,j; int wImgWidth=lpDIBHdr->biWidth; int wImgHeight=lpDIBHdr->biHeight; file://a[]数组用来存放各个灰度级出现的概率; float a[256]; for(i=0;i<256;i++)//初始化数组; { a[i]=0; } file://统计各个灰度级出现的次数; for(i=0;i for(j=0;j a[*(lpDIBBits+WIDTHBYTES(wImgWidth*8)*i+j)]++; } file://统计各个灰度级出现的概率; for(i=0;i<256;i++) { a[i]=a[i]/(wImgHeight*wImgWidth);//得到每个灰度级的出现概率; memcpy(dialog.num,a,256*sizeof(float)); } } dialog.DoModal();//显示直方图对话框; } return; } |
(a)LENA图像 |
(b)直方图 |
S=T (R); | k=0,1…, ; |
void CDibView::OnZftJh() { CClientDC pDC(this); HDC hDC=pDC.GetSafeHdc();//获取当前设备上下文的句柄; SetStretchBltMode(hDC,COLORONCOLOR); CDibDoc *pDoc=GetDocument(); HDIB hdib; hdib=pDoc->GetHDIB(); BITMAPINFOHEADER *lpDIBHdr;//位图信息头结构指针; BYTE *lpDIBBits;//指向位图像素灰度值的指针; lpDIBHdr=( BITMAPINFOHEADER *)GlobalLock(hdib);//得到图像的位图头信息 lpDIBBits=(BYTE*)lpDIBHdr+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD); file://获取图像像素值 float p[256],p1[256],num[256]; int i,j,k; for(i=0;i<256;i++)//清空三个数组; { num[i]=0.0f; p[i]=0.0f; p1[i]=0.0f; } file://num[]存放图象各个灰度级出现的次数; int Height=lpDIBHdr->biHeight; int Width=lpDIBHdr->biWidth; for(i=0;i num[*(lpDIBBits+WIDTHBYTES(Width*8)*i+j)]++; } file://p[]存放图像各个灰度级的出现概率; for(i=0;i<256;i++) { p[i]=num[i]/(Width*Height); } file://p1[]存放各个灰度级之前的概率和,用于直方图变换; for(i=0;i<256;i++) { for(k=0;k<=i;k++) p1[i]+=p[k]; } file://直方图变换; for(i=0;i } StretchDIBits (hDC,0,0,lpDIBHdr->biWidth,lpDIBHdr->biHeight,0,0, lpDIBHdr->biWidth,lpDIBHdr->biHeight, lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS, SRCCOPY);//显示图像; } |
(a)LENA原图 |
(b)直方图均衡化后的效果图 |
(c)原始图象的直方图 |
(d)均衡化后的直方他图 |
void CDibView::OnImagePh() { CClientDC pDC(this); HDC hDC=pDC.GetSafeHdc();//获取当前设备上下文的句柄; SetStretchBltMode(hDC,COLORONCOLOR); HANDLE data1handle; LPBITMAPINFOHEADER lpBi; CDibDoc *pDoc=GetDocument(); HDIB hdib; unsigned char *hData; unsigned char *data; hdib=pDoc->GetHDIB(); BeginWaitCursor(); lpBi=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)hdib); hData=(unsigned char*)FindDIBBits((LPSTR)lpBi); pDoc->SetModifiedFlag(TRUE); data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight); data=(unsigned char*)GlobalLock((HGLOBAL)data1handle); AfxGetApp()->BeginWaitCursor(); int i,j,s,t,ms=1; int sum=0,sumw=0; int mask[3][3]={{1,1,1},{1,2,1},{1,1,1}};//定义的3x3加权平滑模板; for(i=0; i for(j=0; j { sumw=0; sum=0; for(s=(-ms); s<=ms; s++) for(t=(-ms); t<=ms; t++) if(((i+s)>=0)&&((j+t)>=0)&&((i+s) { sumw += mask[1+s][1+t]; sum+=*(hData+(i+s)*WIDTHBYTES(lpBi->biWidth*8)+(j+t))*mask[1+s][1+t]; } if(sumw==0) sumw=1; sum/=sumw; if(sum>255)sum=255; if(sum<0)sum=0; *(data+i*WIDTHBYTES(lpBi->biWidth*8)+j)=sum; } for( j=0; j for(i=0;i StretchDIBits (hDC,0,0,lpBi->biWidth,lpBi->biHeight,0,0, lpBi->biWidth,lpBi->biHeight, hData,(LPBITMAPINFO)lpBi, DIB_RGB_COLORS, SRCCOPY);//显示图像; } |
(a)LENA原图 |
(b)平滑后的效果图 |
(a) |
(b) |
(c) |
void CDibView::OnMenuitem32785() { CClientDC pDC(this); HDC hDC=pDC.GetSafeHdc();//获取当前设备上下文的句柄; SetStretchBltMode(hDC,COLORONCOLOR); CDibDoc *pDoc=GetDocument(); HDIB hdib; hdib=pDoc->GetHDIB(); BITMAPINFOHEADER *lpDIBHdr;//位图信息头结构指针; BYTE *lpDIBBits;//指向位图像素灰度值的指针; lpDIBHdr=( BITMAPINFOHEADER *)GlobalLock(hdib);//得到图像的位图头信息 lpDIBBits=(BYTE*)lpDIBHdr+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);//获取图像像素值 BYTE* pData1; static int a[3][3]={{1,4,1},{4,-20,4},{1,4,1}};//拉普拉斯算子模板; int m,n,i,j,sum; int Width=lpDIBHdr->biWidth; int Height=lpDIBHdr->biHeight; pData1=(BYTE*)new char[WIDTHBYTES(Width*8)*Height]; file://进行拉普拉斯滤波运算; for(i=1;i sum=0; for(m=-1;m<2;m++) for(n=-1;n<2;n++) sum+=*(lpDIBBits+WIDTHBYTES(Width*8)*(i+m)+j+n)*a[1+m][1+n]; if(sum<0) sum=0; if(sum>255) sum=255; *(pData1+WIDTHBYTES(Width*8)*i+j)=sum; } file://原始图像pData减去拉普拉斯滤波处理后的图像pData1 for(i=0;i if(sum<0) sum=0; if(sum>255) sum=255; *(lpDIBBits+WIDTHBYTES(Width*8)*i+j)=sum; } StretchDIBits (hDC,0,0,lpDIBHdr->biWidth,lpDIBHdr->biHeight,0,0, lpDIBHdr->biWidth,lpDIBHdr->biHeight, lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS, SRCCOPY); } |
(a)LENA原图 |
(b)拉普拉斯锐化图 |