Python bindingのエラーを修正しながら仕組みを追う気の遠くなるような長い長い旅

# はじめにのはじめに

本記事は超絶マニアックな誰得な作業ログです。読者を置いていくことが目標と言っても過言ではありません。記事のクオリティの低さたるや、格別です。

さて、pythonからOpenCVを使うというのは大分一般的になってきたと思います。ここで、多くの人は配布されているバイナリを使っていますが、contribや動画処理など、デフォルトでは入っていない機能を使おうとすると、ビルドが必要になります。

すると、大抵python bindingでコケて沼にはまります。コケた際に、OpenCVのcmakeファイルを読んで自力で解決している人は、非常に少ないのでしょうか。でも、**人生、cmakeファイルを読まなくてはいけない時があるんです**。本記事は、そんな時に、俺はこうやって解決した！という作業ログです。人それぞれエラーは違うので、そのまま適用できるケースは無いと思いますが、気合だけでも伝わればと思います。

~~ちなみにマニュアルを読めば早(ry~~

# はじめに

よくこんな質問が寄せられます。
Q: OpenCVをビルドしたいのに、python bindingで失敗する

答えは、
A: cmake fileを読む
です。

失敗ケースとしては、condaを使ったら動かない、Macだと動かない・・・など色々ありますが、今回は各ケースに対する優しいケーススタディではなく、cmakeをガチムチで読むという話です。

# 最初のビルド

まずは成功画面、cmakeするとこんな感じでpython-bindingに成功します。

```
$ mkdir build
$ cd build
$ cmake ..
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/97f80d12-33eb-7763-291a-af9c5b5511a6.png)

という事で、めでたし！・・という感じで記事を締めたいところですが、多くの場合はこんな感じで失敗します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/2073709e-e61e-718c-839c-a9d0c2ceeada.png)

よくある原因は、conda内のpythonを使っていると、OpenCVがリンクを見つけられない事に起因します。こんな時の調査手順を載せます。なお、今回は、ワザと失敗させているため、色々未インストールのものとかも準備しておき、**ログに出ても気づかなかった事にします**。

# 失敗表示されている場所

エラーメッセージでひとまずgitリポジトリ内を検索するとroot dierectory直下のCMakeLists.txtの最後の方にこんな記述が見られます。

```CMakeList.txt
if(BUILD_opencv_python3)
status("")
status("  Python 3:")
status("    Interpreter:"     PYTHON3INTERP_FOUND  THEN "${PYTHON3_EXECUTABLE} (ver ${PYTHON3_VERSION_STRING})"       ELSE NO)
if(PYTHON3LIBS_VERSION_STRING)
  status("    Libraries:"   HAVE_opencv_python3  THEN  "${PYTHON3_LIBRARIES} (ver ${PYTHON3LIBS_VERSION_STRING})"   ELSE NO)
else()
  status("    Libraries:"   HAVE_opencv_python3  THEN  "${PYTHON3_LIBRARIES}"                                      ELSE NO)
endif()
status("    numpy:"         PYTHON3_NUMPY_INCLUDE_DIRS THEN "${PYTHON3_NUMPY_INCLUDE_DIRS} (ver ${PYTHON3_NUMPY_VERSION})" ELSE "NO (Python3 wrappers can not be generated)")
status("    packages path:" PYTHON3_EXECUTABLE         THEN "${PYTHON3_PACKAGES_PATH}"                                    ELSE "-")
endif()
```

ふむふむ、Librariesとnumpyが見つからないと言われているということは、```HAVE_opencv_python3```と```PYTHON3_NUMPY_INCLUDE_DIRS```が空か、OFFになっているっぽいな、となります。

念のため、この付近で、上記２変数を表示させて見ましょう。

````CMakeList.txt
if(BUILD_opencv_python3)
  status("HAVE_open_CV3????? ${HAVE_opencv_python3}")
  status("NUMPY dir????? ${PYTHON3_NUMPY_INCLUDE_DIRS}")
  status("")
```

とすると、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/18626005-06a9-642b-4ec7-72144342558f.png)

と表示されました。というわけで、```HAVE_opencv_python3```をONにするのと、```PYTHON3_NUMPY_INCLUDE_DIRS```にディレクトリ名を設定する旅に出ましょう。

