VSCode で Python と OpenCV を混合でデバッグ(ステップ実行)する方法!

PythonとOpenCVの混合デバッグ方法解説ページのアイキャッチ

このページでは、VSCode で Python と OpenCV を混合でデバッグ(ステップ実行)する方法について解説します。

デバッガーを導入することで Python スクリプトをステップ実行(一行ずつ実行)することが可能になりますが、通常ステップ実行できるのは Python スクリプト部分のみです。

例えば OpenCV の関数内にステップイン(関数の中に入り込んでステップ実行する)しようとしてもスキップされてしまいます。

Python単体でのデバッグの様子

しかし、今回紹介する方法を利用すれば、下のアニメーションのようにOpenCV 等の関数にステップインしてステップ実行することが可能になります(左側が Python、右側が OpenCV のソースコードになります)。

Python+OpenCVでデバッグする様子

つまり、Python スクリプト以外で記述された外部ライブラリも同時にデバッグ(ステップ実行)できるようになるというわけです!

今回は OpenCV を例に挙げて解説しますが、他のライブラリに関しても同様の考え方・手順でデバッグできるようになります。

これができるようになるメリットとしては下記が挙げられると思います。

  • 外部ライブラリ使用時にエラーや問題が発生した場合に、その原因を特定しやすい
    • 外部ライブラリの関数呼び出し時のどの引数が原因でエラーになったか、など
  • 外部ライブラリの動きを確認することで知識や技術が身につけられる

特に OpenCV なんかはコンピュータビジョン関連の技術の塊みたいなものです。

ですので、どのように各機能が実現されているかをプログラムを追いながら確認するだけで多くの知識や技術が身につけられると思います!

ではここからは実際に、VSCode で Python と OpenCV を混合でデバッグ(ステップ実行)する方法について解説していきます。

私が使用しているのが Mac なので、Mac 寄りの解説になっていますが、考え方や手順の流れ自体はどの OS でも同じです。

ですので、他の OS 利用者でも参考になると思います!

足りない情報は適宜ググって情報を補完しながら読み進めていただけると良いと思います。

Python と OpenCV 混合デバッグするまでの流れ

Python 利用者が Python と OpenCV を混合デバッグできるようになるためには、割と多くの準備が必要になります。

多くの準備が必要な一番の理由は「OpenCV は Python スクリプトでは無い」ことです。

OpenCV は C++ で記述されていて Python のデバッガーでばデバッグ出来ないため、まずは C++ がデバッグできる環境が必要です。

また OpenCV はコンパイル済みのライブラリ形式で提供されていますが、そのライブラリにデバッグ情報が含まれていないとデバッグが上手く行えません。

さらにステップ実行等のデバッグを行うためには OpenCV のソースコードも必要です。

これらの課題をクリアして初めて Python と OpenCV との混合デバッグを行うことができます。

またこのデバッグの難しいところは、Python プログラムの中で C++ 言語のプログラムが実行されるところです。

Pythonの中でOpenCVが実行されるイメージ

このため、Python 部分は Python デバッガーで、C++ 部分は C++ のデバッガーという感じで一つのプログラムに対して2つのデバッガーを使ってデバッグする必要があります。

PythonとOpenCVを混合デバッグする様子

こういったことを実現するために VSCode の設定も必要です。

以上をまとめると、Python と OpenCV との混合デバッグを行うための手順の流れは下記のようになります。

  • C++ のデバッグ環境を作成
  • OpenCV のソースコード入手
  • OpenCV をデバッグ情報付きでビルド
  • VSCode の設定
  • デバッグ実行!

前準備

まずは前準備として下記のことを行なっておいてください(もともと準備できている項目は飛ばしてオーケーです)。

OpenCV / NumPy をインストール

事前に OpenCV と NumPy をインストールしておいてください。

NumPy は OpenCV をインストールすれば一緒についてくると思います。

MacOSX であれば pip コマンドで簡単にインストールできます。

pip install opencv-python

VSCode をインストール

デバッグは VSCode から行いますので VSCode も事前にインストールしておいてください。

Python 向け VSCode のインストール方法は下記ページで解説していますので、こちらも是非参考にしてください。

