背景
最近要把一个SBD算法从X86服务器上移植到iOS上,因为该算法的核心要义就是使用了OpenCV的几个API(你懂的,每个API背后就是几代人几十篇paper的辛劳)。
iOS开发可以使用swift和object-c,但是因为object-c可以混合C++的语法(美其名曰object-c++,注意不是一门新语言),因此Gemfield选择使用object-c。反正主要算法都是使用C++写的,object-c无非就当作个胶水语言,一头是iOS上的各种SDK,另外一头是C++编写的算法。不过苹果的Objective-C语言语法奇丑无比,和苹果的硬件产品外观真是完全相反。真是奇怪,你苹果心里没有点数吗?赶紧罢黜object-c,独尊C++!
xcode项目
在xcodeproj目录下,有如下的文件:
project.pbxproj
xcuserdata
project.xcworkspace
- pbxproj文件包含了xcode项目的各种配置信息,我们不直接修改这个文件,而是通过xcode IDE来配置;
- xcuserdata是xcode-user-data的缩写,存放的是用户自己的一些数据,比如当前项目的一些和个人操作相关的记录;
- project.xcworkspace目录就是workspace,这个比较复杂,以后再说。
在XCode的"Build Settings"中主要修改C++的标准,使用的标准库,以及最重要的一项:"Apple Clang - Language"-->"Compile Source As"修改为"Objective-C++",不然你的C++会报各种奇怪的头文件找不到的错误;另外,object-c中引用的C++头文件要放在object-c头文件的前面,否则也会报一些奇怪的错误,比如"Expected identifier"错误。
编译iOS版的OpenCV
Gemfield选择的是OpenCV仓库的master分支(opencv4.2+)。确保你的mac已经从商店下载安装了Xcode。
1, 克隆opencv仓库
git clone https://github.com/opencv/opencv.git
如果还想要额外的opencv module,可以再克隆opencv_contrib.git
git clone https://github.com/opencv/opencv_contrib.git
2,安装cmkae
brew install cmake
3,安装xcode的命令行工具
xcode-select --install
4,编译OpenCV的iOS framework
编译过程已经放在仓库中的build_framework.py脚本里了:
python opencv/platforms/ios/build_framework.py ios
这个python脚本内部调用了cmake命令来进行C++的编译(OpenCV现在已经是C++11的项目了):
cmake -GXcode
-DAPPLE_FRAMEWORK=ON
-DCMAKE_INSTALL_PREFIX=install
-DCMAKE_BUILD_TYPE=Release
-DOPENCV_INCLUDE_INSTALL_PATH=include
-DOPENCV_3P_LIB_INSTALL_PATH=lib/3rdparty
-DIOS_ARCH=armv7
-DCMAKE_TOOLCHAIN_FILE=/Users/civilnet/github/opencv/platforms/ios/cmake/Toolchains/Toolchain-iPhoneOS_Xcode.cmake
-DCPU_BASELINE=DETECT /Users/civilnet/github/opencv
-DCMAKE_C_FLAGS=-fembed-bitcode
-DCMAKE_CXX_FLAGS=-fembed-bitcode
如果还想同时编译opencv_contrib,可以使用--contrib参数:
python opencv/platforms/ios/build_framework.py ios --contrib opencv_contrib
如果还想裁剪掉一些module,可以使用--without参数:
python opencv/platforms/ios/build_framework.py ios --contrib opencv_contrib --without optflow
编译可是需要很长时间,一个重要的原因是默认会编译5种CPU架构的framework:iOS需要的armv7、armv7s、arm64和iPhone模拟器需要的i386、x86_64。如果不想编译这么多种架构的framework,可以像Gemfield一样使用--iphoneos_archs 和 --iphonesimulator_archs 参数。比如,在CivilNet,Gemfield只编译iOS的arm64和模拟器的x86_64:
python opencv/platforms/ios/build_framework.py ios --iphoneos_archs arm64 --iphonesimulator_archs x86_64
再深入OpenCV的iOS构建
1,OpenCV的内部模块
-- Processing WORLD modules...
-- module opencv_core...
-- module opencv_flann...
-- module opencv_imgproc...
-- module opencv_ml...
-- module opencv_photo...
-- module opencv_dnn...
-- Registering hook 'INIT_MODULE_SOURCES_opencv_dnn': /Users/civilnet/github/opencv/modules/dnn/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake
-- opencv_dnn: filter out ocl4dnn source code
-- opencv_dnn: filter out cuda4dnn source code
-- module opencv_features2d...
-- module opencv_gapi...
-- module opencv_imgcodecs...
-- module opencv_videoio...
-- module opencv_calib3d...
-- module opencv_highgui...
-- module opencv_objdetect...
-- module opencv_stitching...
-- module opencv_video...
2,编译arm架构的时候
编译arm架构framework的时候,一些x86的源文件就会被自动排除: