記事の目的
Leap Motionというモーショントラッカーがあります。
これのPython用APIを使って、親指と人差し指の距離をリアルタイムに取得することを試みました。
PythonでLeap Motionを使う方法を紹介した記事は多くありますが、私の環境ではなかなかスムーズにいきませんでした。
ので、自分用メモとして方法を残します。
更新履歴
2020年11月16日:
SDKのV2をDLするためのリンクが切れていたので、現在のリンクを貼りました。
環境
- Windows 10 64bit
- Python 3.7.5
まずPython 2.xで
Leap MotionのPython APIは、Python 2.xにしか対応していません。
Python3系列で動かすのはあとにして、まずはPython 2.7で動かしてみます。
Anacondaを使って、Python2.7環境を作ります。
Leap Motion SDKの準備
次に、Leap Motion Developerのサイトから~~デスクトップ用のSDKをダウンロードします。
V2とV4の選択肢がありますが、V2を選びます。~~
(2020年11月16日追記)リンクが切れていました。
現在のところ、SDKのV2はこちらからダウンロードできるようです。
Windows版の2.3.1をDLしてください。
DLしたzipを解凍すると、中にインストーラがあるので実行しましょう。(←Visualizerいらないなら不要?)
その後、
C:\Program Files\Leap Motion Core Services\Visualizer.exe
を実行すると、Leap Motionの動作確認ができるのでやってみましょう。
Visualizerに何も表示されないようでしたら、この記事を参考にdpinst64.exeを実行してドライバをインストールしてください。
インストーラと一緒に、LeapSDKというフォルダがあります。
さらにその中のlib/Leap.pyをimport
することで、PythonからLeap Motionを扱えるようです。
しかし、例えばLeap.pyと同じディレクトリへ移動してimport
しても、Import Error: No module named LeapPython
となってしまいます。
こちらの記事を参考に、Leap.pyと
LeapSDK/lib/x64の中身と、__init__.py(空のファイル)をひとつのフォルダ(ここでは、leapmotionという名前にします)内にコピーします。
leapmotionがあるディレクトリに移動して、Pythonからfrom leapmotion import Leap
とすると、Leap MotionのAPIが使用できるようになります。
Leap Motion APIの使用
このあたりの記事や公式のドキュメントやdir()
を駆使し、親指と人差し指の距離を出力します。
下記のようにすると、その瞬間における手の情報をframe
として取得できるようです。
controller = Leap.Controller()
frame = controller.frame()
ちなみに、controller.frame(1)
とやると、1フレーム前の情報が得られるようです。
frame
のうち指の情報は、frame.fingers
に収められています。
各指の情報は、以下のように取り出すようです。
frame.fingers[0] # <- Thumb(親指
frame.fingers[1] # <- Index(人差し指
frame.fingers[2] # <- Middle(中指
frame.fingers[3] # <- Ring(薬指
frame.fingers[4] # <- Pinky(小指
親指と人差し指の指先の距離を出力するためには、下記のようにします。
pos_thumb = frame.fingers[0].tip_position
pos_index = frame.fingers[1].tip_position
print(pos_thumb.distance_to(pos_index))
まとめると、こんな感じです。
from time import sleep
from packages.leapmotion import Leap
controller = Leap.Controller()
THUMB = 0
INDEX = 1
MIDDLE = 2
RING = 3
PINKY = 4
while not controller.is_connected:
print('Connecting...')
sleep(.5)
pass
print('...Connected!')
while True:
sleep(.01)
frame = controller.frame()
pos_thumb = frame.fingers[THUMB].tip_position
pos_index = frame.fingers[INDEX].tip_position
print(pos_thumb.distance_to(pos_index))
Python3で動かす
こちらの記事をもとにやっていきます。
記事の設定と違うのは、64bitのWindowsを使っていること、PythonのVer.が3.7であることです。
Swig
Swigを使って、Python用のプログラムを生成してもらいます。
インストール
このサイトを参考に、WindowsにSwigをインストールします。
記事執筆時点での最新版は4.0.1でしたが、4.0.0以降だとエラーを招くようです(参考)。
3.0.12でもエラーは(恐らく)出ませんが、記事の通り2.0.9を使います。
swig.exeまでのパスを環境変数PATHに追加するところまでやりましょう。
スクリプトの手直し
適当なフォルダを作って下記ファイルをコピーします。
- LeapSDK/include/Leap.h
- LeapSDK/include/LeapMath.h
- LeapSDK/include/Leap.i
- LeapSDK/lib/x64/Leap.lib
このフォルダでSwigを実行すればいいのですが、Leap.iがイマイチちゃんとしていないようでエラーになります。
こちらの記事を参考に、手動で直します。
Leap.iをテキストエディタで開いてください。
%pythoncode {% }}
で囲われている部分がPython用のコードなのですが、インデント(字下げ)に間違いがあります。
def
の前など、インデント不要なところはインデントなし、そのほかのインデントは空白4つになるように直しましょう。
一応、手直ししたLeap.iを置いておきます。
コマンドプロンプトにて、そのフォルダの場所へcd
し、下記コマンド。
swig -c++ -python -o LeapPython.cpp -interface LeapPython Leap.i
エラーメッセージがでたら、それをもとにLeap.iのインデントを再度見直しましょう。
成功すれば、Leap.py、LeapPython.cpp、LeapPython.hが同じフォルダ内に作成されます。
Visual Studio
Visual Studioを使い、先ほど生成されたLeapPython.cppを、Pythonから動かせるような形でコンパイルします。
インストール
Python3.7の場合、最新の2019版でなく2017版を用意する必要がある(参照)とのことなので、そちらをDLします。
https://docs.microsoft.com/ja-jp/visualstudio/releasenotes/vs2017-relnotes
Download Enterprise 2017を選んで、インストーラをDL&起動。
どうしてよいかイマイチわからなかったので、ワークロードタブからC++によるデスクトップ開発にチェックを入れてインストール。
空のプロジェクト作成
メニューバーから [ファイル]→[新規作成]→[プロジェクト]。
左のメニューから[Visual C++]→[空のプロジェクト]を選択。
名前と場所を適当に決めて [OK]。
プロジェクトのフォルダに、先ほどSwigを動かしたフォルダの中身をすべて(LeapPython.cppだけでもよい?)コピーしてください。
.filtersなんかがあるファイルと同じディレクトリです。
いろいろ設定
[表示]→[ソリューションエクスプローラー]。
ソリューションエクスプローラーのプロジェクト名を右クリックして[追加]→[既存の項目]。
先ほどSwig済のフォルダからコピーしたファイルをすべて[追加]します。
次は、再度プロジェクト名を右クリックして [プロパティ]。
[プロパティ]が見当たらない場合は、下のスクショのように、上部のアイコンを使ってフォルダビューからソリューションビューに変更。
構成マネージャーをクリックし、校正をRelease、プラットフォームをx64に変えます。
[全般]メニューを選び、[ターゲット名]をLeapPython、[構成の種類]をダイナミックライブラリ(.dll)に設定。
続いて、[C/C++]→[全般]メニューを開き、追加のインクルードディレクトリに、Pythonのincludeフォルダを指定します。
例えば私のAnaconda(Miniconda)環境ですと、
C:\Users\(ユーザー名)\Miniconda3\envs\(環境名)\include
といった感じです。
さらに[リンカー]→[入力]メニューへ飛び、追加の依存ファイルのところに Leap.libと、python37.libへのフルパスを追記します。
python37.libは下記の場所などにあるはずです。
C:\Users\(ユーザー名)\Miniconda3\envs\(環境名)\libs\python37.lib
設定完了です。
プロパティを閉じましょう。
ビルド
コンパイルを実行します。
プロジェクト名を右クリック→[ビルド]
エラーメッセージがどっと出てきたら、python33.libとLeap.libがちゃんと64bit用のものになっているか確認してください。
ビルドが終了すると、表示されているディレクトリにLeadPython.dllが作られています。
これの名前を変更して、拡張子を.pydにしてください。
一応、生成されたLeadPython.pydを置いておきます。
Python3.7で実行
Python2.7で動かした、LeapSDKの中身をあれこれ突っ込んで__init__.pyを作ったフォルダを開いてください。
このうち、Leap.pyとLeapPython.pydを、SwigやVisual Studioで生成されたものに置き換えます。
最後にまた、Leap.pyを手動で直す必要があります。
テキストエディタで開きましょう。
あちこちに、余計な%
が紛れていますので、消してください。
半角スペース2個+%を置換して消してやると速いです。
手直ししたLeap.pyがこちらです。
これで、Python2.7でやったときと同様にLeap MotionのデータをPython3.7で取得できます。
PsychoPyと組み合わせる(おまけ)
こんなスクリプトを書いて↓
from time import sleep
from .leapsdk import Leap
class LeapMotion:
def __init__(self):
self.controller = Leap.Controller()
self.fingers = {'thumb': 0,
'index': 1,
'middle': 2,
'ring': 3,
'pinky': 4}
while not self.controller.is_connected:
sleep(.5)
def calc_dist(self, finger_from: str, finger_to: str):
frame = self.controller.frame()
pos_from = frame.fingers[self.fingers[finger_from]].tip_position
pos_to = frame.fingers[self.fingers[finger_to]].tip_position
return pos_from.distance_to(pos_to)
こんな感じで動かして↓
from time import sleep
from packages.device.leapmotion import LeapMotion
from psychopy import visual
leapmotion = LeapMotion()
window = visual.Window(
colorSpace='rgb255',
fullscr=False,
size=(900, 900),
allowGUI=True,
wintype='pygame',
units='pix')
circle = visual.Circle(window, size=1, autoDraw=True)
while True:
circle.size = leapmotion.calc_dist('thumb', 'index')
window.flip()
sleep(.01)
print(leapmotion.calc_dist('thumb', 'index'))
Visual Studioの代わりにMinGWで(失敗)
MinGWでインストールしたg++を使ってコンパイルしてみようとしたのですが、うまくいきませんでした。
詰むまで記録を残しておきます。
インストール
こちらの記事をもとにMinGW-w64をインストールします。
PATHに追加するところまでやったらOK。
ちなみに私の場合は下記を追加しました。
C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin
そして、コマンドプロンプトでSwig済フォルダへcd
し、
g++ -I C:\Users\issakuss\Miniconda3\envs\study09t\include LeapPython.cpp Leap.lib C:\Users\issakuss\Miniconda3\envs\study09t\libs\python37.lib -shared -o LeapPython.pyd
これで、Visual Studioでやったのと同じことができると思ったのですが、エラーがたんまり出てしまい詰みました。
こっちでできたらVisual Studioインストールしなくて済むので楽だったんですが。