Visual Studio Code で Mac に Python 開発環境を整える

Python デバッグ環境の準備

Python のデバッグ環境も事前に準備しておいてください。

と言っても、VSCode をインストールし、Python プラグインをインストールすればデバッグできるようになると思います。

VSCode のインストールとともに、Python のデバッグ環境の準備の仕方も下記ページで解説しています。

Visual Studio Code で Mac に Python 開発環境を整える

ステップ実行できることを確認できれば準備バッチリです。

cmake と make のインストール

OpenCV をビルドするときに cmake コマンドを実行しますので、cmake も事前にインストールしておきましょう!

MacOS で brew コマンドが使えるのであれば下記コマンドをターミナル等から実行することで簡単にインストールすることができます。

brew install cmake

cmake 同様に make コマンドも必要ですが、Mac であればこちらは XCode のコマンドラインツールを入れておけば一緒に make もインストールされるようです。

下記のページあたりが参考になると思います。

スポンサーリンク

C++ のデバッグ環境の作成

前準備を終えたら、次は C++ のデバッグ環境を作成しましょう!

OpenCV は C++ で書かれていますので、OpenCV をデバッグするためには C++ のデバッグ環境が必要です。

といっても、結局は GDB や LLDB を使用すれば良いだけですので、C言語プログラムをデバッグできる環境があれば良いです。

C言語のデバッグ環境(特に Mac 向け)の作り方は下記ページで解説していますので詳細はこちらを読んでいただければと思います。

VSCodeでMacOSにC言語デバッグ環境を構築する方法の解説ページアイキャッチVSCodeでMacOSにC言語デバッグ環境を構築

OpenCV のソースコードを入手

次は OpenCV のソースコードを入手します。

このソースコードはデバッグ時に一行ずつ実行するためにも必要ですし、次の「デバッグ情報付きのビルド」を行うためにも必要です。

OpenCV のソースコードは GitHub 上にありますので git コマンドが使えれば下記を実行するだけで入手できます。

git clone https://github.com/opencv/opencv

git コマンド使えないのであれば下記の手順でソースコードを入手しましょう!

まずは下記サイトに Web ブラウザでアクセスします。

https://github.com/opencv/opencv

続いて画面右側の「Clone or Download」ボタンをクリックします。

opencvソースコード のダウンロード

続いて「Download ZIP」をクリックします。

これで OpenCV のソースコードがダウンロードされます(Sing in や Sign up するかどうか尋ねられますが、選択しなくてもダウンロードは行われます)。

おそらく ZIP 形式で保存されるので、展開しててきとうなフォルダに置いておいてください。

OpenCV をデバッグ情報付きでビルド

次は入手したソースコードを用いて「デバッグ情報付き」でビルドし、デバッグ情報付きの OpenCV ライブラリファイルを作成していきます。

基本的に MacOSX 向けの説明になりますが、Linux 環境でも同様の手順で作業できると思います。

Windows に関しては下記のサイトなどが情報詳しいと思いますので、参考にすると良いと思います(Debug ビルドすることを忘れないようにしてください)。

https://qiita.com/KurozumiGH/items/ef8cca96a13444b7dcda

事前準備

まずはもともと使用していた OpenCV のライブラリファイルの位置を確認しておきます。

これは下記の Python スクリプトを実行することにより確認することが可能です。

import cv2
print(cv2)

実行すれば、OpenCV のライブラリへのファイルパスが表示されます。

<module 'cv2' from '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/cv2/cv2.cpython-38-darwin.so'>

このファイルが Python で使用している OpenCV のライブラリになります。

この節での目的は、上記のファイルをデバッグ情報付きのものに差し替えることになります。

そのまま差し替えると元々使っていた OpenCV のライブラリが上書きされてしまいますので、必ず事前にコピーなどしてバックアップを取っておいてください

また、この「もともと使用していた OpenCV のライブラリファイルへのパス」は後から必要になるので覚えておいてください。

ビルド手順

MacOSX においては、cmake コマンドと make コマンドにより OpenCV の各種ソースコードをコンパイルし、最終的に Python で使用できるライブラリを作成することができます。

