はじめに
pip install opencv-python
でインストールできるopencvにはGStreamerがついておらず、これを使ってrtspストリームをVideoCaptureするとラグがひどくてとてもリアルタイムとは呼べません。そこでGStreamerを使うために自前でビルドする必要が出てきますが、ビルドを完了すると20~30GBくらいディスクを食われます。こんなのよくないし、他のマシンにコピーだってできません。
この記事では、ビルドしたopencv(cv2フォルダ)をコピーするだけで他のマシンでも使用でき、ビルドに使ったファイルを削除しても問題ないように仕上げます。最終的に600MBくらいになりました。もっと詳しい人ならもっと小さくできるかもしれません。
また、僕の身の回りではpythonバージョンが乱立してるので、マルチバージョン対応(といってもそれぞれのバージョン用のビルドするというやっつけ仕様だが)にします。(ラップトップがPython3.9、仕事用PCには3.10、自宅用PCには3.11がインストールされちゃってます)
ビルドに必要なものの入手
以下を用意します。入手したzipは展開してください。個人的なおすすめは、CドライブにDevelopなどという名前のフォルダを作り、この中に用意したファイルを入れておきます。
- CMake:https://cmake.org/download/ より、make-x.xx.x-windows-x86_64.msiをDL。普通にインストールします。
- OpenCV:https://opencv.org/releases/ より、最新版のSourcesをDL
- OpenCV_contrib:https://github.com/opencv/opencv_contrib/tags よりOpenCVと同じバージョンをDL
- GStreamer:https://gstreamer.freedesktop.org/download/ よりWindowsタブ->x.xx.x runtime installerとx.xx.x development installerをDL。次でインストールします。
- (Visual Studio 2019:ビルドに必要です。)
gstreamerのインストール
runtimeもdevelopも、Completeでインストールします。
CMakeの設定
- OpenCVのパスを設定
- ビルド先のパスを設定(どこでもいい)
- Configureを押下
- 出てきたウィンドウではそのままFinishをクリック
- 以下のようにパラメーターを設定(適宜Searchを使うとよいでしょう):
OPENCV_EXTRA_MODULES_PATH=opencv-contribのmodulesフォルダ
BUILD_opencv_world=ON(なんとなく)
BUILD_SHARED_LIBS=OFF(とても大事(依存関係を一緒に含める))
GSTREAMER_~~をすべて設定(スクショ参照)
OPENCV_GAPI_GSTREAMER=ON(大事)
WITH_GSTREAMER=ON(大事)
PYTHON3_PACKAGES_PATH=C:/Develop/SiTePaCk(できるだけ変な名前/分かりやすい名前にする)
今回は、ソースもビルド先もD:/Develop/に置いてみました。SSD(Cドライブ)の空き容量に不安があったので大容量HDD(Dドライブ)にしただけで、深い意味はないのでみんなはCドライブでいいと思います。gstreamerがDドライブにインストールされているのはたまたまで、通常はCドライブにインストールされるはずです(つまりD:/gstreamer/~をC:/gstreamer/~に読み替えてください)。
PYTHON3_PACKAGES_PATH=C:/Develop/SiTePaCkと変な名前にする理由は、デフォルトだと現在アクティブなpythonのsite-packagesにインストールされてしまうからです。うっかりpip版のopencvが入っていると競合しそうなので、変な名前に設定することでそれを明示的に回避します。 - Configureを押下、その後Generateを押下(configureはしょっちゅう押してもいいらしい)
- 下の画面でビルドオプションを確認する。ダメそうなら設定を見直す。
Video I/OのGStreamerがYESになっていること
Python 3 のinstall path が変な名前のフォルダ/cv2/python3.x のようになっていること - Open Projectを押してVisual Studioを開く
- Releaseにする
- ビルド>ビルド>ALL_BUILDとINSTALL をビルドする(1時間はかかる)
使えるようにする
ビルドが正常終了すると、ビルド先のフォルダにたくさんのデータが(数十GB)、C:/Develop/SiTePaCk(変な名前を付けたフォルダ)にcv2
フォルダができているはずです(80MBくらい)。ビルド先のフォルダの中身はほとんど使いませんが、せっかくなのでbinフォルダの中のopencv_videoio_ffmpeg4xx_64.dll
をcv2フォルダにコピーしておきます。以下の記述はcv2フォルダについてのものです。
僕の環境では(仕事用PCのPython3.10でビルドしたため)、この中にconfig-3.10.py
とpython-3.10
フォルダの中にcv2.cp310-win_amd64.pyd
が居ました。ここからはpython3.10として書いていますが、皆さんのバージョンに合わせて適宜3.xと読み替えてください。
このパソコンのみで使用する場合はこのままで良いのですが、マルチバージョンにしたい場合は、新たに
python-3
フォルダ(名前はなんでもよい)を作り、その中にcv2.pc3x-(略).pyd
を移動させ、紛らわしいのでpython-3.x
フォルダは削除します。
ここで、コントロールパネル>プログラムのアンインストールから、GStreamer 1.0(Development Files)
をアンインストールします(デカくて邪魔なので)。GStreamer 1.0
はまだ残しておきます(これは必要です)。
マルチバージョンにしたい場合は、まだDevelopmentを使用するので先にビルドをしたほうがいいです
cv2/python3.10
フォルダに、C:/gstreamer/1.0/msvc_x86_64/bin
とC:/gstreamer/1.0/msvc_x86_64/lib
をフォルダごとコピーします。
フォルダ構造は次のようになります(一部抜粋):
└ SiTePaCk/
└ cv2/
├ python-3.10/
| ├ bin/
| ├ lib/
| └ cv2.cp310-win_amd64.pyd
├ config-3.10.py
└ ...
(ここまでできたら、ビルドしたマシンでは動作を確認できます。)
続いて、cv2ディレクトリのconfig-3.10.py
の内容を以下のように編集します。
import os
file_path=__file__ #このファイルのパスを取得
dir_path=os.path.dirname(file_path) #このファイルのあるフォルダまでのディレクトリ
PYTHON_EXTENSIONS_PATHS = [
os.path.join(dir_path, 'python-3.10') #相対パスに直す
] + PYTHON_EXTENSIONS_PATHS
BINARIES_PATHS = [ #gstreamerをコピーした理由はポータブルにするため
os.path.join(dir_path, 'python-3.10', 'bin')
] + BINARIES_PATHS
マルチバージョンにしたいときは、config-3.pyなどを新たに作り、これをコピペして'python-3'に直します。
また、__init__.py
に
'config-{}.{}.py'.format(sys.version_info[0], sys.version_info[1]),
という行があるのですが、これは現在実行中のpythonバージョンに合わせて参照ファイルを変えていますので、これを
'config-3.py',
にしちゃいます。
ここで気を付けなければならないのが、後から別バージョン用にビルドすると、__init__.py
が書き換えられてもとに戻ってしまうので、ビルド後には確認するようにしてください。
config-3.pyができれば、もうconfig-3.10.pyはいらないので消しちゃいましょう。
ここでcp932コーデックが云々というエラーが出たので直します。本編とは関係ないです
なんか意味不明なエラーが出たので直します
File "path\to\cv2\load_config_py3.py", line 8, in exec_file_wrapper
code = compile(f.read(), os.path.basename(fpath), 'exec')
^^^^^^^^
UnicodeDecodeError: 'cp932' codec can't decode byte 0x86 in position 22: illegal multibyte sequence
こうやって直すらしい
control.exe -> 地域 -> [管理]タブ -> システム ロケールの変更 -> ベータ: ワールドワイド言語サポートでUTF-8を使用
使ってみる
自前でビルドしたはいいものの、依存関係がないと動かないと思うので、いったん普通にpip install opencv-python
をしたほうがいいと思います。
site-packages
のcv2
フォルダは、僕はとりあえずcv2-original
とリネームして保持しておきました。
site-packages
に自前でビルドしたcv2
フォルダをコピーすれば完成です。普通にコマンドプロンプトからpythonを起動し、
import cv2
print(cv2.getBuildInformation())
などで動作を確認してみます。実際に
cap=cv2.VideoCapture("rtspsrc location=rtsp://ip-address:port latency=0 ! decodebin ! videoconvert ! appsink", cv2.CAP_GSTREAMER)
ができることを確認しましょう。もし動かない場合はProcess Monitorが便利です。
マルチバージョンにする
僕の環境では自宅用PCでもラップトップでも動作させたいので、追加でpython3.9用とpython3.11用にもビルドします。このとき、gstreamerのdevelopmentをアンインストールしちゃった人はもう一回インストールしましょう。
ビルドするマシンにターゲットとなるバージョンのpythonをインストールしましょう。(ここで多分3.9.y、3.11.yなどの孫バージョンは問わないと思います。)
https://www.python.org/downloads/windows/ から目的のバージョンのWindows installer (64-bit)をダウンロードします(embedじゃダメです。見つからない場合はCtrl+Fを使いつつ、下にスクロールしてみましょう。)
ビルド用に一時的にインストールするだけなので、Customize installationを選びます。
いらないのでチェックは全部外しちゃいます。
次の画面でもチェックを全部外し、インストール場所を好きな場所(C:/Develop/ など)にします。(たまたま今回はDドライブにしましたが、みんなはCドライブで良いと思います。)
次にcmakeの設定を別のバージョンのpython用に書き換えます。
いったんcmakeを終了させておきます。
ビルドフォルダ(C:/Develop/BUILD_410GST など)にあるCMakeCache.txt
を開き、pythonのバージョンが書いてあるところを修正していきます。
例えばC:/Users/ユーザー名/AppData/Local/Programs/Python/Python310/python.exe
をC:/Develop/Python311/python.exe
に変えたり、
Python310/include
をPython311/include
に、
Python310/libs/python310.lib
をPython311/libs/python311.lib
に、
3.10.5
と書かれているところを3.11.9
にしたりします。
エディタの検索機能でython310
や3.10
などで検索し、必要に応じてython311
や3.11
、3.11.9
などにします(大文字小文字区別のないp'ython'で検索すると良いでしょう)。一つ注意なのは、numpyのincludeディレクトリのパスにPython310
が入っていてもここは変更しないでください。numpyのバージョンはそろえておきます。
全部できたらCMake GUIを起動し、Configureを押下します。下の画面(⑦)のPythonの項目で目的のPythonバージョンになっているか確認したらGenerateしてOpen Project、ALL_BUILDとINSTALLをビルドします。2回目なので1回目ほど時間はかからないはずです。
この作業を目的のpythonバージョン分繰り返し、目的のcv2.cp3x-win_amd64.pyd
ができたらpython-3
フォルダにコピーしちゃいます。__init__.py
が毎回もとに戻されてしまうので、
'config-{}.{}.py'.format(sys.version_info[0], sys.version_info[1]),
を
'config-3.py',
にしちゃいます。