注意点として、今回はcmakeファイルをいじりながらログを確認していきますが、**前回時のcmakeのログが残ってしまうため、チェックの際はbuildディレクトリ以下は毎回全部消した方が確実です。**

# HAVE_opencv_python3をONにする旅

さて、また同じように、gitリポジトリ内を検索してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/d5fd0907-f9a6-8ff2-90c6-403ef3de4004.png)

　無い・・・・だと・・・・？

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/317e9d6a-dc80-b8e6-a1cf-f40cf546209a.png)

冗談です。頑張ります。手がかりを探すため、まずはCMakeLists.txtの中からpythonを検出している入り口を探しに行きます。すると、こんな記述が・・・！

```CMakeList.txt
# --- Python Support ---
if(NOT IOS)
  include(cmake/OpenCVDetectPython.cmake)
endif()
```

さて、ここでPythonを探しているかを確認するため、この前後で、変数```HAVE_opencv_python3```と```PYTHON3_EXECUTABLE```がどのように変化しているかを見てみましょう。

```CMakeList.txt
if(NOT IOS)
status("HAVE_open_CV3????? ${HAVE_opencv_python3}") <- HAVE_opencv_python3を表示
status("exec????? ${PYTHON3_EXECUTABLE}") <- PYTHON3_EXECUTABLEを表示
include(cmake/OpenCVDetectPython.cmake)
status("HAVE_open_CV3????? ${HAVE_opencv_python3}")
status("exec????? ${PYTHON3_EXECUTABLE}")
endif()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/367d1bc5-87fe-edff-2181-0337a10d20b8.png)

上の????とあるところでは、exec側が何も設定されていませんが、下では```/opt/conda/bin/python3/```が設定されています。というわけで、ここで何かが起きていることは確認できます。なお、```HAVE_opencv_python3```はこの段階ではまだ何も入っておらず、この行より下で、何かのフラグに従ってON/OFFが決まる模様です。どこで```HAVE_opencv_python3```が生成されたかを引き続き探りましょう。と言ってもpythonの文字も特になく手がかりがありません。

**各行に、messageを入れてログを確認しまくります。**

```
message("1: HAVE_open_CV3????? ${HAVE_opencv_python3}")
```

こんな感じのコードを入れまくって、OFFに切り替わる瞬間を探します。・・・すると、以下の所でOFFフラグが生成されることがわかります。

```CMakeList.txt
# OpenCV modules
message("321: HAVE_open_CV3????? ${HAVE_opencv_python3}")
add_subdirectory(modules)
message("322: HAVE_open_CV3????? ${HAVE_opencv_python3}")
```

一番上では、HAVE_open_CV3にはフラグが入っていませんが、一番下では```OFF```が入力されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/56da6df3-02ab-c667-bc27-6e2d3cc28f50.png)

ということで、

```
add_subdirectory(modules)
```

がキーであることが分かります。まずはここを深掘って、```HAVE_opencv_python3```が切り替わる瞬間を探しましょう。modulesディレクトリ内のCMakeファイルを確認すると、内容はとてもシンプルで、

```opencv/modules/CMakeLists.txt
add_definitions(-D__OPENCV_BUILD=1)