具体的なビルド手順は下記のようになります。

  • build フォルダの作成
  • cmake 実行
    • cmake 実行時にはオプションを設定
  • make 実行
  • ライブラリを OpenCV フォルダにコピー

build フォルダの作成

まずはターミナルで OpenCV のソースコードのあるフォルダに移動します。より具体的には、CMakeLists.txt や modules・make フォルダのある階層まで移動してください。

opencvのソースコードのあるフォルダ

そのフォルダ内に、まずはビルド用のフォルダ build を作成します。

コマンド的には下記で build フォルダを作成することができます。

mkdir build

以降で行う cmake や make により、この build フォルダ内に OpenCV のライブラリや各種 Makefile 等が生成されます。

cmake の実行

さらにその build フォルダに移動し、そのフォルダ内で下記のコマンドを実行することで OpenCV のビルドを行うことが可能です。

cmake ../ オプション
make

cmake には引数で CMakeLists.txt の存在するフォルダへのパス “../” とオプションを設定します。

cmake オプションの設定

cmake コマンド実行時に引数でオプションを設定することで、自分の環境に応じた&自分が使いたい形式のライブラリを作成することが可能になります。

引数には下記の形式のように先頭に -D を付加して指定します。複数のオプションを指定可能です

-Dオプション1 -Dオプション2

オプションを設定することで、ライブラリに含ませる機能等を設定することができます。

ですが、このページではデバッグに焦点を当てているため、機能面に関しての説明は省略します。おそらく今まで使っていた OpenCV に対して足りない機能などが出てくると思いますので、その際は必要に応じてオプションを追加してください。

ただし、下記の2つに関してはオプションで設定を行った方が良いと思います(特に 1. は必須)。

  1. ビルドタイプはデバッグビルド(デバッグ情報付きビルド)を指定する
  2. 必要に応じて使用する Python の情報をオプションで指定する

ビルドタイプはデバッグビルドを指定する

まず 1. に関しては、cmake コマンドの引数に下記を追加すれば良いだけです。

-DCMAKE_BUILD_TYPE=Debug

これにより make コマンド実行時にデバッグビルドが行われるようになり、デバッグ情報が生成されるようになります。

さらに、デバッグ情報を生成することで、デバッグ時にソースコード上で1行ずつ止めながらステップ実行等を行えるようになります。

Python の情報をオプションで指定する

2. に関しては、OpenCV ライブラリを「どの Python・どの NumPy」向けに生成するかの設定になります。

指定しなければターミナル等で python3 コマンドを実行した時に使用される Python のバージョンに合わせた OpenCV ライブラリが生成されます。

ですので、python3 コマンド実行した時に使用される Pyhon のバージョン向けの OpendCV ライブラリをビルドするのであれば設定は不要です。

pyenv などを利用している場合など、python3 コマンド実行時に使用されるバージョンとは異なるバージョンの Python 向けの OpenCV ライブラリをビルドしたい場合もあると思います。

その時は下記の4つをオプションに指定します。

  • -DPYTHON3_EXECUTABLE:FILEPATH=“使用する Python 実行ファイルへのファイルパス”
  • -DPYTHON3_INCLUDE_DIR:PATH=“使用する Python のヘッダーフォルダへのフォルダパス”
  • -DPYTHON3_LIBRARY:FILEPATH=“使用する Python ライブラリへのファイルパス”
  • DPYTHON3_NUMPY_INCLUDE_DIRS:PATH=”NumPy 関連ヘッダーフォルダへのフォルダパス”

例えば私の環境で pyenv でインストールした Python3.7.4 に対応した OpenCV をビルドする場合には下記のようにオプションを指定しています。

cmake ../ -DCMAKE_BUILD_TYPE=Debug -DPYTHON3_EXECUTABLE:FILEPATH=/Users/daeu/.pyenv/versions/3.7.4/bin/python3.7 -DPYTHON3_INCLUDE_DIR:PATH=/Users/daeu/.pyenv/versions/3.7.4/include/python3.7m -DPYTHON3_LIBRARY:FILEPATH=/Users/daeu/.pyenv/versions/3.7.4/lib/libpython3.7m.dylib -DPYTHON3_NUMPY_INCLUDE_DIRS:PATH=/Users/daeu/.pyenv/versions/3.7.4/lib/python3.7/site-packages/numpy/core/include

