#include "stdafx.h"
#include <afxwin.h>
#include <array>
#include <iostream>
#include <map>
#include <vector>
// OpenCV 头文件
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
// NiTE 头文件
#include <OpenNI.h>
#include <NiTE.h>
using namespace std;
using namespace openni;
using namespace nite;
const unsigned int roi_offset=70;
const unsigned int BIN_THRESH_OFFSET =5;
const unsigned int MEDIAN_BLUR_K = 5;
const double GRASPING_THRESH = 0.9;
const cv:: Scalar COLOR_BLUE =cv::Scalar(240,40,0);
const cv::Scalar COLOR_DARK_GREEN = cv::Scalar(0, 128, 0);
const cv::Scalar COLOR_LIGHT_GREEN =cv:: Scalar(0,255,0);
const cv::Scalar COLOR_YELLOW =cv:: Scalar(0,128,200);
const cv::Scalar COLOR_RED = cv::Scalar(0,0,255);
float handDepth ;
float handflag=5;
float opencvframe=3;
struct ConvexityDefect
{
cv::Point start;
cv::Point end;
cv::Point depth_point;
float depth;
};
int main( int argc, char **argv )
{
// 初始化OpenNI
OpenNI::initialize();
// 打开Kinect设备
Device mDevice;
mDevice.open( ANY_DEVICE );
// 创建深度数据流
VideoStream mDepthStream;
mDepthStream.create( mDevice, SENSOR_DEPTH );
// 设置VideoMode模式
VideoMode mDepthMode;
mDepthMode.setResolution( 640, 480 );
mDepthMode.setFps( 30 );
mDepthMode.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM );
mDepthStream.setVideoMode(mDepthMode);
// 同样的设置彩色数据流
VideoStream mColorStream;
mColorStream.create( mDevice, SENSOR_COLOR );
// 设置VideoMode模式
VideoMode mColorMode;
mColorMode.setResolution( 640, 480 );
mColorMode.setFps( 30 );
mColorMode.setPixelFormat( PIXEL_FORMAT_RGB888 );
mColorStream.setVideoMode( mColorMode);
// 设置深度图像映射到彩色图像
mDevice.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );
// 初始化 NiTE
NiTE::initialize();
// 创建HandTracker跟踪器
HandTracker mHandTracker;
if( mHandTracker.create() != nite::STATUS_OK )
{
cerr << "Can't create user tracker" << endl;
return -1;
}
// 设定手势探测(GESTURE_WAVE、GESTURE_CLICK和GESTURE_HAND_RAISE)
mHandTracker.startGestureDetection( GESTURE_WAVE );
mHandTracker.startGestureDetection( GESTURE_CLICK );
//mHandTracker.startGestureDetection( GESTURE_HAND_RAISE );
//mHandTracker.setSmoothingFactor(0.1f);
// 创建深度图像显示
cv::namedWindow("Depth Image", CV_WINDOW_AUTOSIZE);
// 创建彩色图像显示
cv::namedWindow( "Color Image", CV_WINDOW_AUTOSIZE );
// 保存点坐标
map< HandId,vector<cv::Point2f> > mapHandData;
map< HandId,float > mapHanddepth;
vector<cv::Point2f> vWaveList;
vector<cv::Point2f> vClickList;
cv::Point2f ptSize( 3, 3 );
array<cv::Scalar,8> aHandColor;
aHandColor[0] = cv::Scalar( 255, 0, 0 );
aHandColor[1] = cv::Scalar( 0, 255, 0 );
aHandColor[2] = cv::Scalar( 0, 0, 255 );
aHandColor[3] = cv::Scalar( 255, 255, 0 );
aHandColor[4] = cv::Scalar( 255, 0, 255 );
aHandColor[5] = cv::Scalar( 0, 255, 255 );
aHandColor[6] = cv::Scalar( 255, 255, 255 );
aHandColor[7] = cv::Scalar( 0, 0, 0 );
// 环境初始化后,开始获取深度数据流和彩色数据流
mDepthStream.start();
mColorStream.start();
// 获得最大深度值
int iMaxDepth = mDepthStream.getMaxPixelValue();
// start
while( true )
{
/* POINT pt;
GetCursorPos(&pt);
cerr<<pt.x<<" "<<pt.y<<endl;*/
// 创建OpenCV::Mat,用于显示彩色数据图像
cv::Mat cImageBGR;
// 读取彩色数据帧信息流
VideoFrameRef mColorFrame;
mColorStream.readFrame( &mColorFrame );
// 将彩色数据流转换为OpenCV格式,记得格式是:CV_8UC3(含R\G\B)
const cv::Mat mImageRGB( mColorFrame.getHeight(), mColorFrame.getWidth(),
CV_8UC3, (void*)mColorFrame.getData() );
// RGB ==> BGR
cv::cvtColor( mImageRGB, cImageBGR, CV_RGB2BGR );
// 获取手Frame
HandTrackerFrameRef mHandFrame;
if( mHandTracker.readFrame( &mHandFrame ) == nite::STATUS_OK )
{
openni::VideoFrameRef mDepthFrame = mHandFrame.getDepthFrame();
// 将深度数据转换成OpenCV格式
const cv::Mat mImageDepth( mDepthFrame.getHeight(), mDepthFrame.getWidth(), CV_16UC1, (void*)mDepthFrame.getData() );
// 为了让深度图像显示的更加明显一些,将CV_16UC1 ==> CV_8U格式
cv::Mat mScaledDepth, mImageBGR;
mImageDepth.convertTo( mScaledDepth, CV_8U, 255.0 / iMaxDepth );
// 将灰度图转换成BGR格式,为了画出点的颜色坐标和轨迹
cv::cvtColor( mScaledDepth, mImageBGR, CV_GRAY2BGR );
// 检测手势
const nite::Array<GestureData>& aGestures = mHandFrame.getGestures();
for( int i = 0; i < aGestures.getSize(); ++ i )
{
const GestureData& rGesture = aGestures[i];
const Point3f& rPos = rGesture.getCurrentPosition();
cv::Point2f rPos2D;
mHandTracker.convertHandCoordinatesToDepth( rPos.x, rPos.y, rPos.z, &rPos2D.x, &rPos2D.y );
HandId mHandID;
if( mHandTracker.startHandTracking( rPos, &mHandID ) != nite::STATUS_OK )
cerr << "Can't track hand" << endl;
}
// 得到手心坐标
const nite::Array<HandData>& aHands = mHandFrame.getHands();
for( int i = 0; i < aHands.getSize(); ++ i )
{
const HandData& rHand = aHands[i];
HandId uID = rHand.getId();
if( rHand.isNew() )
{
mapHandData.insert( make_pair( uID, vector<cv::Point2f>() ) );
mapHanddepth.insert(make_pair(uID,float()));
}
if( rHand.isTracking() )
{
// 将手心坐标映射到彩色图像和深度图像中
const Point3f& rPos = rHand.getPosition();
cv::Point2f rPos2D;
mHandTracker.convertHandCoordinatesToDepth( rPos.x, rPos.y, rPos.z, &rPos2D.x, &rPos2D.y );
handDepth = rPos.z * 255/iMaxDepth;
cv::Point2f aPoint=rPos2D;
cv::circle( cImageBGR, aPoint, 3, cv::Scalar( 0, 0, 255 ), 4 );
cv::circle( mScaledDepth, aPoint, 3, cv::Scalar(0, 0, 255), 4);
// 在彩色图像中画出手的轮廓边
cv::Point2f ctlPoint, ctrPoint, cdlPoint, cdrPoint;
ctlPoint.x = aPoint.x - 100;
ctlPoint.y = aPoint.y - 100;
ctrPoint.x = aPoint.x - 100;
ctrPoint.y = aPoint.y + 100;
cdlPoint.x = aPoint.x + 100;
cdlPoint.y = aPoint.y - 100;
cdrPoint.x = aPoint.x + 100;
cdrPoint.y = aPoint.y + 100;
cv::line( cImageBGR, ctlPoint, ctrPoint, cv::Scalar( 255, 0, 0 ), 3 );
cv::line( cImageBGR, ctlPoint, cdlPoint, cv::Scalar( 255, 0, 0 ), 3 );
cv::line( cImageBGR, cdlPoint, cdrPoint, cv::Scalar( 255, 0, 0 ), 3 );
cv::line( cImageBGR, ctrPoint, cdrPoint, cv::Scalar( 255, 0, 0 ), 3 );
// 在深度图像中画出手的轮廓边
cv::Point2f mtlPoint, mtrPoint, mdlPoint, mdrPoint;
mtlPoint.x = aPoint.x - 100;
mtlPoint.y = aPoint.y - 100;
mtrPoint.x = aPoint.x - 100;
mtrPoint.y = aPoint.y + 100;
mdlPoint.x = aPoint.x + 100;
mdlPoint.y = aPoint.y - 100;
mdrPoint.x = aPoint.x + 100;
mdrPoint.y = aPoint.y + 100;
cv::line( mScaledDepth, mtlPoint, mtrPoint, cv::Scalar( 255, 0, 0 ), 3 );
cv::line( mScaledDepth, mtlPoint, mdlPoint, cv::Scalar( 255, 0, 0 ), 3 );
cv::line( mScaledDepth, mdlPoint, mdrPoint, cv::Scalar( 255, 0, 0 ), 3 );
cv::line( mScaledDepth, mtrPoint, mdrPoint, cv::Scalar( 255, 0, 0 ), 3 );
mapHandData[uID].push_back( rPos2D );
mapHanddepth[uID]=handDepth;
}
if( rHand.isLost() ){
mapHandData.erase(uID );
mapHanddepth.erase(uID);
}
}
for( auto itHand = mapHandData.begin(); itHand != mapHandData.end(); ++ itHand )
{
const cv::Scalar& rColor = aHandColor[ itHand->first % aHandColor.size() ];
const vector<cv::Point2f>& rPoints = itHand->second;
for( int i = 1; i < rPoints.size(); ++ i )
{
cv::line( mImageBGR, rPoints[i-1], rPoints[i], rColor, 2 );
cv::line( cImageBGR, rPoints[i-1], rPoints[i], rColor, 2 );
}
}
cv::imshow( "Depth Image", mImageBGR );
cv::imshow("Color Image", cImageBGR);
mHandFrame.release();
}
else
{
cerr << "Can't get new frame" << endl;
}
// 按键“q”退出循环
if( cv::waitKey( 1 ) == 'q' )
break;
}
mHandTracker.destroy();
mColorStream.destroy();
NiTE::shutdown();
OpenNI::shutdown();
return 0;
}
在手的部位画出一个矩形框,模拟画线,实现效果图