音声認識と手書き認識を使ってみよう
手書きの文字を判別して読み上げる
このサンプルでは、文字認識に「Microsoft 日本語手書き認識エンジン」を使用しています。そのため、日本語版Windows 8.1 OS上でしか動作しないので、注意してください。
また、このアプリの操作には、ペンの付属しているタブレットPCが一番適しているかもしれません。タッチディスプレイでないディスプレイでも動作しますが手書き文字をマウスで書く必要があるため、認識率が低下する恐れがあります。
プロジェクト名は「freeHandRecognize」とします。使用するコントロールは表2を参照してください。
コントロール | 名前 | 役割 |
---|---|---|
Canvas | myCanvas | この領域に文字を手書きで書く |
Button | recognizeButton | 手書き文字を認識して読み上げるボタン |
Button | clearButton | 手書き文字を消すボタン |
MediaElement | MediaElement1 | 読み上げるためのメディア |
表2のコントロールをレイアウトすると図3のようになります。
書き出されるXAMLをリスト3のように編集します。
リスト3 編集されたXAMLコード(MainPage.xaml)
- (1) Grid要素をViewBox要素で括る。ViewBoxは、伸縮およびスケーリングを実行して単一の子を使用可能な領域全体に引き伸ばすことができるコンテンツ デコレータを定義する要素です。これによって画面の解像度に応じてオブジェクトのサイズも調整されて表示されるようになる。
- (2)Canvas要素を配置し、Backgroundで背景色をWhiteにしておく。
- (3)Button要素を配置し、Contentプロパティに「読み上げる」と指定する。プロパティのIsEnabledにFalseを指定して、最初の状態では使用不可としている。このIsEnabledプロパティは、プロパティのペインの中に表示されない。筆者が見つけることができないだけかもしれないが、そこで、直接Button要素の後ろに半角スぺ—スを入れてプロパティを表示させ、そこから設定している。
- (4)Button要素を配置し、Contentプロパティに「消去」と指定している。(3)と同じくIsEnabledにはFalseを指定しておく。
- (5)音声を発するためにMediaElement要素を配置する。
<Page x:Class="freeHandRecognize.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:freeHandRecognize" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Viewbox>■(1) <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="1363"> <Canvas x:Name="myCanvas" Background="White" Margin="-31,101,-31,88"/>■(2) <StackPanel Orientation="Horizontal" Margin="-31,704,-31,0" Background="Black" Height="100"> <Button Content="読み上げる" x:Name="recognizeButton" Height="66" VerticalAlignment="Bottom" Width="158" FontFamily="Meirio UI" FontSize="24" IsEnabled="False" Background="Navy" Foreground="Pink" Margin="20,0,0,19"/>■(3) <Button Content="消去" x:Name="clearButton" Height="66" VerticalAlignment="Bottom" Width="158" FontFamily="Meirio UI" FontSize="24" IsEnabled="False" Background="Navy" Foreground="Pink" Margin="20,0,0,19"/>■(4) </StackPanel> <StackPanel HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="1428" Background="Black" Margin="-31,0" Orientation="Horizontal"> <TextBlock HorizontalAlignment="Left" Height="91" Margin="19,6,0,3" TextWrapping="Wrap" Text="手書き文字の認識読み上げ" Width="936" FontFamily="Meirio UI" FontSize="72" FontWeight="Bold" Foreground="Crimson"/> <MediaElement x:Name="MediaElement1" Height="33" Margin="300,36,0,0" VerticalAlignment="Top" Width="131"/>■(5) </StackPanel> </Grid> </Viewbox>■(1) </Page>
では、次にMainPage.xaml.vb内にプログラムコードを記述します。
プログラムコード
まず名前空間を読み込みます(リスト4)。
リスト4 名前空間の読み込み
Windows 8のインクシステムをサポートするクラスの含まれる、Windows.UI.Input.Inking名前空間をインポートする。インクストロークを描画する場合等に、この名前空間に含まれるクラスを使用する。
Imports Windows.UI.Input.Inking
タッチ、スタイラス ・ ペン、マウス、およびキーボード デバイス等の入力をサポートするクラスの含まれる、Windows.UI.Input名前空間をインポートする。
Imports Windows.UI.Input
ポインター、タッチ、マウス、およびキーボードを識別し、それらのデバイスに関する情報を取得するクラスの含まれる、 Windows.Devices.Input名前空間をインポートする。
Imports Windows.Devices.Input
図形に関するクラスの含まれる、Windows.UI.Xaml.Shapes名前空間をインポートする。
Imports Windows.UI.Xaml.Shapes Imports Windows.UI
最新の HTTP アプリケーションのプログラミング インターフェイスを提供するクラスの含まれる、System.Net.Http 名前空間をインポートする。
Imports System.Net.Http Imports Windows.UI.Popups Public NotInheritable Class MainPage Inherits Page
次にメンバー変数を定義する(リスト5)
リスト5 メンバー変数の定義
ポインター入力位置のクライアント座標を取得して格納する、Point型のメンバー変数prevContactPointを宣言する。(ポインターデバイスが開始された時のポインター入力位置)。Pointクラスは、2 次元の座標系の点をカプセル化するクラスです。
Private prevContactPoint As Point
入力、操作、および 1 つ以上の(手書きの認識を含む)の処理を管理するプロパティとメソッドを提供するクラスである、 InkManagerクラスのインスタンスである、メンバー変数myInkManagerを宣言する。
Private myInkManager As New InkManager
入力ポインターの一意の識別子を取得して格納するメンバー変数myPenIDメンバー変数を宣言する。
Private myPenID As UInteger
ポインター入力位置のクライアント座標を取得して格納する、Pointクラス型のメンバー変数currentContactPointを宣言する(ポインターが移動した時のポインター入力位置)。
Private currentContactPoint As Point
ポインターデバイスが開始された時のX、Y座標(x1,y1)、ポインターが移動した時のX、Y座標(x2,y2)を格納するDouble型のメンバー変数を宣言しておく。
Private x1 As Double Private x2 As Double Private y1 As Double Private y2 As Double
手書き文字を認識した結果の文字を入力しておく文字列型のメンバー変数dummyTextBoxを宣言しておく。
Private dummyTextBox As String
音声として発生する文字を格納する、readingTextメンバー変数を宣言する。
Private readingText As String
次は、ページがアクティブになった時の処理です(リスト6)
リスト6 ページがアクティブになった時の処理
AddHandlerステートメントで、要素内で、プレスアクションを起こし、ポインターデバイスが開始された時に発生する、PointerPressedイベントに、myCanvas_PointerPressedイベントハンドラを追加する。
AddHandlerステートメントで、要素内で、ポインターが移動した時に発生する、PointerMovedイベントに、myCanvas_PointerMovedイベントハンドラを追加する。
AddHandlerステートメントで、要素内で、プレス アクションを開始したポインター デバイスが離された時に発生するPointerReleasedイベントに、myCanvas_PointerReleasedイベントハンドラを追加する。
AddHandlerステートメントで、要素の領域からポインターが離れた時に発生する、PointerExitedイベントに、myCanvas_PointerReleasedイベントハンドラを追加する。
Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs) AddHandler myCanvas.PointerPressed, AddressOf myCanvas_PointerPressed AddHandler myCanvas.PointerMoved, AddressOf myCanvas_PointerMoved AddHandler myCanvas.PointerReleased, AddressOf myCanvas_PointerReleased AddHandler myCanvas.PointerExited, AddressOf myCanvas_PointerReleased End Sub
次は、要素内で、プレスアクションを起こし、ポインターデバイスが開始された時に発生するイベントの処理です(リスト7)
リスト7 要素内で、プレスアクションを起こし、ポインターデバイスが開始された時に発生するイベントの処理
単一のマウス、ペン/スタイラス、またはタッチに関連付けられた入力のポインターを提供するクラスである、PointerPoint型の変数myPointerを宣言し、GetCurrentPointメソッドで、Canvasの現在のポインターを取得する。PointerPointクラスのPositionプロパティで、ポインター入力の位置のクライアント座標を取得し、メンバー変数prevContactPointに格納する。
現在の、ポインターデバイスのPointerDeviceTypeを取得する。
ポインターデバイスのタイプが、ペン、またはマウス、またはタッチで、かつ、入力がマウスの左ボタン押下、またはその他の入力メソッドの左ボタン押下からであった場合の処理です。[読み上げる]ボタンの使用を可能にする。InkManagerクラスのProcessPointerDownメソッドで、Canvasの、初期の接触位置と圧力、および傾きなどの接触点の位置や機能に関する情報を処理する。InkManagerクラスは、入力、操作、および 1つ以上の処理(手書きの認識を含む)を管理するプロパティとメソッドを提供するクラスです。PointerIdで、入力ポインターの一意の識別子を取得して、メンバー変数myPenIDに格納しておく。
Private Sub myCanvas_PointerPressed(sender As Object, e As PointerRoutedEventArgs) Try Dim myPointer As PointerPoint = e.GetCurrentPoint(myCanvas) prevContactPoint = myPointer.Position Dim myPointerDevType As PointerDeviceType = e.Pointer.PointerDeviceType If myPointerDevType = PointerDeviceType.Pen Or myPointerDevType = PointerDeviceType.Mouse Or myPointerDevType = PointerDeviceType.Touch And myPointer.Properties.IsLeftButtonPressed = True Then myInkManager.ProcessPointerDown(myPointer) myPenID = myPointer.PointerId e.Handled = True End If Catch Exit Sub End Try End Sub
次は、要素内で、ポインターが移動した時に発生するイベントの処理です(リスト8)