kinect+openni2+nite2+opencv2.4手势跟踪

#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;
}

在手的部位画出一个矩形框,模拟画线,实现效果图


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值