Leap Motionで画像のトリミングと保存を行うためのサンプルプログラムを作る
メンバー変数の宣言
次にメンバー変数を宣言します。
今回はWin32 APIを使用するためにWin32 APIの宣言も行います。下記のリスト3の部分がWin32 APIに関する宣言か所になります。
リスト3 (Win32 APIに関する宣言)
Private Declare Function SetCursorPos Lib "user32" (x As Integer, y As Integer) As Boolean Private Declare Function apimouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean Private Const MOUSEEVENTF_MOVE = &H1 Private Const MOUSEEVENTF_LEFTDOWN = &H2 Private Const MOUSEEVENTF_LEFTUP = &H4
新しいControllerクラスのインスタンスであるleapメンバー変数を宣言します。次に、インク・ストローク(=System.Windows.Ink名前空間のStrokeクラスで表現される、WPF上でのインクの線)の外観を指定する新しいDrawingAttributesクラス(System.Windows.Ink名前空間)のインスタンスである「touchIndicatorメンバー変数」を宣言します。デジタイザーとスタイラスから収集された単一のデータ・ポイントを表すStylusPoint構造体の「touchPointメンバー変数」を宣言します。
次にRectangleクラス型の「rectメンバー変数」を宣言します。また、System.Wiondows.Pointクラスからの「pメンバー変数」を宣言します。切り出した画像を保存するフォルダ名を格納する「savePathメンバー変数」を宣言します。
そのほかの必要なメンバー変数も宣言しています(リスト4)。
リスト4 メンバー変数の宣言(MainWindow.xaml.vb)
Private leap As New Controller Private touchIndicator As New DrawingAttributes Public touchPoint As StylusPoint Private rect As Rectangle Private p As System.Windows.Point Private savePath As String Private windowWidth As Double = 1920 Private windowHeight As Double = 1080 Private x As Integer Private y As Integer Private tx As Double Private ty As Double Private FingersCount As Integer
MainWindow_Loadedメソッドの処理
MainWindow_Loadedメソッド(=メイン・ウィンドウのLoadedイベントのハンドラー)では、MainWindowが読み込まれたときの処理を実装します。
メンバー変数savePathに切り出した画像を保存するフォルダを指定します。
指定したフォルダが存在しなかった場合は、CreateDirectoryメソッドでフォルダを作成します。
inkCanvas1のEditingMode(ユーザー編集モードの設定)プロパティに、InkCanvasEditingMode.None(ペンがInkCanvasにデータを送信する時に、アクションが実行されないようにする)を指定します。
AddHandlerステートメントを使って、構成ツリーのオブジェクトがレンダリングされる直前に発生する「CompositionTarget.Renderingイベント」に対するイベント・ハンドラーとしてUpdateメソッドを指定します(※Updateメソッドの実装内容は後述)。
インク・ストロークの外観を表す、DrawingAttributesオブジェクトのインスタンス「touchIndicator」のWidthプロパティとHeightプロパティに、それぞれ「20」を指定します。スタイラスの形状を指定するStylusTipプロパティに「StylusTip.Ellipse」を指定して円形とします。Leap Motionの上で指をかざすと、かざした指の本数に応じて20px(px=ピクセル)の円が表示されるようになります(リスト5)。
リスト5 MainWindowが読み込まれたときの処理を行うMainWindow_Loadedメソッドの実装内容(MainWindow.xaml.vb)
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded savePath = "C:\LeapmotionTrimmingImage" ' 切り出した画像を保存するフォルダ If Directory.Exists(savePath) = False Then Directory.CreateDirectory(savePath) End If inkCanvas1.EditingMode = InkCanvasEditingMode.None AddHandler CompositionTarget.Rendering, AddressOf Update ' Updateイベント・ハンドラ—を実行する touchIndicator.Width = 20 touchIndicator.Height = 20 touchIndicator.StylusTip = StylusTip.Ellipse ' 20pxの円が表示される End Sub
Updateメソッドの処理
次は、CompositionTarget.Renderingイベント・ハンドラーであるUpdateメソッドの処理です。
まず、上記のコードを実装した段階で、「Update」の位置に[エラー修正のオプション]というスマート・タグが表示されるので、そのタグのメニューから['ChangeBackgroundLeapMotion.MainWindow' に 'Update' のメソッド スタブを生成]をクリックすると、Updateメソッドのひな型が追加されます。次に、そのメソッド内を実装していきます。
「paintCanvas」という名前のInkPresenter内をクリアします。この処理を行っていないと、Updateメソッドは常に呼び出されているため、円を画面上で動かすと、円の軌跡が残ったまま表示されてしまいます。そのため、InkPresenter内をクリアする必要があります。
Leap Motionのフレームを表すFrame型(Leap名前空間)の変数「frame」を宣言します。InteractionBox型(Leap名前空間)の変数「interactionBox」を宣言し、そこにleap.Frame.InteractionBoxプロパティからInteractionBoxオブジェクトを取得します。InteractionBoxオブジェクトは、Leap Motionで認識できる稼働範囲となります。InteractionBoxオブジェクトを使用することで、指やツール(=ペンなど)の位置を実際のディスプレイの座標系に変換できます(リスト6)。
詳細な図については、「Leap Motionでのタッチ操作はどう開発するのか?」を参照してください。
リスト6 指やツールの位置を実際のディスプレイの座標系に変換する(MainWindow.xaml.vb)
Private Sub Update(sender As Object, e As EventArgs) paintCanvas.Strokes.Clear() windowWidth = Me.Width windowHeight = Me.Height Dim frame As Leap.Frame = leap.Frame Dim interactionBox As InteractionBox = leap.Frame.InteractionBox End Sub
Leap.Frame.Pointablesプロパティで得られるPointableListオブジェクト内を変数「Pointable」で反復処理しながら、1つずつPointableオブジェクトを処理し、それぞれのタッチ位置を取得していきます。
interactionBoxオブジェクトのNormalizePointメソッドに引数としてPointable.StabilizedTipPositionプロパティ値を渡し、ポインター上の位置を取得します。
変数「windowWidth」と「windowHeight」で表されたクライアント領域のウィンドウがある場合、以下のリスト7で示す計算式を使用してこのウィンドウ内のタッチ・ポイントの2D座標を得ることができます。
リスト7 ウィンドウ内のタッチ・ポイントの2D座標を得るコード(MainWindow.xaml.vb)
Private Sub Update(sender As Object, e As EventArgs) ……コード略…… For Each Pointable As Pointable In leap.Frame.Pointables Dim normalizedPosition As Leap.Vector = interactionBox.NormalizePoint(Pointable.StabilizedTipPosition) tx = normalizedPosition.x * windowWidth ty = windowHeight - normalizedPosition.y * windowHeight touchPoint = New StylusPoint(tx, ty) ' ウィンドウ内のタッチ・ポイントの位置を取得する ……コード略(後述)…… Next End Sub
さらに、上記のFor Eachステートメントの一番下に次のリスト8を追記して、ディスプレイ上に円形のタッチ・ポイントを表示します。
リスト8 ディスプレイ上にタッチ・ポイントを表示する処理(MainWindow.xaml.vb)
For Each Pointable As Pointable In leap.Frame.Pointables ……コード略(前述)…… Dim tips As New StylusPointCollection(New StylusPoint() {touchPoint}) Dim touchStroke As New Stroke(tips, touchIndicator) paintCanvas.Strokes.Add(touchStroke) Next
Leap Motionで画像のトリミングと保存を行うためのサンプルプログラム
『新世代モーションコントローラー Leap Motion -Visual Basicによる実践プログラミング-』 第4回のサンプルプログラムです。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- マウス・カーソルで指定した画像の一部を拡大表示するLeap Motionプログラム
- Leap Motionのスクリーン・タップを使った音声の再生と画像の表示
- 画面上の図形を5本の指で操作する基本的なLeap Motionプログラムを作る
- 画面に並んだ写真が指の動きに反応して回転するLeap Motionプログラムを作る
- 写真を突っついて一覧から削除、並び替えするLeap Motionプログラムを作る
- 選択した画像を指の動きに合わせて回転させるLeap Motionプログラムを作る
- 張子の虎をキー・タップすると頭が上下に動くLeap Motionプログラムを作る
- 好きな写真を指で選んで順番に拡大表示するLeap Motionプログラムを作る
- 手の動きに合わせて画面上のキャラクターを操作するLeap Motionプログラムを作る
- Leap MotionアプリをWindowsストアに申請して認定させる