2017/05/10

[C/Cpp] LeapMotion with OpenCV

1. 先到官網下載SDK。https://developer.leapmotion.com/get-started
2. 安裝完之後先跑LeapMotionVisiualizer看看畫面。
3. 網路上有各種語言用的API: https://developer.leapmotion.com/documentation/cpp/api/Leap_Classes.html

因為要搭配OpenCV寫,所以先研究C語言的寫法。



下載安裝完SDK之後,建立一個專案檔,把LeapMotion相關的東西放進去專案,包括include、lib、dll,並且設定好連結環境。
1. 開啟LeapMotion畫面,抓到手指位置,辨識手勢
開始寫程式
#include <Leap.h>
#include <math.h>
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;

Leap::Device cDevice;
Leap::Controller cController;
Leap::Frame cFrame;
Leap::ImageList cImageList;
Leap::Image cImageR;

Leap::HandList cHandList;
Leap::Hand cHand;

Leap::FingerList cFingerList;
Leap::Finger cFinger, cFinger2;

Leap::GestureList cGestureList;
Leap::Gesture cGesture;
Leap::SwipeGesture cSwipeGesture;

cv::Mat LeapMatR, drawMat;

int main()
{
        cController.setPolicy(Leap::Controller::POLICY_IMAGES); 
 cController.enableGesture(Leap::Gesture::TYPE_SWIPE);
 Sleep(1000);

 while(true){
  cFrame = cController.frame();
  if (cFrame.isValid()){
   cImageList = cFrame.images();

   // Get Left Raw Images
   cImageR = cImageList[0];
   LeapMatR.create(rows, cols, CV_8UC1);
   LeapMatR.data = (uchar*)cImageR.data();
   
   Sleep(50);
   
   if (LeapMatR.empty()){
    continue;
   }
   
   // get hand and fingers
   cHandList = cFrame.hands();
   HandNum = cHandList.count();
   cHand = cHandList[0];
   cHand2 = cHandList[1];

   // first hand
   if(cHand.isValid()){

    HandX = cHand.palmPosition().x;
    HandY = cHand.palmPosition().y;
    HandZ = cHand.palmPosition().z;
   
    HandX = ((HandX+200.0)/400.0)*640.0;
    HandZ = ((HandZ+200.0)/400.0)*480.0;

    float pitch = cHand.direction().pitch();
    float yaw = cHand.direction().yaw();
    float roll = cHand.palmNormal().roll();
    
    //pitch, yaw, roll of hand, -1.0~1.0
    //printf("p:%.1f, y:%.1f, r:%.1f\n", pitch, yaw, roll);
    
    // gesture
    cGestureList = cFrame.gestures();
    cGesture = cGestureList[0];
    
    if (HandX > -100 && HandX < 2000 && HandY < 1300 && HandZ > 0 && HandZ < 600){
     if (cGesture.type() == Leap::Gesture::TYPE_SWIPE){
      cSwipeGesture = Leap::SwipeGesture(cGesture);
      bool isHorizontal = abs(cSwipeGesture.direction()[0]) > abs(cSwipeGesture.direction()[1]);
      if (isHorizontal){
       if (cSwipeGesture.direction()[0] > 0){
        Gesture_str = "right";
       }
       else {
        Gesture_str = "left";
       }
       printf("swipe,%s", &Gesture_str);
       Sleep(1000);
      }
     }
     else{
      // grab
      if (cHand.grabAngle() > 3){
       printf("grab\n");
      }
      else{
       printf("release\n");
      }
     }
    }
    // fingers
    for (int i = 0; i < 5; i++){
     cFinger = cHand.fingers()[i];
     FingerX[i] = cFinger.tipPosition().x;
     FingerY[i] = cFinger.tipPosition().y;
     FingerZ[i] = cFinger.tipPosition().z;

     FingerX[i] = ((FingerX[i] + 200.0) / 400.0)*640.0;
     FingerZ[i] = ((FingerZ[i] + 200.0) / 400.0)*480.0;
    }
   }
   // second hand
   if (cHand2.isValid()){
    Hand2X = cHand2.palmPosition().x;
    Hand2Y = cHand2.palmPosition().y;
    Hand2Z = cHand2.palmPosition().z;

    Hand2X = ((Hand2X + 200.0) / 400.0)*640.0;
    Hand2Z = ((Hand2Z + 200.0) / 400.0)*480.0;

    if (Hand2X > -100 && Hand2X < 2000 && Hand2Y < 1300 && Hand2Z > 0 && Hand2Z < 600){
     // grab
     if (cHand2.grabAngle() > 3){
      printf("grab\n");
     }
     else{
      printf("release\n");
     }
    }
    // fingers
    for (int i = 0; i < 5; i++){
     cFinger2 = cHand2.fingers()[i];
     Finger2X[i] = cFinger2.tipPosition().x;
     Finger2Y[i] = cFinger2.tipPosition().y;
     Finger2Z[i] = cFinger2.tipPosition().z;

     Finger2X[i] = ((Finger2X[i] + 200.0) / 400.0)*640.0;
     Finger2Z[i] = ((Finger2Z[i] + 200.0) / 400.0)*480.0;
    }
   }
   if(isShowWindow){
    cv::flip(LeapMatR, LeapMatR, 1);
    imshow("LeapImageR", LeapMatR);
    drawMat.create(600, 800, CV_8UC4);
    // draw first hands and fingers
    cv::Point Handcenter(HandX, HandZ);
    cv::circle(drawMat, Handcenter, 20, cv::Scalar(0, 0, 255), -1, 8, 0);
    for(int i=0; i<5 i="" if="" ingerx="">=0 && FingerZ[i]>=0){
      cv::Point FingerCenter(FingerX[i], FingerZ[i]);
      cv::circle(drawMat, FingerCenter, 10, cv::Scalar(0, 255, 0), -1, 8, 0);
     }
    }
    // draw second hands and fingers
    cv::Point Handcenter2(Hand2X, Hand2Z);
    cv::circle(drawMat, Handcenter2, 20, cv::Scalar(0, 0, 255), -1, 8, 0);
    for (int i = 0; i<5 i="" if="" inger2x="">= 0 && Finger2Z[i] >= 0){
      cv::Point FingerCenter(Finger2X[i], Finger2Z[i]);
      cv::circle(drawMat, FingerCenter, 10, cv::Scalar(0, 255, 0), -1, 8, 0);
     }
    }
    imshow("DrawInfo", drawMat);
    drawMat.release();
    cv::waitKey(20);
   }
   else{
    cv::destroyAllWindows();
   }
  }
  // ctrl+F3: show window
  if(GetAsyncKeyState(17) && GetAsyncKeyState(114)){
   printf("show window flag\n");
   isShowWindow = !isShowWindow;
   // Start time
   time(&start);
   fps = 0;
   count = 0;
   Sleep(200);
  }
  // ctrl+F5: close or open cmd window
  if (GetAsyncKeyState(17) && GetAsyncKeyState(116)){
   cmdFlag = !cmdFlag;
   ShowWindow(CmdhWnd, cmdFlag);
   Sleep(200);
  }
  // ctrl+F1:exit
  if (GetAsyncKeyState(17) && GetAsyncKeyState(112)){
   sprintf(sendChar, "E");
   int sendLen = strlen(sendChar);
   LSockApp.SendData(sendChar, sendLen);
   break;
  }
 }
 CloseServiceHandle(serviceHandle);
 CloseServiceHandle(serviceDbHandle);
 return 0;
}


結束寫程式




沒有留言:

張貼留言