OpenCV学习笔记(22)OpenCV_SVN静态库的编译[转]

之前按照常规方式(http://www.opencv.org.cn/index.php/VC_2008_Express%E4%B8%8B%E5%AE%89%E8%A3%85OpenCV2.0/2.1)用Cmake和VS2008编译了OpenCV_SVN,都是生成动态链接库的,最近写的程序Release版需要静态连接库,于是边查Google边探索怎样生成和使用OpenCV的静态库。

一、参考《编译opencv2.1静态库》(http://blog.csdn.net/sophisticated/archive/2011/03/09/6234943.aspx),生成静态库。

1、在Cmake中去掉BUILD_EXAMPLES,BUILD_NEW_PYTHON_SUPPORT,BUILD_SHARED_LIBS,BUILD_TESTS,勾选OPENCV_BUILD_3RDPARTY_LIBS,  WITH_JASPER,  WITH_JPEG,  WITH_PNG,  WITH_TIFF 选项 (这里没有勾选WITH_OPENNI,如果需要使用应该要用 OpenNI 的源码另外生成相应的静态库)。

2、编译完成后,将静态库.lib文件覆盖复制到原来按常规方式生成的lib文件夹中,例如 VS2008_build/3rdparty/lib 和 VS2008_build/lib 。注意所编译的静态库中不包含 3rdparty 中的 videoInput64.lib 和 videoInput.lib ,这两个文件在 SVN 源码中直接提供,不需要编译生成。

二、使用时的常见问题

1、编译工程的Release版之前,先在项目属性—Configuration Properties—C/C++—Code Generation 的 Runtime Library 设置为 Multi-threaded (/MT)

2、在 项目属性—Configuration Properties—Linker—Input 的 Additional Dependencies 中,除了加入基本的 opencv_***220.lib 外,还要加入第三方lib,即libjasper.lib , libjpeg.lib , libpng.lib , libtiff.lib , zlib.lib , opencv_lapack.lib 等,这些都与 opencv 的 core , highgui 等模块有关。

3、如果出现“error LNK2001: unresolved external symbol __imp__CreateToolbarEx@52” 的错误,则 Additional Dependencies 中需添加 comctl32.lib 。(参考《fatal error LNK1120: 1 unresolved externals》http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=1309&start=0&st=0&sk=t&sd=a

4、如果出现“(cvcap_vfw.obj) : error LNK2001: unresolved external symbol _AVIFileRelease@4” 等错误,并不是opencv链接库的问题,而是opencv在调用win32下的vfw库,需要在 Additional Dependencies 中需加上 vfw32.lib 这个系统库文件,才能顺利编译。(参考《Opencv中highgui静态链接库使用时error LNK2001的错误》http://hi.baidu.com/56908268/blog/item/0f619bef2ce6efe1ce1b3efb.html

5、如果出现“fatal error LNK1104: cannot open file “atlthunk.lib””的错误,是因为VS2005以上版本的ATL和MFC库中已不再带有这个文件,因此一般情况下可去掉对atlthunk.lib 的引用。参考《directshow 问题 找不到 atlthunk.lib》(http://topic.csdn.net/u/20090709/11/f3f9a286-9ef4-4e83-8808-26fb52ad5cb5.html)18、19和26楼的方法,在项目的头文件 stdafx.h 中添加如下代码:

// TODO: reference additional headers your program requires here
//在这添加*************************************************************
#include

#pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")

#if (_ATL_VER < 0x0700)
namespace ATL
{
    inline void * __stdcall __AllocStdCallThunk()
    {
        return ::HeapAlloc(::GetProcessHeap(), 0, sizeof(_stdcallthunk));
    }
    inline void __stdcall __FreeStdCallThunk(void *p)
    {
        ::HeapFree(::GetProcessHeap(), 0, p);
    }
};
#endif //(_ATL_VER < 0x0700)
//***************************************************************添加结束

如果确实需要用到 atlthunk.lib ,可以到这里(http://download.csdn.net/source/1672909)下载WDK7.0的ATL7.1,从中抽取出 atlthunk.lib,放到 $(VCInstallDir)atlmfc/lib 里。

使用OpenCV官方提供文件配置、静态编译并运行OpenCV-2.3.x/2.4.x实例

当我们需要测试程序,或者想将程序发给其他同事或者同学,以让同事或者同学运行以测试程序性能或者逻辑是否恰当时,是不是还要他人也要像你当初开发程序时一样一步一步的配置OpenCV运行环境!?如果不做这些,还会提示像图1所示的系统错误(无法启动程序,因为计算机中丢失“opencv_highgui241d.dll。尝试重新安装该程序以解决此问题”),这是不是太麻烦了,其实我们可以将程序以静态链接的方式编译,如此便少去了配置运行时环境的步骤了。

图1  动态编译的程序在未配置OpenCV的机器上运行提示系统错误

    静态编译,也就是说编译后的程序可以直接拷贝到其他机器上并能直接运行。而不需附带链接库和配置环境变量。

    由于OpenCV自2.3.0版本开始就提供了OpenCV-2.3.x -win-superpack.exe或OpenCV-2.4.x.exe文件,该文件解压后我们会发里面有个名为“build”的文件夹,其中有各个平台的链接库,而且还提供了Windows平台下的静态链接库,本文主要讲述一个例子以说明如何配置使用该静态链接库。

    像前面(OpenCV2.3.x/2.4.x在Visual Studio2005/2008和Visual Studio2010配置方法详解)放置OpenCV库文件配置VC++目录选项,并且配置环境变量(这一步可以不配置,但要在VC++目录中将OpenCV的“bin”目录添加到“VC++ 可执行文件”目录选项中),注意这里使用的库目录是“staticlib”而不是“lib”,这里不多赘述。

配置完Visual Studio 2008中的VC++目录后便可以编写代码了。

(1)编辑代码

“新建项目”,选择“Visual C++-空项目”,输入项目名“StaticOpenCV”,“添加新项-代码-C++ 文件”,输入文件名“StaticOpenCV.cpp”,编辑代码,这里本人使用的测试代码如下所示:

  1. #include <opencv/highgui.h>
  2. int main( int argc, char** argv ) { 
  3.          IplImage*img = cvLoadImage( argv[1] ); 
  4.          cvNamedWindow("OpenCV", CV_WINDOW_AUTOSIZE ); 
  5.          cvShowImage("OpenCV", img ); 
  6.          cvWaitKey(0); 
  7.          cvReleaseImage(&img ); 
  8.          cvDestroyWindow("OpenCV" ); 
  9. return( 0 ); 

(2)添加附加依赖项有两种方法,见《OpenCV 2.3.x/2.4.x在Visual Studio 2005/2008和Visual Studio 2010配置方法详解》一文。

    OpenCV-2.4.1库文件列表(使用的时候适当选择,这里我要用的是libjasperd.lib、libjpegd.lib、libpngd.lib"、libtiffd.lib、zlibd.lib(注意这几个必须要用的,因为这些是OpenCV所使用的第三方库)和opencv_highgui241d.lib、opencv_core241d.lib库文件。

  1. libjasper.lib 
  2. libjasperd.lib 
  3. libjpeg.lib 
  4. libjpegd.lib 
  5. libpng.lib 
  6. libpngd.lib 
  7. libtiff.lib 
  8. libtiffd.lib 
  9. opencv_calib3d241.lib 
  10. opencv_calib3d241d.lib 
  11. opencv_contrib241.lib 
  12. opencv_contrib241d.lib 
  13. opencv_core241.lib 
  14. opencv_core241d.lib 
  15. opencv_features2d241.lib 
  16. opencv_features2d241d.lib 
  17. opencv_ffmpeg241.dll 
  18. opencv_flann241.lib 
  19. opencv_flann241d.lib 
  20. opencv_gpu241.lib 
  21. opencv_gpu241d.lib 
  22. opencv_haartraining_engine.lib 
  23. opencv_haartraining_engined.lib 
  24. opencv_highgui241.lib 
  25. opencv_highgui241d.lib 
  26. opencv_imgproc241.lib 
  27. opencv_imgproc241d.lib 
  28. opencv_legacy241.lib 
  29. opencv_legacy241d.lib 
  30. opencv_ml241.lib 
  31. opencv_ml241d.lib 
  32. opencv_nonfree241.lib 
  33. opencv_nonfree241d.lib 
  34. opencv_objdetect241.lib 
  35. opencv_objdetect241d.lib 
  36. opencv_photo241.lib 
  37. opencv_photo241d.lib 
  38. opencv_stitching241.lib 
  39. opencv_stitching241d.lib 
  40. opencv_ts241.lib 
  41. opencv_ts241d.lib 
  42. opencv_video241.lib 
  43. opencv_video241d.lib 
  44. opencv_videostab241.lib 
  45. opencv_videostab241d.lib 
  46. zlib.lib 
  47. zlibd.lib 

    为方便我们知道到我们到底需要使用哪些库文件,这里我们使用《OpenCV2.3.x/2.4.x在Visual Studio2005/2008和Visual Studio2010配置方法详解》一文中所讲述的第二种方法添加程序依赖库。我们在头文件与主函数之间添加如下代码:

  1. #pragma comment( lib,"libjasperd.lib" )
  2. #pragma comment( lib,"libjpegd.lib" )
  3. #pragma comment( lib,"libpngd.lib" )
  4. #pragma comment( lib,"libtiffd.lib" )
  5. #pragma comment( lib, "zlibd.lib")
  6. #pragma comment( lib,"opencv_highgui241d.lib" )
  7. #pragma comment( lib,"opencv_core241d.lib" )

    编译程序,会发发现程序不能正常编译(错误如图2所示),这主要与MSVCRT.lib(MSVCR90.dll)有关。

图2  编译产生很多错误

    经过查询相关资料可知,需要对项目属性进行如下配置:右击项目名称,选择“属性-配置属性-C/C++-代码生成”,这里我们发现“运行库”选项默认值选项为“多线程调试 DLL (/MDd)”,同时这里有四个选项(/MT,/MTd, /MD, /MDd),前两个一组,为静态链接运行时库,运行时不需要运行时库的支持,代码直接插入到程序中去;后两个一组,为动态链接运行时库,运行时需要MSVCR90.dll或MSVCP90.dll支持。

    所以,这里我们将“运行库”选项设置为“多线程(/MT)”或“多线程调试(/MTd)”(注意你的编译模式(Debug还是Release)),如图3所示,设置完成全单击确定。

图3  将“运行库”选项设置为“多线程调试(/MTd)”

    然后我们再次编译程序,发现还有两个错误,如图4所示。

当我们需要测试程序,或者想将程序发给其他同事或者同学,以让同事或者同学运行以测试程序性能或者逻辑是否恰当时,是不是还要他人也要像你当初开发程序时一样一步一步的配置OpenCV运行环境!?如果不做这些,还会提示像图1所示的系统错误(无法启动程序,因为计算机中丢失“opencv_highgui241d.dll。尝试重新安装该程序以解决此问题”),这是不是太麻烦了,其实我们可以将程序以静态链接的方式编译,如此便少去了配置运行时环境的步骤了。

图1  动态编译的程序在未配置OpenCV的机器上运行提示系统错误

    静态编译,也就是说编译后的程序可以直接拷贝到其他机器上并能直接运行。而不需附带链接库和配置环境变量。

    由于OpenCV自2.3.0版本开始就提供了OpenCV-2.3.x -win-superpack.exe或OpenCV-2.4.x.exe文件,该文件解压后我们会发里面有个名为“build”的文件夹,其中有各个平台的链接库,而且还提供了Windows平台下的静态链接库,本文主要讲述一个例子以说明如何配置使用该静态链接库。

    像前面(OpenCV2.3.x/2.4.x在Visual Studio2005/2008和Visual Studio2010配置方法详解)放置OpenCV库文件配置VC++目录选项,并且配置环境变量(这一步可以不配置,但要在VC++目录中将OpenCV的“bin”目录添加到“VC++ 可执行文件”目录选项中),注意这里使用的库目录是“staticlib”而不是“lib”,这里不多赘述。

配置完Visual Studio 2008中的VC++目录后便可以编写代码了。

(1)编辑代码

“新建项目”,选择“Visual C++-空项目”,输入项目名“StaticOpenCV”,“添加新项-代码-C++ 文件”,输入文件名“StaticOpenCV.cpp”,编辑代码,这里本人使用的测试代码如下所示:

  1. #include <opencv/highgui.h>
  2. int main( int argc, char** argv ) { 
  3.          IplImage*img = cvLoadImage( argv[1] ); 
  4.          cvNamedWindow("OpenCV", CV_WINDOW_AUTOSIZE ); 
  5.          cvShowImage("OpenCV", img ); 
  6.          cvWaitKey(0); 
  7.          cvReleaseImage(&img ); 
  8.          cvDestroyWindow("OpenCV" ); 
  9. return( 0 ); 

(2)添加附加依赖项有两种方法,见《OpenCV 2.3.x/2.4.x在Visual Studio 2005/2008和Visual Studio 2010配置方法详解》一文。

    OpenCV-2.4.1库文件列表(使用的时候适当选择,这里我要用的是libjasperd.lib、libjpegd.lib、libpngd.lib"、libtiffd.lib、zlibd.lib(注意这几个必须要用的,因为这些是OpenCV所使用的第三方库)和opencv_highgui241d.lib、opencv_core241d.lib库文件。

  1. libjasper.lib 
  2. libjasperd.lib 
  3. libjpeg.lib 
  4. libjpegd.lib 
  5. libpng.lib 
  6. libpngd.lib 
  7. libtiff.lib 
  8. libtiffd.lib 
  9. opencv_calib3d241.lib 
  10. opencv_calib3d241d.lib 
  11. opencv_contrib241.lib 
  12. opencv_contrib241d.lib 
  13. opencv_core241.lib 
  14. opencv_core241d.lib 
  15. opencv_features2d241.lib 
  16. opencv_features2d241d.lib 
  17. opencv_ffmpeg241.dll 
  18. opencv_flann241.lib 
  19. opencv_flann241d.lib 
  20. opencv_gpu241.lib 
  21. opencv_gpu241d.lib 
  22. opencv_haartraining_engine.lib 
  23. opencv_haartraining_engined.lib 
  24. opencv_highgui241.lib 
  25. opencv_highgui241d.lib 
  26. opencv_imgproc241.lib 
  27. opencv_imgproc241d.lib 
  28. opencv_legacy241.lib 
  29. opencv_legacy241d.lib 
  30. opencv_ml241.lib 
  31. opencv_ml241d.lib 
  32. opencv_nonfree241.lib 
  33. opencv_nonfree241d.lib 
  34. opencv_objdetect241.lib 
  35. opencv_objdetect241d.lib 
  36. opencv_photo241.lib 
  37. opencv_photo241d.lib 
  38. opencv_stitching241.lib 
  39. opencv_stitching241d.lib 
  40. opencv_ts241.lib 
  41. opencv_ts241d.lib 
  42. opencv_video241.lib 
  43. opencv_video241d.lib 
  44. opencv_videostab241.lib 
  45. opencv_videostab241d.lib 
  46. zlib.lib 
  47. zlibd.lib 

    为方便我们知道到我们到底需要使用哪些库文件,这里我们使用《OpenCV2.3.x/2.4.x在Visual Studio2005/2008和Visual Studio2010配置方法详解》一文中所讲述的第二种方法添加程序依赖库。我们在头文件与主函数之间添加如下代码:

  1. #pragma comment( lib,"libjasperd.lib" )
  2. #pragma comment( lib,"libjpegd.lib" )
  3. #pragma comment( lib,"libpngd.lib" )
  4. #pragma comment( lib,"libtiffd.lib" )
  5. #pragma comment( lib, "zlibd.lib")
  6. #pragma comment( lib,"opencv_highgui241d.lib" )
  7. #pragma comment( lib,"opencv_core241d.lib" )

    编译程序,会发发现程序不能正常编译(错误如图2所示),这主要与MSVCRT.lib(MSVCR90.dll)有关。

图2  编译产生很多错误

    经过查询相关资料可知,需要对项目属性进行如下配置:右击项目名称,选择“属性-配置属性-C/C++-代码生成”,这里我们发现“运行库”选项默认值选项为“多线程调试 DLL (/MDd)”,同时这里有四个选项(/MT,/MTd, /MD, /MDd),前两个一组,为静态链接运行时库,运行时不需要运行时库的支持,代码直接插入到程序中去;后两个一组,为动态链接运行时库,运行时需要MSVCR90.dll或MSVCP90.dll支持。

    所以,这里我们将“运行库”选项设置为“多线程(/MT)”或“多线程调试(/MTd)”(注意你的编译模式(Debug还是Release)),如图3所示,设置完成全单击确定。

图3  将“运行库”选项设置为“多线程调试(/MTd)”

    然后我们再次编译程序,发现还有两个错误,如图4所示。

这是因为我们的程序是win32程序的问题,我们还需要添加vfw32.lib和comctl32.lib这两个依赖库文件,最终代码如下所示:

  1. #include <opencv/highgui.h>
  2. // 这几个依赖库文件必须要添加,
  3. // 因为这些是OpenCV所使用的第三方库
  4. #pragma comment( lib, "libjasperd.lib" )
  5. #pragma comment( lib, "libjpegd.lib" )
  6. #pragma comment( lib, "libpngd.lib" )
  7. #pragma comment( lib, "libtiffd.lib" )
  8. #pragma comment( lib, "zlibd.lib" )
  9. // 这里根据你的程序添加依赖库文件
  10. #pragma comment( lib, "opencv_highgui241d.lib" )
  11. #pragma comment( lib, "opencv_core241d.lib" )
  12. // 添加这两个是因为win32程序
  13. #pragma comment( lib, "vfw32.lib" )
  14. #pragma comment( lib, "comctl32.lib" )
  15. int main( int argc, char** argv ) { 
  16.     IplImage* img = cvLoadImage( argv[1] ); 
  17.     cvNamedWindow( "OpenCV", CV_WINDOW_AUTOSIZE ); 
  18.     cvShowImage( "OpenCV", img ); 
  19.     cvWaitKey(0); 
  20.     cvReleaseImage( &img ); 
  21.     cvDestroyWindow( "OpenCV" ); 
  22. return ( 0 ); 

    再次编译,成功了!!!此时,我们可以将编译后的执行程序复制到其他机器(没有配置OpenCV函数库及环境变量)以测试是否OK。


备注:

1.根据需要可能还需要忽略libcmt库;

2.静态编译后的可执行程序比动态编译后的可执行程序大得多;

3.不能静态编译C++版本的OpenCV程序,可能和VS有关;

4.参考链接:http://blog.csdn.net/shuxiao9058/article/details/7525067

原文地址:https://www.cnblogs.com/freedesert/p/3016958.html