OpenCV 3(core + contrib)をWindows & Python 3の環境にインストール&OpenCV 2とOpenCV 3の違い&簡単な動作チェック

  • 60
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

OpenCV(Open Source Computer Vision Library)はBSDライセンスの映像/画像処理ライブラリ集です。画像のフィルタ処理、テンプレートマッチング、物体認識、映像解析、機械学習などのアルゴリズムが多数用意されています。

OpenCVを使った動体追跡の例 (OpenCV Google Summer of Code 2015)
https://www.youtube.com/watch?v=OUbUFn71S4s

pipは、Python 3.3以降からPython標準ライブラリの1つになったPythonのパッケージ管理ツールです。
本ページでは、Python 3.5にOpenCVパッケージとPyNumパッケージのみ追加して、OpenCVを試してみるための環境構築について説明します。

OpenCVのインストール方法の動向

Anaconda → OpenCV の順にインストールするのが最近の流れのようです。
簡単にpython3とOpenCV3を導入する

でも、「Anacondaって巨大だよね。」とか、「Anacondaを入れると、今までのpip環境はどうなるの?」とか、Anacondaを使っていない私の環境に与える影響がよくわからなかったので、pipでOpenCVのインストールを試みてみました。

  • 調査対象の環境

    • Windows 10(Intel Core i5)
    • Python 3.5.1(pythonとpipは予めインストール済み)
    • OpenCV 3.1.0(core + opencv_contrib)
  • 結果
    pipを使た簡単なモジュール追加で、上記環境が問題なく動作しました。

