Leap Motionで画像のトリミングと保存を行うためのサンプルプログラムを作る
今回のLeap Motionアプリは、画面上に表示された画像の一部分を切り取って保存するアプリです。早速開発手順を見ていきましょう。
まずWPFプロジェクトを作成しよう
今回のLeap MotionアプリもWPFで作成します。
これには、Visual Studio 2012(以下、VS 2012)のIDEを起動して、メニューバーから[ファイル]−[新規作成]−[プロジェクト]と選択して、それにより表示される[新しいプロジェクト]ダイアログで「Visual Basic」のテンプレートから「WPF アプリケーション」を選択します。
※(Leap Motionは、.NET Framework 3.5と4.0に対応しています。しかし、.NET Framework 4.5でも動作します。今回のアプリは全て.NET Framework 4.5で作成しています。
しかし、あくまでも対応しているのは、.NET Framework 3.5と4.0です。心配な方は、.NET Framework 4.0で作成すると安心でしょう)。
[名前]欄には、ここでは「ImageTrimmingLeapMotion」と指定します。
ソリューション・エクスプローラー内にImageというフォルダを作成して、画像を1枚配置しています。画像サイズは640×480サイズの画像にしてください。今回はJPEG画像を使用していますが、PNG画像でも問題はありません。
ダウンロードされたサンプルファイルには、これらのファイルは追加済です。
WPFの基本的な作成手順は、「画面上の図形を5本の指で操作する基本的なLeap Motionプログラムを作る」と同じ手順となるので、説明を割愛します。具体的な手順は、第1回の「参照の追加」「プロジェクトのルートに「LeapCSharp.dll」と「Leapd.dll」を追加する」「プロパティを設定する」を参考にしてください。
ポーリング方式の採用
今回のサンプルは今までのサンプルとは異なり、「ポーリング方式」を作用しています。「ポーリング方式」とは、Controllerクラス(Leap名前空間)だけを使用した方式です。詳細については、Build Insiderの「C#によるLeap Motion開発の全体像(http://www.buildinsider.net/small/leapmotioncs/01)」を参照してください。
NuGetパッケージの管理
ソリューション・エクスプローラー内の「参照設定」を選択して、右クリックのメニューで表示される「NuGetパッケージの管理」から、コンポーネントをインストールする必要があります。
WriteableBitmapExをインストールする
NuGetの検索欄に「WriteableBitmapEx」と入力すると、WriteableBitmapExパッケージのインストール画面が表示されるので、[インストール]をタップします。筆者の場合はすでにインストール済みであるため、インストール済みの緑色のチェックが表示されています(図1)。
今回のLeap Motionアプリについて
今回のアプリは、画面に配置した画像の一部分を切り抜いて保存するアプリです。このトリミング操作をLeap Motionで行います(図2参照)。
保存される画像のファイル名はTrimmingTest.pngで固定されており、上書き保存になります。
実際に動かした動画は次のようになります。選択範囲を指定するには、コツが必要なため動画を見てください。
画面のレイアウト(MainWindow.xaml)
今回はCanvasではなく、デフォルトのGridを使っています。
まず、サイズが640×480サイズでのBackgroundがTransparentのGridを配置し、その子要素として、名前がImage1というImageコントロールを配置。し、サイズを640×480とし、SourceプロパティにImageフォルダの画像を指定しておきます。
次に、名前がInkCanvas1という名前のInkCanvasコントロールを配置し、サイズは640×480で、BackgroundにTransparentと指定しておきます。InkCanvas要素は、インク・ストロークを受け取って表示する領域を定義する要素です。
次に名前がButton1というButtonコントロールを配置し、Contentに「切り出す」と指定しておきます。
切り出した画像を表示させるのに、resultImageという名前のImageコントロールを配置し、StretchにNoneと指定しておきます。切り取ったサイズの状態を保持したまま表示されます。
名前がsaveButtonという名前のButtonコントロールを配置し、Contentに「保存」と指定しておきます。
保存した旨のメッセージを表示するmessageTextBlockという名前のTextBlockコントロールを配置します。
ルートのGridコントロールの1番最後に
書き出されるXAMLはリスト1のようになります。
リスト1 (MainWindow.xaml)
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="1080" Width="1920" WindowState="Maximized"> <Grid> <Grid Background="Transparent" VerticalAlignment="Top" HorizontalAlignment="Left" Width="640" Height="480"> <Image x:Name="Image1" Height="480" Stretch="UniformToFill" Source="Image/冬の桜.jpg" Width="640"/> <InkCanvas x:Name="inkCanvas1" Height="480" Width="640" Background="Transparent"/> </Grid> <Button x:Name="Button1" Content="切り出す" HorizontalAlignment="Left" Height="154" VerticalAlignment="Top" Width="621" FontFamily="Meiryo UI" FontSize="36" IsEnabled="False" Margin="10,485,0,0" FontWeight="Bold" /> <Image x:Name="resultImage" Stretch="None" Width="640" Height="480" Canvas.Left="854" Canvas.Top="57" Margin="858,20,414,549" /> <Button x:Name="saveButton" Content="保存" HorizontalAlignment="Left" Height="143" VerticalAlignment="Top" Width="174" IsEnabled="False" Canvas.Left="659" Canvas.Top="57" FontSize="36" FontWeight="Bold" Margin="662,10,0,0" /> <TextBlock x:Name="messageTextBlock" HorizontalAlignment="Left" Height="138" Margin="662,559,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="1126" FontSize="36" Foreground="Red" FontWeight="Bold"/> <InkPresenter Name="paintCanvas"/> </Grid> </Window>
レイアウトは図3のようになります。
プログラム・コード(MainWindow.xaml.vb)
では、次にプログラム・コード(MainWindows.xaml.vbファイル)を見ていきましょう。
名前空間の読み込み
まず、Leap Motionを扱うため、「Leap」名前空間を読み込み、次に、インクの操作を行うクラスを提供する「System.Windows.Ink」名前空間を読み込みます。
XAMLまたはコードで使用できる基本図形のライブラリにアクセスできるようにする、「System.Windows.Shapes」名前空間を読み込みます。
ファイル・モード、ファイル・アクセス、ファイル共有のための列挙体、およびパス操作やストリームの操作のためのクラスが含まれる、「System.IO」名前空間を読み込みます(リスト2)。
リスト2 名前空間の読み込み(MainWindow.xaml.vb)
Imports Leap Imports System.Windows.Ink Imports System.Windows.Shapes Imports System.IO
メンバー変数の宣言
次にメンバー変数を宣言します。
今回は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のタッチ処理になります。タッチのイメージは次の図3のようなイメージです。
Updateメソッド(ホバー)の処理
手前側が「ホバー状態(hovering)」、奥側が「タッチ状態(touching)」を表わします。空間の範囲は前後「1」〜「-1」となっています。
まずホバーの場合は、表示されている円がBlueの色になります。タッチ・ポイントの位置をメンバー変数「x」と「y」に格納します。
Win32 APIのSetCursorPos(touchPoint.X, touchPoint.Y)と指定します。タッチ・ポイントの位置とマウスカーソルの位置が同じ位置に表示されます。
apimouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)と指定して、マウスの左ボタンを外した状態にします。
画面に表示されている指の数をleap.Frame.Fingers.Countプロパティで取得して、メンバー変数「FingersCount」に格納しておきます(リスト9)。
リスト9 ホバー時の処理(MainWindow.xaml.vb)
For Each Pointable As Pointable In leap.Frame.Pointables ……コード略(前述)…… If Pointable.TouchDistance > 0 AndAlso Pointable.TouchZone <> Global.Leap.Pointable.Zone.ZONENONE Then touchIndicator.Color = Colors.Blue x = 0 y = 0 x = touchPoint.X y = touchPoint.Y SetCursorPos(touchPoint.X, touchPoint.Y) apimouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) FingersCount = leap.Frame.Fingers.Count' 表示されている指の本数を取得して、メンバ変数FingersCountに格納しておく ……コード略(続きは後述)…… End If Next
次にタッチした処理になります。タッチした場合は、表示されている円が赤に変わります。
Updateメソッド(タッチ)の処理
指が1本認識されている場合は、SetCursorPos(touchPoint.X, touchPoint.Y)と指定して、タッチ・ポイントとカーソルの位置を同じ位置に表示します。
apimouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0) apimouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
と指定して、マウスを動かした処理と、マウスの左ボタンを押した処理を行います。
タッチ以外の処理ではタッチ・ポイントの色がGoldになり、
SetCursorPos(touchPoint.X, touchPoint.Y) apimouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
と指定します。
具体的にはリスト10のコードになります。
リスト10 タッチとタッチ以外の処理
If Pointable.TouchDistance > 0 AndAlso Pointable.TouchZone <> Global.Leap.Pointable.Zone.ZONENONE Then ……コード略(前述)…… ElseIf Pointable.TouchDistance <= 0 Then touchIndicator.Color = Colors.Red If FingersCount = 1 Then SetCursorPos(touchPoint.X, touchPoint.Y) ' 指が1本認識されている場合は、タッチ・ポイントとカーソルの位置を同じ位置に表示する。 apimouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0) apimouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) End If 'タッチ対象外 Else touchIndicator.Color = Colors.Gold SetCursorPos(touchPoint.X, touchPoint.Y) apimouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) End If Next End Sub
inkCanvas1_MouseDownメソッドの処理
次にinkCanvas1の上でマウスが押下された時の処理です。
一度inkCanvas1の内容をクリアしておきます。
inkCanvas1の編集モードがInkCanvasEdithingMode.Noneの時の処理です。
新しいRectangleクラスのインスタンスrectを作成します。Point型メンバー変数pにinkCanvas1に対する相対的なマウスポインターの位置をe.GetPosition(inkCanvas1)で格納します。
RectオブジェクトのSetValueメソッドでInkCanvasのLeftPropertyとTopPropertyにinkCanvas1に対するXとY座標を指定します。RectオブジェクトのWidthとHeightを設定します。rectオブジェクトのStrokeDashArray(破線パターンを設定するプロパティ)プロパティに変数doubles(2,2)の値を指定して、破線とします。StrokeThickness(アウトラインの幅)には3を指定します。アウトラインの色にはGoldを指定し、FillにはTransparent(透明色)を指定します。inkCanvas1にrectオブジェクトを追加します。
画像の上でタッチするとGoldの破線枠が表示されます。具体的なコードはリスト11になります。
リスト11 inkCanvas1_MouseDownメソッドの処理
Private Sub inkCanvas1_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles inkCanvas1.MouseDown messageTextBlock.Text = String.Empty inkCanvas1.Children.Clear() Button1.IsEnabled = True If inkCanvas1.EditingMode = InkCanvasEditingMode.None Then rect = New Rectangle p = e.GetPosition(inkCanvas1) rect.SetValue(InkCanvas.LeftProperty, p.X) rect.SetValue(InkCanvas.TopProperty, p.Y) rect.Width = p.X rect.Height = p.Y Dim doubles As New DoubleCollection doubles.Add(2) doubles.Add(2) rect.StrokeDashArray = doubles ' StrokeDashArray(2,2)と同じ rect.StrokeThickness = 3 rect.Stroke = New SolidColorBrush(Colors.Gold) rect.Fill = New SolidColorBrush(Colors.Transparent) inkCanvas1.Children.Add(rect) End If End Sub
inkCanvas1_MouseMoveメソッドの処理
inkCanvas1上でマウスカーソルを移動させた時の処理です。
Point型変数p2にinkCanvas1に対する相対的なマウスポインターの位置をe.GetPosition(inkCanvas1)で格納します。
選択した移動距離の範囲を変数wとhに格納します。移動距離のwの値が0.1と同じか少なかった場合は、rectオブジェクトのSetValueメソッドでInkCanvas.LeftPropertyに移動した範囲のXの値を指定します。rectのWidthに移動した距離を指定します。
移動した距離のhの値が0.1かそれより少なかった場合は、rectオブジェクトのSetValueメソッドでInkCanvas.TopPropertyに移動した範囲のYの値を指定します。rectのHeightに移動した距離を指定します。
具体的なコードはリスト12になります。
リスト12 inkCanvas1_MouseMoveメソッドの処理
Private Sub inkCanvas1_MouseMove(sender As Object, e As MouseEventArgs) Handles inkCanvas1.MouseMove If rect Is Nothing = False Then Dim p2 As Point = e.GetPosition(inkCanvas1) Dim w As Double = p2.X - p.X ' X座標の移動した距離 Dim h As Double = p2.Y - p.Y ' Y座標の移動した距離 If (w <= 0.1) Then rect.SetValue(InkCanvas.LeftProperty, p2.X) rect.Width = p.X - p2.X Else rect.Width = w End If If (h <= 0.1) Then rect.SetValue(InkCanvas.TopProperty, p2.Y) rect.Height = p.Y - p2.Y Else rect.Height = h End If Else Exit Sub End If End Sub
[切り取る(Button1)]がクリックされた時の処理(Button1_Clickメソッド)
File.OpenReadメソッドで、ソリューション・エクスプローラー内のImageフォルダ内の画像を読み取り、streamで参照します。
BitmapImageの新しいインスタンスbmpオブジェクトを作成します。BeginInitでBitmapImageの初期化を開始します。BitmapImageのストリームソースにstreamを指定します。EndInitで初期化を終了します。
bmpオブジェクトで初期化された新しいWriteableBitmapのインスタンスmyWriteableBitmapオブジェクトを作成します。BitmapFactory.ConvertToPbgra32Format(bmp)でbmpをPbgra32フォーマットに変換します。
この変換を行っていないとエラーが表示されますので、注意してください。
WriteableBitmapExのCropメソッドで、選択した範囲を切り取ります。切り取った画像をresultImageに表示します。[保存]ボタンの使用を可能にします。
具体的なコードはリスト13になります。
リスト13 Button1_Clickメソッド処理
Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Using stream = File.OpenRead("Image/冬の桜.jpg") Dim bmp As BitmapImage = New BitmapImage bmp.BeginInit() bmp.StreamSource = stream bmp.EndInit() Dim myWriteableBitmap = New WriteableBitmap(bmp) myWriteableBitmap = BitmapFactory.ConvertToPbgra32Format(bmp) Dim myCrop = myWriteableBitmap.Crop(rect.GetValue(InkCanvas.LeftProperty), rect.GetValue(InkCanvas.TopProperty), rect.Width, rect.Height) ' 選択した範囲をCropメソッドで切り取る resultImage.Source = Nothing resultImage.Source = myCrop ' 切り取った画像を表示する End Using saveButton.IsEnabled = True End Sub
inkCanvas1_MouseUpメソッドの処理
ReleaseAllTouchCapturesメソッドで、キャプチャされている全てのタッチデバイスをこの要素から解放します。
コードはリスト14になります。
リスト14 inkCanvas1_MouseUpメソッドの処理
Private Sub inkCanvas1_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles inkCanvas1.MouseUp inkCanvas1.ReleaseAllTouchCaptures() End Sub
[保存(saveButton)]がクリックされた時の処理(saveButton_Clickメソッド)
切り出された画像の表示されている、resultImage.Sourceで初期化された、新しいWriteableBitmapのオブジェクトbmpを作成します。PngBitmapEncoderでPNG形式のイメージのエンコードに使用される新しいエンコーダーのインスタンス、myEncoderを作成します。
指定したBitmapSourceから新しいBitmapFrameを作成して、myEncoderに追加します。
File.Opneメソッドで保存するフォルダとファイル名(TrimmingTest.png)を連結して、フォルダにファイルを書きこみ、FileStream変数fsで参照します。
myEncoder.Save(fs)でビットマップイメージを指定したStream(fs)にエンコードします。
保存した旨のメッセージを表示し、[切り取る]と[保存]ボタンの使用を不可とします。
具体的なコードはリスト15になります。
リスト15 saveButton_Clickメソッド
Private Sub saveButton_Click(sender As Object, e As RoutedEventArgs) Handles saveButton.Click Dim bmp As New WriteableBitmap(resultImage.Source) Dim myEncoder = New PngBitmapEncoder myEncoder.Frames.Add(BitmapFrame.Create(bmp)) Using fs As FileStream = File.Open(System.IO.Path.Combine(savePath, "TrimmingTest.png"), FileMode.Create) myEncoder.Save(fs) ' 指定したフォルダにTrimmingTest.pngとして保存する End Using messageTextBlock.Text = savePath & "フォルダにTrimmingTest.pngとして保存しました。" Button1.IsEnabled = False saveButton.IsEnabled = False End Sub
※注意
今回紹介したサンプルコードを動かす際には、「LeapCSharp.NET4.0.dll」や「LeapCSharp.dll」、「Leap.dll」を読者の皆さん自身のフォルダ内にあるDLLファイルに指定し直さなければ動かない可能性があるので、動かない場合は再指定して下さい。
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ストアに申請して認定させる