今までのエントリーで利用してきた音声認識エンジンはSpeechPlatform10.2でした。
しかし、すでにSpeechPlatform11がリリースされています。
今回は新しいバージョンで動くのかチェックしてみました。
すでに10.2をインストールしている場合にはアンインストールする必要があります。
バージョン11のダウンロード先です。
SDK
http://www.microsoft.com/download/en/details.aspx?id=27226
リンク先にはx86用とx64用がありますが使用中のOSに合わせてダウンロードすればいいと思います。SDKは2つともインストールする必要はないでしょう。
Runtime
http://www.microsoft.com/download/en/details.aspx?id=27225
ランタイムはOSが64ビットの場合x86、x64ともにインストールする必要があると思います。
Runtime Languages
http://www.microsoft.com/download/en/details.aspx?id=27224
ダウンロードするファイルは「MSSpeech_SR_ja-JP_TELE.msi」になります。
上記のファイルをすべてインストールしてください。
プログラム上の変更点は認識エンジンのIDを設定する箇所を「SR_MS_ja-JP_TELE.11.0」に変更すればOKです。
ちなみにバージョン11では「SR_MS_en-US_Kinect.10.0」は利用できないので11用のRuntimeLanguageをダウンロードしましょう。
2011年12月29日木曜日
2011年12月26日月曜日
KINECT SDK 日本語で音声認識(VB+WPF)
KINECT SDKの音声認識サンプルプログラムはコンソールアプリでしたが、WPFでも動くようにしてみました。WPFの場合はUI部分と音声認識部分は別スレッドにする必要があります。
まずは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="241" Width="668">
<Grid Name="Grid1" Height="151">
<TextBox Height="54" HorizontalAlignment="Left" Margin="0,12,0,0" Name="TextBox1" VerticalAlignment="Top" Width="634" FontSize="20" Grid.ColumnSpan="2" Grid.RowSpan="2" />
<TextBox Height="54" HorizontalAlignment="Left" Margin="0,72,0,0" Name="TextBox2" VerticalAlignment="Top" Width="634" FontSize="20" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="2" />
</Grid>
</Window>
Imports Microsoft.Research.Kinect.Audio
Imports Microsoft.Research.Kinect.Nui
Imports Microsoft.Speech.AudioFormat
Imports Microsoft.Speech.Recognition
Imports System.Media
Imports System.IO
Imports System.Threading
Imports System.Windows.Threading
Class MainWindow
Inherits Window
Private nui As Runtime
Private cam As Camera
Private readerThread As Thread
Const ri_ID As String = "SR_MS_ja-JP_TELE_10.0"
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
If Runtime.Kinects.Count > 0 Then
''KINECT初期化
nui = Runtime.Kinects(0)
nui.Initialize(RuntimeOptions.UseColor)
cam = nui.NuiCamera
camInit()
Else
MsgBox("KINECTが見つかりません。")
Exit Sub
End If
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
''音声認識スレッド
readerThread = New Thread(New ThreadStart(AddressOf SpeechThread))
''スレッドスタート
readerThread.Start()
End Sub
Private Sub SpeechThread()
''音声認識準備
Dim source = New KinectAudioSource()
With source
.FeatureMode = True
.AutomaticGainControl = False
.SystemMode = SystemMode.OptibeamArrayOnly
End With
''認識エンジン選択
Dim ri As RecognizerInfo = GetKinectRecognizer()
If IsNothing(ri) = True Then
MsgBox("認識エンジンが見つかりませんでした。")
Exit Sub
End If
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
TextBox1.Text = ri.Name
End Sub))
Dim sre As New SpeechRecognitionEngine(ri.Id)
Dim w As New Choices
With w
.Add("うえ")
.Add("した")
.Add("最初")
.Add("終わり")
End With
Dim gb As New GrammarBuilder
gb.Culture = ri.Culture
gb.Append(w)
Dim g As New Grammar(gb)
sre.LoadGrammar(g)
AddHandler sre.SpeechRecognized, AddressOf SreSpeechRecognized
AddHandler sre.SpeechRecognitionRejected, AddressOf SreSpeechRecognitionRejected
Dim s As Stream = source.Start
sre.SetInputToAudioStream(s,
New SpeechAudioFormatInfo(EncodingFormat.Pcm,
16000,
16,
1,
32000,
2,
Nothing))
sre.RecognizeAsync(RecognizeMode.Multiple)
End Sub
Private Sub camInit()
''カメラ初期位置
cam.ElevationAngle = 0
End Sub
Private Sub camUp()
''カメラ上向き
Dim nowangle = cam.ElevationAngle + 5
If nowangle > 25 Then
cam.ElevationAngle = 25
Else
cam.ElevationAngle = nowangle
End If
End Sub
Private Sub camDown()
''カメラ下向き
Dim nowangle = cam.ElevationAngle - 5
If nowangle < -25 Then
cam.ElevationAngle = -25
Else
cam.ElevationAngle = nowangle
End If
End Sub
Private Function GetKinectRecognizer()
Return SpeechRecognitionEngine.InstalledRecognizers().Where(Function(r) r.Id = ri_ID).FirstOrDefault
End Function
Private Sub SreSpeechRecognized(ByVal sender As Object, ByVal e As SpeechRecognizedEventArgs)
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
TextBox2.Text = "認識しました:" & e.Result.Text
End Sub))
Select Case e.Result.Text
Case "うえ"
camUp()
Case "した"
camDown()
Case "最初"
camInit()
''Case "終わり"
End Select
End Sub
Private Sub SreSpeechRecognitionRejected(ByVal sender As Object, ByVal e As SpeechRecognitionRejectedEventArgs)
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
TextBox2.Text = "認識できません。"
End Sub))
End Sub
Private Sub Window_Unloaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
''KINECT終了
nui.Uninitialize()
''スレッド終了
readerThread.Abort()
readerThread.Join()
End Sub
End Class
まずは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="241" Width="668">
<Grid Name="Grid1" Height="151">
<TextBox Height="54" HorizontalAlignment="Left" Margin="0,12,0,0" Name="TextBox1" VerticalAlignment="Top" Width="634" FontSize="20" Grid.ColumnSpan="2" Grid.RowSpan="2" />
<TextBox Height="54" HorizontalAlignment="Left" Margin="0,72,0,0" Name="TextBox2" VerticalAlignment="Top" Width="634" FontSize="20" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="2" />
</Grid>
</Window>
---------------------------------------------------------------------------------
テキストボックスを2つ配置しています。
メインソースです。
---------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Audio
Imports Microsoft.Research.Kinect.Nui
Imports Microsoft.Speech.AudioFormat
Imports Microsoft.Speech.Recognition
Imports System.Media
Imports System.IO
Imports System.Threading
Imports System.Windows.Threading
Class MainWindow
Inherits Window
Private nui As Runtime
Private cam As Camera
Private readerThread As Thread
Const ri_ID As String = "SR_MS_ja-JP_TELE_10.0"
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
If Runtime.Kinects.Count > 0 Then
''KINECT初期化
nui = Runtime.Kinects(0)
nui.Initialize(RuntimeOptions.UseColor)
cam = nui.NuiCamera
camInit()
Else
MsgBox("KINECTが見つかりません。")
Exit Sub
End If
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
''音声認識スレッド
readerThread = New Thread(New ThreadStart(AddressOf SpeechThread))
''スレッドスタート
readerThread.Start()
End Sub
Private Sub SpeechThread()
''音声認識準備
Dim source = New KinectAudioSource()
With source
.FeatureMode = True
.AutomaticGainControl = False
.SystemMode = SystemMode.OptibeamArrayOnly
End With
''認識エンジン選択
Dim ri As RecognizerInfo = GetKinectRecognizer()
If IsNothing(ri) = True Then
MsgBox("認識エンジンが見つかりませんでした。")
Exit Sub
End If
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
TextBox1.Text = ri.Name
End Sub))
Dim sre As New SpeechRecognitionEngine(ri.Id)
Dim w As New Choices
With w
.Add("うえ")
.Add("した")
.Add("最初")
.Add("終わり")
End With
Dim gb As New GrammarBuilder
gb.Culture = ri.Culture
gb.Append(w)
Dim g As New Grammar(gb)
sre.LoadGrammar(g)
AddHandler sre.SpeechRecognized, AddressOf SreSpeechRecognized
AddHandler sre.SpeechRecognitionRejected, AddressOf SreSpeechRecognitionRejected
Dim s As Stream = source.Start
sre.SetInputToAudioStream(s,
New SpeechAudioFormatInfo(EncodingFormat.Pcm,
16000,
16,
1,
32000,
2,
Nothing))
sre.RecognizeAsync(RecognizeMode.Multiple)
End Sub
Private Sub camInit()
''カメラ初期位置
cam.ElevationAngle = 0
End Sub
Private Sub camUp()
''カメラ上向き
Dim nowangle = cam.ElevationAngle + 5
If nowangle > 25 Then
cam.ElevationAngle = 25
Else
cam.ElevationAngle = nowangle
End If
End Sub
Private Sub camDown()
''カメラ下向き
Dim nowangle = cam.ElevationAngle - 5
If nowangle < -25 Then
cam.ElevationAngle = -25
Else
cam.ElevationAngle = nowangle
End If
End Sub
Private Function GetKinectRecognizer()
Return SpeechRecognitionEngine.InstalledRecognizers().Where(Function(r) r.Id = ri_ID).FirstOrDefault
End Function
Private Sub SreSpeechRecognized(ByVal sender As Object, ByVal e As SpeechRecognizedEventArgs)
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
TextBox2.Text = "認識しました:" & e.Result.Text
End Sub))
Select Case e.Result.Text
Case "うえ"
camUp()
Case "した"
camDown()
Case "最初"
camInit()
''Case "終わり"
End Select
End Sub
Private Sub SreSpeechRecognitionRejected(ByVal sender As Object, ByVal e As SpeechRecognitionRejectedEventArgs)
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
TextBox2.Text = "認識できません。"
End Sub))
End Sub
Private Sub Window_Unloaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
''KINECT終了
nui.Uninitialize()
''スレッド終了
readerThread.Abort()
readerThread.Join()
End Sub
End Class
---------------------------------------------------------------------------------
UIスレッドでは音声スレッドのスタートのみ行っています。
コンソール版での音声認識部分を音声認識スレッドとしています。
2011年12月19日月曜日
KINECT SDK Beta2 でスケルトンデータを扱う( VB+ WPF )
このエントリはKINECT SDK Advent Calendar : ATNDの12月19日分です。
kaorun55氏の「KINECT SDK Beta2 でスケルトンデータを扱う( C# + WPF ) のVB版になります。
いつもと同じように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="521" Width="661">
<Grid>
<Image Height="480" Name="Image1" Width="640" />
</Grid>
</Window>
kaorun55氏の「KINECT SDK Beta2 でスケルトンデータを扱う( C# + WPF ) のVB版になります。
いつもと同じように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="521" Width="661">
<Grid>
<Image Height="480" Name="Image1" Width="640" />
</Grid>
</Window>
--------------------------------------------------------------------------------
特別なところはありません。Imageコントロールが1つだけです。
メインソースです。
--------------------------------------------------------------------------------
Imports System.Threading
Imports System.Windows.Threading
Imports System.Windows.Media
Imports Microsoft.Research.Kinect.Nui
Class MainWindow
Inherits Window
Private readerThread As Thread
Private shouldRun As Boolean
Private kinect As Runtime
Private usercolor() As Color = {Color.FromRgb(0, 0, 0), Colors.Red, Colors.Green, Colors.Blue, Colors.Yellow, Colors.Magenta, Colors.Pink}
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
If Runtime.Kinects.Count > 0 Then
''KINECT初期化
kinect = Runtime.Kinects(0)
kinect.Initialize(RuntimeOptions.UseColor Or RuntimeOptions.UseDepthAndPlayerIndex Or RuntimeOptions.UseSkeletalTracking)
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color)
kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex)
''スレッドの開始
shouldRun = True
readerThread = New Thread(New ThreadStart(AddressOf RenderThread))
readerThread.Start()
End If
End Sub
Sub RenderThread()
While (shouldRun)
''タイムアウトは100ms
Dim video As ImageFrame = kinect.VideoStream.GetNextFrame(100)
Dim depth As ImageFrame = kinect.DepthStream.GetNextFrame(100)
Dim skeleton As SkeletonFrame = kinect.SkeletonEngine.GetNextFrame(100)
''メインスレッドにイメージデータの書き込みを指示
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
Dim drawingVisual As New DrawingVisual
Using drawingContext As DrawingContext = drawingVisual.RenderOpen()
drawingContext.DrawImage(DrawPixels(kinect, video, depth), New Rect(0, 0, video.Image.Width, video.Image.Height))
''骨格の部位ごとに座標を求める
For Each s In skeleton.Skeletons
If s.TrackingState = SkeletonTrackingState.Tracked Then
For Each j In s.Joints
Dim point As Point = GetVideoPoint(j)
'円を描く
drawingContext.DrawEllipse(New SolidColorBrush(Colors.Red), New Pen(Brushes.Red, 1), New Point(point.X, point.Y), 5, 5)
Next
End If
Next
End Using
'描画可能なビットマップを作る
Dim bitmap As RenderTargetBitmap = New RenderTargetBitmap(video.Image.Width, video.Image.Height, 96, 96, PixelFormats.Default)
bitmap.Render(drawingVisual)
Image1.Source = bitmap
End Sub
))
End While
End Sub
Function DrawPixels(ByVal kinect As Runtime, ByVal video As ImageFrame, ByVal depth As ImageFrame) As WriteableBitmap
Dim x, y, index As Integer
Dim playerIndex, distance As Integer
Dim videoX, videoY, videoIndex As Integer
Dim byte0, byte1 As Byte
'ピクセルごとのユーザーID
For y = 0 To depth.Image.Height - 1
For x = 0 To depth.Image.Width - 1
index = (x + (y * depth.Image.Width)) * 2
byte0 = depth.Image.Bits(index)
byte1 = depth.Image.Bits(index + 1)
'ユーザーIDと距離
playerIndex = byte0 And &H7
distance = byte1 << 5 Or byte0 >> 3
If playerIndex <> 0 Then
videoX = 0
videoY = 0
''深度データの座標からカラーデータの座標へ変換
kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, New ImageViewArea(), x, y, 0, videoX, videoY)
videoIndex = (videoX + (videoY * video.Image.Width)) * video.Image.BytesPerPixel
videoIndex = Math.Min(videoX, video.Image.Bits.Length - video.Image.BytesPerPixel)
video.Image.Bits(videoIndex) = usercolor(playerIndex).R
video.Image.Bits(videoIndex + 1) = usercolor(playerIndex).G
video.Image.Bits(videoIndex + 2) = usercolor(playerIndex).B
End If
Next
Next
'バイト列をビットマップに展開
'描画可能なビットマップを作る
Dim bitmap As WriteableBitmap = New WriteableBitmap(video.Image.Width, video.Image.Height, 96, 96, PixelFormats.Bgr32, Nothing)
bitmap.WritePixels(New Int32Rect(0, 0, video.Image.Width, video.Image.Height), video.Image.Bits, video.Image.Width * video.Image.BytesPerPixel, 0)
Return bitmap
End Function
Function GetVideoPoint(ByVal joint As Joint) As Point
Dim kinect As Runtime = Runtime.Kinects(0)
Dim depthX, depthY As Single
Dim videoX, videoY As Integer
depthX = 0
depthY = 0
''骨格データ(ベクタ座標)から深度データの座標へ変換
kinect.SkeletonEngine.SkeletonToDepthImage(joint.Position, depthX, depthY)
depthX = Math.Min(depthX * kinect.DepthStream.Width, kinect.DepthStream.Width)
depthY = Math.Min(depthY * kinect.DepthStream.Height, kinect.DepthStream.Height)
videoX = 0
videoY = 0
''深度データの座標をカラーデータの座標に変換
kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, New ImageViewArea(), CInt(depthX), CInt(depthY), 0, videoX, videoY)
Return New Point(Math.Min(videoX, kinect.VideoStream.Width), Math.Min(videoY, kinect.VideoStream.Height))
End Function
Private Sub Window_Unloaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
shouldRun = False
End Sub
End Class
--------------------------------------------------------------------------------
Skeletonの座標データはKINECTを中心にXYZの3D座標になります。
XYは-1~1までの単精度浮動小数になるのでこれを2Dの座標に変換しなければいけないのですが、手順としてSkeleton座標>Depth(深度)座標>Video(カラー)座標の順番に変換しています。
Skeleton>Depthの変換はSkeletonToDepthImageで変換します。
Depth>Videoの変換はGetColorPixelCoordinatesFromDepthPixelを使って変換しています。
変換した座標をもとにShapeを描画すればVideo,Depthのイメージに骨格情報を重ねて表示できます。
2011年12月18日日曜日
KINECT SDK Beta2 でユーザーデータを扱う( VB + WPF )
このエントリはKINECT SDK Advent Calendar : ATNDの12月18日分です。
kaorun55氏の「KINECT SDK Beta2 でユーザーデータを扱う( C# + WPF )」 を参考にVBに書き換えました。
まずは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="521" Width="661">
<Grid>
<Image Height="480" Name="Image1" Width="640" />
</Grid>
</Window>
--------------------------------------------------------------------------------
今までのサンプルと同様です。
メインソースです。
--------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Imports System.Threading
Imports System.Windows.Threading
Class MainWindow
Inherits Window
Private readerThread As Thread
Private shuldRun As Boolean
Private kinect As Runtime
Private usercolor() As Color = {Color.FromRgb(0, 0, 0), Colors.Red, Colors.Green, Colors.Blue, Colors.Yellow, Colors.Magenta, Colors.Pink}
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
If Runtime.Kinects.Count > 0 Then
''KINECT初期化
kinect = Runtime.Kinects(0)
kinect.Initialize(RuntimeOptions.UseColor Or RuntimeOptions.UseDepthAndPlayerIndex)
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color)
kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex)
shuldRun = True
''スレッド作成
readerThread = New Thread(New ThreadStart(AddressOf RenderThread))
''スレッド開始
readerThread.Start()
End If
End Sub
Sub RenderThread()
''Imageコントロールに書き込むスレッド
While (shuldRun)
''映像データの取り込み
kinect = Runtime.Kinects(0)
''タイムアウトは100ms
Dim video As ImageFrame = kinect.VideoStream.GetNextFrame(100)
Dim depth As ImageFrame = kinect.DepthStream.GetNextFrame(100)
For y = 0 To depth.Image.Height - 1
For x = 0 To depth.Image.Width - 1
Dim index As Integer = (x + (y * depth.Image.Width)) * 2
Dim byte0 As Byte = depth.Image.Bits(index)
Dim byte1 As Byte = depth.Image.Bits(index + 1)
Dim playerIndex As Integer = byte0 And &H7
Dim distance As Integer = byte1 << 5 Or byte0 >> 3
If playerIndex <> 0 Then
Dim videoX As Integer = 0
Dim videoY As Integer = 0
''深度データからカラーデータに座標変換
kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, New ImageViewArea(), x, y, 0, videoX, videoY)
Dim videoIndex As Integer = (videoX + (videoY * video.Image.Width)) * video.Image.BytesPerPixel
videoIndex = Math.Min(videoIndex, video.Image.Bits.Length - video.Image.BytesPerPixel)
video.Image.Bits(videoIndex) = usercolor(playerIndex).R
video.Image.Bits(videoIndex + 1) = usercolor(playerIndex).G
video.Image.Bits(videoIndex + 2) = usercolor(playerIndex).B
End If
Next
Next
''メインスレッド経由でイメージの書込み
Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
Sub()
Image1.Source = BitmapImage.Create(video.Image.Width, video.Image.Height, 96, 96, PixelFormats.Bgr32, Nothing, video.Image.Bits, video.Image.Width * video.Image.BytesPerPixel)
End Sub))
End While
End Sub
Private Sub Window_Unloaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
shuldRun = False
End Sub
End Class
--------------------------------------------------------------------------------
7人まで認識するはずですが、試していません。
2011年12月17日土曜日
KINECT SDK 挿抜状態検出サンプル
このエントリはKINECT SDK Advent Calendar : ATNDの12月17日分です。
kaorun55氏の「KINECT SDK Beta2 で、挿抜状態に応じたアプリの動作をする 」 を参考にVBに書き換えました。
まずは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="557" Width="669">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="149*" />
<RowDefinition Height="389*" />
</Grid.RowDefinitions>
<TextBox Name="kinectCount" Margin="0,0,0,97" FontSize="18" Text="Text" TextAlignment="Center" FontWeight="Bold" FontStretch="Normal" TextWrapping="NoWrap" VerticalContentAlignment="Center" />
<Image Name="image1" Height="240" Width="320" Margin="0,50,332,248" Grid.RowSpan="2" />
<Image Height="240" Margin="326,50,6,248" Name="image2" Width="320" Grid.RowSpan="2" />
<Image Height="240" Margin="0,149,332,0" Name="image3" Width="320" Grid.Row="1" />
<Image Height="240" Margin="326,149,6,0" Name="image4" Width="320" Grid.Row="1" />
</Grid>
</Window>
--------------------------------------------------------------------------------
TextBoxが1つとGrid内に4つのImageコントロールを配置しています。
メインソースです。
--------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Class MainWindow
''Imageコントロール用配列
Public images As New ArrayList
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
'イベントハンドラの追加
AddHandler Runtime.Kinects.StatusChanged, AddressOf Kinects_StatusChanged
''接続されているKINECTを確認
ShowKinectCount()
''接続されているKINECTの初期化
Dim kinect As Runtime
For Each kinect In Runtime.Kinects
InitKinect(kinect)
Next
''配列にImegeコントロールを追加
With images
.Add(image1)
.Add(image2)
.Add(image3)
.Add(image4)
End With
End Sub
Sub InitKinect(kinect As Runtime)
''KINECTの初期化
kinect.Initialize(RuntimeOptions.UseColor)
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color)
''イベントハンドラの追加
AddHandler kinect.VideoFrameReady, AddressOf Kinect_VideoFrameReady
End Sub
Sub Kinects_StatusChanged(ByVal sender As Object, ByVal e As StatusChangedEventArgs)
''KINECT接続数の確認
ShowKinectCount()
''ステータス別に処理
If e.Status = KinectStatus.Connected Then
''接続されたとき初期化
InitKinect(e.KinectRuntime)
ElseIf e.Status = KinectStatus.Disconnected Then
''切断されたとき
''一度すべてのImegeコントロールを初期化
Dim i As Integer
For i = 0 To Runtime.Kinects.Count
images(i).Source = Nothing
Next
''イベントハンドラの削除
RemoveHandler e.KinectRuntime.VideoFrameReady, AddressOf Kinect_VideoFrameReady
''KINECTの終了処理
e.KinectRuntime.Uninitialize()
End If
End Sub
Sub ShowKinectCount()
''接続されている台数を確認
kinectCount.Text = Runtime.Kinects.Count & "台のKINECTが有効です"
End Sub
Sub Kinect_VideoFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)
''切断された瞬間は書き込まないようにする
If IsNothing(sender) = False And sender.InstanceIndex >= 0 Then
Dim source As PlanarImage = e.ImageFrame.Image
images(sender.InstanceIndex).Source = BitmapSource.Create(source.Width, source.Height, 96, 96, PixelFormats.Bgr32, Nothing, source.Bits, source.Width * source.BytesPerPixel)
End If
End Sub
End Class
KINECTを1台しか持っていないので複数台接続してのチェックはできていません。
0台の状態での動作は大丈夫でした。
kaorun55氏の「KINECT SDK Beta2 で、挿抜状態に応じたアプリの動作をする 」 を参考にVBに書き換えました。
まずは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="557" Width="669">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="149*" />
<RowDefinition Height="389*" />
</Grid.RowDefinitions>
<TextBox Name="kinectCount" Margin="0,0,0,97" FontSize="18" Text="Text" TextAlignment="Center" FontWeight="Bold" FontStretch="Normal" TextWrapping="NoWrap" VerticalContentAlignment="Center" />
<Image Name="image1" Height="240" Width="320" Margin="0,50,332,248" Grid.RowSpan="2" />
<Image Height="240" Margin="326,50,6,248" Name="image2" Width="320" Grid.RowSpan="2" />
<Image Height="240" Margin="0,149,332,0" Name="image3" Width="320" Grid.Row="1" />
<Image Height="240" Margin="326,149,6,0" Name="image4" Width="320" Grid.Row="1" />
</Grid>
</Window>
--------------------------------------------------------------------------------
TextBoxが1つとGrid内に4つのImageコントロールを配置しています。
メインソースです。
--------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Class MainWindow
''Imageコントロール用配列
Public images As New ArrayList
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
'イベントハンドラの追加
AddHandler Runtime.Kinects.StatusChanged, AddressOf Kinects_StatusChanged
''接続されているKINECTを確認
ShowKinectCount()
''接続されているKINECTの初期化
Dim kinect As Runtime
For Each kinect In Runtime.Kinects
InitKinect(kinect)
Next
''配列にImegeコントロールを追加
With images
.Add(image1)
.Add(image2)
.Add(image3)
.Add(image4)
End With
End Sub
Sub InitKinect(kinect As Runtime)
''KINECTの初期化
kinect.Initialize(RuntimeOptions.UseColor)
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color)
''イベントハンドラの追加
AddHandler kinect.VideoFrameReady, AddressOf Kinect_VideoFrameReady
End Sub
Sub Kinects_StatusChanged(ByVal sender As Object, ByVal e As StatusChangedEventArgs)
''KINECT接続数の確認
ShowKinectCount()
''ステータス別に処理
If e.Status = KinectStatus.Connected Then
''接続されたとき初期化
InitKinect(e.KinectRuntime)
ElseIf e.Status = KinectStatus.Disconnected Then
''切断されたとき
''一度すべてのImegeコントロールを初期化
Dim i As Integer
For i = 0 To Runtime.Kinects.Count
images(i).Source = Nothing
Next
''イベントハンドラの削除
RemoveHandler e.KinectRuntime.VideoFrameReady, AddressOf Kinect_VideoFrameReady
''KINECTの終了処理
e.KinectRuntime.Uninitialize()
End If
End Sub
Sub ShowKinectCount()
''接続されている台数を確認
kinectCount.Text = Runtime.Kinects.Count & "台のKINECTが有効です"
End Sub
Sub Kinect_VideoFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)
''切断された瞬間は書き込まないようにする
If IsNothing(sender) = False And sender.InstanceIndex >= 0 Then
Dim source As PlanarImage = e.ImageFrame.Image
images(sender.InstanceIndex).Source = BitmapSource.Create(source.Width, source.Height, 96, 96, PixelFormats.Bgr32, Nothing, source.Bits, source.Width * source.BytesPerPixel)
End If
End Sub
End Class
--------------------------------------------------------------------------------
KINECTを1台しか持っていないので複数台接続してのチェックはできていません。
0台の状態での動作は大丈夫でした。
2011年12月13日火曜日
KINECT SDK Beta2 で距離データを扱う( VB + WPF )
このエントリはKINECT SDK Advent
Calendar : ATNDの12月13日分です。
kaorun55氏の「KINECT SDK Beta2 で距離データを扱う( C# + WPF )」をVBに変更してみました。
まずは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="521" Width="663">
<Grid>
<Image Name="DepthImage" Height="480" Width="640" />
</Grid>
</Window>
kaorun55氏の「KINECT SDK Beta2 で距離データを扱う( C# + WPF )」をVBに変更してみました。
まずは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="521" Width="663">
<Grid>
<Image Name="DepthImage" Height="480" Width="640" />
</Grid>
</Window>
-------------------------------------------------------------------------------
特に変わったところはないです。Imegeコントロールを1つ貼り付けているだけです。
次にメインのソースです。
-------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Class MainWindow
Inherits Window
Public nui As Runtime
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
'KINECT確認
If Runtime.Kinects.Count > 0 Then
nui = Runtime.Kinects(0)
Else
MsgBox("KINECTが接続されていません。")
Exit Sub
End If
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
'KINECT初期化
nui.Initialize(RuntimeOptions.UseDepth)
nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution640x480, ImageType.Depth)
'イベント追加
AddHandler nui.DepthFrameReady, AddressOf Kinect_DepthFrameReady
End Sub
Private Sub Kinect_DepthFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)
'Imageコントロールに1フレーム分のデータを設定
Dim image As PlanarImage = e.ImageFrame.Image
DepthImage.Source = BitmapSource.Create(image.Width, image.Height, 96, 96, PixelFormats.Gray16, Nothing, ConvGrayScale(image).Bits, image.Width * image.BytesPerPixel)
'リソース不足になるので強制的にGCを実行
System.GC.Collect()
End Sub
Private Function ConvGrayScale(ByVal source As PlanarImage) As PlanarImage
'深度情報をグレースケールに変換
Dim i As Integer
Dim depth As Integer
For i = 0 To source.Bits.Length - 2 Step 2
depth = CInt((source.Bits(i) Or (source.Bits(i + 1) << 8)))
depth = CInt(&HFFFF - (&HFFFF * depth / &HFFF))
source.Bits(i) = CByte(depth And &HFF)
source.Bits(i + 1) = CByte((depth >> 8) And &HFF)
Next
ConvGrayScale = source
End Function
End Class
-------------------------------------------------------------------------------
距離カメラのデータをグレースケールに変更する必要があります。
実はこの辺りの処理をしてくれるtoolがあります。
http://c4fkinect.codeplex.com/からToolkitをダウンロードして、適当な場所に解凍してください。
プロジェクトの参照の追加で先ほど解凍したフォルダの中の「Coding4Fun.Kinect.Wpf.dll」を追加しましょう。
次にメインソースの先頭に「Imports Coding4Fun.Kinect.Wpf」を書き加えます。
Kinect_DepthFrameReadyサブルーチン内の「Dim image As PlanarImage = e.ImageFrame.Image」は削除してください。
次に
「DepthImage.Source = BitmapSource.Create(image.Width, image.Height, 96, 96, PixelFormats.Gray16, Nothing, ConvGrayScale(image).Bits, image.Width * image.BytesPerPixel)」を
「DepthImage.Source = e.ImageFrame.ToBitmapSource()」に変更します。
「ConvGrayScale」ファンクションは必要ありません。
これだけで距離データをグレースケールで表示できます。
変更したソースは以下のようになります。
-------------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Imports Coding4Fun.Kinect.Wpf
Class MainWindow
Inherits Window
Public nui As Runtime
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
'KINECT確認
If Runtime.Kinects.Count > 0 Then
nui = Runtime.Kinects(0)
Else
MsgBox("KINECTが接続されていません。")
Exit Sub
End If
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
'KINECT初期化
nui.Initialize(RuntimeOptions.UseDepth)
nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution640x480, ImageType.Depth)
'イベント追加
AddHandler nui.DepthFrameReady, AddressOf Kinect_DepthFrameReady
End Sub
Private Sub Kinect_DepthFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)
'Imageコントロールに1フレーム分のデータを設定
DepthImage.Source = e.ImageFrame.ToBitmapSource()
'リソース不足になるので強制的にGCを実行
System.GC.Collect()
End Sub
End Class
-------------------------------------------------------------------------------
ずいぶんと短くなります。
ToolkitはライブラリですのでC#からも利用できます。
ちなみに初期のころにToolkitの名称で公表されていたライブラリはToolboxに名前が変更になったようです。Toolboxの方はKINECT SDKが標準で持っていないジェスチャー認識ができるライブラリのようです。
2011年12月12日月曜日
KINECT SDK VBでカラーイメージを表示
このエントリはKINECT SDK Advent Calendar : ATNDの12月12日分です。
kaorun55氏のC#+WPFを参考にVB+WPFに変更しました。
基本となるRGB画像を表示します。
いきなりソースコードから
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="518" Width="665">
<Grid>
<Image Height="480" Name="kinectImage" Width="640" />
</Grid>
</Window>
----------------------------------------------------------------------------
画面についてはImageコントロールのNameプロパティだけ注意すれば特に問題はないですね。
予め、メニューの「プロジェクト」->「参照の追加」->「.NET」タブから「Microsoft.Reseach.Kinect」を追加するようにしましょう。(C#だとソリューションエクスプローラーに「参照設定」が表示されるのにVBにはないんですよね。なぜなのかな?)
MainWindow.xaml.vb
----------------------------------------------------------------------------
Imports Microsoft.Research.Kinect.Nui
Class MainWindow
Inherits Window
Public nui As Runtime
Public Sub New()
' この呼び出しはデザイナーで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
'KINECTの確認
If Runtime.Kinects.Count > 0 Then
nui = Runtime.Kinects(0)
Else
MsgBox("KINECTが接続されていません。")
Exit Sub
End If
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
''KINECT初期化
nui.Initialize(RuntimeOptions.UseColor)
''Videoデータの取得
nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color)
''イベントハンドルの追加
AddHandler nui.VideoFrameReady, AddressOf kinect_VideoFrameReady
End Sub
Private Sub kinect_VideoFrameReady(ByVal sender As Object, ByVal e As ImageFrameReadyEventArgs)
Dim image As PlanarImage = e.ImageFrame.Image
''ImageコントロールにVideoストリームを割り当て
kinectImage.Source = BitmapSource.Create(image.Width, image.Height, 96, 96, PixelFormats.Bgr32, Nothing, image.Bits, image.Width * image.BytesPerPixel)
'リソース不足でエラーが出るので強制的にGC
System.GC.Collect()
End Sub
End Class
----------------------------------------------------------------------------
処理の大まかな流れは
1.初期化とKINECTの確認
2.Window表示
3.KINECT初期化
4.VideoStreamのオープン後、1フレームごとにインベント呼び出し
5.ImageコントロールにVideoStreamデータを割り当て
となります。
内容についてはコメントを見てもらえれば何をしているのかはわかると思います。
2011年12月10日土曜日
KINECT SDK 日本語で音声認識
先日の英語バージョンをちょっと変更して日本語も認識できるようにしてみました。
予め以下のランゲージパックをダウンロードしてインストールしてください。
http://www.microsoft.com/download/en/details.aspx?id=21924より
「MSSpeech_SR_ja-JP_TELE.msi」をダウンロードしてください。
リストの下の方には「MSSpeech_TTS_ja-JP_Haruka.msi」がありますがこちらは音声合成用のランゲージパックになりますので間違えないようにしてください。
それから最新のSpeechPlatfprmのバージョンは11ですが、ランゲージパックはバージョンに依存するみたいですので間違えないようにしましょう。KINECTの環境は10.2になります。
次にソースコードです。
---------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Research.Kinect.Nui; //追加
using Microsoft.Research.Kinect.Audio; //追加
using Microsoft.Speech.Recognition; //追加
using Microsoft.Speech.AudioFormat; //追加
namespace SpeechElevation
{
public partial class Program
{
static Runtime nui;
static Camera cam;
public static void Main(string[] args)
{
//初期化
if (Runtime.Kinects.Count == 0)
{
return;
}
nui = Runtime.Kinects[0];
nui.Initialize(RuntimeOptions.UseColor);
cam = nui.NuiCamera;
//カメラの位置を初期化
CamInit();
//オーディオソース
using (var source = new KinectAudioSource())
{
source.FeatureMode = true;
source.AutomaticGainControl = false; //音声認識のときは必ずfalse
source.SystemMode = SystemMode.OptibeamArrayOnly;
//認識エンジンの選択
RecognizerInfo ri = GetKinectRecognizer();
if (ri == null)
{
Console.WriteLine("認識エンジンが見つかりません。");
return;
}
Console.WriteLine("認識エンジン: {0}", ri.Name);
//認識エンジンの準備
using (var sre = new SpeechRecognitionEngine(ri.Id))
{
//認識する語句の準備
var wd = new Choices();
wd.Add("ぜろ");
wd.Add("うえ");
wd.Add("した");
wd.Add("最初"); //漢字も使える
var gb = new GrammarBuilder();
//GrammerBuilderのCultureと認識エンジンのCultureを合わせる
gb.Culture = ri.Culture;
gb.Append(wd);
var g = new Grammar(gb);
sre.LoadGrammar(g);
//イベントハンドラの追加
sre.SpeechRecognized += SreSpeechRecognized;
sre.SpeechHypothesized += SreSpeechHypothesized;
sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected;
//認識の開始
using (Stream s = source.Start())
{
sre.SetInputToAudioStream(s,
new SpeechAudioFormatInfo(
EncodingFormat.Pcm, 16000, 16, 1,
32000, 2, null));
Console.WriteLine("認識開始:");
sre.RecognizeAsync(RecognizeMode.Multiple);
Console.ReadLine();
}
}
}
}
private static RecognizerInfo GetKinectRecognizer()
//認識エンジンを直に設定
{
return SpeechRecognitionEngine.InstalledRecognizers().Where(r => r.Id == "SR_MS_ja-JP_TELE_10.0").FirstOrDefault();
}
static void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
{
Console.WriteLine("\n認識できません。");
}
static void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
{
Console.Write("\r入力音声: \t{0}", e.Result.Text);
}
static void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine("\n認識しました。: \t{0}", e.Result.Text);
switch (e.Result.Text)
{
case "うえ":
CamUp();
break;
case "した":
CamDown();
break;
case "ぜろ":
CamInit();
break;
case "最初":
CamInit();
break;
}
}
//カメラを上に
static void CamUp()
{
var nowangle = cam.ElevationAngle + 5;
if (nowangle > 25)
{
cam.ElevationAngle = 25;
}
else
{
cam.ElevationAngle = nowangle;
}
}
//カメラを下に
static void CamDown()
{
var nowangle = cam.ElevationAngle - 5;
if (nowangle < -25)
{
cam.ElevationAngle = -25;
}
else
{
cam.ElevationAngle = nowangle;
}
}
//カメラを水平に
static void CamInit()
{
cam.ElevationAngle = 0;
}
}
}
---------------------------------------------------------------------------------
変更したところはテキストの色を変えていますが、一番のキモは認識エンジンに読み込ませるランゲージパックの名前です。
このことから他の言語でも同じくランゲージパックをインストールしてあげれば問題なく動作すると思います。
すこし謎なのが、なぜわざわざKINECT用にランゲージパックを用意しているのかですが、実際にSpeechPlatform用en-USランゲージパックとKINECT用では内容が少し違うようです。推測ですがKINECT用は文法関係の辞書に何か手を加えてあるのかもしれません。容量はKINECT用の方が大きいですので。
しかし、SpeechPlatformの情報は少ないです。
今は単語レベルでの認識までですが、短めの文章なんかも認識できるのか試してみたいです。
予め以下のランゲージパックをダウンロードしてインストールしてください。
http://www.microsoft.com/download/en/details.aspx?id=21924より
「MSSpeech_SR_ja-JP_TELE.msi」をダウンロードしてください。
リストの下の方には「MSSpeech_TTS_ja-JP_Haruka.msi」がありますがこちらは音声合成用のランゲージパックになりますので間違えないようにしてください。
それから最新のSpeechPlatfprmのバージョンは11ですが、ランゲージパックはバージョンに依存するみたいですので間違えないようにしましょう。KINECTの環境は10.2になります。
次にソースコードです。
---------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Research.Kinect.Nui; //追加
using Microsoft.Research.Kinect.Audio; //追加
using Microsoft.Speech.Recognition; //追加
using Microsoft.Speech.AudioFormat; //追加
namespace SpeechElevation
{
public partial class Program
{
static Runtime nui;
static Camera cam;
public static void Main(string[] args)
{
//初期化
if (Runtime.Kinects.Count == 0)
{
return;
}
nui = Runtime.Kinects[0];
nui.Initialize(RuntimeOptions.UseColor);
cam = nui.NuiCamera;
//カメラの位置を初期化
CamInit();
//オーディオソース
using (var source = new KinectAudioSource())
{
source.FeatureMode = true;
source.AutomaticGainControl = false; //音声認識のときは必ずfalse
source.SystemMode = SystemMode.OptibeamArrayOnly;
//認識エンジンの選択
RecognizerInfo ri = GetKinectRecognizer();
if (ri == null)
{
Console.WriteLine("認識エンジンが見つかりません。");
return;
}
Console.WriteLine("認識エンジン: {0}", ri.Name);
//認識エンジンの準備
using (var sre = new SpeechRecognitionEngine(ri.Id))
{
//認識する語句の準備
var wd = new Choices();
wd.Add("ぜろ");
wd.Add("うえ");
wd.Add("した");
wd.Add("最初"); //漢字も使える
var gb = new GrammarBuilder();
//GrammerBuilderのCultureと認識エンジンのCultureを合わせる
gb.Culture = ri.Culture;
gb.Append(wd);
var g = new Grammar(gb);
sre.LoadGrammar(g);
//イベントハンドラの追加
sre.SpeechRecognized += SreSpeechRecognized;
sre.SpeechHypothesized += SreSpeechHypothesized;
sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected;
//認識の開始
using (Stream s = source.Start())
{
sre.SetInputToAudioStream(s,
new SpeechAudioFormatInfo(
EncodingFormat.Pcm, 16000, 16, 1,
32000, 2, null));
Console.WriteLine("認識開始:");
sre.RecognizeAsync(RecognizeMode.Multiple);
Console.ReadLine();
}
}
}
}
private static RecognizerInfo GetKinectRecognizer()
//認識エンジンを直に設定
{
return SpeechRecognitionEngine.InstalledRecognizers().Where(r => r.Id == "SR_MS_ja-JP_TELE_10.0").FirstOrDefault();
}
static void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
{
Console.WriteLine("\n認識できません。");
}
static void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
{
Console.Write("\r入力音声: \t{0}", e.Result.Text);
}
static void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine("\n認識しました。: \t{0}", e.Result.Text);
switch (e.Result.Text)
{
case "うえ":
CamUp();
break;
case "した":
CamDown();
break;
case "ぜろ":
CamInit();
break;
case "最初":
CamInit();
break;
}
}
//カメラを上に
static void CamUp()
{
var nowangle = cam.ElevationAngle + 5;
if (nowangle > 25)
{
cam.ElevationAngle = 25;
}
else
{
cam.ElevationAngle = nowangle;
}
}
//カメラを下に
static void CamDown()
{
var nowangle = cam.ElevationAngle - 5;
if (nowangle < -25)
{
cam.ElevationAngle = -25;
}
else
{
cam.ElevationAngle = nowangle;
}
}
//カメラを水平に
static void CamInit()
{
cam.ElevationAngle = 0;
}
}
}
---------------------------------------------------------------------------------
変更したところはテキストの色を変えていますが、一番のキモは認識エンジンに読み込ませるランゲージパックの名前です。
このことから他の言語でも同じくランゲージパックをインストールしてあげれば問題なく動作すると思います。
すこし謎なのが、なぜわざわざKINECT用にランゲージパックを用意しているのかですが、実際にSpeechPlatform用en-USランゲージパックとKINECT用では内容が少し違うようです。推測ですがKINECT用は文法関係の辞書に何か手を加えてあるのかもしれません。容量はKINECT用の方が大きいですので。
しかし、SpeechPlatformの情報は少ないです。
今は単語レベルでの認識までですが、短めの文章なんかも認識できるのか試してみたいです。
2011年12月9日金曜日
KINECT SDK 音声認識
KINECT SDKのSpeechサンプルプログラムにちょっと手を加えてみました。
サンプルは音声認識だけですが、それだけでは面白くないので声で首ふりできるようにしてみました。
C#のプログラムは初めてなので少し変なところもあるかもしれないですが、動作は問題ないはず・・・・
環境は
Windows7 Ultimate 64bit
KINECT SDK Beta2
SpeechPlatform SDK 10.2
SpeechPlatform Runtime 10.2
Kinect for Windows Language Pack, version 0.9
上の3つはKINECT SDKのダウンロードページ左下のリンクからダウンロードできます。
Visual C# 2010 Express
以下はソースです。
-------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Research.Kinect.Nui; //追加
using Microsoft.Research.Kinect.Audio; //追加
using Microsoft.Speech.Recognition; //追加
using Microsoft.Speech.AudioFormat; //追加
namespace SpeechElevation
{
public partial class Program
{
static Runtime nui;
static Camera cam;
public static void Main(string[] args)
{
//初期化
if (Runtime.Kinects.Count == 0)
{
return;
}
nui = Runtime.Kinects[0];
nui.Initialize(RuntimeOptions.UseColor);
cam = nui.NuiCamera;
//カメラの位置を初期化
CamInit();
//オーディオソース
using (var source = new KinectAudioSource())
{
source.FeatureMode = true;
source.AutomaticGainControl = false; //音声認識のときは必ずfalse
source.SystemMode = SystemMode.OptibeamArrayOnly;
//認識エンジンの選択
RecognizerInfo ri = GetKinectRecognizer();
if (ri == null)
{
Console.WriteLine("認識エンジンが見つかりません。");
return;
}
Console.WriteLine("認識エンジン: {0}", ri.Name);
//認識エンジンの準備
using (var sre = new SpeechRecognitionEngine(ri.Id))
{
//認識する語句の準備
var wd = new Choices();
wd.Add("init");
wd.Add("up");
wd.Add("down");
wd.Add("suihei"); //ローマ字も使える
var gb = new GrammarBuilder();
//GrammerBuilderのCultureと認識エンジンのCultureを合わせる
gb.Culture = ri.Culture;
gb.Append(wd);
var g = new Grammar(gb);
sre.LoadGrammar(g);
//イベントハンドラの追加
sre.SpeechRecognized += SreSpeechRecognized;
sre.SpeechHypothesized += SreSpeechHypothesized;
sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected;
//認識の開始
using (Stream s = source.Start())
{
sre.SetInputToAudioStream(s,
new SpeechAudioFormatInfo(
EncodingFormat.Pcm, 16000, 16, 1,
32000, 2, null));
Console.WriteLine("認識開始:");
sre.RecognizeAsync(RecognizeMode.Multiple);
Console.ReadLine();
}
}
}
}
private static RecognizerInfo GetKinectRecognizer()
//認識エンジンを直に設定
{
return SpeechRecognitionEngine.InstalledRecognizers().Where(r=>r.Id=="SR_MS_en-US_Kinect_10.0").FirstOrDefault();
}
static void SreSpeechRecognitionRejected(object sender,SpeechRecognitionRejectedEventArgs e)
{
Console.WriteLine("\n認識できません。");
}
static void SreSpeechHypothesized(object sender,SpeechHypothesizedEventArgs e)
{
Console.Write("\r入力音声: \t{0}",e.Result.Text);
}
static void SreSpeechRecognized(object sender,SpeechRecognizedEventArgs e)
{
Console.WriteLine("\n認識しました。: \t{0}", e.Result.Text);
switch (e.Result.Text)
{
case "up":
CamUp();
break;
case "down":
CamDown();
break;
case "init":
CamInit();
break;
case "suihei":
CamInit();
break;
}
}
//カメラを上に
static void CamUp()
{
var nowangle = cam.ElevationAngle + 5;
if (nowangle > 25)
{
cam.ElevationAngle = 25;
}
else
{
cam.ElevationAngle = nowangle;
}
}
//カメラを下に
static void CamDown()
{
var nowangle = cam.ElevationAngle - 5;
if (nowangle < -25)
{
cam.ElevationAngle = -25;
}
else
{
cam.ElevationAngle = nowangle;
}
}
//カメラを水平に
static void CamInit()
{
cam.ElevationAngle = 0;
}
}
}
--------------------------------------------------------------------------------
ソースコードを見ればわかると思いますが、「up」、[down」で上下にカメラが首を振ります。
「init」、「suihei」で初期位置(水平位置)に移動します。
KINECTの可動範囲は27°~-27°らしいですが壊れると困るので念のために25°~-25°までにしています。
ローマ字でも認識してくれます。すべてではないでしょうけどね。
初めは初期位置にするのに「zero」にしていたのですが「r」の発音が悪いらしくなかなか認識してくれないので変更しました^^;
次はこのソースを少し変更して日本語で認識できるようにします。
2011年11月29日火曜日
KINECT 始めました
KINECT 購入しました。Xboxは持ってません^^;
PCに接続して色々試していますが、面白いですね。
KINECT 関係の本を数週間で6冊も購入しちゃいました。
当所VB2010でプログラムを書くつもりでしたが、やはりサンプルプログラムの関係でC#2010で書くことにしました。
C#初めてです。 まぁ、最近のVBと違いがほとんどないというか最近のVBもあまりわかってないですけど・・・・(VB2005ぐらいまでしかわかりません。)
音声認識をいろいろ試していますが、SDKは英語しかありません。
ただ、単語レベルでの認識はローマ字でもちゃんと認識するので、まったく使えないわけではないようです。
PCに接続して色々試していますが、面白いですね。
KINECT 関係の本を数週間で6冊も購入しちゃいました。
当所VB2010でプログラムを書くつもりでしたが、やはりサンプルプログラムの関係でC#2010で書くことにしました。
C#初めてです。 まぁ、最近のVBと違いがほとんどないというか最近のVBもあまりわかってないですけど・・・・(VB2005ぐらいまでしかわかりません。)
音声認識をいろいろ試していますが、SDKは英語しかありません。
ただ、単語レベルでの認識はローマ字でもちゃんと認識するので、まったく使えないわけではないようです。
登録:
投稿 (Atom)