この辺りは結構複雑ですので、とりあえず設定を省略し、python3 コマンド時に使用される Python のバージョン向けにビルドするのが楽だとは思います。

MEMO

pyenv でインストールした Python を利用する場合、-DPYTHON3_LIBRARY:FILEPATH で指定する dylib ファイルが存在しないことがあります

この場合は下記のコマンドで dylib ファイル込みで Python をインストールすることができます。

PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.7.4

まとめると、OpenCV をビルドするためには build フォルダ以下で下記コマンドを実行すれば良いです。

cmake ../ -DCMAKE_BUILD_TYPE=Debug
make

ただし、python3 コマンドで実行される Python とは異なる Python 向けの OpenCV をビルドしたいのであれば、オプションに下記の4つを指定する必要があります。

  • -DPYTHON3_EXECUTABLE:FILEPATH=“使用する Python へのファイルパス”
  • -DPYTHON3_INCLUDE_DIR:PATH=“使用する Python のヘッダーフォルダへのフォルダパス”
  • -DPYTHON3_LIBRARY:FILEPATH=“使用する Python ライブラリへのファイルパス”
  • DPYTHON3_NUMPY_INCLUDE_DIRS:PATH=”NumPy 関連ヘッダーフォルダへのフォルダパス”
MEMO

上記は python3 に絞った解説になっていますが、python2 に対して同様の設定を行いたい方は “3” を “2” に置き換えて同様のオプションを追加すれば良いと思います

make の実行

cmake コマンドを実行すると同じフォルダ内に Makefile 等が生成されます。

さらに make コマンドを実行すれば各種ソースコードが cmake コマンド実行時に引数で指定したオプションに合わせてコンパイル&ライブラリ生成が行われます。

make

かなり時間はかかりますので注意してください…。

ライブラリを OpenCV フォルダにコピー

ビルドが終われば、build/lib/python3 以下に下記のような名前のファイルが生成されていると思います。これが Python3 で OpenCV のインポート時に使用されるライブラリファイルになります。

OpenCV の関数等は全てこの中に入っています。

cv2.cpython-38-darwin.so

38 の部分は OpenCV をどのバージョンの Python 向けでビルドしたかによって異なると思います。

設定がうまくできていれば、事前に確認した .so ファイルと同じ名前のファイルが生成されているはずです。

このファイルを事前準備で確認した「もともと使用していた OpenCV  ライブラリ」に上書きします(上書きするともともとの OpenCV が消えてしまうので事前にバックアップを取っておきましょう)。

これにより、Python から OpenCV 使用時に使用されるライブラリが、自分でビルドして作成したデバッグ情報付きのライブラリに差し替えられたことになります。

つまり、今まで通りの利用方法(import や関数実行など)で、デバッグ情報付きの OpenCV が利用できることになります。

デバッグ情報にはビルド時のソースコードの位置も記録されています。したがって、ビルドした後にソースコードを移動してしまうとデバッグ情報とソースコードの位置に食い違いが発生してデバッグできなくなります。

ビルド後はソースコードの位置は変更しないようにしましょう!

スポンサーリンク

VSCode の設定

次は VSCode の設定です。

具体的には OpenCV のデバッグ時に用いるソースコードや、Python と OpenCV のデバッガーの設定を行います。

VSCode のウィンドウを2つ開く

まずは VSCode のウィンドウを2つ開きます。

メニューバーの「ファイル」→「新しいウィンドウ」を選択することで複数のウィンドウを開くことができます。

一方のウィンドウでは Python のソースコードを開いて Python のデバッグを行います。

他方のウィンドウでは OpenCV  のソースコードを開いて OpenCV(C++)のデバッグを行います

ソースコードの用意

続いてデバッグするソースコードを開きます。

Python のデバッグを行うウィンドウでは OpenCV を利用する Python のスクリプトファイルを開いておけば良いです。

OpenCV のデバッグを行うウィンドウでは入手した OpenCV のソースコードのあるフォルダを開きます。