if(NOT OPENCV_MODULES_PATH)
  set(OPENCV_MODULES_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
endif()

ocv_glob_modules(${OPENCV_MODULES_PATH} EXTRA ${OPENCV_EXTRA_MODULES_PATH})
```

となっています。```ocv_glob_modules```が具体的に何かを処理しているようですね・・・ということで検索。・・・すると、```cmake/OpenCVModule.cmake```の中で定義されているようです。中を軽く読んでみましょう。

長いけど、今回はHAVE_を探す旅なので、細かいところは飛ばしつつ、ファイル全体を見て行きましょう。とりあえず、ざっくりと```HAVE```の文字を探すと、たくさんヒットする。ここのどこかで```HAVE_opencv_python3```がON/OFFされる予感がします。さて、ocv_glob_modules関数を見てみると、大まかに、collect modules, ```__ocv_resolve_dependencies```, create modulesから成っています。最初と最後は、add_subdirectoryで飛ばしているだけ、```__ocv_resolve_dependencies```が怪しそうなので中を見てみましょう。

すると、すぐ見つかりました。

```cmake/OpenCVModule.cmake
  foreach(m ${OPENCV_MODULES_DISABLED_USER})
    set(HAVE_${m} OFF CACHE INTERNAL "Module ${m} will not be built in current configuration")
  endforeach()
  foreach(m ${OPENCV_MODULES_BUILD})
    set(HAVE_${m} ON CACHE INTERNAL "Module ${m} will be built in current configuration")
  endforeach()
```

ここが、怪しい。ということで、お決まりのmessageチェックをしてみましょう。前後をさっきのmessageコマンドで挟む。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/e0d81e99-39e3-df2d-df86-e514b15b2793.png)

...人生は厳しい

ここに来た時点で、既にOFFが入っていた。もう少し前に戻ってみよう。最初のブロックのどこかがターゲットなので、ひたすらmessageを入れる。結果として、ここがターゲットであることが分かりました。

```cmake/OpenCVModule.cmake
  message("4 HAVE_open_CV3 in ocv_resolve_dependencies ????? ${HAVE_opencv_python3}")
message("${__modpath} ${CMAKE_CURRENT_BINARY_DIR}/${mod}/.${mod}")
            add_subdirectory("${__modpath}" "${CMAKE_CURRENT_BINARY_DIR}/${mod}/.${mod}")
  message("5 HAVE_open_CV3 in ocv_resolve_dependencies ????? ${HAVE_opencv_python3}")
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/54c40751-63cd-5a23-0f7a-d243de04a4c5.png)


何をやっているか見てみましょう。

```
message("${__modpath} ${CMAKE_CURRENT_BINARY_DIR}/${mod}/.${mod}")
```

とすると・・・

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/f71250ad-365b-a1fb-1d46-8cd280541681.png)

みたいな感じで、```/opencv/modules/python```というディレクトリをaddすると、目的のフラグがON/OFFになるらしい。なお、後者の```.python```はadd_subdirectoryの定義上ここでは不要。というわけで、```/opencv/modules/python```を覗きましょう。

まず、```/opencv/modules/python```を見ると、CMakeLists.txtがいますので、ここの中に入って見ましょう。念のため、入り口と出口で目的のフラグが変化するかを確認するため、messageデバッグしましょう。ファイルの先頭と、最後でメッセージを表示させる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/9a1e7ac5-aaa3-d8f7-fa29-ffd0ae8557bf.png)

というわけで、このどこかで目的のフラグがON/OFFされているらしいことが分かる。いつものようにmessageを出しまくって確認すると、

```
add_subdirectory(python3)
```

でフラグが変わることが分かる。さて、```/opencv/modules/python/python3```ディレクトリを漁って行きましょう。

```/modules/python/python3/CMakeLists.txt
message("in /modules/python/python3/CMakeLists.txt 1 ????? ${HAVE_opencv_python3}")
if(NOT PYTHON3_INCLUDE_PATH OR NOT PYTHON3_NUMPY_INCLUDE_DIRS)
  ocv_module_disable(python3)
endif()
message("in /modules/python/python3/CMakeLists.txt 2 ????? ${HAVE_opencv_python3}")

set(the_description "The python3 bindings")
set(MODULE_NAME python3)
set(MODULE_INSTALL_SUBDIR python3)

set(PYTHON PYTHON3)

message("in /modules/python/python3/CMakeLists.txt 3 ????? ${HAVE_opencv_python3}")
include(../common.cmake)

message("in /modules/python/python3/CMakeLists.txt 4 ????? ${HAVE_opencv_python3}")
unset(MODULE_NAME)
unset(MODULE_INSTALL_SUBDIR)

message("in /modules/python/python3/CMakeLists.txt head ????? ${HAVE_opencv_python3}")
if(MSVC)
  ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
else()
  ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-declarations)
endif()
message("in /modules/python/python3/CMakeLists.txt head ????? ${HAVE_opencv_python3}")
```

こんな感じで、ところどころmessageを入れて、cmakeすると最初のmessageの時点で

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/3a633973-a644-93d6-16a9-5385cf5d63e6.png)

