MacOSX
OpenCV
OpenCV3
OpenCV-Python

複数バージョンのOpenCVを共存させたい on macOS

動機

コンピュータビジョン関連の開発をしたり,ライブラリを使っていると,OpenCVの2系と3系を切り替えたいときがある.(特にPython)

そこで,

  • virtualenvでOpenCVのバージョンを使い分けたいけど,どこのcv2.soからシンボリックリンクを作ればいいのか.
  • pyenvしか使っていないときにOpenCVのバージョンを使い分けたいとき,PYTHONPATHには何を設定すればいいのか.
  • g++でOpenCVを使ったプログラムをビルドする際は,cmakeするときのパスをどこに設定すればいいのか.
  • 簡単にOpenCV2系とOpenCV3系を切り替える方法.

をメモしておく.

brew unlink & brew linkで管理していたら事故を起こして不具合が出たので,別の方法を考案.
Linuxでもパスを適切に設定すれば,この方法は使えるはず.

準備

HomebrewでOpenCVの2系と3系をインストールする

Terminal
# まずインストールする
# Python2系に切り替えておく
$ brew update
$ brew tap homebrew/science
$ brew install cmake pkg-config jpeg libpng libtiff eigen openexr numpy
$ brew install tbb
$ brew install ffmpeg

# OpenCV2系のインストール
# Python2系バインドが一緒に入るはず
$ brew install opencv --with-tbb --with-ffmpeg —-with-vtk

# OpenCV3系のインストール
# Python2系バインドを入れる場合
$ brew install opencv3 —-with-contrib --with-ffmpeg --with-tbb —with-vtk
# Python3系バインドを入れる場合 (Python3に切り替えてから実行すること)
$ brew install opencv3 —-with-contrib --with-ffmpeg --with-python3 --with-tbb —with-vtk --without-python

必要であればunlinkしておく.

Terminal
$ brew unlink opencv opencv3

パスの設定

unlinkをしてあっても,パスを通せばコンパイル・リンク時に参照できる.

cmakeするときのオプション

  • -DオプションでOpenCV_DIRを設定 (OpenCVConfig.cmakeがあるディレクトリ)
    • OpenCV2 : -DOpenCV_DIR=/usr/local/opt/opencv/share/OpenCV/
    • OpenCV3 : -DOpenCV_DIR=/usr/local/opt/opencv3/share/OpenCV/

OpenCV_DIRが設定されている状態でfind_package(OpenCV REQUIRED)をすると,OpenCV_INCLUDE_DIRSOpenCV_LIBSが設定されるので,

CMakeLists.txt
cmake_minimum_required(VERSION 2.8)

project(Sample)

add_executable(Project main.cpp)

find_package(OpenCV REQUIRED)

if(OpenCV_FOUND)
  include_directories(${OpenCV_INCLUDE_DIRS})
  target_link_libraries(Project ${OpenCV_LIBS})
endif(OpenCV_FOUND)

cmakeが通るようになる.

cv2.soのシンボリックリンク元

OpenCV3のPython2バインドをHomebrewでインストール,OpenCV3のPython3バインドは自前ビルドしていると仮定する.
OpenCVモジュールを使いたいPythonのインストールパス以下のディレクトリ,/path/to/python/lib/python2.7/site-packagesに,以下のcv2.soからシンボリックリンクを貼る.
(OpenCV, Pythonのバージョンは適宜変更する)

  • OpenCV2 for Python2
    • /usr/local/Cellar/opencv/2.4.13.2/lib/python2.7/site-packages/cv2.so
    • または /usr/local/opt/opencv/lib/python2.7/site-packages/cv2.so
  • OpenCV3 for Python2
    • /usr/local/Cellar/opencv3/3.2.0/lib/python2.7/site-packages/cv2.so
    • または /usr/local/opt/opencv3/lib/python2.7/site-packages/cv2.so
  • OpenCV3 for Python3
    • /path/to/own-built-opencv3/lib/python3.5/site-packages/cv2.so

環境変数でシステムの設定自体をまとめて変える

g++関連の環境変数

  • OpenCV_DIR
    • OpenCV2 : /usr/local/opt/opencv/share/OpenCV/
    • OpenCV3 : /usr/local/opt/opencv3/share/OpenCV/
  • CPLUS_INCLUDE_PATH
    • OpenCV2 : /usr/local/opt/opencv/include/:$CPLUS_INCLUDE_PATH
    • OpenCV3 : /usr/local/opt/opencv3/include/:$CPLUS_INCLUDE_PATH
  • LIBRARY_PATH
    • OpenCV2 : /usr/local/opt/opencv/lib/:$LIBRARY_PATH
    • OpenCV3 : /usr/local/opt/opencv3/lib/:$LIBRARY_PATH
  • PATH
    • OpenCV2 : /usr/local/opt/opencv/bin:$PATH
    • OpenCV3 : /usr/local/opt/opencv3/bin:$PATH

