xcode修改时间后就要重新编译_OpenCV(2/2):编译

为方便断点调试、可视化管理,等等,編译OpenCV要通过編写该平台IDE需要的工程文件。Windows是*.sln(Visual Studio),iOS是project.pbxproj(XCode),Android则是*.mk(Android Studio+NDK)。但OpenCV官方写的是CMake,为此編译要分两个步骤。第一步是使用opencv官方介绍的方法,用CMake编译出结果。第二步是复制第一步生成的哪些文件,结合须要编译的cpp,基于各平台的IDE(Visual Studo/Xcode/NDK)新建opencv工程。

因为已有替代模块,Rose用到的opencv不编译dnn、highgui、imgcodec、videoio。如何不让CMake编译它们,以不编译highgui为例,让CMake找不到<opencv>/modules/highgui/CMakeLists.txt就行了,像把文件名改为CMakeLists.txt_。注:一旦少了模块,CMake将不会生成官方自带的app。

CMake生成的文件

CMake生成的既有头文件(hpp),也有源文件(cpp),按影响范围分为两类,一类是全局文件,一类是模块私有文件。

全局文件都是头文件,包括opencv_modules.hpp、custom_hal.hpp、cv_cpu_config.h、cvconfig.h。另外有个version_string.inc,它的内容就是一串字符,描述了編译、链接该版本opencv时概述,像包括哪些模块,涉及到哪些开源库,虽然生成时是放在core模块,但把它归到全局文件。在不同平台,全局文件会有不一样内容。除了version_string.inc外的四个文件,Rose给出了能用于Windows、iOS、Android的统一版本。Rose给的version_string.inc是Windows版本,不过把当中换行符由“rn”改到了“n”。

模块私有文件分为两类。第一类是opencl脚本,像opencl_kernels_core.cpp、opencl_kernels_core.hpp。第二类和simd优化相关,像accum.avx.cpp,stat.sse4_2.cpp。对不同平台,这些文件内容是一样的(iOS不支持superres,因而没有opencl_kernels_superres.cpp/hpp)。Rose把它们放在了<opencv>/autogen。

Windows

预定义宏

  • __OPENCV_BUILD=1。iOS、Android都需要
  • CVAPI_EXPORTS。要把相关函数、类放入opencv.dll
  • _VARIADIC_MAX=10。还不清楚为什么要定义这宏,只是CMake生成的sln定义了

换到Visual Studio自建工程时,由于CMake生成的sln用的字符集是Multi-Byte Character Set,为换到Unicode Character Set,须修改OpenCV源码。

<opencv>/modules/core/src/glob.cpp 
WIN32_FIND_DATA data---->WIN32_FIND_DATAA data;

编译Windows要做到让app和opencv使用同样运行库!

#include <opencv2/core/utility.hpp>
int main( int argc, const char** argv )
{	
	cv::Point2f point = cv::Point2f((float)500, (float)500);

	std::vector<cv::Point2f> tmp;
	tmp.push_back(point);
	std::vector<cv::Point2f>* tmp2 = &tmp;
	{
		cv::InputOutputArray _corners(tmp);
		cv::Mat cornersmat = _corners.getMat();
		// if error, cornersmat is empty!
		int count = cornersmat.checkVector(2, CV_32F);
		CV_Assert( count >= 0 );
	}
	return 0;
}

以上代码如果正确执行,cornersmat的rows、cols都是1,后面count也是1。但会出错,出错时cornersmat是个空Mat,后面的count值是-1!查这问题原因,要深入到getMat内部,它会执行下面语句。

const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;

同样是这条语句,app中得到tmp是转换后的正确值(见代码中tmp2),但库中(opencv)代码转换后却是nil!而且可以确定两处的obj值是同一个。要解决这问题,找到办法是让app和opencv使用同一个运行库。