と、一行表示されただけで他の行まで行きませんでした。なので、```PYTHON3_INCLUDE_PATH```か```PYTHON3_NUMPY_INCLUDE_DIRS```が定義されていないと、ここで終了となるようです。

```/modules/python/python3/CMakeLists.txt
if(NOT PYTHON3_INCLUDE_PATH OR NOT PYTHON3_NUMPY_INCLUDE_DIRS)
  ocv_module_disable(python3)
endif()
```

さて、フラグがセットされて、終了する様子を確認しましょう。```ocv_module_disable```を探して見てみると・・・

```opencv/cmake/OpenCVModule.cmake
set(HAVE_${__modname} OFF CACHE INTERNAL "Module ${__modname} can not be built in current configuration")
```

という感じで```HAVE_opencv_python3```がOFFにされるのを確認できました。

さて、ここで目的は、```PYTHON3_INCLUDE_PATH```の設定と、```PYTHON3_NUMPY_INCLUDE_DIRS```の設定に変わります。これらの変数に何が入っているか、```/modules/python/python3/CMakeLists.txt```の先頭に以下を追加して確認すると・・・

```/modules/python/python3/CMakeLists.txt
message("PYTHON3_INCLUDE_PATH ${PYTHON3_INCLUDE_PATH}")
message("PYTHON3_NUMPY_INCLUDE_DIRS ${PYTHON3_NUMPY_INCLUDE_DIR}")
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/767ecb5b-8a11-beba-3c76-4365dd3a8e9b.png)

てな感じで、NUMPYが未設定となっています。つまり**Numpyを先に入れないと、```HAVE_opencv_python3```のチェックまで進めない**ことが分かります。

ちなみに、PYTHON3_INCLUDE_PATHが入っていない場合、apt-getなどでpythonを入れている場合は、python-devを入れれば、ここに値が入るはず。入らなければ、頑張って探しましょう！

# 進路変更、PYTHON3_NUMPY_INCLUDE_DIRを入れる旅に出る

さて、これについては、最初から最後まで何も設定されないので手掛かりがありません。とりあえず検索してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/5400ec59-e41d-591a-43e2-b2b136ad91d4.png)

なお、rootなのはDockerで作業しているからです。この中で、今まで通ってきた経路を選びましょう。怪しいのは、

```
cmake/OpenCVDetectPython.cmake
modules/python/common.cmake
```

でしょう。他のファイルは、これまでに確認済みで、NUMPYに設定するような記述はなかったはず。また、後者は、実は```opencv/modules/python/python3/CMakeLists.txt```の真ん中でincludeされており、まだ通っていない。という訳で、```cmake/OpenCVDetectPython.cmake```を読みましょう。

さて、ザーッと読んでみると、こんな構成です。

```opencv/cmake/OpenCVDetectPython.cmake
function(find_python preferred_version min_version library_env include_dir_env
         found executable version_string version_major version_minor
         libs_found libs_version_string libraries library debug_libraries
         debug_library include_path include_dir include_dir2 packages_path
         numpy_include_dirs numpy_version)
.
.
.
endfunction(find_python)

find_python(2.7 "${MIN_VER_PYTHON2}" PYTHON2_LIBRARY PYTHON2_INCLUDE_DIR
    PYTHON2INTERP_FOUND PYTHON2_EXECUTABLE PYTHON2_VERSION_STRING
    PYTHON2_VERSION_MAJOR PYTHON2_VERSION_MINOR PYTHON2LIBS_FOUND
    PYTHON2LIBS_VERSION_STRING PYTHON2_LIBRARIES PYTHON2_LIBRARY
    PYTHON2_DEBUG_LIBRARIES PYTHON2_LIBRARY_DEBUG PYTHON2_INCLUDE_PATH
    PYTHON2_INCLUDE_DIR PYTHON2_INCLUDE_DIR2 PYTHON2_PACKAGES_PATH
    PYTHON2_NUMPY_INCLUDE_DIRS PYTHON2_NUMPY_VERSION)

