在Windows上采用Cmake + Visual Studio编译并使用静态opencv库并打包发布成裸机可执行程序
环境:Windows 7 64bit
工具
- Cmake-3.11.1
- 确保是64位
- 确保安装了GUI
- Visual Studio 2015
- 确保是64位
- 确保采用vc14作为编译器(支持c++11标准部分语法)
原料:OpenCV 3.4.1 & opencv-contrib-3.4.1
- 中文:从官方网站或者Github上下载opencv3.4.1以及opencv-contrib-3.4.1的源码.
- English: source all code packages from official website of opencv or Github.
- 日本語:公式サイトまたGithubからのOpenCV-3.4.1をソースコードしてください。
操作步骤
-
解压opencv-3.4.1源码包,设解码后根目录为OPENCV_DIR,解压opencv-contrib-3.4.1源码包,设解码后的根目录为OPENCV_CONTRIB_DIR;
-
打开Cmake-3.11.1,选择source code的路径为OPENCV_DIR/sources,创建静态库存放目录build-static在opencv根目录下,如图;
-
点击configure(配置)按钮,选择visual studio 14 2015 Win64,如图;
-
等待初次configure完成,中间区域内会出现一系列编译选项,如图-3所示;
-
更改编译选项使得编译为静态库而非动态库:搜索SHARED,在中间区域修改BUILD_SHARED_LIBS的选中状态为OFF(checkbox未选中状态),如图;
-
更改编译选项使得包含opencv-contrib-3.4.1中的模块:搜索EXTRA,在中间区域修改OPENCV_EXTRA_MODULES_PATH的Value为opencv-contrib-3.4.1的解压路径下的子路径:OPENCV_CONTRIB_DIR/modules,如图;
-
(可选)更改编译选项去掉不太必要编译的测试应用程序,因为它们体积巨大,耗时过久:搜索BUILD_EXAMPLES,设置状态为OFF;搜索BUILD_TESTS,设置状态为OFF;搜索BUILD_PERF_TESTS,设置为OFF,如图;
-
点击Configure按钮开始配置项目,会发现依然存在红色的编译选项,表示这些编译选项在本机上是不支持的(平台限制以及安装的依赖软件限制等因素造成的不支持),如图;
-
检查最下方的消息框内,如果发现红色文字,表示存在失败项目,一般而言是由于配制过程中下载失败导致,如图;
-
重新点击configure,发现依然存在下载失败导致的配置错误,但上次下载失败的ffmpeg组件下载成功了,这表明,这些只是网络不稳定导致的下载失败,多尝试几次configure,也许能解决问题,如果实在不行,请自行下载放置于对应的目录,例如对于contrib下的xfeatures模块,将对应的vggnet模型文件等下载后放到OPENCV_CONTRIB_DIR/modules/xfeatures/src/, 如图,具体的下载源地址以及放置路径请查看cmake编译结果存放的目录下的CMakeDownloadLog.txt;
-
再次点击Configure配置,发现依然存在下载失败,但已经没有红色配置错误消息了,点击Generate按钮生成visual studio的项目文件,如图;
-
点击open project打开visual studio 2015进行opencv的编译,如图;
-
设置编译类型为Release x64,如图;
-
右键点击BUILD_ALL,选择生成,如图;
-
等待编译结束,但是,一般会发生c++ compiler driver崩溃以及tracker.exe崩溃的情况,这是因为visual studio的分布式编译器崩溃了导致的,进而,会发现编译进度条长时间卡死在某处,也不在输出新的编译信息,这表明,要清空重新编译opencv。如图;
-
强制关闭visual studio,一般需要打开任务管理器,结束进程后,再打开visual studio,将Debug再改成Release(可能是崩溃后导致配置信息丢失),清理项目后再生成,如图;
-
再次编译opencv的ALL_BUILD(在编译过程中确保不要运行其他的程序,尤其是谷歌浏览器chrome等占用内存极大的软件!)得到编译结果,如图;
-
注意到有3个模块因为xfeatures2d的cuda.hpp头文件找不到而编译失败,但实际上,这些文件是存在的,只是不再它所预期的位置,那么需要将这些头文件拷贝至其所期待的位置,不要气馁,不要烦躁,开源的乐趣就是自己动手解决一切!这里的cuda.hpp其实是在opencv-contrib-3.4.1中,不在核心源码中,需要拷贝到stitching模块中,如图;
-
再次生成,本次生成vs2015会执行增量编译,因此不需担心再耗时长久,得到编译结果如图(需要等待至少10分钟左右);
-
可以看到,编译全部成功,一共79个模块,现在需要安装静态库,其实也就是执行拷贝操作,将分散的模块都整到一个文件夹下,右键点击INSTALL,执行生成,如图;
-
关闭visual studio以及cmake,自此,opencv编译完成!!!おめでたい!おめでたい!如图;
-
需要注意的是:staticlib文件夹下存放的是opencv及其依赖的静态库文件,依赖项一共11项,剩下的以opencv_为前缀的模块都是Opencv自己的模块,如图;
-
在bin中,存放着测试应用,还有一个ffmpeg_64模块的动态组件,这个似乎无论如何都是编译为动态的,在使用到视频解码的时候会用到,需要自行拷贝到自己开发的程序的bin目录下,否则无法运行!如图;
-
现在开始创建一个基于静态opencv库的静态发布的应用,创建一个控制台应用程序,vc++目录配置为install目录下的include/opencv以及inclue/opencv2、staticlib目录,如图;
-
配置项目为Release x64,和编译opencv一样,然后创建opencvConfig.h头文件,加入以下代码来导入所需的库文件;
#pragma once
#include <opencv2/opencv.hpp>
#define CV_VERSION_ID CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
#define CALC_CV_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#ifdef _DEBUG
#define cvLIB(name) "opencv_" name CV_VERSION_ID "d"
#else
#define cvLIB(name) "opencv_" name CV_VERSION_ID
#endif
// WINDOWS LIBS
#pragma comment(lib, "wsock32")
#pragma comment(lib, "ws2_32")
#pragma comment(lib, "kernel32")
#pragma comment(lib, "user32")
#pragma comment(lib, "gdi32")
#pragma comment(lib, "winspool")
#pragma comment(lib, "comdlg32")
#pragma comment(lib, "advapi32")
#pragma comment(lib, "shell32")
#pragma comment(lib, "ole32")
#pragma comment(lib, "oleaut32")
#pragma comment(lib, "uuid")
#pragma comment(lib, "odbc32")
#pragma comment(lib, "odbccp32")
//opencv3.4.1 requirements
#pragma comment(lib, "IlmImf")
#pragma comment(lib, "ippicvmt")
#pragma comment(lib, "ippiw")
#pragma comment(lib, "ittnotify")
#pragma comment(lib, "libjasper")
#pragma comment(lib, "libjpeg")
#pragma comment(lib, "libpng")
#pragma comment(lib, "libprotobuf")
#pragma comment(lib, "libtiff")
#pragma comment(lib, "libwebp")
#pragma comment(lib, "zlib")
//opencv3.4.1 modules
#pragma comment(lib,cvLIB("aruco"))
#pragma comment(lib,cvLIB("bgsegm"))
#pragma comment(lib,cvLIB("bioinspired"))
#pragma comment(lib,cvLIB("calib3d"))
#pragma comment(lib,cvLIB("ccalib"))
#pragma comment(lib,cvLIB("core"))
#pragma comment(lib,cvLIB("datasets"))
#pragma comment(lib,cvLIB("dpm"))
#pragma comment(lib,cvLIB("face"))
#pragma comment(lib,cvLIB("features2d"))
#pragma comment(lib,cvLIB("flann"))
#pragma comment(lib,cvLIB("fuzzy"))
#pragma comment(lib,cvLIB("hfs"))
#pragma comment(lib,cvLIB("highgui"))
#pragma comment(lib,cvLIB("imgcodecs"))
#pragma comment(lib,cvLIB("imgproc"))
#pragma comment(lib,cvLIB("img_hash"))
#pragma comment(lib,cvLIB("line_descriptor"))
#pragma comment(lib,cvLIB("ml"))
#pragma comment(lib,cvLIB("objdetect"))
#pragma comment(lib,cvLIB("optflow"))
#pragma comment(lib,cvLIB("phase_unwrapping"))
#pragma comment(lib,cvLIB("photo"))
#pragma comment(lib,cvLIB("plot"))
#pragma comment(lib,cvLIB("reg"))
#pragma comment(lib,cvLIB("rgbd"))
#pragma comment(lib,cvLIB("saliency"))
#pragma comment(lib,cvLIB("shape"))
#pragma comment(lib,cvLIB("stereo"))
#pragma comment(lib,cvLIB("stitching"))
#pragma comment(lib,cvLIB("structured_light"))
#pragma comment(lib,cvLIB("superres"))
#pragma comment(lib,cvLIB("surface_matching"))
#pragma comment(lib,cvLIB("tracking"))
#pragma comment(lib,cvLIB("video"))
#pragma comment(lib,cvLIB("videoio"))
#pragma comment(lib,cvLIB("videostab"))
#pragma comment(lib,cvLIB("xfeatures2d"))
#pragma comment(lib,cvLIB("ximgproc"))
#pragma comment(lib,cvLIB("xobjdetect"))
#pragma comment(lib,cvLIB("xphoto"))
其中,windows库最好一个都不能少,否则如果用到了某些组件依赖于windows内置组件,会链接失败;剩下的库是opencv依赖库以及opencv自身模块了,opencv模块选择自己当前应用所依赖的就行;
-
(重要)配置项目属性,选择代码生成为MT类型,这表示编译时所依赖的公共运行时库会被直接嵌入到生成的可执行文件中,这确保运行时不依赖其他任何外部代码,如图;
-
最后执行生成就能得到静态的打包在一个独立的可执行程序中的文件,如图,可以看到这个文件大小超出寻常!将这个文件拷贝至任何同样的操作系统平台下都可以直接运行,教程结束!