最近跟一商业公司合作,开发地铁场景中交通信号灯的检测模块。所以需要将检测模块类封装成动态链接库,提供给该公司。现将该简单的封装过程记录下来,以便日后查看。
该检测模块类还依赖VS2013和OpenCV3.1中的类库。步骤其实很简单,如下:
第一步,建立一个win32项目的一个工程,工程名最好为要封装的类的类名,如下:
这样我们就建立了一个准备导出CTrafficLightsExtract类的动态链接库。
第二步,在头文件中TrafficLightsExtract.h,我们可以加入相关OpenCV库的头文件,这样我们在后面使用这个动态库的时候就只需要包含TrafficLightsExtract.h;然后在类的声明中增加类的方法,如下
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 TRAFFICLIGHTIDENTIFYTESTDLL_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// TRAFFICLIGHTIDENTIFYTESTDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef TRAFFICLIGHTIDENTIFYTESTDLL_EXPORTS
#define TRAFFICLIGHTIDENTIFYTESTDLL_API __declspec(dllexport)
#else
#define TRAFFICLIGHTIDENTIFYTESTDLL_API __declspec(dllimport)
#endif
#include <opencv.hpp>
#include <list>
#include <math.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace std;
using namespace cv;
using namespace cv::ml;
// 此类是从 TrafficLightIdentifyTestDLL.dll 导出的
class TRAFFICLIGHTIDENTIFYTESTDLL_API CTrafficLightsExtract{
public:
CTrafficLightsExtract(void);
// TODO: 在此添加您的方法。
void setMat(Mat& inMat);
void Preprocess_equalizeHist(Mat& equaled_img);
void extractTrafficLightsRects(Mat& inMat, Mat& templateMat, vector<vector<Rect>>& rectVec_trafficLights, Mat& redMat, Mat& greenMat);
void draw_showResultImg(Mat& resultMat, vector<vector<Rect>>& rectVec_trafficLights);
void calcMatROIHist(Mat& inMat, Rect rectROI, Mat& hisMat);
void trainMySVM(Mat& inMatP, Mat& inMatN);
void mergeRows(Mat& A, Mat& B);
private:
void extractROI(Mat& inMat, Mat& outMat);
void extractROI(Mat& equaled_img, Mat& redMat, Mat& greenMat, Mat& blackMat);
void FindtrafficLightOutlineRects(Mat& equaled_img, vector<Rect>& rectVec_trafficLightOutline);
void FindPotentialLightsBoundingRects(Mat& inMat, VecPotentialLightRects& potentialLightRects);
void chooseLights_AreaCircleRegiongrow(Mat& equaled_img, Mat& gray_img, Mat& templateMat, Mat& colourMat, VecPotentialLightRects& colour_potentialLightRects, vector<Rect>& rectVec_trafficLights);
bool expandCondition(Mat& gray_img, Mat& colourMat, Rect lightRect);
bool templateMatchCondition(Mat& equaled_img, Mat& templateMat, Mat& colourMat, Rect lightRect);
bool svmMatchCondition(Mat& equaled_img, Rect lightRect);
void generateRects(Mat& equaled_img, Rect lightRect, vector<Rect>& rectsVec);
private:
int thr_areaMin;
int thr_areaMax;
float thr_circle;
double thr_correlation;
double thr_diff;
Mat m_inMat;
Ptr<SVM> m_svmNew;
};
extern TRAFFICLIGHTIDENTIFYTESTDLL_API int nTrafficLightIdentifyTestDLL;
TRAFFICLIGHTIDENTIFYTESTDLL_API int fnTrafficLightIdentifyTestDLL(void);
第三步,在源文件中TrafficLightsExtract.cpp,对增加类的方法进行相应的定义。
第四步,编译该工程。如果是在Debug环境下,则在Debug目录下会生成dll文件和lib文件;同样的道理在Release环境下。
第五步,我们可以将以下三个文件TrafficLightsExtract.h,TrafficLightsExtract.lib,TrafficLightsExtract.dll放置在OpenCV库中相应位置;这样在其它工程中使用该库,我们就像配置OpenCV环境一样,加载我们的动态链接库。这样我们就能在其它工程中调用我们封装类的方法。