Ejemplo n.º 1
0
int main(int argc, char **argv)
{
#pragma region InitialNite And Ni
	// Initial NiTE
	if (NiTE::initialize() != STATUS_OK)
	{
		cerr << "NiTE initial error" << endl;
		system("PAUSE");
		return -1;
	}

	if (openni::OpenNI::initialize() != openni::STATUS_OK){
		cerr << "NiTE initial error" << endl;
		system("PAUSE");
		return -1;
	}
#pragma endregion


#pragma region GetAllDevice
	openni::Array<openni::DeviceInfo> deviceInfoList;
	openni::OpenNI::enumerateDevices(&deviceInfoList);
	cout << endl;
	cout << "Device numbers: " << deviceInfoList.getSize() << endl;

	vector<CDevice> vDevices;
	for (int i = 0; i < deviceInfoList.getSize(); ++i)
	{
		cout << "Device " << i << "\n";
		const openni::DeviceInfo& rDevInfo = deviceInfoList[i];

		cout << " " << rDevInfo.getName() << " by " << rDevInfo.getVendor() << "\n";
		cout << " PID: " << rDevInfo.getUsbProductId() << "\n";
		cout << " VID: " << rDevInfo.getUsbVendorId() << "\n";
		cout << " URI: " << rDevInfo.getUri() << endl;

		// initialize
		CDevice mDevWin(i, deviceInfoList[i].getUri());
		vDevices.push_back(mDevWin);
	}
#pragma endregion


	// start
	while (true)
	{
		for (vector<CDevice>::iterator itdev = vDevices.begin(); itdev != vDevices.end(); ++itdev){
			// get user frame
			UserTrackerFrameRef	mUserFrame;
			if (itdev->pUserTracker->readFrame(&mUserFrame) == nite::STATUS_OK)
			{
				// get depth data and convert to OpenCV format
				openni::VideoFrameRef vfDepthFrame = mUserFrame.getDepthFrame();
				const cv::Mat mImageDepth(vfDepthFrame.getHeight(), vfDepthFrame.getWidth(), CV_16UC1, const_cast<void*>(vfDepthFrame.getData()));
				// re-map depth data [0,Max] to [0,255]
				cv::Mat mScaledDepth;
				mImageDepth.convertTo(mScaledDepth, CV_8U, 255.0 / 10000);

				// convert gray-scale to color
				cv::Mat mImageBGR;
				cv::cvtColor(mScaledDepth, mImageBGR, CV_GRAY2BGR);

				// get users data
				const nite::Array<UserData>& aUsers = mUserFrame.getUsers();
				for (int i = 0; i < aUsers.getSize(); ++i)
				{
					const UserData& rUser = aUsers[i];

					// check user status
					if (rUser.isNew())
					{
						cout << "New User [" << rUser.getId() << "] found." << endl;
						//  start tracking for new user
						itdev->pUserTracker->setSkeletonSmoothingFactor(0.65); //平滑控制。
						itdev->pUserTracker->startSkeletonTracking(rUser.getId());
					}
					else if (rUser.isLost())
					{
						cout << "User [" << rUser.getId() << "] lost." << endl;
					}

					if (rUser.isVisible())
					{
						// get user skeleton
						const Skeleton& rSkeleton = rUser.getSkeleton();
						if (rSkeleton.getState() == SKELETON_TRACKED)
						{
#pragma region DrawSkeletonLineAndCircle
							// build joints array
							nite::SkeletonJoint aJoints[15];
							aJoints[0] = rSkeleton.getJoint(JOINT_HEAD);
							aJoints[1] = rSkeleton.getJoint(JOINT_NECK);
							aJoints[2] = rSkeleton.getJoint(JOINT_LEFT_SHOULDER);
							aJoints[3] = rSkeleton.getJoint(JOINT_RIGHT_SHOULDER);
							aJoints[4] = rSkeleton.getJoint(JOINT_LEFT_ELBOW);
							aJoints[5] = rSkeleton.getJoint(JOINT_RIGHT_ELBOW);
							aJoints[6] = rSkeleton.getJoint(JOINT_LEFT_HAND);
							aJoints[7] = rSkeleton.getJoint(JOINT_RIGHT_HAND);
							aJoints[8] = rSkeleton.getJoint(JOINT_TORSO);
							aJoints[9] = rSkeleton.getJoint(JOINT_LEFT_HIP);
							aJoints[10] = rSkeleton.getJoint(JOINT_RIGHT_HIP);
							aJoints[11] = rSkeleton.getJoint(JOINT_LEFT_KNEE);
							aJoints[12] = rSkeleton.getJoint(JOINT_RIGHT_KNEE);
							aJoints[13] = rSkeleton.getJoint(JOINT_LEFT_FOOT);
							aJoints[14] = rSkeleton.getJoint(JOINT_RIGHT_FOOT);

							// convert joint position to image
							cv::Point2f aPoint[15];
							for (int s = 0; s < 15; ++s)
							{
								const Point3f& rPos = aJoints[s].getPosition();
								itdev->pUserTracker->convertJointCoordinatesToDepth(rPos.x, rPos.y, rPos.z, &(aPoint[s].x), &(aPoint[s].y));
							}

							// draw line
							cv::line(mImageBGR, aPoint[0], aPoint[1], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[1], aPoint[2], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[1], aPoint[3], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[2], aPoint[4], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[3], aPoint[5], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[4], aPoint[6], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[5], aPoint[7], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[1], aPoint[8], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[8], aPoint[9], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[8], aPoint[10], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[9], aPoint[11], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[10], aPoint[12], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[11], aPoint[13], cv::Scalar(255, 0, 0), 3);
							cv::line(mImageBGR, aPoint[12], aPoint[14], cv::Scalar(255, 0, 0), 3);

							// draw joint
							for (int s = 0; s < 15; ++s)
							{
								if (aJoints[s].getPositionConfidence() > 0.5)
									cv::circle(mImageBGR, aPoint[s], 3, cv::Scalar(0, 0, 255), 2);
								else
									cv::circle(mImageBGR, aPoint[s], 3, cv::Scalar(0, 255, 0), 2);
							}

							cv::putText(mImageBGR, "USER" + to_string(rUser.getId()), aPoint[0], cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255, 255, 255));

#pragma endregion

							//獲取初始值
							if (itdev->detectFlag == 0)//第一次偵測
							{
#pragma region 初始化Algorithm
								itdev->DSTimes++;
								if (itdev->DSTimes == 1)
								{
									itdev->fheadf.x = aJoints[0].getPosition().x;//站立時的頭的位置;
									itdev->fheadf.y = aJoints[0].getPosition().y;
									itdev->fheadf.z = aJoints[0].getPosition().z;

									itdev->ftorsof.x = aJoints[8].getPosition().x;//站立時的質心位置;
									itdev->ftorsof.y = aJoints[8].getPosition().y;
									itdev->ftorsof.z = aJoints[8].getPosition().z;

									itdev->lefthand.x = aJoints[6].getPosition().x;
									itdev->lefthand.y = aJoints[6].getPosition().y;
									itdev->lefthand.z = aJoints[6].getPosition().z;

									itdev->righthand.x = aJoints[7].getPosition().x;
									itdev->righthand.y = aJoints[7].getPosition().y;
									itdev->righthand.z = aJoints[7].getPosition().z;
									//左右手距離*0.55。 為什麼要乘0.55?
									itdev->armLen = sqrt((itdev->lefthand.x - itdev->righthand.x)*(itdev->lefthand.x - itdev->righthand.x) +
										(itdev->lefthand.y - itdev->righthand.y)*(itdev->lefthand.y - itdev->righthand.y) +
										(itdev->lefthand.z - itdev->righthand.z)*(itdev->lefthand.z - itdev->righthand.z))*0.55;
								}
								else if (itdev->DSTimes > 1 && itdev->DSTimes <= 200)	//偵測次數於200次以內
								{
									itdev->fheadf.x = itdev->fheadf.x + aJoints[0].getPosition().x;//站立時的頭的位置(累加);
									itdev->fheadf.y = itdev->fheadf.y + aJoints[0].getPosition().y;
									itdev->fheadf.z = itdev->fheadf.z + aJoints[0].getPosition().z;

									itdev->ftorsof.x = itdev->ftorsof.x + aJoints[8].getPosition().x;//站立時的質心位置(累加);
									itdev->ftorsof.y = itdev->ftorsof.y + aJoints[8].getPosition().y;
									itdev->ftorsof.z = itdev->ftorsof.z + aJoints[8].getPosition().z;

									itdev->lefthand.x = aJoints[6].getPosition().x;
									itdev->lefthand.y = aJoints[6].getPosition().y;
									itdev->lefthand.z = aJoints[6].getPosition().z;

									itdev->righthand.x = aJoints[7].getPosition().x;
									itdev->righthand.y = aJoints[7].getPosition().y;
									itdev->righthand.z = aJoints[7].getPosition().z;
									//?????
									int cc = sqrt((itdev->lefthand.x - itdev->righthand.x)*(itdev->lefthand.x - itdev->righthand.x) +
										(itdev->lefthand.y - itdev->righthand.y)*(itdev->lefthand.y - itdev->righthand.y) +
										(itdev->lefthand.z - itdev->righthand.z)*(itdev->lefthand.z - itdev->righthand.z))*0.55;

									//	cout << "測試下身長:" << cc << endl;
									itdev->armLen = itdev->armLen + cc;
								}
								if (itdev->DSTimes >= 200)//計算頭、身初始值、跌倒閥值
								{
									itdev->detectFlag = 1;
									itdev->fhead_Ini.x = itdev->fheadf.x / itdev->DSTimes;
									itdev->fhead_Ini.y = itdev->fheadf.y / itdev->DSTimes;
									itdev->fhead_Ini.z = itdev->fheadf.z / itdev->DSTimes;

									itdev->ftorso_Ini.x = itdev->ftorsof.x / itdev->DSTimes;
									itdev->ftorso_Ini.y = itdev->ftorsof.y / itdev->DSTimes;
									itdev->ftorso_Ini.z = itdev->ftorsof.z / itdev->DSTimes;

									itdev->fallDownThreshold = ((int)((itdev->armLen / itdev->DSTimes) / 100) * 100);

									cout << "跌倒的閾值:" << itdev->fallDownThreshold << endl;

									//計算頭 身當前的值
									itdev->fhead.x = aJoints[JOINT_HEAD].getPosition().x;
									itdev->fhead.y = aJoints[JOINT_HEAD].getPosition().y;
									itdev->fhead.z = aJoints[JOINT_HEAD].getPosition().z;
									itdev->fhead_Pre = itdev->fhead;

									itdev->ftorso.x = aJoints[JOINT_TORSO].getPosition().x;
									itdev->ftorso.y = aJoints[JOINT_TORSO].getPosition().y;
									itdev->ftorso.z = aJoints[JOINT_TORSO].getPosition().z;
									itdev->ftorso_Pre = itdev->ftorso;

									cout << "第" << itdev->DSTimes << "次" << "的頭部h:" << itdev->fhead.y << endl;
								}
#pragma endregion
							}
							else
							{
								if (itdev->cishu == 8)
								{
									itdev->cishu = 0;
#pragma region MainAlgorithm 
									itdev->fhead.x = aJoints[0].getPosition().x;
									itdev->fhead.y = aJoints[0].getPosition().y;
									itdev->fhead.z = aJoints[0].getPosition().z;

									itdev->ftorso.x = aJoints[8].getPosition().x;
									itdev->ftorso.y = aJoints[8].getPosition().y;
									itdev->ftorso.z = aJoints[8].getPosition().z;

									itdev->neck.x = aJoints[1].getPosition().x;
									itdev->neck.y = aJoints[1].getPosition().y;
									itdev->neck.z = aJoints[1].getPosition().z;

									itdev->event_Now = eventDetect(itdev->fhead_Pre, itdev->ftorso_Pre, itdev->fhead, itdev->ftorso, itdev->fhead_Ini, itdev->ftorso_Ini, itdev->neck, itdev->fallDownThreshold);//(前一幀,後一幀,初始幀)


#pragma region 統計時間,依時間檢查動作是否正確,發生錯誤僅作顯示,對程式邏輯沒有影響
									//統計時間
									if (itdev->event_Now == INCIDENT_SIT_DOWN)
										itdev->zuo = clock();
									if (itdev->event_Now == INCIDENT_FALLDOWN)
										itdev->die = clock();
									if (itdev->event_Now == INCIDENT_SIT_UP)
										itdev->zql = clock();
									if (itdev->event_Now == INCIDENT_STANDUP)
										itdev->zanql = clock();

									//僅顯示出可能的錯誤資訊、沒有實際影響
									if (itdev->event_Now == INCIDENT_FALLDOWN && difftime(itdev->zuo, itdev->firsttime) > 0 && difftime(itdev->zuo_Pre, itdev->zuo) != 0)
									{
										automendG(itdev->event_Now, difftime(itdev->die, itdev->zuo));//若"跌倒"與"坐下"事件大於10秒 則顯示警告
										itdev->zuo_Pre = itdev->zuo;
									}

									if (itdev->event_Now == INCIDENT_STANDUP && difftime(itdev->zql, itdev->firsttime) > 0 && difftime(itdev->zql_Pre, itdev->zql) != 0)
									{
										automendG(itdev->event_Now, difftime(itdev->zanql, itdev->zql));////若"站起來"與"坐起來"事件大於10秒 則顯示警告
										itdev->zql_Pre = itdev->zql;
									}
#pragma endregion


#pragma region 用於調試的,直接顯示出事件偵測結果,對程式邏輯沒有影響。
									if (itdev->event_Pre != itdev->event_Now)
									{
										if (itdev->event_Now == INCIDENT_NONE)
											cout << "沒偵測到事件發生!" << endl;
										if (itdev->event_Now == INCIDENT_STOP)
											cout << "發生的事件: " << "停止" << endl;
										if (itdev->event_Now == INCIDENT_WALK)
											cout << "發生的事件: " << "走" << endl;
										if (itdev->event_Now == INCIDENT_SIT_UP)
											cout << "發生的事件: " << "坐起來" << endl;
										if (itdev->event_Now == INCIDENT_STANDUP)
											cout << "發生的事件: " << "站起來" << endl;
										if (itdev->event_Now == INCIDENT_FALLDOWN)
											cout << "發生的事件: " << "跌倒" << endl;
										if (itdev->event_Now == INCIDENT_SIT_DOWN)
											cout << "發生的事件: " << "坐下" << endl;
										if (itdev->event_Now == INCIDENT_LAYDOWN)
											cout << "發生的事件: " << "躺下" << endl;
									}
									itdev->event_Pre = itdev->event_Now;
#pragma endregion


									if (itdev->weizhi == 0)
									{
										itdev->nextState = firststate(itdev->event_Now);
										if (itdev->nextState != 0)
											itdev->weizhi = 1;
										displayState(itdev->nextState, itdev->nowState,itdev->deviceID);
										itdev->nowState = itdev->nextState;
									}
									else if (itdev->weizhi == 1)
									{
										if (itdev->event_Now != 0)
										{
											if (unnormalzhenc(itdev->event_Now, itdev->nowState) == 1);
											{
												itdev->weizhi = 0;
											}
											itdev->nextState = stateTransfer(itdev->event_Now, itdev->nowState);
										}
										displayState(itdev->nextState, itdev->nowState, itdev->deviceID);
										itdev->nowState = itdev->nextState;
									}
									itdev->fhead_Pre = itdev->fhead;
									itdev->ftorso_Pre = itdev->ftorso;
#pragma endregion
								}
								itdev->cishu++;
							}
						}
					}
				}

				// show image
				cv::imshow(itdev->sWindow.c_str(), mImageBGR);
				mUserFrame.release();
			}
			else
			{
				cerr << "Can't get user frame" << endl;
			}
		}
		// check keyboard
		if (cv::waitKey(1) == 'q')
			break;
	}

	// stop
	for (vector<CDevice>::iterator itDev = vDevices.begin(); itDev != vDevices.end(); ++itDev){
		itDev->pUserTracker->destroy();
		delete itDev->pUserTracker;
		itDev->pDevice->close();
		delete itDev->pDevice;
	}

	cv::destroyAllWindows();
	NiTE::shutdown();
	openni::OpenNI::shutdown();
	system("PAUSE");

	return 0;
}
Ejemplo n.º 2
0
void NIModule::UpdateData()
{
	UserTrackerFrameRef mFrame;
	if( m_UserTracker.readFrame( &mFrame ) == nite::STATUS_OK )
	{
		auto& aUsers = mFrame.getUsers();
		for( int i = 0; i < aUsers.getSize(); ++ i )
		{
			auto& rUser = aUsers[i];
			const UserId& uID = rUser.getId();

			if( rUser.isNew() )
			{
				m_funcOnInfo( ( boost::format( "Found new user: %1%" ) % uID ).str() );
				m_UserTracker.startSkeletonTracking( uID );
				m_UserList.insert( make_pair( uID, CUserData() ) );
			}
			else if( rUser.isLost() )
			{
				m_funcOnInfo( ( boost::format( "Lost user: %1%" ) % uID ).str() );
				m_UserList.erase( uID );
			}
			else
			{
				auto& rUserData = m_UserList[uID];
				if( rUser.isVisible() )
				{
					const Skeleton& rSkeleton = rUser.getSkeleton();
					if( rSkeleton.getState() == nite::SKELETON_TRACKED )
					{
						SkeletonJoint aJointList[15];
						aJointList[ 0]	= rSkeleton.getJoint( nite::JOINT_HEAD				);
						aJointList[ 1]	= rSkeleton.getJoint( nite::JOINT_NECK				);
						aJointList[ 2]	= rSkeleton.getJoint( nite::JOINT_LEFT_SHOULDER		);
						aJointList[ 3]	= rSkeleton.getJoint( nite::JOINT_RIGHT_SHOULDER	);
						aJointList[ 4]	= rSkeleton.getJoint( nite::JOINT_LEFT_ELBOW		);
						aJointList[ 5]	= rSkeleton.getJoint( nite::JOINT_RIGHT_ELBOW		);
						aJointList[ 6]	= rSkeleton.getJoint( nite::JOINT_LEFT_HAND			);
						aJointList[ 7]	= rSkeleton.getJoint( nite::JOINT_RIGHT_HAND		);
						aJointList[ 8]	= rSkeleton.getJoint( nite::JOINT_TORSO				);
						aJointList[ 9]	= rSkeleton.getJoint( nite::JOINT_LEFT_HIP			);
						aJointList[10]	= rSkeleton.getJoint( nite::JOINT_RIGHT_HIP			);
						aJointList[11]	= rSkeleton.getJoint( nite::JOINT_LEFT_KNEE			);
						aJointList[12]	= rSkeleton.getJoint( nite::JOINT_RIGHT_KNEE		);
						aJointList[13]	= rSkeleton.getJoint( nite::JOINT_LEFT_FOOT			);
						aJointList[14]	= rSkeleton.getJoint( nite::JOINT_RIGHT_FOOT		);

						#pragma omp parallel for
						for( int i = 0; i < 15; ++ i )
						{
							const Point3f& rPos = aJointList[i].getPosition();
							rUserData.m_aSkeleton3D[ i * 4     ] = rPos.x;
							rUserData.m_aSkeleton3D[ i * 4 + 1 ] = rPos.y;
							rUserData.m_aSkeleton3D[ i * 4 + 2 ] = rPos.z;
							rUserData.m_aSkeleton3D[ i * 4 + 3 ] = aJointList[i].getPositionConfidence();

							m_UserTracker.convertJointCoordinatesToDepth( rPos.x, rPos.y, rPos.z, &(rUserData.m_aSkeleton2D[ i * 3 ]), &(rUserData.m_aSkeleton2D[ i * 3 + 1 ]) );
							rUserData.m_aSkeleton2D[ i * 3 + 2 ] = aJointList[i].getPositionConfidence();
						}

						if( rUserData.m_eStatus != CUserData::USER_TRACKED )
						{
							rUserData.m_eStatus = CUserData::USER_TRACKED;
							m_funcOnInfo( ( boost::format( "Strat tracking user: %1%" ) % uID ).str() );
						}
					}
					else
					{
						rUserData.m_eStatus = CUserData::USER_NORMAL;
					}
				}
				else
				{
					rUserData.m_eStatus = CUserData::USER_INVISIBLE;
				}
			}
		}
	}
}
Ejemplo n.º 3
0
void elApp::run()
{
    while (!terminateExec)
    {
        if (devOK)
        {
            UserTrackerFrameRef frame;
            if (userTracker.readFrame(&frame) != STATUS_OK)
            {
                printf("Unable to obtain next frame!\n");
            }
            else
            {
                const nite::Array<nite::UserData>& users = frame.getUsers();
                const s32 len = users.getSize();
                // if multiple users exist AND are active, take the closest one
                s32 userIdx = -1;
                for (s32 i = 0; i < len; i++)
                {
                    const nite::UserData& user = users[i];
                    if (user.isNew())
                    {
                        userTracker.startSkeletonTracking(user.getId());
                    }
                    else if (user.isLost())
                    {
                        if (user.getId() == userId) //the active player was lost, set back info, look for another player in the next frame
                        {
                            userId = -1;
                            userIdx = -1;
                            i = len;    //break from loop
                        }
                        userTracker.stopSkeletonTracking(user.getId());
                    }
                    else if (user.getId() == userId)
                    {
                        const Point3f& tPos = user.getSkeleton().getJoint(nite::JOINT_TORSO).getPosition();
                        //create temp pos for skeleton putting it LH (irrlicht)
                        core::vector3df targetPos(-tPos.x, tPos.y, tPos.z);
                        //set eval height to same level to neglect three-dimensionality
                        evalPos.Y = tPos.y;
                        if (evalPos.getDistanceFrom(targetPos) < evalRadius)
                        {
                            userIdx = i;
                            i = len;
                        }
                    }
                    else if (user.getSkeleton().getState() == nite::SKELETON_TRACKED)
                    {
                        const Point3f& tPos = user.getSkeleton().getJoint(nite::JOINT_TORSO).getPosition();
                        //create temp pos for skeleton putting it LH (irrlicht)
                        core::vector3df targetPos(-tPos.x, tPos.y, tPos.z);
                        //set eval height to same level to neglect three-dimensionality
                        evalPos.Y = tPos.y;
                        if (evalPos.getDistanceFrom(targetPos) < evalRadius)
                        {
                            userIdx = i;
                            userId = user.getId();
                            i = len;
                        }
                    }
                }

                if (userIdx != -1)
                {
                    const nite::UserData& user = users[userIdx];
                    skeleton->parseSkeleton(user.getSkeleton());
                    stateEvaluator->evaluateSkeleton(*skeleton);
                }
                else
                {
                    //no active tracking, inform stateEval
                    stateEvaluator->evaluateSkeleton(*skeleton, false);
                }

                if (showDepth)
                {
                    openni::VideoFrameRef depthFrameRef = frame.getDepthFrame();
                    memcpy(pixBuffer, depthFrameRef.getData(), depthFrameRef.getDataSize());
                    pixBufferCount = depthFrameRef.getDataSize();
                    newFrame = true;
                }
                updateUserPositions(users);
            }
        }
    }
}