在opencv的实际使用,经常遇到这种情况,自己在电脑上配置了opencv,写好了opencv的代码工程,在环境变量中加了opencv的dll的路径,这样可以在自己电脑上运行代码。但是如果将该工程拷贝到其他没有配置opencv的电脑上就无法运行。解决办法:在配置了opencv的电脑上(但是在环境变量中没有添加dll的路径),将调用相关函数的代码封装成函数,生成dll文件,拷贝到其他没配置opencv的电脑上,再解析该dll,将该dll中调用的一些opencv的函数涉及到的opencv的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
// 调用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 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 matchePoints;
matcher.match(imageDesc1,imageDesc2,matchePoints,Mat());
sort(matchePoints.begin(),matchePoints.end()); //特征点排序
//获取排在前N个的最优匹配特征点
vector 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"<//输出映射矩阵
//图像配准
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 kp1;
siftdtc.detect(img,kp1);
Mat outimg1;
drawKeypoints(img,kp1,outimg1);
imshow("image1 keypoints",outimg1);
//此函数等待按键,按键盘任意键就返回
waitKey();
}
注意:编译的时候,在整个工程属性需要设置成:配置类型->动态库dll,编译后在该工程下就会生成dll_sift的dll、lib等文件。在这里需要按照正常流程配置opencv,不过不能把opencv的dll路径加到环境变量中。
在完全没有opencv的电脑上,新建一个工程test_sift,将第一步中生成的dll_sift.dll文件拷贝到该工程目录下,添加一个cpp文件,代码如下:
#include
#include
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拷贝到该工程目录下。
问题在这里,因为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)