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);
搞定!運行結果如下:


