PageRenderTime 425ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/face_detect/face_detect/main.cpp

https://github.com/kaorun55/kinect_sdk_sandbox
C++ | 158 lines | 110 code | 26 blank | 22 comment | 26 complexity | b3d5d858861de987a0103622f6eec37a MD5 | raw file
  1. // 顔を検出して、カメラの角度を動かすサンプル
  2. #include <iostream>
  3. #include <sstream>
  4. #include "kinect\nui\Kinect.h"
  5. #include "kinect\nui\ImageFrame.h"
  6. #include <opencv2/opencv.hpp>
  7. const char* FACE_CASCADE_PATH = "C:/OpenCV2.2/data/haarcascades/haarcascade_frontalface_alt.xml";
  8. void moveTilt( kinect::nui::Kinect& kinect, const POINT& pt )
  9. {
  10. kinect::nui::ImageStream& video = kinect.VideoStream();
  11. const RECT place[] = {
  12. { 0, 0, video.Width(), video.Height() / 3 },
  13. { 0, video.Height() / 3, video.Width(), video.Height() / 3 * 2 },
  14. { 0, video.Height() / 3 * 2, video.Width(), video.Height() },
  15. };
  16. // 顔の位置によって、Kinectの首を動かす
  17. // 上1/3にいれば、上に動かす
  18. LONG angle = kinect.GetAngle();
  19. if ( ::PtInRect( &place[0], pt ) ) {
  20. angle += 5;
  21. if ( angle < kinect.CAMERA_ELEVATION_MAXIMUM ) {
  22. kinect.SetAngle( angle );
  23. }
  24. }
  25. // 中1/3にいれば、何もしない
  26. else if ( ::PtInRect( &place[1], pt ) ) {
  27. }
  28. // 下1/3にいれば、下に動かす
  29. else if ( ::PtInRect( &place[2], pt ) ) {
  30. angle -= 5;
  31. if ( angle > kinect.CAMERA_ELEVATION_MINIMUM ) {
  32. kinect.SetAngle( angle );
  33. }
  34. }
  35. }
  36. void main()
  37. {
  38. try {
  39. kinect::nui::Kinect kinect;
  40. kinect.Initialize( NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON );
  41. kinect::nui::ImageStream& video = kinect.VideoStream();
  42. video.Open( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480 );
  43. kinect::nui::ImageStream& depth = kinect.DepthStream();
  44. depth.Open( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240 );
  45. kinect::nui::SkeletonEngine& skeleton = kinect.Skeleton();
  46. skeleton.Enable();
  47. // OpenCVの初期設定
  48. char* windowName = "camera_elevation";
  49. ::cvNamedWindow( windowName );
  50. cv::Ptr< IplImage > videoImg = ::cvCreateImage( cvSize(video.Width(), video.Height()), IPL_DEPTH_8U, 4 );
  51. // 画像を読み込んでKinectにあわせて変換する
  52. cv::Ptr< IplImage > face = ::cvLoadImage( "lena.jpg" );
  53. cv::Ptr< IplImage > faceImg = ::cvCreateImage( cvSize(face->width, face->height), IPL_DEPTH_8U, 4 );
  54. ::cvCvtColor( face, faceImg, CV_RGB2RGBA );
  55. // 検出器のロード
  56. CvHaarClassifierCascade* faceCascade = (CvHaarClassifierCascade*)::cvLoad( FACE_CASCADE_PATH, 0, 0, 0 );
  57. if( !faceCascade ) {
  58. throw std::runtime_error("error : cvLoad");
  59. }
  60. // 顔検出用のストレージ
  61. CvMemStorage* storage = ::cvCreateMemStorage();
  62. bool isDetected = false;
  63. bool isSkelton = true;
  64. // 前回の検出時間
  65. DWORD prevTime = ::GetTickCount();
  66. while ( 1 ) {
  67. // データの更新を待って、次のフレームを取得する
  68. kinect.WaitAndUpdateAll();
  69. kinect::nui::VideoFrame videoMD( video );
  70. // データのコピー
  71. memcpy( videoImg->imageData, (BYTE*)videoMD.Bits(), videoImg->widthStep * videoImg->height );
  72. // 顔の検出
  73. if (isDetected) {
  74. // モータを回しすぎるといかんので、1秒に一回
  75. if ( (::GetTickCount() - prevTime) > 1000 ) {
  76. prevTime = ::GetTickCount();
  77. // 顔の検出
  78. cvClearMemStorage(storage);
  79. CvSeq* faces = ::cvHaarDetectObjects( videoImg, faceCascade, storage );
  80. for ( int i = 0; i < faces->total; ++i ) {
  81. // 検出した座標の取得
  82. CvRect rect = *(CvRect*)::cvGetSeqElem( faces, i );
  83. // 検出した顔に画像を貼り付ける
  84. ::cvSetImageROI( videoImg, rect );
  85. cv::Ptr< IplImage > resizeImg = ::cvCreateImage( cvSize( rect.width, rect.height), faceImg->depth, faceImg->nChannels );
  86. ::cvResize( faceImg, resizeImg );
  87. ::cvCopy( resizeImg, videoImg );
  88. ::cvResetImageROI( videoImg );
  89. // 顔の中心点を基準にKinectの首を振る
  90. POINT c = { rect.x + (rect.width / 2), rect.y + (rect.height / 2) };
  91. moveTilt( kinect, c );
  92. }
  93. }
  94. }
  95. // 骨格検出
  96. else if ( isSkelton ) {
  97. // 骨格情報を取得する
  98. kinect::nui::SkeletonFrame skeletonMD = skeleton.GetNextFrame();
  99. // 骨格を見つけた
  100. if ( skeletonMD.IsFoundSkeleton() ) {
  101. skeletonMD.TransformSmooth();
  102. for ( int i = 0; i < kinect::nui::SkeletonFrame::SKELETON_COUNT; ++i ) {
  103. // 骨格追跡している場合、右手を基準にKinectの首を振る
  104. if ( skeletonMD[i].TrackingState() == NUI_SKELETON_TRACKED ) {
  105. int trac = NUI_SKELETON_POSITION_HAND_RIGHT;
  106. kinect::nui::SkeletonData::Point p = skeletonMD[i].TransformSkeletonToDepthImage( trac );
  107. CvPoint pt = cvPoint( (p.x * video.Width()) + 0.5f, (p.y * video.Height()) + 0.5f );
  108. cvCircle( videoImg, pt, 5, cvScalar( 255, 0, 0 ), -1 );
  109. POINT c = { pt.x, pt.y };
  110. moveTilt( kinect, c );
  111. }
  112. }
  113. }
  114. }
  115. ::cvShowImage( windowName, videoImg );
  116. int key = ::cvWaitKey( 10 );
  117. if ( key == 'q' ) {
  118. break;
  119. }
  120. else if ( key == 'd' ) {
  121. isDetected = !isDetected;
  122. }
  123. else if ( key == 's' ) {
  124. isSkelton = !isSkelton;
  125. }
  126. }
  127. ::cvDestroyAllWindows();
  128. }
  129. catch ( std::exception& ex ) {
  130. std::cout << ex.what() << std::endl;
  131. }
  132. }