macOS Sierra源码编译 opencv3.2

macOS Sierra 安装 opencv3

macOS Sierra源码编译 opencv3.2


ps:之所以要编译安装原因是用了很多种网上的方法最终发现不行,或者是有一次行,下一次就不行了。。


网上流传的简单的安装 python 版本的 opencv 的方法

使用 conda 安装

1
2
3
4
5
# 利用 anaconda 安装 opencv
anaconda search -t conda opencv
# 假设有如下的包 ver228/opencv3 | 3.2.0 | conda | linux-64, osx-64, win-64
# 然后直接下载
conda install -c ver228 opencv

这种方法的问题,就是我之前提到的,有时候有这个库,但有时候又没有这个库。。而且兼容性一般都存在着问题,有时候会和 numpy 库冲突。。

使用 brew 安装

直接用 brew 装。。

1
2
brew tap homebrew/science
brew install opencv

但是使用 brew 装这个会有很多 bug 。。我也不推荐这样安装。。
可以参考 这个网址

源码编译安装

这个是我这里要提到的重头戏。。
是我觉得最稳、最不容易翻车的方法。
这里还是得先用 brew 安装一些依赖库

准备工作

先安装 python、pip 这些我就不说了。。

然后安装 Xcode 还有 Xcode Command Line Tools。。这里我也不再赘述,具体怎么安装 Google 一下。
然后就是用 pip 安装一下 numpy 库,这个是必须的。scipy matplotlib 可选,这三个一般放一起,是做科学计算的 python 库。

1
pip install --ignore-installed numpy scipy matplotlib

另外在啰嗦一下,我推荐在 mac 上使用 anaconda 来进行分离 python 版本,和安装一些库,比较方便。

具体可以参考我的另外一篇博文下载anaconda 部分。

安装依赖库

后面的依赖库使用 brew 下载,如果没有,可以下载一下。

1
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

然后安装一些依赖包和图像处理,这会用掉比较长的时间。建议备好梯子。

1
brew install cmake pkg-config ffmpeg jpeg libpng libtiff eigen tbb gcc git openni libgphoto2 jasper webp

其中 cmake 是我们等下要对源码进行编译的包,其余的是图像和视频处理相关的包。

另外在 mac 上面我还推荐使用 Cmake.app 替代手工敲 makefile。。。

https://cmake.org/download/

正式开始

1
2
3
4
5
6
7
8
$ cd ~
# 源码
$ git clone https://github.com/opencv/opencv.git
# opencv 3.0之后的添加的额外库
$ git clone https://github.com/opencv/opencv_contrib.git

$ cd ~/opencv
$ mkdir build

如果使用的是 cmake.app 的话打开得到类似如下界面(没进行 configure 时会是红色,刚打开应该是什么都没有的),把源码和刚刚建立的build目录添加进来。

点击 configure出现下面这个界面

点击 done 等待configure 完成之后进行调整。
找到 OPENCV_EXTRA_MODULES_PATH 添加自己的额外库的地址。
例如 /Users/username/opencv_contrib/modules/

然后配置里面的 python 环境,默认的也行。
我使用的是 anaconda 的虚拟环境的位置。

类似于这样子,具体根据自己的情况调整:

我这里的路径和最终配置好的也不完全一样,仅供参考.

然后就可以 generate 了。

这里面值得提的一点的是其中有些第三方库实在是下载速度。例如 ippicv。。

推荐直接去opencv_3rdparty里面找你需要的文件,然后覆盖掉.cache里面的正在下载的文件,重新进行configure and generate。

然后就可以编译了,大概几十分钟吧。

1
2
3
$ cd ~/opencv/build 
$ make -j8
$ sudo make install

如果没有安装 cmake.app 的话也可以在终端中进行编译:

1
2
3
4
$ cd ~/opencv/build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules ..
$ make -j8
$ sudo make install

收尾工作

如果上面之后能够正常工作,后面的就可以忽略了.

macOS Sierra 加入了被称作 SIP (System Integrity Protection)的东西,简单点来说就是系统完整性保护。。这就导致了编译之后 python 调用时候路径产生了问题。

我是选择了关闭 SIP。。具体做法就是重启按住 command+R , 再在上面实用工具找到终端

1
2
csrutil disable
reboot

然后使用如下的脚本对相对路径进行处理,脚本来源是 stackflow 的一个回答

这里面需要根据自己的路径进行微调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import glob
import subprocess
import os.path

ABSPATH = "/usr/local/lib/" # absolute path to relative libraries
# libraries to correct
LIBPATHS = ['/usr/local/lib/python2.7/site-packages/cv2.so', '/usr/local/lib/libopencv*']
PREFIX = 'sudo install_name_tool -change '

assert(ABSPATH.startswith('/') and ABSPATH.endswith('/'),
'please provide absolute library path ending with /')

libs = []
for path in LIBPATHS:
libs += glob.glob(path)

cmd = []
err = []
for lib in libs:
if not os.path.isfile(lib):
err.append(lib+" library not found") # glob should take care
datastr = subprocess.check_output(['otool','-l','-v', lib])
data = datastr.split('\n')
for line in data:
ll = line.split()
if not ll: continue
if (ll[0] == 'name' and ll[1].endswith('.dylib') and not ll[1].startswith('/')):
libname = ll[1].split('/')[-1]
if os.path.isfile(ABSPATH+libname):
cmd.append(PREFIX+ll[1]+" "+ABSPATH+libname+' '+lib)
else:
err.append(ABSPATH+libname+" does not exist, hence can't correct: "+ll[1]+" in: "+lib)

ohandle = open("rpathChangeCmd.txt", 'w')
for lib in cmd:
ohandle.write(lib+'\n')
ohandle.close()

if err:
ehandle = open("rpathChangeErr.txt", 'w')
for e in err:
ehandle.write(e+'\n')
ehandle.close()

处理完之后还是有个一个小问题。

/anaconda/envs/py27/lib/libjpeg.9.dylib does not exist, hence can’t correct: @rpath/libjpeg.9.dylib in: /anaconda/envs/py27/lib/libopencv_highgui.2.4.12.dylib

/anaconda/envs/py27/lib/libjpeg.9.dylib does not exist, hence can’t correct: @rpath/libjpeg.9.dylib in: /anaconda/envs/py27/lib/libopencv_highgui.2.4.dylib

/anaconda/envs/py27/lib/libjpeg.9.dylib does not exist, hence can’t correct: @rpath/libjpeg.9.dylib in: /anaconda/envs/py27/lib/libopencv_highgui.dylib

这时候进行 python import cv2的时候会报错。。实际根据自己情况手工输入地址

1
2
# 大概是这样子的具,体可以看rpathChangeCmd.txt里面的格式选择自己的文件位置(自己找一下啦):
sudo install_name_tool -change @rpath/libjpeg.9.dylib /xxx/xxx/x/x/x/xxx.dylib /xx/xx/xx/cv2.so

我是直接找到那个文件,然后直接复制进对应的位置就没报错了。。:)不知道之后有没有问题,跑了一个例子正常显示。我觉得不太影响。。

遇到的问题

/anaconda3/envs/cv/lib/python3.6/site-packages/numpy/core/include/numpy/npy_common.h:17:5: warning:
‘NPY_INTERNAL_BUILD’ is not defined, evaluates to 0 [-Wundef]

编辑相应的目录下面 npy_common.h

1
2
3
4
5
6
// 将
#if NPY_INTERNAL_BUILD
//改为
#ifndef NPY_INTERNAL_BUILD
//再在之后加入
#ifndef NPY_INTERNAL_BUILD

重新make即可

Buy me a coffe. XD