find_python(3.4 "${MIN_VER_PYTHON3}" PYTHON3_LIBRARY PYTHON3_INCLUDE_DIR
    PYTHON3INTERP_FOUND PYTHON3_EXECUTABLE PYTHON3_VERSION_STRING
    PYTHON3_VERSION_MAJOR PYTHON3_VERSION_MINOR PYTHON3LIBS_FOUND
    PYTHON3LIBS_VERSION_STRING PYTHON3_LIBRARIES PYTHON3_LIBRARY
    PYTHON3_DEBUG_LIBRARIES PYTHON3_LIBRARY_DEBUG PYTHON3_INCLUDE_PATH
    PYTHON3_INCLUDE_DIR PYTHON3_INCLUDE_DIR2 PYTHON3_PACKAGES_PATH
    PYTHON3_NUMPY_INCLUDE_DIRS PYTHON3_NUMPY_VERSION)
```

ここで、pythonを探してるらしいことはわかります。```find_python```の定義をよんでみると、

```opencv/cmake/OpenCVDetectPython.cmake
#   numpy_include_dirs (variable): Output of found Python Numpy include dirs
#   numpy_version (variable): Output of found Python Numpy version
```

という記述が。という訳で、numpy_include_dirsに値がセットされているタイミング、条件を確認してみます。

まず、明らかに中間にある

```opencv/cmake/OpenCVDetectPython.cmake
set(_numpy_include_dirs ${${numpy_include_dirs}})
```

が怪しいですね。```_numpy_include_dirs```を追っかけると、すぐ下に、

```opencv/cmake/OpenCVDetectPython.cmake
execute_process(COMMAND "${_executable}" -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))"
                          RESULT_VARIABLE _numpy_process
                          OUTPUT_VARIABLE _numpy_include_dirs
                          OUTPUT_STRIP_TRAILING_WHITESPACE)
