//////////////////////////////////直方圖對話框構造函數; 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)拉普拉斯銳化圖 |
原文轉自:http://www.anti-gravitydesign.com