手順は簡単で、メニューバーの「ファイル」→「フォルダーをワークスペースに追加…」を選択し、さらに OpenCV のソースコードのあるフォルダ(CmakeLIsts.txt や modules フォルダが置いてあるフォルダ)を選んで「追加」ボタンをクリックすれば良いです。

基本的に modules の下に OpenCV のソースコードが存在しています。

launch.json の設定

さらに、launch.json の設定を行います。

まずは Python 側のウィンドウではデバッグ環境を既に整えているのであれば設定は不要です。

念のため私が使用している Python デバッグ時に使用している launch.json を載せておきます(justMyCodefalse にしておくと外部ライブラリの Python スクリプトも含めてデバッグできます)。

Pythonのlaunch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "justMyCode": false,
        }
    ]
}

C++ 側のウィンドウでは、下記によりまず launch.json を追加します。

  • メニューバーの「実行」を選択
  • 「構成の追加」を選択
  • 環境の選択リストが表示されるので、使用するデバッガーを選択(LLDB を利用するのであれば「 LLDB」、GDB を利用するのであれば「C(GDB/LLDB)」を選択
    • おそらくこれはどれを選択しても良いです

ワークスペース直下に .vscode フォルダが作成され、さらにその中に launch.json が作成されます。

今度は launch.json を開き、下記をコピペして上書きします。

OpenCV(C++)のlaunch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach",
            "type": "lldb",
            "request": "attach",
            "pid": "${command:pickProcess}"
        }
    ]
}

簡単に上記の launch.json の設定について解説します。

"name"

"name" ではデバッグ構成の名前を指定します。わかりやすい名前であればなんでも良いです。

"type"

"type" では使用するデバッガーのタイプを指定しています。私の環境では LLDB を利用しているので "lldb" を指定していますが、GDB を利用している方は "gdb" を指定してください。

"request"

"request" では "attach" を指定していますが、この "attach" を指定することで、既に起動しているプログラムをデバッグできるようになります。

attachの説明図

同様に "request" では "launch" が指定可能ですが、この "launch" 指定の場合はプログラムを起動させ、その起動したプログラムをデバッグするための指定になります。

launchの説明図

実行可能ファイルのデバッグでは "request""launch" を指定すれば良いですが、今回のデバッグ対象は実行可能でないライブラリファイルですので、"launch" は指定できません。

そのため、一旦 Python 側のデバッガー("request" :"launch")で Python プログラムを起動させ、そのプログラムに C++ デバッガー("request" :"attach")することで、起動中のプログラム内で動作する OpenCV のデバッグを行えるようにします。

launchとattachによる混合デバッグの説明図

"pid"

前述のとおり、"request" に "attach" を指定することで既に動作中のプログラムをデバッグすることが可能です。

そして、この "pid" は、動作中の “どの” プログラム(プロセス)をデバッグするかを指定する属性になります。

この "pid" にはプログラムのプロセス ID を指定します。

pidとattachの説明図

プロセス ID はプログラム起動時に決まる&プログラムを起動するたびに変化するのでアタッチ前にプロセス ID を調べ、"pid" にそのプロセス ID を設定してからデバッガーを起動する必要があります。

"pid":"${command:pickProcess}" と設定しておくことで、デバッガー起動時に全プロセスの ID がリストとして表示され、その中からアタッチしたいプロセスを選択することができるようになります。

プロセスIDの選択画面

実際にどのプロセス ID を指定するかは後述で説明します。

MEMO

"program" 属性を指定すればプロセス名でどのプログラムをデバッグするかを指定することも可能です

ですが、VSCode から Python プログラムを起動すると、「Python」という名前のプロセスが複数起動して上手く指定できなかったので、"pid" を指定する手段をとっています

デバッグ実行

次はいよいよデバッグ(ステップ実行)を行なっていきます!

デバッグでは前述の通り2つの VSCode ウィンドウを使って行います。

1つは Python デバッグ用、もう1つは OpenCV(C++)デバッグ用のウィンドウになります。

下記の簡単な Python スクリプトを用いて、実際の動きを踏まえながら解説していきたいと思います。

imreadresizecvtColor は OpenCV の関数になります。os モジュールを利用しているのはプロセス ID を表示するためです(後述で説明)。

