利用MFC中的picture control 控制元件顯示影象
參考博文
本文是根據opencv246和VS2012在用MFC做影象顯示時出現的問題做出解釋
一、建立MFC1 首先建立一個MFC對話方塊應用程式(Dialog-based Application);2 點選OK -- Next進入下一步,在這裡我們建立一個Dialog-based Application,大部分選項按預設設定就行,不過最下面的“Use Unicode libraries”最好去掉。如果勾選了這
個選項,程式程式碼就會使用16bit的Unicode字符集來編碼,但是很多函式雖然使用 char* (ASCII stings) 型別字元,而將字串從 Unicode 轉換到 ASCII
二、編寫程式碼
1 開啟工程檔案,進入資源檢視:LoadPicture(工程名稱)->LoadPicture.rc->Dialog雙擊IDD_LoadPicture
選中單個控制元件、右擊選擇屬性(Properties),可以看到控制元件的ID號,這個號可以自行編輯,例如 Picture 控制元件的 ID 號我設定為 IDC_ShowImg,這個 ID 號在後面的影象顯示函式中要用到。
2 將庫加入到VS中,沒有配置會出錯opencv246+VS2012的配置課參考
3 然後在 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
4 在 類視圖面板右擊 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 );
5 然後雙擊 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佔用的記憶體。
6 寫讀取和處理圖片的功能函式。
回到資源檢視,雙擊按鈕 ReadImage,,建立按鈕點選的訊息響應程式:OnBnClickedReadimage,主要的響應操作包括 彈出對話方塊選擇圖片檔案、讀入圖片檔案、對圖片統一縮放至256*256的大小、顯示影象,程式碼如下:
- // TODO: 在此新增控制元件通知處理程式程式碼
- CFileDialog dlg(
- TRUE, _T("*.bmp"), NULL,
- OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
- _T("image files (*.bmp; *.jpg) |*.bmp; *.jpg | All Files (*.*) |*.*||"), NULL
- ); // 選項圖片的約定
- dlg.m_ofn.lpstrTitle = _T("Open Image"); // 開啟檔案對話方塊的標題名
- if(dlg.DoModal()!=IDOK ) // 判斷是否獲得圖片
- return;
- CString mPath = dlg.GetPathName(); // 獲取圖片路徑
- IplImage* ipl = cvLoadImage( mPath, 1 ); // 讀取圖片、快取到一個區域性變數 ipl 中
- if(!ipl) // 判斷是否成功讀取圖片
- return;
- if(TheImage) // 對上一幅顯示的圖片資料清零
- cvZero( TheImage );
- ResizeImage( ipl ); // 對讀入的圖片進行縮放,使其寬或高最大值者剛好等於 256,再複製到 TheImage 中
- ShowImage( TheImage, IDC_ShowImg); // 呼叫顯示圖片函式
- cvReleaseImage(&ipl); // 釋放 ipl 佔用的記憶體
7 在上面的程式碼中包含了兩個新的成員函式 ResizeImage 和 ShowImage,前者的作用是對讀入的不同大小的影象進行縮放,再通過設定 ROI 的方式將影象存入 256*256 的 TheImage 中;後者是將影象 TheImage 顯示到圖片顯示控制元件 IDC_ShouImg 視窗的正中部位。為了實現這兩個功能,首先在類檢視 面板右擊 CtestPicControlDlg,選擇 Add –> Add Function,建立兩個函式:void ShowImage( IplImage* img, UINT ID ) 和 void ResizeImage(IplImage* img)。以下是這兩個函式的實現程式碼:
函式新增如下
- void CLoadPicControlDlg::ShowImage(IplImage* img, UINT ID)// ID 是Picture Control控制元件的ID號
- {
- CDC* pDC=GetDlgItem(ID)->GetDC();// 獲得顯示控制元件的 DC
- HDC hDC=pDC->GetSafeHdc();// 獲取 HDC(裝置控制代碼) 來進行繪圖操作
- CRect rect;
- GetDlgItem(ID)->GetClientRect(&rect);
- int rw=rect.right-rect.left; // 求出picture control的寬和高
- int rh=rect.bottom-rect.top;
- int iw=img->width; // 讀取圖片的寬和高
- int ih=img->height;
- int tx = (int)(rw - iw)/2; // 使圖片的顯示位置正好在控制元件的正中
- int ty = (int)(rh - ih)/2;
- SetRect( rect, tx, ty, tx+iw, ty+ih );
- CvvImage cimg;
- cimg.CopyOf(img); // 複製圖片
- cimg.DrawToHDC(hDC,&rect);
- ReleaseDC(pDC);
- }
- void CtestPicControlDlg::ResizeImage(IplImage* img)
- {
- // 讀取圖片的寬和高
- int w = img->width;
- int h = img->height;
- // 找出寬和高中的較大值者
- int max = (w > h)? w: h;
- // 計算將圖片縮放到TheImage區域所需的比例因子
- float scale = (float) ( (float) max / 256.0f );
- // 縮放後圖片的寬和高
- int nw = (int)( w/scale );
- int nh = (int)( h/scale );
- // 為了將縮放後的圖片存入 TheImage 的正中部位,需計算圖片在 TheImage 左上角的期望座標值
- int tlx = (nw > nh)? 0: (int)(256-nw)/2;
- int tly = (nw > nh)? (int)(256-nh)/2: 0;
- // 設定 TheImage 的 ROI 區域,用來存入圖片 img
- cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );
- // 對圖片 img 進行縮放,並存入到 TheImage 中
- cvResize( img, TheImage );
- // 重置 TheImage 的 ROI 準備讀入下一幅圖片
- cvResetImageROI( TheImage );
- }
注意
1:如果你的CvvImage出現紅色的底線提示沒有定義那說明你的opencv版本是比較新的裡面的CvvImage函式已經被去掉了,我的opencv246就沒有這個函式。只要在工程中加入CvvImage.h和CvvImage.cpp
2:如果你編譯後出現error C4996: 'fopen': This function or variable may be unsafe.的錯誤提示說明的
原文地址:http://blog.csdn.net/lxy201700/article/details/16921903