封装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)
- 封装opencv的函数成dll,独立调用
- 在vs.net2005中将webservice封装成独立的dll
- dll导出函数调用封装
- 函数封装成DLL
- DLL函数封装及调用实例
- vs下opencv的人脸检测以及qt下dll的封装调用(二、dll的创建)
- vs下opencv的人脸检测以及qt下dll的封装调用(三、vs下测试dll)
- vs下opencv的人脸检测以及qt下dll的封装调用(四、qt下测试dll)
- OpenCV程序封装为64位DLL给Java调用
- 如何通过C#调用OpenCV函数(自制OpenCV的c++ dll文件)
- java调用c++封装的dll
- 动态调用用dll封装的控件
- 【C++】多个类的DLL封装及调用
- 【C++】多个类的DLL封装及调用
- [Unity3d]调用自己封装的dll
- 【C++】多个类的DLL封装及调用
- 【C++】多个类的 DLL 封装及调用
- 【C++】多个类的DLL封装及调用
- <转载>java(37):java中length,length(),size()区别
- Codeforces 897C(递归)
- 小白使用react---ajax请求后的数据在另一个页面显示
- mysql数据库中管理员用户(root@localhost)被误删除,怎么恢复
- 单链表上机实验
- 封装opencv的函数成dll,独立调用
- 【Scikit-Learn 中文文档】聚类
- 从最大子数组和问题详尽贪心算法策略
- N的阶乘末尾有多少个0 51Nod
- Android使用自定义控件实现无限轮播
- hdoj-1570A C
- 可持久化Treap(范浩强Treap)
- WPF下DataGrid header 居中及分隔线等属性设置
- Edit Distance