opencvデバッグ用スクリプト
import cv2
import os

# プロセス ID を表示
print(os.getpid())


# CV2画像オブジェクトを生成
# 画像を読み込んでCV2画像オブジェクトを生成
image = cv2.imread("cute_cat.png")

# 画像の拡大
resize_image = cv2.resize(image, None, fx=2, fy=2)

# BGR -> RGB
rgb_image = cv2.cvtColor(resize_image, cv2.COLOR_BGR2RGB)

print(rgb_image)

Python のデバッグ実行(Python ウィンドウ)

Python のウィンドウで行うのは通常のデバッグ時と同様の操作になります。

Python プログラムを起動させ、C++ のデバッガーからアタッチ可能な状態にします。

ブレークポイントの設定

まずはブレークポイントを設定します。

OpenCV の関数実行前にブレークポイントを設定しておくと良いと思います。

ここでは下記の場所(赤丸が付いている行)にブレークポイント設定する例を用いて解説していきます。

ブレークポイントの設定例

デバッグ実行

ブレークポイントを設定したら、メニューバーの「実行」→「デバッグ開始」を選択してデバッグを開始しましょう!

プログラム起動後、設定したブレークポイントで停止するはずです(黄色の行を実行する直前、つまり imread 関数実行直前で停止している)。

ブレークポイントでPythonが停止する例

プログラムは停止していますが、既に起動している状態ですので、C++ のデバッガーからアタッチすることが可能になります。

attachの説明図

OpenCV のアタッチ実行(C++ ウィンドウ)

次は OpenCV デバッグのウィンドウでデバッグ(アタッチ)を実行していきます。

プロセス ID の確認

前述の通り、アタッチする場合はどのプロセスにアタッチするかをプロセス ID を指定することにより設定します。

このプロセス ID は MacOSX や「アクティブモニタ」、Windows では「タスクマネージャー」で調べることができます。

ですが面倒なので、Python 実行時にプロセス ID を表示してやるのが楽だと思います。

プロセス ID を表示するためには Python スクリプトの先頭に下記を記述しておけば良いです。

プロセスIDの表示
import os

print(os.getpid())

ブレークポイント設定箇所より前に上記を実行してやれば、ブレークポイント停止前に、例えば下記のような数字としてプロセス ID が表示されます。

32092

この表示された数字を覚えておきましょう(覚えておかなくても表示されているのを後で確認するのでも良いです)。

ブレークポイントの設定

続いて OpenCV のソースコードにブレークポイントを設定します。

ブレークポイントは、Python スクリプトから実行される関数の中に設定します。上手くアタッチできていれば、Python スクリプトでその関数を実行した際に、その OpenCV の関数の中でプログラムを停止させることができます。

ここでは imread 関数の中にブレークポイントを貼りたいと思います。

OpenCVへのブレークポイント設定の例

ちなみに imread 関数は OpenCV の下記ファイルで定義されています。

modules/imgcodecs/src/loadsave.cpp

また、resize 関数は OpenCV の下記ファイルで、

modules/imgproc/src/resize.cpp

cvtColor 関数は OpenCV の下記ファイルでそれぞれ定義されていますので、興味のある方はこれらの関数の中にもブレークポイントを設定しておくと良いと思います。

modules/imgproc/src/color.cpp

デバッグ実行

ブレークポイントを設定したら、メニューバーの「実行」→「デバッグ開始」を選択してデバッグを開始しましょう!

デバッグ実行をすると、"pid" に "${command:pickProcess}" を設定している場合、下のようなプロセス ID の選択画面が表示されます。

プロセスIDの選択画面

ここで入力欄にプロセス ID の確認で調べたプロセス ID を指定します。私が調べた際にはプロセス ID が “32092” だったので、例えば下図のように “32092” を入力します。

プロセスIDの指定

そうすると、プロセス ID が入力した数値のものだけリストアップされるので、その項目をクリックします。クリックするとデバッガー起動します。

しばらくすると VSCode のウィンドウの下側のバーがオレンジ色に変わるはずです。また、デバッグコンソールには、先ほど指定した ID のプロセスにアタッチしたことを示すメッセージも表示されるはずです。

