在MFC中使用OpenCV(OpenCV教程_基礎篇。2.8節例子程序)


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);

搞定!運行結果如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM