zoukankan      html  css  js  c++  java
  • 请教tornadomeet大神Kinect+OpenNI学习笔记之8(Robert Walter手部提取代码的分析)(OpenNI2、NiTE2改编)

    // skeletonHand.cpp : Defines the entry point for the console application.
    //
    
    // STL Header
    #include "stdafx.h"
    #include <iostream>
    
    #include <vector>
      
    // OpenCV Header
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
      
    // o1. OpenNI Header
    #include <OpenNI.h>
      
    // n1. NiTE Header
    #include <NiTE.h>
      
    // namespace
    using namespace std;
    using namespace openni;
    using namespace nite;
    using std::vector;
    
    const unsigned int ROI_OFFSET            = 70;
    const unsigned int XRES                    = 640;
    const unsigned int YRES                    = 480;
    const unsigned int BIN_THRESH_OFFSET    = 5;
    const unsigned int MEDIAN_BLUR_K        = 5;
    const unsigned int GRASPING_THRESH        = 0.9;
    //define color
    const cv::Scalar COLOR_DARK_GREEN    =    cv::Scalar (0 , 128, 0);
    const cv::Scalar COLOR_YELLOW        =    cv::Scalar (0 , 128, 200 );
    const cv::Scalar COLOR_BLUE            =    cv::Scalar ( 240, 40, 0);
    const cv::Scalar COLOR_LIGHT_GREEN    =    cv::Scalar (0, 255 ,0);
    const cv::Scalar COLOR_RED            =    cv::Scalar ( 0, 0, 255);
    
    
    
    struct ConvexityDefect
    {
        cv::Point start;
        cv::Point end;
        cv::Point depth_point;
        float depth;
    };
    
    bool handApproachingDisplayPerimeter(float x, float y)
    {
        return (x > (XRES - ROI_OFFSET)) || (x < (ROI_OFFSET)) ||
               (y > (YRES - ROI_OFFSET)) || (y < (ROI_OFFSET));
    }
    //
    //// Thanks to Jose Manuel Cabrera for part of this C++ wrapper function
    ////Convexity為凸的意思,Defect為缺陷的意思,hull為殼的意思
    ////貌似這個函數在opencv中已經被實現了
    //    void findConvexityDefects(vector<cv::Point>& contour, vector<int>& hull, vector<ConvexityDefect>& convexDefects)
    //    {
    //        if(hull.size() > 0 && contour.size() > 0)
    //        {    
    //        CvSeq* contourPoints;
    //        CvSeq* defects;
    //        CvMemStorage* storage;
    //        CvMemStorage* strDefects;
    //        CvMemStorage* contourStr;
    //        CvConvexityDefect *defectArray = 0;
    //
    //        strDefects = cvCreateMemStorage();
    //        defects = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq),sizeof(CvPoint), strDefects );
    //
    //        //We transform our vector<Point> into a CvSeq* object of CvPoint.
    //        contourStr = cvCreateMemStorage();
    //        contourPoints = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), contourStr);
    //        for(int i = 0; i < (int)contour.size(); i++) {
    //            CvPoint cp = {contour[i].x,  contour[i].y};
    //            cvSeqPush(contourPoints, &cp);
    //        }
    //
    //        //Now, we do the same thing with the hull index
    //        int count = (int) hull.size();
    //        //int hullK[count];
    //        int* hullK = (int*) malloc(count*sizeof(int));
    //        for(int i = 0; i < count; i++) { hullK[i] = hull.at(i); }
    //        CvMat hullMat = cvMat(1, count, CV_32SC1, hullK);
    //
    //        // calculate convexity defects
    //        storage = cvCreateMemStorage(0);
    //        defects = cv::convexityDefects(*contourPoints, &hullMat, *storage);
    //        defectArray = (CvConvexityDefect*)malloc(sizeof(CvConvexityDefect)*defects->total);
    //        cvCvtSeqToArray(defects, defectArray, CV_WHOLE_SEQ);
    //        //printf("DefectArray %i %i\n",defectArray->end->x, defectArray->end->y);
    //
    //        //We store defects points in the convexDefects parameter.
    //        for(int i = 0; i<defects->total; i++){
    //            ConvexityDefect def;
    //            def.start       = cv::Point(defectArray[i].start->x, defectArray[i].start->y);
    //            def.end         = cv::Point(defectArray[i].end->x, defectArray[i].end->y);
    //            def.depth_point = cv::Point(defectArray[i].depth_point->x, defectArray[i].depth_point->y);
    //            def.depth       = defectArray[i].depth;
    //            convexDefects.push_back(def);
    //        }
    //
    //    // release memory
    //    cvReleaseMemStorage(&contourStr);
    //    cvReleaseMemStorage(&strDefects);
    //    cvReleaseMemStorage(&storage);
    //
    //    }
    //}
    //
    //
    //  
    int main( int argc, char **argv )
    {
      // o2. Initial OpenNI
      OpenNI::initialize();
      
      // o3. Open Device
      Device  mDevice;
      mDevice.open( ANY_DEVICE );
      
      // o4. create depth stream
      VideoStream mDepthStream;
      mDepthStream.create( mDevice, SENSOR_DEPTH );
      // o4a. set video mode
      VideoMode mDMode;
      mDMode.setResolution( 640, 480 );
      mDMode.setFps( 30 );
      mDMode.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM );
      mDepthStream.setVideoMode( mDMode);
      
      // o5. Create color stream
      VideoStream mColorStream;
      mColorStream.create( mDevice, SENSOR_COLOR );
      // o5a. set video mode
      VideoMode mCMode;
      mCMode.setResolution( 640, 480 );
      mCMode.setFps( 30 );
      mCMode.setPixelFormat( PIXEL_FORMAT_RGB888 );
      mColorStream.setVideoMode( mCMode);
       
      // o6. image registration
      mDevice.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );
      
      // n2. Initial NiTE
      NiTE::initialize();
      
      // n3. create user tracker
      UserTracker mUserTracker;
      mUserTracker.create( &mDevice );
      mUserTracker.setSkeletonSmoothingFactor( 0.1f );
      
      //set ROI
      cv::Rect ROI;
      ROI.width = ROI_OFFSET * 2;
      ROI.height = ROI_OFFSET * 2;
    
      // create OpenCV Window
      cv::namedWindow( "User Image",  CV_WINDOW_AUTOSIZE );
      cv::namedWindow( "Depth Image", CV_WINDOW_AUTOSIZE );
      cv::namedWindow( "leftHandFrame Image", CV_WINDOW_AUTOSIZE );
      cv::namedWindow( "rightHandFrame Image", CV_WINDOW_AUTOSIZE );
      // p1. start
      mColorStream.start();
      mDepthStream.start();
      
       int iMaxDepth = mDepthStream.getMaxPixelValue();
    
      while( true )
      {
        // main loop
    
        cv::Mat cImageBGR;
        cv::Mat cImageDepth;
        cv::Mat handDebug;
    
        vector< cv::Mat > debugFrames;
    
        // p2a. get color frame
        VideoFrameRef mColorFrame;
        VideoFrameRef mDepthFrame;
    
        mColorStream.readFrame( &mColorFrame );
        mDepthStream.readFrame( &mDepthFrame );
    
        // p2b. convert data to OpenCV format
        const cv::Mat mImageRGB( mColorFrame.getHeight(), mColorFrame.getWidth(), CV_8UC3, (void*)mColorFrame.getData() );
        // p2c. convert form RGB to BGR
        cv::cvtColor( mImageRGB, cImageBGR, CV_RGB2BGR );
        
        // now we do same thing to the depth 
        const cv::Mat mImageDepth( mDepthFrame.getHeight(), mDepthFrame.getWidth(), CV_16UC1, (void*)mDepthFrame.getData() );
        // 8c. re-map depth data [0,Max] to [0,255]
        mImageDepth.convertTo( cImageDepth, CV_8U, 255.0 / iMaxDepth );
     
        // p3. get user frame
        UserTrackerFrameRef  mUserFrame;
        mUserTracker.readFrame( &mUserFrame );
     
        // p4. get users data
        const nite::Array<UserData>& aUsers = mUserFrame.getUsers();
        for( int i = 0; i < aUsers.getSize(); ++ i )
        {
            const UserData& rUser = aUsers[i];
     
            // p4a. check user status
            if( rUser.isNew() )
            {
                // start tracking for new user
                mUserTracker.startSkeletonTracking( rUser.getId() );
            }
     
            if( rUser.isVisible() )
            {
                // p4b. get user skeleton
                const Skeleton& rSkeleton = rUser.getSkeleton();
                
                int handDepth = -1;
    
                if ( rSkeleton.getState() == SKELETON_TRACKED )
                {
                    for ( int handI = 0; handI < 2; handI++)
                    {
                        //get the position of the hand
                        //struct SkeletonJoint
                        //{
                        //    float x, y, z, confidence;
                        //};
                        SkeletonJoint hand;
    
                        if ( handI == 0)
                        {
                            hand = rSkeleton.getJoint( JOINT_RIGHT_HAND );
                        }
                        else
                        {
                            hand = rSkeleton.getJoint( JOINT_LEFT_HAND );
                        }
    
                        if ( hand.getPositionConfidence() >= 0.5 )
                        {
                            const Point3f& handPosition = hand.getPosition();
                            
                            //change to 8 bites image
                            handDepth = handPosition.z * 255.0 / iMaxDepth;
    
                            //get the roi
                            if(!handApproachingDisplayPerimeter(handPosition.x, handPosition.y))
                            {
                                ROI.x = handPosition.x - ROI_OFFSET;    
                                ROI.y = handPosition.y - ROI_OFFSET;
                            }
                        }
    
                        // set the ROI in depth image
                        cv::Mat handCpy( cImageDepth, ROI );
                        cv::Mat handMat = handCpy.clone ();
                        
                        //binary threshold
                        if ( handDepth != -1)
                            handMat = (handMat > (handDepth - BIN_THRESH_OFFSET)) & (handMat < (handDepth + BIN_THRESH_OFFSET));
    
                        //median blur
                        medianBlur(handMat, handMat, MEDIAN_BLUR_K);
    
                        handDebug = handMat.clone();
                        debugFrames.push_back(handDebug);
                        cvtColor(debugFrames[handI], debugFrames[handI], CV_GRAY2RGB);
    
                        std::vector< std::vector < cv::Point >> contours;
                        std::vector<cv::Vec4i> hierarchy;
    
                        findContours(handMat, contours,  hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    
                        if (contours.size()) 
                        {
                            for (int i = 0; i < contours.size(); i++) 
                            {
                                vector<cv::Point> contour = contours[i];
                                //将vector转换成Mat型,此时的Mat还是列向量,只不过是2个通道的列向量而已
                                cv::Mat contourMat = cv::Mat(contour);
                                //返回轮廓的面积
                                double cArea = contourArea(contourMat);
                                
                                if(cArea > 2000)
                                {
                                    cv::Scalar center = mean(contourMat);
                                    cv::Point centerPoint = cv::Point(center.val[0], center.val[1]);
    
                                    // approximate the contour by a simple curve
                                    vector<cv::Point> approxCurve;
                                    //求出轮廓的封闭的曲线,保存在approxCurve,轮廓和封闭曲线直接的最大距离为10
                                    approxPolyDP(contourMat, approxCurve, 10, true);
    
                                    vector< vector<cv::Point> > debugContourV;
                                    debugContourV.push_back(approxCurve);
                                    //在参数1中画出轮廓参数2,参数2必须是轮廓的集合,所以参数2是
                                    //vector< vector<Point> >类型
                                    //深绿色代表近似多边形
                                    drawContours(debugFrames[handI], debugContourV, 0, COLOR_DARK_GREEN , 3);
    
                                    vector<int> hull;
                                    //找出近似曲线的凸包集合,集合hull中存储的是轮廓中凸包点的下标
                                    convexHull(cv::Mat(approxCurve), hull, false, false);
    
                                    // draw the hull points
                                    for(int j = 0; j < hull.size(); j++)
                                    {
                                        int index = hull[j];
                                        //凸顶点用黄色表示
                                        circle(debugFrames[handI], approxCurve[index], 3, COLOR_YELLOW, 2);
                                    }
    
                                    // find convexity defects
                                    vector<cv::Vec4i> convexDefects;
                                    cv::convexityDefects(cv::Mat(approxCurve), hull, convexDefects);
                                    printf("Number of defects: %d.\n", (int) convexDefects.size());
    
                                    for(int j = 0; j < convexDefects.size(); j++)
                                    {
                                        //缺陷点用蓝色表示
                                        circle(debugFrames[handI], approxCurve[convexDefects[j][2]], 3, COLOR_BLUE, 2);
                                    }
    
    
                                    // assemble point set of convex hull
                                    //将凸包集以点的坐标形式保存下来
                                    vector<cv::Point> hullPoints;
                                    for(int k = 0; k < hull.size(); k++)
                                    {
                                        int curveIndex = hull[k];
                                        cv::Point p = approxCurve[curveIndex];
                                        hullPoints.push_back(p);
                                    }
    
    
    
                                    // area of hull and curve
                                    double hullArea  = contourArea(cv::Mat(hullPoints));
                                    double curveArea = contourArea(cv::Mat(approxCurve));
                                    double handRatio = curveArea/hullArea;
                            
                                    // hand is grasping
                                    //GRASPING_THRESH == 0.9
                                    if(handRatio > GRASPING_THRESH)
                                    //握拳表示绿色
                                    circle(debugFrames[handI], centerPoint, 5, COLOR_LIGHT_GREEN, 5);
                                    else
                                    //一般情况下手张开其中心点是显示红色
                                    circle(debugFrames[handI], centerPoint, 5, COLOR_RED, 5);
                                }
                            }
                        }
                    }
                }
            }
        }
    
        // p5. show image
        cv::imshow( "User Image", cImageBGR );
        cv::imshow( "Depth Image", cImageDepth );
        
        //debugFrames只保存2帧图像
        if(debugFrames.size() >= 2 )
        {
            //长和宽的尺寸都扩大3倍
            resize(debugFrames[0], debugFrames[0], cv::Size(), 3, 3);
            resize(debugFrames[1], debugFrames[1], cv::Size(), 3, 3);
            imshow("leftHandFrame Image",  debugFrames[0]);
            imshow("rightHandFrame Image",  debugFrames[1]);
            debugFrames.clear();
        }
    
        cv::waitKey (20);
        // p6. check keyboard
        if( cv::waitKey( 1 ) == 'q' )
          break;
      }
      
      // p7. stop
      mUserTracker.destroy();
      mColorStream.destroy();
      mDepthStream.destroy();
      mDevice.close();
      NiTE::shutdown();
      OpenNI::shutdown();
      
      return 0;
    }
  • 相关阅读:
    docker应用
    docker 安装--2
    docker容器--1
    oracle表可以跨操作系统文件,也可以跨表空间(分区表即可)
    linux 上的 oracle问题
    ftp默认是按ASCII模式传输文件
    5、Jmeter动态随机参数
    4、Jmeter请求参数
    的撒
    3、Jmeter断言
  • 原文地址:https://www.cnblogs.com/hqqxyy/p/2970345.html
Copyright © 2011-2022 走看看