Attached to process 32092

アタッチした場合は、デバッグ用の操作バーが下の図のように表示されます。

アタッチ時のデバッグ操作バー

一番右のボタンは「切断ボタン」であり、クリックすることでアタッチを解除し、OpenCV 側のデバッグを終了することができます。

MEMO

アタッチを解除しても Python 側のデバッグは続けることができます

また Python プログラムが起動中であれば、再度同じ "pid 設定でアタッチしてデバッグすることも可能です

次は、OpenCV を本当にデバッグできる環境が構築できているかを確認していきます。

アタッチ後に、先ほど設定したブレークポイント部分のソースコード部分を再度確認してみましょう。

ブレークポイントを設定した行の左側に赤丸のままで表示されていれば、おめでとうございます!OpenCV デバッグ実行できる環境が整いました!

ブレークポイントが赤丸で表示される様子

もしアタッチ後に赤丸ではなく、黒丸に変化している場合は、残念ながらデバッグ環境の構築に失敗しています…。

ブレークポイントが黒丸で表示される様子

この場合は下記を見直してみると良いと思います。

  • cmake 実行時に引数 -DCMAKE_BUILD_TYPE=Debug を指定しているか
  • 自身でビルドした OpenCV が Python から利用されているか
  • ビルド時からソースコードの位置を変更していないか
  • ブレークポイントを設定した関数はビルド時のオプションで無効化されていないか
    • 無効化されている場合はビルド時のオプションで有効化する

Python と OpenCV との混合でバッグ

アタッチ後は、まずは Python 側のウィンドウのデバッガーで Python プログラムをステップ実行していきます。

ステップ実行を進め、ブレークポイントを設定している OpenCV の関数を実行すると、おそらく OpenCV 側のウィンドウに切り替わり、OpenCV のソースコード上に設定したブレークポイントでプログラムが停止するはずです(自動的に切り替わらない場合は手動で OpenCV 側のウィンドウを表示してみましょう)。

OpenCVをブレークポイントで停止させた様子

通常のデバッグ時同様、画面左側の「変数」ウィンドウでは変数の中身が確認できますし、「コールスタック」ウィンドウでは、どのようにして関数コールが行われて今の位置のプログラムが実行されているかを確認することができます。

もちろん、ステップ実行も可能です。デバッグ操作バーを操作して、ステップオーバー実行やステップイン実行等を進めてみましょう!OpenCV のプログラムが1行ずつ停止させながら動作できていることが確認できるはずです! 

OpenCVをステップ実行していく様子

ステップ実行等でプログラムを進め、OpenCV の関数が終了した際には、今度は Python 側のウィンドウに戻ります。

Pythonウィンドウのデバッグに戻る様子

ここからは Python 側のウィンドウでステップ実行等でデバッグしていき、ブレークポイントを設定している OpenCV の関数を実行すると、また OpenCV のウィンドウに移り、OpenCV のステップ実行をすることができます。

こんな感じで Python 側のウィンドウと OpenCV 側のウィンドウを交互に使って、Python と OpenCV のステップ実行を行っていくことができます。

デバッグの終了

デバッグを終了したい場合は、下記の手順で操作を行います。

  • OpenCV 側のウィンドウのデバッグ操作バーで「切断」をクリック
  • Python 側のウィンドウのデバッグ操作バーで「停止」をクリック

順番が逆になると変なゴミみたいなプロセスが残ることがありますので注意してください(実害はないと思いますが、気になる場合はアクティブモニタやタスクマネージャー等からプロセスを終了させてください)。

ウィンドウ1つで混合デバッグする方法

ここまでウィンドウ2つで混合デバッグする方法について解説してきましたが、実はウィンドウ1つでも混合デバッグすることは可能です。

