1. 程式人生 > >利用MFC中的picture control 控制元件顯示影象

利用MFC中的picture control 控制元件顯示影象

參考博文

本文是根據opencv246和VS2012在用MFC做影象顯示時出現的問題做出解釋

一、建立MFC首先建立一個MFC對話方塊應用程式(Dialog-based Application;點選OK -- Next進入下一步,在這裡我們建立一個Dialog-based Application,大部分選項按預設設定就行,不過最下面的“Use Unicode libraries”最好去掉。如果勾選了這

個選項,程式程式碼就會使用16bitUnicode字符集來編碼,但是很多函式雖然使用 char* (ASCII stings) 型別字元,而將字串從 Unicode 轉換到 ASCII 

是非常麻煩的。使用 Unicode 在編譯時可能會遇到下列錯誤:    cannot convert parameter 1 from 'CString' to 'const char *'    cannot convert from 'const char [11]' to 'LPCWSTR'這意味著在UnicodeMulti-byte字串的轉換中出現了問題。故這裡的去掉“Use Unicode libraries”選項。

二、編寫程式碼

開啟工程檔案,進入資源檢視:LoadPicture(工程名稱)->LoadPicture.rc->Dialog雙擊IDD_LoadPicture

_DIALOG,可以看到一個初始的GUI介面,往裡面新增兩個 Button 和 一個 Picture 控制元件

選中單個控制元件、右擊選擇屬性(Properties),可以看到控制元件的ID號,這個號可以自行編輯,例如 Picture 控制元件的 ID 號我設定為 IDC_ShowImg,這個 ID 號在後面的影象顯示函式中要用到。

庫加入到VS中,沒有配置會出錯opencv246+VS2012的配置課參考

然後在 LoadPicture.h 的 #include "resource.h" 程式碼行下面加入如下程式碼:

#include <opencv\cv.h>

#include <opencv\highgui.h>

#define IMAGE_WIDTH 256

#define IMAGE_HEIGHT 256

#define IMAGE_CHANNELS 3

在 類視圖面板右擊 CloadPictureDlg,選擇 Add > Add Variable,新增一個 IplImage* 型別的變數 TheImage


再點選 CLoadPictureDlg,在下面視窗的列表中雙擊 OnInitDialog,在// TODO: 在此新增額外的初始化程式碼下面新增 TheImage 的初始化程式碼:

CvSize ImgSize;    

ImgSize.height = IMAGE_HEIGHT;    

ImgSize.width = IMAGE_WIDTH;    

TheImage=cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS );

然後雙擊 OnPaint,在 if(IsIconic())…的 else 裡新增以下程式碼,用來重繪視窗:

CDialog::OnPaint();   // 重繪對話方塊        

CDialog::UpdateWindow();   // 更新windows視窗,如果無這步呼叫,圖片顯示還會出現問題        

ShowImage( TheImage, IDC_ShowImg );     // 重繪圖片函式

接著在 CtestPicControlApp 下面的成員列表中雙擊 InitInstance,在兩個“// TODO: Place code here to handle when the dialog is…”下面新增:cvReleaseImage( &dlg.TheImage );

即按下“OK”或“Cancel”時,釋放TheImage佔用的記憶體。

寫讀取和處理圖片的功能函式。

回到資源檢視,雙擊按鈕 ReadImage,,建立按鈕點選的訊息響應程式:OnBnClickedReadimage,主要的響應操作包括 彈出對話方塊選擇圖片檔案、讀入圖片檔案、對圖片統一縮放至256*256的大小、顯示影象,程式碼如下:

  1. // TODO: 在此新增控制元件通知處理程式程式碼
  2.         CFileDialog dlg(  
  3.                 TRUE, _T("*.bmp"), NULL,  
  4.                 OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,  
  5.                 _T("image files (*.bmp; *.jpg) |*.bmp; *.jpg | All Files (*.*) |*.*||"), NULL  
  6.                 );                                                                              // 選項圖片的約定
  7.         dlg.m_ofn.lpstrTitle = _T("Open Image");         // 開啟檔案對話方塊的標題名
  8.         if(dlg.DoModal()!=IDOK )      // 判斷是否獲得圖片
  9.                 return;  
  10.         CString mPath = dlg.GetPathName();   // 獲取圖片路徑
  11.         IplImage* ipl = cvLoadImage( mPath, 1 );   // 讀取圖片、快取到一個區域性變數 ipl 中
  12.         if(!ipl)                                                                       // 判斷是否成功讀取圖片
  13.                 return;  
  14.         if(TheImage)                                                           // 對上一幅顯示的圖片資料清零
  15.                 cvZero( TheImage );  
  16.         ResizeImage( ipl );      // 對讀入的圖片進行縮放,使其寬或高最大值者剛好等於 256,再複製到 TheImage 中
  17.         ShowImage( TheImage, IDC_ShowImg);                     // 呼叫顯示圖片函式     
  18.         cvReleaseImage(&ipl);                                          // 釋放 ipl 佔用的記憶體