pipを使ったOpenCV 3.1.0(core + opencv_contrib)のインストール

  • ダウンロード
    リンク(http://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv) から opencv_python-3.1.0+contrib_opencl-cp35-cp35m-win32.whl をダウンロードします。
     
  • インストール
    pip installコマンドでインストールします。
    • 32bit版Pythonの場合
      bash $ pip install opencv_python-3.1.0+contrib_opencl-cp35-cp35m-win32.whl
    • 64bit版Pythonの場合
      bash $ pip install opencv_python-3.1.0+contrib_opencl-cp35-cp35m-win_amd64.whl
       
  • バージョンを確認

    $ python
    Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:38:48) [MSC v.1900 32 bit     (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import cv2
    >>> cv2.__version__
    '3.1.0'
    >>> exit()
    
  • OpenCV 3.1.0 の各種サンプル

    • ダウンロード
      OpenCVのGitHubからダウンロードします。
      https://github.com/opencv
    • 展開
      opencv → releases → OpenCV 3.1 → Downloads → opencv-3.1.0.exe → 実行 → 展開フォルダを指定 → Extract
      サンプル(写真、動画)は、以下に格納されています。
      opencv\sources\samples\data
       
  • NumPyのインストール

    PythonでOpenCVを使う場合、行列計算/数値計算ライブラリNumPyも必要になることが多いので、あわせてインストール。

    $ conda install numpy
    

     

  • Anaconda + opencv_ontrib付きのOpenCV
    Anacondaにopencv_contrib付きのOpenCVをインストールする方法も参考までに載せておきます。
    Anacondaをインストール後、下記でopencv_contrib付きのOpenCVをインストールすることができます。

    conda install -c https://conda.anaconda.org/menpo opencv3

    インストールされたOpenCVのライブラリは以下のディレクトリに展開されています。

    ~/Anaconda3/pkgs/opencv3-3.1.0-py35_0/Library/bin

    ディープラーニングのライブラリ(opencv_dnn310.lib)やディープフローも可能なオプティカルフローのライブラリ(opencv_optflow310.lib)がインストールされていることが分かります。
     

  • OpenCV 3のAPI一覧
    こちらを参考にしてください。⇒ OpenCV3のPython API一覧

OpenCV 2.4とOpenCV 3.xの違い

OpenCV 2.4のサンプルプログラムをOpenCV 3.5で動かしてみて気づいた部分がいくつかあるのであげておきます。

  • cv2.cvがなくなった
    OpenCV 2.4では、

    import cv2.cv as cv
    

    というコードがスクリプトの先頭によく登場していましたが、OpenCV 3.xではなくなったようです。
    これをOpenCV 3.xで書くとこんなエラーがでます。

    Traceback (most recent call last):
      File "~\sample.py", line 4, in <module>
        import cv2.cv as cv
    ImportError: No module named 'cv2.cv'; 'cv2' is not a package
    
  • メソッド名が変更された
    例えば、OpenCV2.4のcv2.cv.CV_FOURCCが、OpenCV3.1ではcv2.VideoWriter_fourccに変わっています。

    opencv2.4.py
    import cv2.cv as cv
    cv.CV_FOURCC('X', 'V', 'I', 'D')
    
    opencv3.1.py
    import cv2
    cv2.VideoWriter_fourcc(*'XVID')
    

    もし、OpenCV2.xとOpenCV3.xで共通で動作するプログラムにしなければいけない場合は、以下のように自分で同等のメソッドを定義しなければならなりません。
    例)

    opencv2.4_3.1.py
    # cv2.cv.CV_FOURCC, cv2.VideoWriter_fourcc
    def cv_fourcc(c1, c2, c3, c4):
        return (ord(c1) & 255) + ((ord(c2) & 255) << 8) + \
            ((ord(c3) & 255) << 16) + ((ord(c4) & 255) << 24)
    
    cv_fourcc('X', 'V', 'I', 'D')
    

    もしくは、ビデオのコーデックがプログラム内で決まっている場合は、これでOKです。

    opencv3.1.py
    XVID = 0x44495658
    

    他のコーデックについては、こちらの記事にまとめましたので(中ほどの「コーデックの指定方法」の章)、必要な方は参考にしてください。
    コーデックとFOURCC対応表
     

  • 非標準ライブラリopencv_contribに移動したメソッドがある
    代表的なものは、updateMotionHistory(...)calcGlobalOrientation(...)でしょうか。
    OpenCV 2.4ではこうでしたが、

    cv2.updateMotionHistory(...)
    cv2.calcGlobalOrientation(...)
    

    OpenCV 3.xでは、opencv_contribのmotemplに移動したため、opencv_contribをインストールし以下のように書く必要があります。

    cv2.motempl.updateMotionHistory(...)
    cv2.motempl.calcGlobalOrientation(...)
    

    OpenCV 2.xのときと同じように、OpenCV 3.xに対して cv2.updateMotionHistory(...) と書くと、以下のエラーがでます。

    Traceback (most recent call last):
      File "~\sample.py", line 10, in <module>
        cv2.updateMotionHistory(...)
    AttributeError: module 'cv2' has no attribute 'updateMotionHistory'
    
  • 消えた定数がある
    線や丸を描くときにアンチエイリアスを指定する定数cv2.CV_AAがOpenCV 3.xでは定義がなくなりました。cv2.CV_AAを指定すると以下のエラーが表示されます。

    AttributeError: module 'cv2' has no attribute 'CV_AA'
    

    アンチエイリアスを指定する場合は、プログラム内で直接、値を定数定義すると、この問題を回避することができます。

    CV_AA = 16
    

    また、πの値を格納した定数cv2.CV_PIもOpenCV 3.xでは定義がなくなりました。cv2.CV_PIを指定すると以下のエラーが表示されます。

    AttributeError: module 'cv2' has no attribute 'CV_PI'
    

    OpenCVで定数πといえば、「度 → ラジアン」、「ラジアン → 度」といった角度の変換でよく使用すると思います。
    実は、Pythonは、これらの定数や変換メソッドを標準ライブラリで提供しています。OpenCVの定数πではなく、Pythonが標準で提供している定数πを利用すれば、OpenCV 3.xで定数πの定義がなくなった問題を回避することができます。

    import math
    # 定数π : 3.141592653589793
    math.pi
    # 度 → ラジアン 変換
    math.radians([deg])
    # ラジアン → 度 変換
    math.degrees([rad])
    
  • バグで動作しないメソッドがある
    OpenCV 2では動作していたメソッドが、OpenCV 3に移行する際にバグで動作しなくなってしまっているケースがありました。
    顔認識で使うcv2.faceモジュールのFaceRecognizerのpredict()メソッドが、この記事を書いている時点の最新正式版(opencv_contrib ver.3.1.0 2015/12/18 Release)では動作しませんでした。
    実行するとpredict()メソッドの行で以下のエラーがでます。

    TypeError: 'int' object is not iterable

    2016/4/21に修正がGitHubにコミットされましたので、最新のソースコードをGitHubからダウンロードし、自分でコンパイルしなければならないようです。

    • バグを指摘している質問サイト (リンク
    • 解決方法を書いたサイト (リンク
    • 2016/4/21にGitHubに入った修正 (リンク
    • Repository for OpenCV's extra modules (リンク
  • チュートリアルが動作しない

    • OpenCV 3 for Pythonのチュートリアル(リンク
      OpenCV 3 for Pythonのチュートリアルは、OpenCV 2のままになっています。
      動作しないのでみんな困っていますが、放置されたままです。
      例えば、特徴量マッチングのチュートリアル。
      http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_matcher/py_matcher.html
      FLANN based Matcherのサンプルを実行してみると下記の行でエラーが発生します。

      matches = flann.knnMatch(des1,des2,k=2)

      # 以下のエラー発生
      # error: C:\dev\opencv-3.1.0\modules\python\src2\cv2.cpp:163: error: (-215) The data should normally be NULL! in function NumpyAllocator::allocate

OpenCV 3の簡単な動作チェック

OpenCV 3でカラー画像をグレースケールに変換するプログラムを作成してみます。

readImage.py
import cv2

filename = "sample.png"
img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
cv2.imshow('window title', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

imread(filename, flags)の第1引数にはファイル名を指定します。
対応しているファイルフォーマットは以下になります。

フォーマット 拡張子
Windowsビットマップ BMP, DIB
JPEG JPEG, JPG, JPE
JPEG 2000 JP2
Portable Network Graphics PNG
TIFF TIFF, TIF
Portable Anymap Format PBM, PGM, PPM
Sunラスタ形式 SR, RAS

imread(filename, flags)の第2引数は以下から選択します。

定数 意味
cv2.IMREAD_UNCHANGED -1 無変換(αチャネルも保持)
cv2.IMREAD_GRAYSCALE 0 グレー(8bit 1チャンネル)
cv2.IMREAD_COLOR 1 カラー(8bit 3チャンネル)
cv2.IMREAD_ANYDEPTH 2 任意の深度
cv2.IMREAD_ANYCOLOR 3 任意のカラー

今回は、カラー→グレー 変換をするので、cv2.IMREAD_GRAYSCALE を選択します。

imshow()の第1引数は、ウィンドウのタイトルを指定します。

sample.png
元画像(カラー):sample.png

スクリプトを実行すると、カラー → 白黒変換 された画像が別ウィンドウに表示されます。
ウィンドウがアクティブな状態(フォーカスがあたった状態)で何かキーを押すとウィンドウが閉じてスクリプトが終了します。

Gray.png
グレースケール化した画像

Anacondaをインストールしませんでしたが、既にpipがインストールされている場合は、pipを使った簡単なモジュール追加で、OpenCVが動作するようです。また、python3で問題はないようです。

イメージの中身を見てみる

OpenCVでは、画像をNumpyライブラリのnumpy.ndarray(N-dimensional array)という単位で扱います。
Python標準のリストは、内部で要素をリストでつないでいますが、ndarrayはC言語の配列のように固定長なため、以下のような違いがあります。
+ 大量のデータを効率的に扱うことができます。
+ 配列内の要素はすべて同じデータ型である必要があります。
+ 各次元ごとの要素数が等しくなくてはなりません。
+ 配列長を変更する場合は元の配列を削除して新しく配列を作り直します。

それでは、下記のような5×2ピクセルの画像がndarrayではどのようになるのか見てみます。

color_l.png
カラー画像

ndarray.py
import cv2

filename_c = "color.png"
array_c = cv2.imread(filename_c, cv2.IMREAD_COLOR)
print("===== color image array =====")
print(array_c)

print("")

filename_g = "gray.png"
array_g = cv2.imread(filename_g, cv2.IMREAD_GRAYSCALE)
print("===== gray image array =====")
print(array_g)
===== color image array =====
[[[ 36  28 237]
  [  0   0   0]
  [ 36  28 237]
  [255 255 255]
  [ 76 177  34]]

 [[ 76 177  34]
  [204  72  63]
  [127 127 127]
  [204  72  63]
  [ 36  28 237]]]

OpenCVでは、BGRの順にピクセルデータが格納されます。Webの世界ではRGBの順が標準なので注意が必要です。なぜRGBではなくBGRなのかは、こちらのリンクを参照してください。

color_gry.png
グレー画像

===== gray image array =====
[[138   0 138 255 142]
 [142  98 127  98 138]]

カラー画像は3次元、グレー画像は2次元の配列になっていることが分かります。

参考情報

下記、チュートリアルを参考にしました。
OpenCV本家
Qiita日本語訳

★ matplotlib をインストールしたい場合は、やはり Anaconda がおすすめです。

つづく

次は、画像のエッジを検出してみます。
http://qiita.com/olympic2020/items/2c3a2bfefe73ab5c86a4