下記の手順によりウィンドウ1つでデバッグすることができます。基本的にここまで解説してきた「ウィンドウ2つでデバッグするための手順」をウィンドウ1つで実施するだけです。

  • VSCode のウィンドウで OpenCV を利用する Python スクリプトを開く
  • そのウィンドウで OpenCV のソースコードが置かれているフォルダを開く
    • メニューバーの「ファイル」「フォルダーをワークスペースに追加…」からフォルダを開く
  • Python と OpenCV の launch.json を必要に応じて追加
    • launch.json の設定はウィンドウ2つの時と同じで良い
  • Python と OpenCV のソースコード上にブレークポイントを設定
  • Python のデバッグを開始
    • 実行ウィンドウで Python デバッグを実行する構成を選択して▶︎をクリック
      実行構成の選択1
    • デバッガーが起動してPython プログラムがブレークポイントで停止する
  • Python プログラムのプロセス ID を確認
  • OpenCV のデバッグを開始
    • 実行ウィンドウで OpenCV デバッグを実行する構成を選択して▶︎をクリック
      実行構成の選択(OpenCV)
    • プロセス ID を選択してデバッガー起動
    • Python プログラムにアタッチされる
  • Python のステップ実行を進めて OpenCV の関数を実行
  • OpenCV のブレークポイントを設定したソースコードで停止する

1度でもウィンドウ2つでのデバッグを実行して launch.json を設定しておけば、OpenCV のフォルダを追加したときに同時にその launch.json も読み込まれるため、別途 launch.json の設定を行う必要はありません。

1つのウィンドウでデバッグを行う場合は、1つのウィンドウでデバッガーを2つ起動することになります。

表示されるデバッグ操作バー1つのみですが、一番右のボタン(下矢印みたいなボタン)をクリックすれば、2つのデバッガーを切り替えて操作することができます。

デバッガー2つ起動時のデバッグ操作バー

上記手順を実施すると、下のアニメのようにウィンドウ1つで Python と OpenCV 両方のデバッグを行うことができます。

ウィンドウ1つで混合デバッグする様子

OpenCV のみをデバッグする方法

別に Python と OpenCV を混合でデバッグできなくても、OpenCV のみデバッグできればいいよーという方は、下記の太字部分を launch.json に追加すれば良いです。

OpenCV 単体デバッグのlaunch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "justMyCode": false,
        },
        {
            "name": "Cのデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "Pythonへのパス",
            "args": ["${file}"],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "lldb"
        },
    ]
}

上記は LLDB を使用する際の例になりますので、GDB を使用する場合などは適宜修正していただければと思います。

ポイントは "program""args" です。

"program" には Python 自体(python コマンドで実行される実行ファイル)へのパスを指定します。これにより C++ のデバッガーを介して Python が実行されることになります。

さらに "args" には Python スクリプトファイル(.py)へのパスを指定します。

"${file}" を指定すれば、現在 VSCode で画面に表示している Python スクリプトへのパスが自動的に設定されます。 

例えば opencv_debug.py というファイルを VSCode の画面に表示している場合、下記のコマンドを C++ のデバッガーを介して実行されることになります。

python opencv_debug.py

あとは実行ウィンドウから「Cのデバッグ」を選択して▶︎ボタンをクリックすれば、OpenCV のソースコードの中に設定したブレークポイントでプログラムが停止するようになります。もちろんステップ実行も可能です。

OpenCVのみのデバッグを行う実行構成

C++ のデバッガーで起動しているので、Python 部分にブレークポイントを設定してもそこで停止はしないですが、OpenCV のみをデバッグしたい場合はこれでも十分な場合はあると思います!

まとめ

このページでは Python と OpenCV を混合でデバッグ(ステップ実行)する方法について解説しました!

Python と OpenCV を同時にデバッグできるようになり、OpenCV をステップ実行したり、変数の中身の変化を確認しながらプログラムを実行することができます。

何より、OpenCV の動きが分かって面白いと思います。OpenCV はコンピュータビジョンに関する技術の塊ですので、どのようにそれらの技術が実現されているかを調べることで、知識や技術を身につけることも可能です。

今回は OpenCV を取り上げて解説しましたが、他の外部ライブラリ(特にC言語やC++で書かれているライブラリ)に関しても、同様の手順でデバッグできるようになるはずです。

要は「ソースコードの入手」「デバッグ情報付きでビルド」ができれば、あとは VSCode のデバッガーでアタッチするだけでデバッグできます。

いろんなライブラリをデバッグ・ステップ実行して、一歩踏み込んだ知識や技術を身につけるのに是非活用してください!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です