封装opencv的函数成dll,独立调用

来源:互联网 发布:mac如何移除桌面图标 编辑:程序博客网 时间:2024/05/21 10:02

在opencv的实际使用,经常遇到这种情况,自己在电脑上配置了opencv,写好了opencv的代码工程,在环境变量中加了opencv的dll的路径,这样可以在自己电脑上运行代码。但是如果将该工程拷贝到其他没有配置opencv的电脑上就无法运行。解决办法:在配置了opencv的电脑上(但是在环境变量中没有添加dll的路径),将调用相关函数的代码封装成函数,生成dll文件,拷贝到其他没配置opencv的电脑上,再解析该dll,将该dll中调用的一些opencv的函数涉及到的opencv的dll拷贝下就行
下面自己写了一个例子,作为记载。

1、将相关需要实现的功能封装成函数,生成dll

比如自己要实现一个调用opencv的sift的特征检测和配准的函数,将其封装成dll,再调用。用VS新建一个dll_sift的空的工程,添加dll_sift.h和dll_sift.cpp文件。
–dll_sift.h文件代码如下:

#ifndef DLL_SIFT_H#define DLL_SIFT_H#include<iostream>// 调用opencv的sift相关的功能需要的头文件#include "highgui/highgui.hpp"    #include "opencv2/nonfree/nonfree.hpp"    #include "opencv2/legacy/legacy.hpp"  using namespace cv;  using namespace std;  #endif

–dll_sift.cpp文件代码如下:

#include"dll_sift.h"//生成dll文件声明  extern "C" __declspec(dllexport) void sift(char* src, char* dst);           //sift配准函数extern "C" __declspec(dllexport) void sift_pixel(char* src);   //sift特征提取函数void sift(char* src, char* dst)  {        Mat image01=imread(src);        Mat image02=imread(dst);      imshow("原始测试图像",image01);      imshow("基准图像",image02);      //灰度图转换      Mat image1,image2;        cvtColor(image01,image1,CV_RGB2GRAY);      cvtColor(image02,image2,CV_RGB2GRAY);      //提取特征点        SurfFeatureDetector surfDetector(800);  // 海塞矩阵阈值      vector<KeyPoint> keyPoint1,keyPoint2;        surfDetector.detect(image1,keyPoint1);        surfDetector.detect(image2,keyPoint2);        //特征点描述,为下边的特征点匹配做准备        SurfDescriptorExtractor SurfDescriptor;        Mat imageDesc1,imageDesc2;        SurfDescriptor.compute(image1,keyPoint1,imageDesc1);        SurfDescriptor.compute(image2,keyPoint2,imageDesc2);          //获得匹配特征点,并提取最优配对         FlannBasedMatcher matcher;      vector<DMatch> matchePoints;        matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());      sort(matchePoints.begin(),matchePoints.end()); //特征点排序        //获取排在前N个的最优匹配特征点      vector<Point2f> imagePoints1,imagePoints2;          for(int i=0;i<10;i++)      {                 imagePoints1.push_back(keyPoint1[matchePoints[i].queryIdx].pt);               imagePoints2.push_back(keyPoint2[matchePoints[i].trainIdx].pt);           }      //获取图像1到图像2的投影映射矩阵 尺寸为3*3      Mat homo=findHomography(imagePoints1,imagePoints2,CV_RANSAC);      ////也可以使用getPerspectiveTransform方法获得透视变换矩阵,不过要求只能有4个点,效果稍差      //Mat   homo=getPerspectiveTransform(imagePoints1,imagePoints2);             cout<<"变换矩阵为:\n"<<homo<<endl<<endl; //输出映射矩阵      //图像配准      Mat imageTransform1,imageTransform2;      warpPerspective(image01,imageTransform1,homo,Size(image02.cols,image02.rows));        imshow("经过透视矩阵变换后",imageTransform1);      waitKey(1000);      }  void sift_pixel(char* src){    //从文件中读入图像    Mat img = imread(src);    //如果读入图像失败    if(img.empty())        fprintf(stderr, "Can not load image %s\n", src);    //显示图像    imshow("image before", img);    //sift特征检测    SiftFeatureDetector  siftdtc;    vector<KeyPoint>kp1;    siftdtc.detect(img,kp1);    Mat outimg1;    drawKeypoints(img,kp1,outimg1);    imshow("image1 keypoints",outimg1);    //此函数等待按键,按键盘任意键就返回    waitKey();}

注意:编译的时候,在整个工程属性需要设置成:配置类型->动态库dll,编译后在该工程下就会生成dll_sift的dll、lib等文件。在这里需要按照正常流程配置opencv,不过不能把opencv的dll路径加到环境变量中。
这里写图片描述

2、在没opencv的电脑上解析dll_sift.dll

在完全没有opencv的电脑上,新建一个工程test_sift,将第一步中生成的dll_sift.dll文件拷贝到该工程目录下,添加一个cpp文件,代码如下:

#include<windows.h>#include<iostream>using namespace std;//所调用dll文件的存放路径  const char* DllName="dll_sift.dll";  //获取dll句柄  HMODULE dll_sift=LoadLibraryA(DllName);  //类型声明  typedef void(*sift)(char*, char*);  typedef void(*sift_pixel)(char*);  //获取函数地址 ,解析dll获取函数 sift sift0 = sift(GetProcAddress(dll_sift, "sift"));  sift_pixel sift1 = sift_pixel(GetProcAddress(dll_sift, "sift_pixel"));  void main(){    // 输入图像路径    char* path1 = "22.jpg";    char* path2 = "112.jpg";    sift0(path1,path2);    sift1(path2);}

运行该工程,会出现,
这里写图片描述
原因: 在上面的dll_sift.dll中相关的函数还调用了其他的opencv的dll但是这部分dll在该工程下没有,因此,需要将dll_sift.dll中相关函数调用需要用到的opencv的dll拷贝到该工程目录下。

3、获取dll_sift.dll中相关函数调用到的opencv的dll

问题在这里,因为opencv中的各种函数调用错综复杂,互相调用的很多,怎么知道自己调用的这个sift的相关函数调用哪些dll,如果将opencv的全部的dll都拷贝,太多了。方法如下:将生成dll的工程dll_sift的属性设置成:配置类型->应用程序(.exe),同时在dll_sift.cpp 文件中写一个空的main函数,再编译生成exe文件,在这个过程中一直会提示应用程序差opencvxxxx.dll,在opencv库目录下找到对应的dll,拷贝出来放在该工程下,再编译,再提示差dll,再拷贝相关的dll,知道exe可以编译成功
这里写图片描述
这些所有的拷贝出来的opencv的dll就是dll_sift.dll所有的需要的opencv的dll文件,再将这些dll文件拷贝到test_sift工程目录下即可。
最后根据提示显示差这些dll:
这里写图片描述
将这些dll全部拷贝到test_sift工程下,再次运行:
这里写图片描述
运行成功。这样后面需要的时候,直接将上述的opencv的dll以及dll_sift.dll拷贝到没有opencv的电脑上就可以实现对opencv的sift工程的调用。

后记

在opencv的配置中一般需要配置h文件、以及lib文件,但是这些文件都只是在编译中有用的,真正运行的时候需要调用的是dll文件,一般在配置opencv的都是将opencv中dll的路径写到path变量中,这样写的程序运行的时候会从环境变量中找到dll的路径并调用。所以只要知道真正需要运行所需要的opencv的dll并将其拷贝,就可以将opencv的应用程序在没有opencv 的系统上运行。

例程代码下载:

(http://download.csdn.net/download/u012273127/10143339)

原创粉丝点击