Python関連の環境変数

OpenCV3のPython2バインドをHomebrewでインストール,OpenCV3のPython3バインドは自前ビルドしていると仮定する.
site-packagesにはcv2.soが存在するはず.
(/usr/local/opt/opencv/usr/local/opt/opencv3に同様のディレクトリがあればそちらでもOKかもしれない)

  • PYTHONPATH
    • OpenCV2 for Python2 : /usr/local/Cellar/opencv/2.4.13.2/lib/python2.7/site-packages/:$PYTHONPATH
    • OpenCV3 for Python2 : /usr/local/Cellar/opencv3/3.2.0/lib/python2.7/site-packages/:$PYTHONPATH
    • OpenCV3 for Python3 : /path/to/own-built-opencv3/lib/python3.5/site-packages:$PYTHONPATH
      • 自前でOpenCV3のPython3バインドをビルドし,ホームディレクトリ以下などの適当な場所に置いておく

OpenCV_DIRもOpenCVのバージョンに合わせて正しく設定しておいたほうがよい.

実例

システムの設定ごと変えるために~/.bash_profileに以下のようなスクリプトを書いた
(メッセージが邪魔ならechoの行を消す)

~/.bash_profile
# OpenCV version setting
OpenCV_VERSION="3.2.0"
export OpenCV_DIR=""
if [ "$OpenCV_VERSION" = "2.4.13.2" ]; then
  # OpenCV 2.4.13.2
  echo "OpenCV 2.4.13.2"
  export OpenCV_DIR="/usr/local/opt/opencv/share/OpenCV/"
  export CPLUS_INCLUDE_PATH="/usr/local/opt/opencv/include/:$CPLUS_INCLUDE_PATH"
  export LIBRARY_PATH="/usr/local/opt/opencv/lib/:$LIBRARY_PATH"
  export PATH="/usr/local/opt/opencv/bin:$PATH"
  # Python bindings (only Python 2)
  export PYTHONPATH="/usr/local/Cellar/opencv/2.4.13.2/lib/python2.7/site-packages/:$PYTHONPATH"
elif [ "$OpenCV_VERSION" = "3.2.0" ]; then
  # OpenCV 3.2.0
  echo "OpenCV 3.2.0"
  export OpenCV_DIR="/usr/local/opt/opencv3/share/OpenCV/"
  export CPLUS_INCLUDE_PATH="/usr/local/opt/opencv3/include/:$CPLUS_INCLUDE_PATH"
  export LIBRARY_PATH="/usr/local/opt/opencv3/lib/:$LIBRARY_PATH"
  export PATH="/usr/local/opt/opencv3/bin:$PATH"
  # Python binding (Python 2 or Python 3)
  PYTHON_VERSION="2"
  if [ "$PYTHON_VERSION" = "2" ]; then
    export PYTHONPATH="/usr/local/Cellar/opencv3/3.2.0/lib/python2.7/site-packages/:$PYTHONPATH"
  elif [ "$PYTHON_VERSION" = "3" ]; then
    # Own-built library
    export PYTHONPATH="/Users/username/usr/lib/python3.5/site-packages:$PYTHONPATH"
  else
    echo "Invalid Python version"
  fi
else
  echo "Invalid OpenCV version"
fi

OpenCV_VERSIONPYTHON_VERSIONを切り替えて再読み込みするとOpenCVのバージョンが切り替えられる.

Terminal
$ source ~/.bash_profile
OpenCV 3.2.0
$ 

切り替えられるか確認

g++

以下のC++コードをコンパイルする.

main.cc
#include <iostream>
#include <opencv2/core.hpp>

int main()
{
  std::cout << "version: " << CV_VERSION << std::endl;
}
Terminal
# OpenCV_VERSION="3.2.0"のとき
$ g++ main.cc -o main
$ ./main
version: 3.2.0

# OpenCV_VERSION="2.4.13.2"のとき
$ g++ main.cc -o main
$ ./main
version: 2.4.13.2

Python

import cv2して,cv2.__version__cv2.__file__を確認する.

Terminal
# OpenCV_VERSION="3.2.0"のとき
$ python
Python 2.7.13 |Anaconda custom (x86_64)| (default, Dec 20 2016, 23:05:08) 
>>> import cv2
>>> cv2.__version__
'3.2.0'
>>> cv2.__file__
'/usr/local/Cellar/opencv3/3.2.0/lib/python2.7/site-packages/cv2.so'

# OpenCV_VERSION="2.4.13.2"のとき
$ python
Python 2.7.13 |Anaconda custom (x86_64)| (default, Dec 20 2016, 23:05:08) 
>>> import cv2
>>> cv2.__version__
'2.4.13.2'
>>> cv2.__file__
'/usr/local/Cellar/opencv/2.4.13.2/lib/python2.7/site-packages/cv2.so'

おわりに

頑張れば with CUDA/with non-CUDA も切り替えられそう?