```

という表記が！という訳で、ここにデバッグコードを入れて何をやっているか確認してみましょう。

```
message("${_executable} -c import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))")
```

というのを直前に入れると、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/8afd0ad1-4751-bebc-c559-f581f591b4a7.png)

と出ました。ということで、numpyを呼び出そうとしたら、import errorが出ていることが確認できました。そこで、ようやくnumpyをインストールしてみます！（**そんくらい先にやっとけというツッコミは、今回はそういう記事なので・・・**ということで）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/25b4eb49-a1c3-e4b7-9026-371619afd3f6.png)

無事、エラーが消えました！さて、PYTHON3_NUMPY_INCLUDE_DIRがセットされたかを確認しましょう。一番最初のCMakeの画面に戻ると・・・・

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/bf88ab13-0a64-9bd4-3b47-677ea4902d70.png)

numpyに値がセットされていました！！めでたし！さて、困ったことに、実はこれだけが原因だったらしく、pythonが認識されてしまいました。これだけだとnumpyインストールするだけかよ！となってしまいます。

ちなみに、結局```HAVE_opencv_python3```がどこでON/OFFになるか見つける前に動いてしまった。

**が、ここまでは初心者コース、macに鞍替えしてもう一回やってみましょう**。

# Macでやってみる。

めちゃめちゃ汚い環境と化している手元のMacでもう一度確認してみますと、この有様。何も見つからない、素晴らしいですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/10197a10-f5c1-4941-8448-0782161ca42e.png)

pythonはどこに行ったレベル。ちなみにnumpyもpythonも入っています。さて、もう一度同じ手順を踏む訳ですが、**正直全部書くのが面倒になってきたので、message命令を入れまくって見つかった事にします**。

さて、先ほどの```OpenCVDetectPython.cmake```で色々とチェックしているのがわかりましたので、ここを見ていきましょう。全部認識されていないので、頭から確認します。

```cmake/OpenCVDetectPython.cmake
if(NOT ${found})
  message(WARNING, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ${executable}")
  message(WARNING, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ${${executable}}")
  ocv_check_environment_variables(${executable})
```

とすると

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/98331ec9-f9da-3cd3-1f70-b400cb98c9ac.png)

と表示されます。これは、```executable```には、```PYTHON3_EXECUTABLE```が入っており、ここに、何か値をセットすると、```${${executable}}```とすると、その値が実施されます。さて、PYTHON3_EXECUTABLEはどこでセットされるか。検索するとマニュアルがヒットし、

```
-# [optional] Building python. Set the following python parameters: 
- PYTHON2(3)_EXECUTABLE = <path to python> 
- PYTHON_INCLUDE_DIR = /usr/include/python<version> 
- PYTHON_INCLUDE_DIR2 = /usr/include/x86_64-linux-gnu/python<version> - PYTHON_LIBRARY = /usr/lib/x86_64-linux-gnu/libpython<version>.so 
- PYTHON2(3)_NUMPY_INCLUDE_DIRS = /usr/lib/python<version>/dist-packages/numpy/core/include/
```

と、cmakeコマンドを使う際に自分で入れろ、と書いてあります。

```sh
$ which python
/Users/peisuke/*************/python
```

として、自分のpythonのパスを調べて、cmake実施時に、コマンドに追加しましょう。

```sh
-D PYTHON3_EXECUTABLE=/Users/peisuke/*************/python
```

みたいに。すると・・・

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/042902b1-a3dd-5ce4-9cb7-d10783dc6e81.png)

として、実行スクリプトが認識されました！Summaryの所も、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/631e1e8c-13ab-082e-5ca0-16200f650061.png)

ちょっと情報が増えました。次にいきましょう。SummaryからはInterpreterが発見されているけど、それ以外がないと言われているので下の方を見ていきましょう。すると、

```cmake/OpenCVDetectPython.cmake
find_package(PythonLibs...)
```

みたいな記述があるので、その後ろに

```
      message(WARNING, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ${PYTHON_LIBRARY}")
      message(WARNING, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ${PYTHON_INCLUDE_DIR}")
```

を仕込んで見ると、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/eac7fc1b-f5ac-f901-3279-834f5192c068.png)

として、Includeディレクトリ、とLibが見つかっているのは確認できます。Libraryが見つかっているのに、Summaryに表示されないということは、先ほどと同様Numpyが原因と考えられます。先ほどはNumpyのインストールだけで認識されましたが、今回は既にNumpyは入っているのに見つからない。Mac+Conda+pyenvとかゴチャゴチャ入っていて、うまくincludeパスが見つかっていない模様です。なので、手動でnumpyのディレクトリを設定しましょう。

```
python -c "import numpy;print(numpy.get_include())"
```

とすると、ディレクトリが表示されるので、cmakeのパスに加えてみましょう。

```
-D PYTHON3_NUMPY_INCLUDE_DIRS=XXXXXXXXXX
```

結果は・・・

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146529/19b95b6f-b0c6-98c0-c8df-5cb60ba873ec.png)

認識されました！

他にうまくいかないケースとしては、```PYTHON_LIBRARY```と```PYTHON_INCLUDE_DIR```が見つからないケースです。無理やり設定してもいいですし、```find_package(PythonLibs)```が見つけられるように、**cmakeがデフォルトで持っているFindPythonLib.cmakeに潜るのも一興ですね。少し大変ですが僕もたまにやります。**問題を難しくしているのは、Numpyが見つからないだけなのに、```PYTHON_LIBRARY```が見つからないと怒られたりと、問題を分けられないことがしばしばある点です。その場合にも、この辺のコードを見て、どこが問題なのかをチェックすれば、いつでも解決できますね。

# その他のケース

condaだと、PythonLibsが見つからない場合もよくある。python3.6を入れてるのであれば、例えば、

```
-D PYTHON_LIBRARY=/opt/conda/lib/libpython3.6m.so 
-D PYTHON_INCLUDE_DIR=/opt/conda/include/python3.6m/
```

をビルドオプションに入れると良かったりする。

# おわりに

長くてダラダラした記事になってしまいましたが、個人的にpython bindingで失敗することは結構あるので、作業ログは取っておきたいなぁと思っており、ちょうど良い機会でした。多分ここまで読む人は世の中にいないと思いますが、これを機にpython bindingの達人を目指してみるのは如何でしょうか。

なお、この上級編として、OpenCV内のpython　bindingのコードを切り貼りして、C++とpythonを繋げる[マニアックな技を昨年のAdvent Calenderで公開しています](https://qiita.com/peisuke/items/f648375c8fa8f9a08541)（一年前はPython2.7を使っていたので、3系では動きませんが）。そちらも併せて読んでいただければと思います。では、よいお年を〜。