Kinect for Windows SDK v2.0入門 目次
「音の方向」について紹介します。まずは音の方向の取得の方法について解説します。音の方向とボディの関連付けは次回に解説します。
音の方向について、v1ではKinectを中心に左右50度、10度単位での取得でしたが、v2では左右50度(変わらず)、1度以下の単位で取得できるようになり、より細かくなりました。
環境
筆者の環境は次の通りです。
- Windows 8.1 Pro Update1 64bit
- Visual Studio 2013 Ultimate(Express for Windows Desktopでも可)
- Kinect for Windows SDK v2.0-1409(リリース版)
- 32bitアプリケーション
- サンプルコードのリポジトリ
実行結果
線が音の方向に移動します。
また「音の方向の角度」および「音の方向の角度の信頼性」が表示されます。
解説
音の取得についての初期化手順ははほかのデータとほぼ同じ方法で取得します。AudioSource、AudioBeamFrameReaderを使用します。データ取得については、ビームフレームおよびビームサブフレームをリストとして持っており、これらを順に取得して、最終的にはビームサブフレームから音データを受け取ります。
なお、定かではありませんが、ビームフレームがリストになっていること、サンプルのコメントを見ると「現状ではビーム方向は1つだけ」と書かれていることから、ビーム方向を複数検出する機能も持っているのではないかと推測できます。
初期化
初期化の手順は次の通りです
- Kinectを開く
- ビームリーダーを開く
まずKinectを開きます。続いてAudioSourceを使って赤外線画像リーダーを作成し、データの読み込み準備を行います。データの読み込みは、C++ではポーリング、C#ではイベントハンドラの登録を行います。
C++
void initializeAudioSource(){
// オーディオを開く
ComPtr<IAudioSource> audioSource;
ERROR_CHECK( kinect->get_AudioSource( &audioSource ) );
ERROR_CHECK( audioSource->OpenReader( &audioBeamFrameReader ) );
}
C#(デスクトップ)
private void Window_Loaded( object sender, RoutedEventArgs e ){
try {
// Kinectを開く
kinect = KinectSensor.GetDefault();
kinect.Open();
// 音声リーダーを開く
audioBeamFrameReader = kinect.AudioSource.OpenReader();
audioBeamFrameReader.FrameArrived += audioBeamFrameReader_FrameArrived;
}
catch ( Exception ex ) {
MessageBox.Show( ex.Message );
Close();
}
}
C#(Windows ストアアプリ)
なし
データの取得
続いてデータを取得し表示します。C++ではポーリング、C#ではイベントハンドラになります。
- AudioBeamFrameListを取得する
- AudioBeamFrameListから、最初(0番目)のAudioBeamFrameを取得する
- AudioBeamFrameから、最初(0番目)のAudioBeamSubFrameを取得する
- AudioBeamSubFrameから「音の方向の角度」および「音の方向の角度の信頼性」を取得する
- 取得した角度を表示する
音の角度の値(ラジアン)はAudioBeamSubFrame.BeamAngleで、角度の信頼性の値(0.0-1.0)はAudioBeamSubFrame.BeamAngleConfidenceで取得します。
C++
void updateAudioFrame(){
ComPtr<IAudioBeamFrameList> audioBeamFrameList;
auto ret = audioBeamFrameReader->AcquireLatestBeamFrames( &audioBeamFrameList );
if ( ret != S_OK ){
return;
}
ComPtr<IAudioBeamFrame> audioBeamFrame;
ERROR_CHECK( audioBeamFrameList->OpenAudioBeamFrame( 0, &audioBeamFrame ) );
ComPtr<IAudioBeamSubFrame> audioBeamSubFrame;
ERROR_CHECK( audioBeamFrame->GetSubFrame( 0, &audioBeamSubFrame ) );
// 角度および角度の信頼性を取得する
ERROR_CHECK( audioBeamSubFrame->get_BeamAngle( &beamAngle ) );
ERROR_CHECK( audioBeamSubFrame->get_BeamAngleConfidence( &beamAngleConfidence ) );
}
表示は取得した角度分回転させた座標に、線を描いています。
void draw(){
cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC4);
// ラジアンから度に変換する
auto angle = beamAngle * 180 / 3.1416;
// 線を回転させる(逆回転)
auto alpha = 3.1416 / -angle;
int offsetX = 320;
int offsetY = 240;
auto X2 = 0 * cos( alpha ) - offsetY * sin( alpha );
auto Y2 = 0 * sin( alpha ) + offsetY * cos( alpha );
回転させた線を描画する
cv::line( image, cv::Point( offsetX, 0 ), cv::Point( offsetX + X2, Y2 ), cv::Scalar( 255, 255, 255 ), 10 );
cv::imshow("AudioBeamAngle", image);
}
C#(デスクトップ)
void audioBeamFrameReader_FrameArrived( object sender, AudioBeamFrameArrivedEventArgs e ){
using ( var audioFrame = e.FrameReference.AcquireBeamFrames() ) {
if ( audioFrame == null ) {
return;
}
var subFrame = audioFrame[0].SubFrames[0];
// 音の方向
LineBeamAngle.Angle = (int)(subFrame.BeamAngle * 180 / Math.PI);
// 音の方向の信頼性[0-1]
TextBeamAngleConfidence.Text = subFrame.BeamAngleConfidence.ToString();
}
}
XAMLは次のようになっており、BorderのRotateTransformに角度を設定することで、方向を表すようにしています。
<Grid><StackPanel Width="960" Height="540" Orientation="Vertical">
<Border Height="300" Width="20" Background="Black" CornerRadius="10" VerticalAlignment="Top" RenderTransformOrigin="0.5,0">
<Border.RenderTransform>
<TransformGroup>
<RotateTransform Angle="0" x:Name="LineBeamAngle" />
<ScaleTransform ScaleX="-1" />
</TransformGroup>
</Border.RenderTransform>
</Border>
<TextBlock Text="{Binding ElementName=LineBeamAngle, Path=Angle}" FontSize="20" HorizontalAlignment="Center"/>
<TextBlock x:Name="TextBeamAngleConfidence" Text="0" FontSize="20" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
C#(Windows ストアアプリ)
なし
まとめ
v1では音の方向はイベントで取得していましたが、v2ではストリームデータの一つとして取得できるようになっています。また角度の単位もより細かくなっており、実用的になったのではないでしょうか。