基於VS2013 MFC的OPENCV3.1環境構建及測試
1. 創建OPENCV工程
1)打開VS2013,點擊新建項目->MFC應用程序,並選擇保存名稱及路徑,如下圖,
2) 點擊確定進入MFC應用程序向導,設置如下,
3) 配置OPENCV,具體可參考http://www.cnblogs.com/yunfung/p/6756367.html
2. MFC 界面設計
在資源視圖中,雙擊IDD_TESTOPENCV_MFC_DIALOG,在顯示的窗口中,添加兩個按鈕(通過工具箱中的對話框編輯器),並適當修改(單擊相應對話框部件,在屬性窗口中,調整Caption的顯示值及ID值;如Open Image 的ID值為ID_OPEN,Process 的ID值為ID_PROCESS)及調整布局,如下圖
3. 完善工程
1) 分別將相應工程文件colordetector.h、colordetector.cpp、colorDetectController.h添加到工程。註意在源文件首行添加#include "stdafx.h"定義
colordetector.h
1 #if !defined COLORDETECT 2 #define COLORDETECT 3 4 #include <opencv2/core/core.hpp> 5 #include <opencv2/imgproc/imgproc.hpp> 6 7 classView CodeColorDetector { 8 private: 9 int maxDist; // minimum acceptable distance 10 cv::Vec3b target; // target color 11 cv::Mat result; // image containing resulting binary map 12 public: 13 14 ColorDetector() : maxDist(20), target(0,0,0){} 15 16 17 // Computes the distance from target color.18 int getDistanceToTargetColor(const cv::Vec3b& color) const; // no{ } 19 int getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const; 20 21 // Processes the image. Returns a 1-channel binary image. 22 cv::Mat process(const cv::Mat &image); 23 24 25 void setColorDistanceThreshold(int distance); 26 // Gets the color distance threshold 27 int getColorDistanceThreshold() const; 28 29 // Sets the color to be detected 30 void setTargetColor(uchar blue, uchar green, uchar red); 31 // Sets the color to be detected 32 void setTargetColor(cv::Vec3b color); 33 34 // Gets the color to be detected 35 cv::Vec3b getTargetColor() const; 36 }; // semicolons need 37 38 #endif
colordetector.cpp
1 #include "stdafx.h" 2 // Classes split .h & .cpp 3 #include "colordetector.h" 4 #include <vector> 5 6 7 int ColorDetector::getDistanceToTargetColor(const cv::Vec3b& color) const{ 8 return getColorDistance(color, target); 9 } 10 11 int ColorDetector::getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const{ 12 return abs(color1[0] - color2[0]) + abs(color1[1] - color2[1]) + abs(color1[2] - color2[2]); 13 } 14 15 void ColorDetector::setColorDistanceThreshold(int distance){ 16 if (distance < 0) 17 distance = 0; 18 maxDist = distance; 19 } 20 21 22 int ColorDetector::getColorDistanceThreshold() const { 23 return maxDist; 24 } 25 26 void ColorDetector::setTargetColor(uchar blue, uchar green, uchar red) { 27 target = cv::Vec3b(blue, green, red); 28 } 29 30 void ColorDetector::setTargetColor(cv::Vec3b color) { 31 target = color; 32 } 33 34 cv::Vec3b ColorDetector::getTargetColor() const { 35 return target; 36 } 37 38 cv::Mat ColorDetector::process(const cv::Mat &image) { 39 // re-allocate binary map if necessary same size as input image, but 1-channel 40 result.create(image.size(),CV_8U); 41 // get the iterators 42 cv::Mat_<cv::Vec3b>::const_iterator it= image.begin<cv::Vec3b>(); 43 cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>(); 44 cv::Mat_<uchar>::iterator itout= result.begin<uchar>(); 45 for ( ; it!= itend; ++it, ++itout) 46 { 47 // compute distance from target color 48 if (getDistanceToTargetColor(*it) < maxDist) { 49 *itout= 255; 50 } 51 else { 52 *itout= 0; 53 } 54 } 55 return result; 56 }View Code
colorDetectController.h
1 #if !defined CD_CNTRLLR 2 #define CD_CNTRLLR 3 4 #include <opencv2/highgui/highgui.hpp> 5 #include "colordetector.h" 6 7 class ColorDetectController { 8 9 private: 10 //create the classes required to execute the application 11 ColorDetector *cdetect; 12 //need two member variables in order to hold a reference to the input and output results 13 cv::Mat image; 14 cv::Mat result; 15 public: 16 ColorDetectController() { 17 //use a dynamic allocation for our class setting up the application 18 cdetect = new ColorDetector(); 19 } 20 21 void setColorDistanceThreshold(int distance) { 22 cdetect->setColorDistanceThreshold(distance); 23 } 24 25 int getColorDistanceThreshold() const { 26 return cdetect->getColorDistanceThreshold(); 27 } 28 29 void setTargetColor(unsigned char red, unsigned char green, unsigned char blue) { 30 cdetect->setTargetColor(blue, green, red); 31 } 32 33 void getTargetColour(unsigned char &red, unsigned char &green, unsigned char &blue) const { 34 cv::Vec3b colour = cdetect->getTargetColor(); 35 red = colour[2]; 36 green = colour[1]; 37 blue = colour[0]; 38 } 39 40 bool setInputImage(std::string filename) { 41 image = cv::imread(filename); 42 return !image.empty(); 43 } 44 45 const cv::Mat getInputImage() const { 46 return image; 47 } 48 49 void process() { 50 result = cdetect->process(image); 51 } 52 53 const cv::Mat getLastResult() const { 54 return result; 55 } 56 57 // Deletes all processor objects created by the controller. 58 ~ColorDetectController() { 59 delete cdetect; 60 } 61 }; 62 63 #endifView Code
2) 在TestOpencv_MFCDlg.h中添加OPENCV相應的頭文件,並創建一個ColorDetectController類對象,如下圖
3) 在布局窗口中雙擊相應的部件,會將相應的代碼自動添加到工程中(TestOpencv_MFCDlg.h、TestOpencv_MFCDlg.cpp),如下圖
4) 填充相應CTestOpencv_MFCDlg::OnBnClickedOpen()、CTestOpencv_MFCDlg::OnBnClickedProcess()相應代碼,即可完善工程
TestOpencv_MFCDlg.h
1 #include <opencv2/core/core.hpp> 2 #include <opencv2/highgui/highgui.hpp> 3 #include <iostream> 4 #include "colorDetectController.h" 5 #include <stdio.h> 6 7 8 // TestOpencv_MFCDlg.h : 頭文件 9 // 10 11 #pragma once 12 13 14 // CTestOpencv_MFCDlg 對話框 15 class CTestOpencv_MFCDlg : public CDialogEx 16 { 17 // 構造 18 public: 19 CTestOpencv_MFCDlg(CWnd* pParent = NULL); // 標準構造函數 20 21 ColorDetectController controller; 22 // 對話框數據 23 enum { IDD = IDD_TESTOPENCV_MFC_DIALOG }; 24 25 protected: 26 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 27 // 實現 28 protected: 29 HICON m_hIcon; 30 31 // 生成的消息映射函數 32 virtual BOOL OnInitDialog(); 33 afx_msg void OnPaint(); 34 afx_msg HCURSOR OnQueryDragIcon(); 35 DECLARE_MESSAGE_MAP() 36 public: 37 afx_msg void OnBnClickedOpen(); 38 afx_msg void OnBnClickedProcess(); 39 afx_msg void OnBnClickedOk(); 40 afx_msg void OnBnClickedCancel(); 41 };View Code
TestOpencv_MFCDlg.cpp
1 // TestOpencv_MFCDlg.cpp : 實現文件 2 // 3 4 #include "stdafx.h" 5 #include "TestOpencv_MFC.h" 6 #include "TestOpencv_MFCDlg.h" 7 #include "afxdialogex.h" 8 9 #ifdef _DEBUG 10 #define new DEBUG_NEW 11 #endif 12 13 14 // CTestOpencv_MFCDlg 對話框 15 16 17 18 CTestOpencv_MFCDlg::CTestOpencv_MFCDlg(CWnd* pParent /*=NULL*/) 19 : CDialogEx(CTestOpencv_MFCDlg::IDD, pParent) 20 { 21 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 22 } 23 24 void CTestOpencv_MFCDlg::DoDataExchange(CDataExchange* pDX) 25 { 26 CDialogEx::DoDataExchange(pDX); 27 } 28 29 BEGIN_MESSAGE_MAP(CTestOpencv_MFCDlg, CDialogEx) 30 ON_WM_PAINT() 31 ON_WM_QUERYDRAGICON() 32 33 ON_BN_CLICKED(ID_OPEN, &CTestOpencv_MFCDlg::OnBnClickedOpen) 34 ON_BN_CLICKED(ID_PROCESS, &CTestOpencv_MFCDlg::OnBnClickedProcess) 35 ON_BN_CLICKED(IDOK, &CTestOpencv_MFCDlg::OnBnClickedOk) 36 ON_BN_CLICKED(IDCANCEL, &CTestOpencv_MFCDlg::OnBnClickedCancel) 37 END_MESSAGE_MAP() 38 39 40 // CTestOpencv_MFCDlg 消息處理程序 41 42 BOOL CTestOpencv_MFCDlg::OnInitDialog() 43 { 44 CDialogEx::OnInitDialog(); 45 46 // 設置此對話框的圖標。 當應用程序主窗口不是對話框時,框架將自動 47 // 執行此操作 48 SetIcon(m_hIcon, TRUE); // 設置大圖標 49 SetIcon(m_hIcon, FALSE); // 設置小圖標 50 51 // TODO: 在此添加額外的初始化代碼 52 53 return TRUE; // 除非將焦點設置到控件,否則返回 TRUE 54 } 55 56 // 如果向對話框添加最小化按鈕,則需要下面的代碼 57 // 來繪制該圖標。 對於使用文檔/視圖模型的 MFC 應用程序, 58 // 這將由框架自動完成。 59 60 void CTestOpencv_MFCDlg::OnPaint() 61 { 62 if (IsIconic()) 63 { 64 CPaintDC dc(this); // 用於繪制的設備上下文 65 66 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 67 68 // 使圖標在工作區矩形中居中 69 int cxIcon = GetSystemMetrics(SM_CXICON); 70 int cyIcon = GetSystemMetrics(SM_CYICON); 71 CRect rect; 72 GetClientRect(&rect); 73 int x = (rect.Width() - cxIcon + 1) / 2; 74 int y = (rect.Height() - cyIcon + 1) / 2; 75 76 // 繪制圖標 77 dc.DrawIcon(x, y, m_hIcon); 78 } 79 else 80 { 81 CDialogEx::OnPaint(); 82 } 83 } 84 85 //當用戶拖動最小化窗口時系統調用此函數取得光標 86 //顯示。 87 HCURSOR CTestOpencv_MFCDlg::OnQueryDragIcon() 88 { 89 return static_cast<HCURSOR>(m_hIcon); 90 } 91 92 93 94 void CTestOpencv_MFCDlg::OnBnClickedOpen() 95 { 96 // TODO: 在此添加控件通知處理程序代碼 97 CFileDialog dlg(TRUE, _T("*.bmp"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, 98 _T("imagefile(*.bmp; *.jpg)|*.bmp; *.jpg|All Files(*.*)|*.*||"), NULL); 99 dlg.m_ofn.lpstrTitle = _T("Open Image"); 100 // if a filename has been selected 101 if (IDOK == dlg.DoModal()) 102 { 103 104 //std::string filename = dlg.GetPathName(); 105 // Note CString string 106 107 CString strMfc = dlg.GetPathName(); 108 std::string filename = CT2CA(strMfc.GetBuffer(0)); 109 // set and display the input image 110 controller.setInputImage(filename); 111 cv::imshow("Input Image", controller.getInputImage()); 112 } 113 114 } 115 116 117 void CTestOpencv_MFCDlg::OnBnClickedProcess() 118 { 119 // TODO: 在此添加控件通知處理程序代碼 120 // target color is hard-coded here 121 controller.setTargetColor(240, 0, 0); 122 // process the input image and display result 123 controller.process(); 124 cv::imshow("Output Result", controller.getLastResult()); 125 } 126 127 128 void CTestOpencv_MFCDlg::OnBnClickedOk() 129 { 130 // TODO: 在此添加控件通知處理程序代碼 131 CDialogEx::OnOK(); 132 } 133 134 135 void CTestOpencv_MFCDlg::OnBnClickedCancel() 136 { 137 // TODO: 在此添加控件通知處理程序代碼 138 CDialogEx::OnCancel(); 139 }View Code
4. 運行結果
基於VS2013 MFC的OPENCV3.1環境構建及測試