少し乗り遅れ気味ですが、Kinectネタを。
OpenNIの登場でKinectのユーザーのスケルトン情報が一通り取れるようになったので、
それをFlashへの橋渡しをして、マルチユーザー・マルチタッチな環境を作りました。
これでFlashでもNaturalInterfaceコンテンツを作れるんダゼ!
今回は「OpenNI解析編」ということで、
Kinectを購入してから、OpenNIを解析、Flashへ信号を投げるまでの解説です。
■開発環境
kinect制御端末 : WinXP VisualC++ Express2010
コンテンツ端末:MacOSX FlashCS4
ソケット通信で Win→Macへユーザーの手の位置を送ります。
Kinectハックの手順は先人たちをお手本に。
WindowでKinectを繋ぐまでの手順:
OpenNI: WindowsでKinectを使う
OpenNIをビルドするまでの手順:
OpenNIをVisual C++ 2010 Expressでビルド&デバックするまでの手順。
上記サイトを参考にOpenNIを改変できるようにしたら、
OpenNIと一緒にインストールされたサンプルから改変しやすそうなのを探します。
NiUserTracker.exeはスケルトン表示までできているので、
今回はこれにソケット通信を追加しました。
C++は初めてなので、ここから、かなり試行錯誤してます…。
「【C++】ソケット通信」を参考にして、SocketServerクラスを作りました。
クラスファイル間のアクセス方法がわからなかったんですが、
ハッシュファイルというのを作るんですね。ちょっと面倒です…。
SocketServerクラスにconnectとsend関数を作り、
send関数に送りたい信号を投げるとソケットで通信するようになりました。
#include#include SOCKET s, s1; //ソケット // //connect int connect(){ int result; //戻り値 //接続を許可するクライアント端末の情報 struct sockaddr_in source; char buffer[1024]; //受信データのバッファ領域 char ans[] = "送信成功"; memset(&buffer, '\0', sizeof(buffer)); //送信元の端末情報を登録する memset(&source, 0, sizeof(source)); source.sin_family = AF_INET; //ポート番号はクライアントプログラムと共通 source.sin_port = htons(3000); source.sin_addr.s_addr = htonl(INADDR_ANY); //ソケット通信の開始準備 WSADATA data; result = WSAStartup(MAKEWORD(2, 0), &data); if (result < 0){ printf("%d\n", GetLastError()); printf("ソケット通信準備エラー\n"); } //ソケットの生成 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0){ printf("%d\n", GetLastError()); printf("ソケット生成エラー\n"); } //ソケットのバインド result = bind(s, (struct sockaddr *)&source, sizeof(source)); if (result < 0){ printf("%d\n", GetLastError()); printf("バインドエラー\n"); } //接続の許可 result = listen(s, 1); if (result < 0){ printf("接続許可エラー\n"); } printf("接続開始\n"); s1 = s; //クライアントから通信があるまで待機 s1 = accept(s, NULL, NULL); if (s1 < 0){ printf("待機エラー\n"); } //クライアントから送信されたデータの受信 result = recv(s1, buffer, 10, 0); if (result < 0){ printf("受信エラー\n"); } printf("%sを受信しました\n", buffer); return 0; } // //send int send(char id[],char part[] ,char px[],char py[],char pz[]){ int result; //戻り値 char str[50]= ""; // sprintf_s(str,"%s,%s,%s,%s,%s",id,part,px,py,pz); // result = send(s1, str, strlen(str)+1, 0); return result; }
Flashには、ユーザーの手の情報を送りたいので、 スケルトンを描画しているクラスを解析します。
SceneDrawer.cppの中のDrawLimb()がそれです。
void DrawLimb(XnUserID player, XnSkeletonJoint eJoint1, XnSkeletonJoint eJoint2) { if (!g_UserGenerator.GetSkeletonCap().IsTracking(player)) { printf("not tracked!\n"); return; } XnSkeletonJointPosition joint1, joint2; g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint1, joint1); g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint2, joint2); if (joint1.fConfidence < 0.5 || joint2.fConfidence < 0.5) { return; } XnPoint3D pt[2]; pt[0] = joint1.position; pt[1] = joint2.position; g_DepthGenerator.ConvertRealWorldToProjective(2, pt, pt); glVertex3i(pt[0].X, pt[0].Y, 0); glVertex3i(pt[1].X, pt[1].Y, 0); }
このコードからGetSkeletonJointPosition()がユーザーの部位の位置を返す関数だとわかります。
ユーザーIDと体の部位を指定するとx,y,z座標を返してくれます。
DrawLimb()を改変した関数SendPosition()を作り、SocketServerのsendに送ります。
void SendPosition(XnUserID player,int id, XnSkeletonJoint part,char _part[2]) { if (!g_UserGenerator.GetSkeletonCap().IsTracking(player)) { printf("not tracked!\n"); return; } XnSkeletonJointPosition joint1; g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, part, joint1); XnPoint3D pt[1]; pt[0] = joint1.position; g_DepthGenerator.ConvertRealWorldToProjective(1, pt, pt); // char _id[2] = ""; sprintf( _id, "%d", id); // char _px[10] = ""; sprintf( _px, "%.3f", pt[0].X); // char _py[10] = ""; sprintf( _py, "%.3f", pt[0].Y); // char _pz[10] = ""; sprintf( _pz, "%.3f", pt[0].Z); // send(_id,_part,_px,_py,_pz); }
以上で、OpenNIにソケット通信を追加できました。
今回は手の位置だけですが、顔や胴、足の位置も同じ仕組みで取得できます。
[追記 2010.12.22]
exeでも動くようになりました。
OpenNI/Data内の「SamplesConfig.xml」を読み込んでいたのですが、
開発環境とexeではパスが変わってしまうので、読めなくなっていたようです。
main.cppの
#define SAMPLE_XML_PATH "../../Data/SamplesConfig.xml"を
#define SAMPLE_XML_PATH "SamplesConfig.xml"として、
exeと同じディレクトリにSamplesConfig.xmlをコピーすれば、
落ちなくになります。
続きはFlash編へ。
定価:¥ 14,800 新品最安価格:¥ 17,300 (2店出品) 売上ランク:62位 レビュー平均: | |
by amazon通販最速検索 at 2010/12/21 |
Multitouch-vista has a tuio imput server on 127.0.0.1 port tcp 3333, if your software output the blobs coordinate in tuio format, we have a windows 7 multitouch with Kinect.
返信削除Please implement tuio output to this sample
Thank you for your comment, and for your interest in our works.
返信削除C++ does not fall within the realm of our specialty, and therefore we are
not sure that we can do it, and it may take some time. We will,
however, do our best for you!
where i can download the EXE (binaries)for Windows?
返信削除We do not publish compiled EXE files,because OpenNI has the policy of opoen source.
返信削除Please check this post.
you can download the improved program. but not EXE.
http://www.sd-tech-blog.com/2010/12/kinect-sdkinectio.html
I tryed to compile your modification to NiUserTracker. When I start it up it sais
返信削除'Open Connection'
Then when i hit connect in the flash app the NiUserTracker sais
'test received
InitFromXml failed: File not found!'
could you help me out with this?
ok that was just an xml pathing issue
返信削除