OpenCV编程准备(VS C++)
编程环境为VS2010,opencv版本为2.4.9(更高版本需要VS的高版本)。
A、准备工作
在开始之前,需要做一些准备工作,首先在VS中建立一个实例工程:
W32App工程,打开vs2010,全择新建项目,选择visual C++项目类型,选择W32项目(也可以使用w32控制台应用程序的类型),给工程去一个名称,并放在适当的目录下,这里工程名为w32App。
准备OpenCV,首先下载并解压OpenCV到一个目录下(这里使用的是D:\ Program Files (x86)\openCV)。然后配置vs2010:
- 打开w32App项目
- 选择项目>项目属性菜单,打开属性对话框
如图:
- 在包含目录项添加:
D:\Program Files (x86)\opencv\build\include\opencv2
D:\Program Files (x86)\opencv\build\include\opencv
D:\Program Files (x86)\opencv\build\include
- 在库目录添加:
D:\Program Files (x86)\opencv\build\x86\vc10\lib
- 打开C/C++ > 优化项,选择禁止优化(/Od)。
- 选择连接器项 > 输入项,编辑输入:
opencv_calib3d249.lib
opencv_contrib249.lib
opencv_core249.lib
opencv_features2d249.lib
opencv_flann249.lib
opencv_gpu249.lib
opencv_highgui249.lib
opencv_imgproc249.lib
opencv_legacy249.lib
opencv_ml249.lib
opencv_objdetect249.lib
opencv_ts249.lib
opencv_video249.lib
opencv_nonfree249.lib
opencv_ocl249.lib
opencv_photo249.lib
opencv_stitching249.lib
opencv_superres249.lib
opencv_videostab249.lib
opencv_calib3d249d.lib
opencv_contrib249d.lib
opencv_core249d.lib
opencv_features2d249d.lib
opencv_flann249d.lib
opencv_gpu249d.lib
opencv_highgui249d.lib
opencv_imgproc249d.lib
opencv_legacy249d.lib
opencv_ml249d.lib
opencv_objdetect249d.lib
opencv_ts249d.lib
opencv_video249d.lib
opencv_nonfree249d.lib
opencv_ocl249d.lib
opencv_photo249d.lib
opencv_stitching249d.lib
opencv_superres249d.lib
opencv_videostab249d.lib
这些是C++使用的库文件(对debug的)
- 可能还需要一些其他的设置,比如字符集等,遇到问题时可以在网上找到解决方法。
- 如果想要示例程序能够跟踪到openCV内部函数,则需要使用cmake对openCV源码进行编译,生成VS下的opencv项目。具体请参考cmake的使用方法。这里需要注意的是:应该根据vs版本对应下载opencv,和使用cmake编译。
- 有时候还需要visual assist x 辅助插件,它能够在opencv中获得联想帮助信息。
B、辅助程序
因为opencv主要是控制台下的界面应用,示例程序中的一些选择项需要随时变换,这就需要一些辅助操作的对话框进行参数的选择,和结果的显示。下面是程序中实现的对话框:
这里给出一个简单地打开文件对话框,包括滤波核矩阵,边缘算法选择等,文件是简单地直接输入文件位置。可以根据需要增加对话框的各种选项。
具体操作是:
在程序的WndProc回调函数消息WM_COMMAND中添加ID_EDITOPEN(或在资源中定义的打开对话框消息)处理:
DialogBox(hInst, MAKEINTRESOURCE(IDD_OPENDIALOG), hWnd, dlgEditOpenFile);
其中IDD_OPENDIALOG为资源中定义的对话框界面dlgEditOpenFile为对话框消息回调函数。写一个对话框的消息回调函数处理对话框消息,在程序中就是设置一些操作参数。
以同样的方式定义信息显示对话框,和其他需要的对话框。
C、引用windows的SDK函数(c函数)和openCV库函数,需要在程序中添加:
#include <commctrl.h>
#include <stdio.h>
#include <math.h>
#include <Shellapi.h>
#include <shlobj.h>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
其中highgui.hpp主要是为了图像文件的输入输出,比如imread(fln),imwrite(fln)等。core.hpp中包含了openCV中最基本的数据类型和操作。
环境配置方法,网络上都有比较详细的介绍。
如果希望使用Windows界面操作方式,可以改变主函数main()中的winproc程序和对话框返回消息:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
int fsz = 0;
//
Mat kmat;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_FILEOPEN:
butt_sta = false;
DialogBox(hInst, MAKEINTRESOURCE(IDD_FILEEDIT), hWnd, dlgOpenFile);
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case ID_32774://bilateralFilter()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_bilateralFilter), hWnd, dlgFilter_bilateralFilter);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32775://blur()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_blur), hWnd, dlgFilter_blur);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32776://boxFilter()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_boxFilter), hWnd, dlgFilter_boxFilter);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32777://GaussianBlur()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_GaussianBlur), hWnd, dlgFilter_GaussianBlur);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32778://medianBlur()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_medianBlur), hWnd, dlgFilter_medianBlur);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32779://filter2D()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_filter2D), hWnd, dlgFilter_filter2D);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32780://sepFilter2D()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_sepFilter2D), hWnd, dlgFilter_sepFilter2D);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32781://erode()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_erode), hWnd, dlgFilter_erode);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32782://dilate()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_dilate), hWnd, dlgFilter_dilate);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32783://Laplacian()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_Laplacian), hWnd, dlgFilter_Laplacian);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32784://Sobel()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_Sobel), hWnd, dlgFilter_Sobel);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32785://Scharr()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_Scharr), hWnd, dlgFilter_Scharr);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32786://spatialGradient()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_spatialGradient), hWnd, dlgFilter_spatialGradient);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32787://sqrBoxFilter()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_sqrBoxFilter), hWnd, dlgFilter_sqrBoxFilter);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32788://buildPyramid()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_buildPyramid), hWnd, dlgFilter_buildPyramid);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32789://getGaussianKernel()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_getGaussianKernel), hWnd, dlgFilter_getGaussianKernel);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32790://getDerivKernels()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_getDerivKernels), hWnd, dlgFilter_getDerivKernels);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32791://getStructuringElement()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_getStructuringElement), hWnd, dlgFilter_getStructuringElement);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
case ID_32792://显示原图
if(MyImageCls.img.data)
{
MyImageCls.showImageToWin(IMAGE_COLOR);
}
break;
case ID_32793://显示灰度图
if(MyImageCls.Gry_img.data)
{
MyImageCls.showImageToWin(IMAGE_GRAY);
}
break;
case ID_32794://显示滤波图
if(MyImageCls.Flt_img.data)
{
MyImageCls.showImageToWin(IMAGE_FILTER);
}else
DialogShowMessage(hWnd, "还没有生成滤波图像。");
break;
case ID_32795://morphologyEx()
if(MyImageCls.handCnt > 0)
DialogBox(hInst, MAKEINTRESOURCE(IDD_morphologyEx), hWnd, dlgFilter_morphologyEx);
else
DialogShowMessage(hWnd, "还没有装入图像文件。");
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
AppClosed();//处理应用退出消息
PostQuitMessage(0);
break;
case MAIN_WIN_USER_MSG_OK://文件打开对话框的操作消息,OK
switch(filterID){
case IDC_RADIO1:
fsz = 3;
break;
case IDC_RADIO2:
fsz = 5;
break;
case IDC_RADIO3:
fsz = 7;
break;
case IDC_RADIO4:
fsz = 9;
break;
default:
break;
}
//opencv_showImage(hWnd, false, fsz);//建立数据处理类(全局),操作数据。
opencv_ImageCls(hWnd, fsz);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
首先定义菜单功能的对话框及回调函数:
DialogBox(hInst, MAKEINTRESOURCE(IDD_FILEEDIT), hWnd, dlgOpenFile);
其中IDD_FILEEDIT为对话框资源标识,dlgOpenFile为对话框的回调函数:
INT_PTR CALLBACK dlgOpenFile(HWND, UINT, WPARAM, LPARAM);
在WM_INITDIALOG消息中初始化对话框控件的状态,在WM_COMMAND消息中接收对话框操作,如IDC_OK为Ok按钮操作。当用户按下OK键后,使用:
PostMessage(hWndMain, MAIN_WIN_USER_MSG_OK, 0 , 0);
将控制返回到main()中的winproc()函数,其中MAIN_WIN_USER_MSG_OK为自定义消息常量。打开文件对话框的形式为:
为了消除控制台界面,本程序都是采用如下控制过程:
1、在wenproc()中处理主菜单功能,引出对话框,如上形式(在资源视图中定义),并声明对话框回调函数处理对话框操作。
2、当对话框返回(关闭)时,使用自定义消息将控制返回到winproc(),处理对话框的Ok/Cancel操作,比如,使用上述对话框打开图像文件,可以在Winproc中处理MAIN_WIN_USER_MSG_OK消息。