编译基于Rose的app时,使用的是Release,运行库Multi-threaded(/MT)。可使用下来,如果opencv是debug,运行库用(/MT)会使编译失败。为让调试app时能进入opencv,只好让opencv也是release,而为支持断点,须要修改opencv的几处设置。

  • C/C++——General。Debug Information Format改为“Program Database(/Zi)”。
  • C/C++——Optimization。Optimization改为“Disabled(/Od)”)。

iOS

ios不支持superres,要跨平台的app不要用当中的api。

不管是debug还是release,xcode默认都会让ipa带调试符号文件,这会使得opencv达到上百M。为减少尺寸,Release时手动把Generate Debug Symbols设为No。

43665c4bf42da9933d218f99c03fc991.png

Android

至少到opencv-3.4.1,官方CMake編译时用的还是gcc,不是NDK推荐的llvm。NDK文档有写r15之后虽然还会保留gcc,但不保证不出问题。于是要用CMake編译opencv,r14b可能是能用的最高版本。当然,用Android.mk方法不受这个限制。

在CMake編译时,有些库可能会给編译造成小麻烦,而你已确认不须要它,像libtiff。为强制不編译,可以这么做。1)用文本編辑器打开<opencv>/CMakeLists.txt。2)找到“OCV_OPTION(WITH_TIFF...ON...“,把ON改为OFF。以下是在Windows用CMake編译。

$ cd opencv-3.4.1
$ mkdir android
$ cd android
$ cmake.exe -G"MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=../platforms/android/android.toolchain.cmake -DANDROID_NDK="c:UsersancientccAppDataLocalAndroidsdkndk-bundle" -DCMAKE_MAKE_PROGRAM="c:UsersancientccAppDataLocalAndroidsdkndk-bundleprebuiltwindows-x86_64binmake.exe" -DANDROID_NATIVE_API_LEVEL=21 -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" -DANDROID_STL=c++_shared -DBUILD_SHARED_LIBS=ON ..
$ cmake --build .
  • ANDROID_NDK:NDK路径,这个路径建议用绝对路径,相对路径时可能会找不到NDK错误。
  • ANDROID_NATIVE_API_LEVEL:要使用的API Level。为较少改动,开始使用21。使用18会出更多错误。
  • ANDROID_STL:默认使用的是gnustl,但app要求用c++_shared。
  • BUILD_SHARED_LIBS:默认编译成静态库(*.a),但现在编译成*.a时在链接出错,先强制为*.so。

opencv支持在Mac OS X编译,编译方法类似Windows,当然啦,不再须要-G"MinGW Makefiles"、-DCMAKE_MAKE_PROGRAM。编译方法类似编译boringssl中介绍的Android部分。以下是当中的cmake命令。

cmake -DCMAKE_TOOLCHAIN_FILE=../platforms/android/android.toolchain.cmake -DANDROID_NDK=/Users/ancientcc/android-ndk-r14b -DANDROID_NATIVE_API_LEVEL=21 -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" -DANDROID_STL=c++_shared -DBUILD_SHARED_LIBS=ON ..

为成功编译,须要修改两个ndk中的.h,修改原因:“<ndk>/platforms/android-21/arch-arm/usr/include下有同名文件,因为是“<>”,底下的cmath会优先读这目录下文件,导致编译时出错。”

<ndk>/sources/cxx-stl/llvm-libc++/include/cmath
line 305-->#include <math.h>--->#include "math.h"
<ndk>sourcescxx-stlllvm-libc++includecstdlib
line 86-->#include <stdlib.h>--->#include "stdlib.h"

升级

一旦有了OpenCV新版本,可按下以下步骤让尽快保持同步。

  • 把dnn、highgui、imgcodec、videoio下的CMakeLists.txt改名为CMakeLists.txt_。
  • 按官方写的,在Windows平台用CMake編译出OpenCV。
  • 查看opencv_modules.hpp、custom_hal.hpp、cv_cpu_config.h、cvconfig.h有没有出现变化,有的话修改。
  • 复制模块私有文件到<opencv>/autogen,version_string.inc到<opencv>/。各文件中的换行符由“rn”改到“n”。
  • 通过CMake編译出的结果,修改工程要編译哪些源文件。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值