1、創建新項目
我的項目取名為MFC_OpenCV_1,在創建項目的第三步中“您希望使用MFC庫嗎?”,選擇“作為靜態的DLL”,其他步驟都選默認選項。
2、設置OpenCV環境變量
工程—>設置—>“C/C++”選項卡,在“分類”選項中,選擇“預編譯器”,在“附加包含路徑”中填寫OpenCV的路徑(用英文字符的逗號隔開),如我的路徑為:
C:/Program Files/OpenCV/cv/include,
C:/Program Files/OpenCV/cxcore/include,
C:/Program Files/OpenCV/otherlibs/_graphics/include,
C:/Program Files/OpenCV/otherlibs/highgui
工程—>設置—>“連接”選項卡,在“分類”選項中,選擇“輸入”,在“對象/庫模板”中輸入:cv.lib cxcore.lib highgui.lib (空格隔開)
“附加庫路徑”中輸入:C:/Program Files/OpenCV/lib
值得注意的是,因為OpenCV的版本不同,在../OpenCV/lib路徑下的lib文件也有微小區別,比如有的版本中各個lib文件中多加了一個d,故在“對象/庫模板”中就要輸入:cvd.lib cxcored.lib highguid.lib (空格隔開),如何知道呢?編譯一下就明白了!
3、分步創建例程
在File View面板中的MFC_OpenCV_1.h中的#include "resource.h"下面添加一下代碼:
#include "cv.h" #include "HighGUI.h" #define IMAGE_WIDTH 256 //這里說明程序用到的程序必須是256*256大小的圖片,否則會有錯。 #define IMAGE_HEIGHT 256 //可以在這里改變圖片參數,以適應自己用到圖片的大小 #define IMAGE_CHANNELS 3
在Class View窗口中,為CMFC_OpenCV_1Dlg頭文件中添加成員變量(雙擊CMFC_OpenCV_1Dlg即可打開):
public: IplImage* TheImage;
再添加一下代碼:
protected: BITMAPINFO* bmi; BITMAPINFOHEADER* bmih; RGBQUAD* palette; unsigned int buffer[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256];
雙擊對話框初始化函數OnInitDialog(),在// TODO: Add extra initialization here下面添加代碼:
//創建IPL圖像 CvSize ImgSize; ImgSize.width = IMAGE_WIDTH; ImgSize.height = IMAGE_HEIGHT; TheImage = cvCreateImage(ImgSize,IPL_DEPTH_8U,IMAGE_CHANNELS); //在對話框中顯示一幅創建的圖像 if (TheImage->nChannels == 1) //灰度圖像 { float dx = TheImage->width/256.0f; for (int w = 0; w<TheImage->width;w++) { for (int h = 0;h<TheImage->height;h++) { //復制數據到IPL TheImage->imageData[TheImage->height*w+h] = (char)(w/dx); } } } else if (TheImage->nChannels == 3) //對RGB圖像 { IplImage* temp = cvCreateImage(ImgSize,IPL_DEPTH_8U,1); int h,w; float dx = temp->width/256.0f; for (w= 0; w<temp->width;w++) { for (h=0;h<temp->height;h++) { temp->imageData[temp->height*w+h] = (char)(w/dx); } } cvSetImageCOI(TheImage,1);//選擇藍色通道 cvCopy(temp,TheImage); for (w= 0; w<temp->width;w++) { for (h=0;h<temp->height;h++) { temp->imageData[temp->height*w+h] = (char)(256- w/dx); } } cvSetImageCOI(TheImage,2);//選擇綠色通道 cvCopy(temp,TheImage); for (w= 0; w<temp->width;w++) { for (h=0;h<temp->height;h++) { temp->imageData[temp->height*w+h] = (char)(w/dx); } } cvSetImageCOI(TheImage,3);//選擇紅色通道 cvCopy(temp,TheImage); cvReleaseImage(&temp); } //初始化BMP顯示緩存 bmi = (BITMAPINFO* )buffer; bmih = &(bmi->bmiHeader); memset(bmih,0,sizeof(*bmih)); bmih->biSize = sizeof(BITMAPINFOHEADER); bmih->biWidth =IMAGE_WIDTH; bmih->biHeight = -IMAGE_HEIGHT; bmih->biPlanes = 1; bmih->biCompression = BI_RGB; bmih->biBitCount = 8*TheImage->nChannels; palette= bmi->bmiColors; if (TheImage->nChannels == 1) { for (int i= 0;i<256;i++) { palette[i].rgbBlue= palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; palette[i].rgbReserved = 0; } }
為CMFC_OpenCV_1Dlg添加成員函數:
public:
void DisplayMyData();
並添加代碼:
void CMFC_OpenCV_1Dlg::DisplayMyData() { CPaintDC dc(this); CDC* pDC=&dc; int res=StretchDIBits( pDC->GetSafeHdc(), //hdc 0, //XDest 0, //YDest int(IMAGE_WIDTH), //nDestWidth int(IMAGE_HEIGHT), //nDestHeight 0, //XSrc 0, //YSrc IMAGE_WIDTH, //src x dims IMAGE_HEIGHT, //src y dims TheImage->imageData,//array of DIB bits (BITMAPINFO*)bmi, //bitmap infomation DIB_RGB_COLORS, //RGB or palette indexes SRCCOPY); //光柵操作碼 //更新窗口,重新繪制 RedrawWindow( NULL, NULL, RDW_INVALIDATE ); }
然后在OnPaint()函數中調用它:
。。。。。。。 else { DisplayMyData(); CDialog::OnPaint(); }
然后在類CMFC_OpenCV_1的成員函數InitInstance()中調用釋放圖像內存的函數
if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK cvReleaseImage(&dlg.TheImage); }
4、讀入圖像並顯示處理
添加一個新類,用類向導:
右擊MFC_OpenCV_1 classes—>new class,選擇Generic Class,類名為MyIplClass,如圖:
然后雙擊CMFC_OpenCV_1APP,在打開的頭文件中,#include "resource.h" // main symbols下方添加頭文件:
#include "MyIplClass.h"
同時將這里原來的代碼:
#include "cv.h" #include "HighGUI.h" #define IMAGE_WIDTH 256//這里說明程序用到的程序必須是256*256大小的圖片,否則會有錯。 #define IMAGE_HEIGHT 256 //可以在這里改變圖片參數,以適應自己用到圖片的大小 #define IMAGE_CHANNELS 3
轉移到新建的類MyIplClass的頭文件中,代碼如下:
// MyIplClass.h: interface for the MyIplClass class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_MYIPLCLASS_H__64EAB832_8C9A_4B0B_B3DD_48F44840B147__INCLUDED_) #define AFX_MYIPLCLASS_H__64EAB832_8C9A_4B0B_B3DD_48F44840B147__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "cv.h" #include "HighGUI.h" #define IMAGE_WIDTH 256//這里說明程序用到的程序必須是256*256大小的圖片,否則會有錯。 #define IMAGE_HEIGHT 256 //可以在這里改變圖片參數,以適應自己用到圖片的大小 #define IMAGE_CHANNELS 3 class MyIplClass { 。。。。。。
為MyIplClass添加成員變量:
public:
IplImage* m_Ipl;
分別在MyIplClass的構造函數和析構函數中添加代碼:
MyIplClass::MyIplClass() { //Create the IPL image m_Ipl = cvCreateImage(cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U,IMAGE_CHANNELS); } MyIplClass::~MyIplClass() { cvReleaseImage(&m_Ipl); //釋放內存 }
在為MyIplClass添加兩個成員函數:
public:
void GetIplData(IplImage* ipl);
void LoadBMP(CString FileName);
並添加代碼:
void MyIplClass::GetIplData(IplImage* ipl) { memcpy(ipl->imageData,m_Ipl->imageData,m_Ipl->imageSize); } void MyIplClass::LoadBMP(CString FileName) { //調用OpenCV中的highgui庫函數cvLoadImage讀取圖像 m_Ipl = cvLoadImage(FileName,1); }
現在在Resource View面板中,打開ID為IDD_MFC_OPENCV_1_DIALOG的界面,添加一個按鈕,設置屬性值:
ID:IDC_PROCESS,標題:Process
雙擊該按鈕,在自動生成的OnProcess函數中添加代碼如下:
void CMFC_OpenCV_1Dlg::OnProcess() { // TODO: Add your control notification handler code here MyIplClass *Img = new MyIplClass; CString filename; //this file should be part of the OpenCV kit filename = "F://StdSoft//OpenCV//fruits.bmp"; Img->LoadBMP(filename); Img->GetIplData(TheImage); Img->ProcessIpl(TheImage); delete Img; RedrawWindow(NULL,NULL,RDW_INVALIDATE); //Force update of dialog }
現在要對前面讀入的圖像進行邊緣化處理,為MyIplClass添加成員函數:
public:
void ProcessIpl(IplImage* Img);
並為該函數添加代碼:
void MyIplClass::ProcessIpl(IplImage *Img) { IplImage *gray = 0, *edge = 0; gray = cvCreateImage(cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U,1); edge = cvCreateImage(cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U,1); cvCvtColor(Img,gray,CV_BGR2GRAY); //Run the edge detector on gryscale cvCanny(gray,edge,30,100,3); cvCvtColor(edge,Img,CV_GRAY2BGR); //save result //這句解除后有錯,http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=5108&start=0&st=0&sk=t&sd=a // cvCopyImage(Img,m_Ipl); //release image cvReleaseImage(&gray); cvReleaseImage(&edge); }
再在CMFC_OpenCV_1Dlg的OnProcess()函數中,在 Img->GetIplData(TheImage);下方調用該處理函數:
Img->ProcessIpl(TheImage);
搞定!運行結果如下: