昨日、寝る前にふと思ったんですよ。
Kinectを使って、Kinect SDKとOpenNIは共存できないけど、デバイスの違うKinect + Kinect SDK と Xtion + OpenNIなら共存できるのではないか?と
で、今朝やってみたら、できましたね。これで、いちいちPCを分けずに済みそうです...
今までそこまで頭が回らなかったw
ソース
やってることは単純に、KinectとXtionのカメラ画像を表示してます。
プロジェクト全体はこちらです。
XAML
<Window x:Class="KinectAndXtion.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="312" Width="702" Closing="Window_Closing"> <Grid> <Image Height="240" HorizontalAlignment="Left" Name="imageKinectSDK" Stretch="Fill" VerticalAlignment="Top" Width="320 " Margin="0,34,0,0" /> <Image Height="240" HorizontalAlignment="Left" Margin="360,34,0,0" Name="imageOpenNI" Stretch="Fill" VerticalAlignment="Top" Width="320" /> <Label Content="Kinect & Kinect SDK" Height="39" HorizontalAlignment="Left" Name="label1" VerticalAlignment="Top" Width="320" HorizontalContentAlignment="Center" FontSize="18" /> <Label Content="Xtion & OpenNI" Height="39" HorizontalAlignment="Right" Name="label2" VerticalAlignment="Top" Width="320" HorizontalContentAlignment="Center" FontSize="18" /> </Grid> </Window>
CS
using System; using System.Windows; using Coding4Fun.Kinect.Wpf; using Microsoft.Research.Kinect.Nui; using System.Threading; using OpenNI; using System.Windows.Threading; using System.Windows.Media.Imaging; using System.Windows.Media; namespace KinectAndXtion { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { private Context context; private ImageGenerator image; private Thread readerThread; private bool shouldRun; public MainWindow() { InitializeComponent(); try { InitKinectSDK(); InitOpenNI(); } catch ( Exception ex ) { MessageBox.Show( ex.Message ); Close(); } } private void InitOpenNI() { // ContextとImageGeneratorの作成 ScriptNode node; context = Context.CreateFromXmlFile( "SamplesConfig.xml", out node ); context.GlobalMirror = false; image = context.FindExistingNode( NodeType.Image ) as ImageGenerator; // 画像更新のためのスレッドを作成 shouldRun = true; readerThread = new Thread( new ThreadStart( () => { while ( shouldRun ) { context.WaitAndUpdateAll(); ImageMetaData imageMD = image.GetMetaData(); // ImageMetaDataをBitmapSourceに変換する(unsafeにしなくてもOK!!) this.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action( () => { imageOpenNI.Source = BitmapSource.Create( imageMD.XRes, imageMD.YRes, 96, 96, PixelFormats.Rgb24, null, imageMD.ImageMapPtr, imageMD.DataSize, imageMD.XRes * imageMD.BytesPerPixel ); } ) ); } } ) ); readerThread.Start(); } private void InitKinectSDK() { // Kinectインスタンスを取得する Runtime kinect = Runtime.Kinects[0]; kinect.Initialize( RuntimeOptions.UseColor ); // RGBカメラの初期化と、イベントを登録する kinect.VideoStream.Open( ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color ); kinect.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>( kinect_VideoFrameReady ); } // RGBカメラのフレーム更新イベント void kinect_VideoFrameReady( object sender, ImageFrameReadyEventArgs e ) { // RGBカメラの画像を、Imageに表示する // ToBitmapSource()は、Coding4Fun.Kinect.Wpfにある拡張メソッド imageKinectSDK.Source = e.ImageFrame.ToBitmapSource(); } private void Window_Closing( object sender, System.ComponentModel.CancelEventArgs e ) { shouldRun = false; } } }
まとめ
何も特別なことをせずに、両方使えるのはいいですね:-)