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