在上面的程式碼中包含了兩個新的成員函式 ResizeImage 和 ShowImage,前者的作用是對讀入的不同大小的影象進行縮放,再通過設定 ROI 的方式將影象存入 256*256 的 TheImage 中;後者是將影象 TheImage 顯示到圖片顯示控制元件 IDC_ShouImg 視窗的正中部位。為了實現這兩個功能,首先在類檢視 面板右擊 CtestPicControlDlg,選擇 Add > Add Function,建立兩個函式:void ShowImage( IplImage* img, UINT ID ) 和 void ResizeImage(IplImage* img)。以下是這兩個函式的實現程式碼:

函式新增如下


  1. void CLoadPicControlDlg::ShowImage(IplImage* img, UINT ID)// ID 是Picture Control控制元件的ID號
  2. {  
  3.         CDC* pDC=GetDlgItem(ID)->GetDC();// 獲得顯示控制元件的 DC
  4.         HDC hDC=pDC->GetSafeHdc();// 獲取 HDC(裝置控制代碼) 來進行繪圖操作
  5.         CRect rect;  
  6.         GetDlgItem(ID)->GetClientRect(&rect);  
  7.         int rw=rect.right-rect.left;    // 求出picture control的寬和高
  8.         int rh=rect.bottom-rect.top;  
  9.         int iw=img->width;             // 讀取圖片的寬和高
  10.         int ih=img->height;  
  11.         int tx = (int)(rw - iw)/2;                                       // 使圖片的顯示位置正好在控制元件的正中
  12.         int ty = (int)(rh - ih)/2;  
  13.         SetRect( rect, tx, ty, tx+iw, ty+ih );  
  14.         CvvImage cimg;  
  15.         cimg.CopyOf(img);    // 複製圖片
  16.         cimg.DrawToHDC(hDC,&rect);  
  17.         ReleaseDC(pDC);  
  18. }  

  1. void CtestPicControlDlg::ResizeImage(IplImage* img)  
  2. {  
  3.         // 讀取圖片的寬和高
  4.         int w = img->width;  
  5.         int h = img->height;  
  6.         // 找出寬和高中的較大值者
  7.         int max = (w > h)? w: h;  
  8.         // 計算將圖片縮放到TheImage區域所需的比例因子
  9.         float scale = (float) ( (float) max / 256.0f );  
  10.         // 縮放後圖片的寬和高
  11.         int nw = (int)( w/scale );  
  12.         int nh = (int)( h/scale );  
  13.         // 為了將縮放後的圖片存入 TheImage 的正中部位,需計算圖片在 TheImage 左上角的期望座標值
  14.         int tlx = (nw > nh)? 0: (int)(256-nw)/2;  
  15.         int tly = (nw > nh)? (int)(256-nh)/2: 0;  
  16.         // 設定 TheImage 的 ROI 區域,用來存入圖片 img
  17.         cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );  
  18.         // 對圖片 img 進行縮放,並存入到 TheImage 中
  19.         cvResize( img, TheImage );  
  20.         // 重置 TheImage 的 ROI 準備讀入下一幅圖片
  21.         cvResetImageROI( TheImage );  
  22. }  

注意

1:如果你的CvvImage出現紅色的底線提示沒有定義那說明你的opencv版本是比較新的裡面的CvvImage函式已經被去掉了,我的opencv246就沒有這個函式。只要在工程中加入CvvImage.hCvvImage.cpp

2:如果你編譯後出現error C4996: 'fopen': This function or variable may be unsafe.的錯誤提示說明的


原文地址:http://blog.csdn.net/lxy201700/article/details/16921903