博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kinect2+opencv之Body篇:显示Kinect2的Body
阅读量:313 次
发布时间:2019-03-04

本文共 7388 字,大约阅读时间需要 24 分钟。

目录



一、目的:

1、显示出Kinect2的Body 

 

二、参考

1、

①总结:good:作者翻译了一个系列的Kinect2的文章,目前测试Color、Depth、BodyIndex篇,都能实现,下面是参考后直接实现的代码

 

2、Kinect2+opencv之Color篇:显示Kinect2的画面

①总结:good:这是我总结的Color,有直接实现的代码

 

3、Kinect2+opencv之Depth篇:显示Kinect2的深度图

①总结:good:这是我总结的Depth,有直接实现的代码

 

4、Kinect2+opencv之Depth篇:显示Kinect2的BodyIndex

①总结:good:这是我总结的BodyIndex,有直接实现的代码

 

三、步骤

1、创建MFC工程,配置Kinect2和Opencv的环境

这个再次就不赘述了,网上很多的教程

 

2、头文件

①导入Kinect、opencv所需的头文件

#include "Kinect.h"#include 
#include "cv.h"#include "opencv2/opencv.hpp"

②测试Kinect代码

//Kinect2	public:	int Test_kinect2();

 

3、cpp源文件文件

①安全释放函数:ColorBasics-D2D里面有的直接复制过来

// Safe release for interfacestemplate
inline void SafeRelease(Interface *& pInterfaceToRelease){ if (pInterfaceToRelease != NULL) { pInterfaceToRelease->Release(); pInterfaceToRelease = NULL; }}

②OnInitDialog函数中使用到Test_kinect函数

③Test_kinect:函数

//功能:显示Kinect2的Body//参考网站: https://mp.csdn.net/console/editor/html/105449249    https://www.cnblogs.com/TracePlus/p/4138615.html    int CMyKinect2Dlg::Test_kinect2(){	//第一步:取得「Sensor」	IKinectSensor* pSensor;//Kinect v2预览版的Sensor接口。	HRESULT hResult = S_OK;	hResult = GetDefaultKinectSensor(&pSensor);//取得默认的Sensor。	if (FAILED(hResult))	{		std::cerr << "Error : GetDefaultKinectSensor" << std::endl;		return -1;	}	hResult = pSensor->Open();// 打开Sensor。	if (FAILED(hResult))	{		std::cerr << "Error : IKinectSensor::Open()" << std::endl;		return -1;	}	//第二步:Body部分:从「Sensor」取得「Source」。	IBodyFrameSource* pBodySource;//Body Frame的Source接口。	hResult = pSensor->get_BodyFrameSource(&pBodySource);//从Sensor取得Source。	if (FAILED(hResult))	{		std::cerr << "Error : IKinectSensor::get_BodyFrameSource()" << std::endl;		return -1;	}	//第三步:Body部分:「Source」从打开「Reader」。	IBodyFrameReader* pBodyReader;//Body  Frame的Reader接口。	hResult = pBodySource->OpenReader(&pBodyReader);//从Source打开Reader。	if (FAILED(hResult))	{		std::cerr << "Error : IBodyFrameSource::OpenReader()" << std::endl;		return -1;	}	//第四步:Body部分:从「Sensor」取得「Coordinate Mapper」。  	//在这之前,为了可以和从传感器取得的坐标匹配,取得ICoordinateMapper的接口(列表1.4),由于Color照相机和Depth传感器的位置是分开的,因此需要把body数据和Color图像的位置进行匹配。	ICoordinateMapper* pCoordinateMapper;//Frame之间的坐标匹配的接口。	hResult = pSensor->get_CoordinateMapper(&pCoordinateMapper);//从Sensor获取坐标匹配的接口。	if (FAILED(hResult))	{		std::cerr << "Error : IKinectSensor::get_CoordinateMapper()" << std::endl;		return -1;	}	//第五步:Color部分:从「Sensor」取得「Source」。	// 这里只是关于取得Body的源代码解说,不过,为了案例程序的显示,也同时取得了Color。	IColorFrameSource* pColorSource;	hResult = pSensor->get_ColorFrameSource(&pColorSource);	if (FAILED(hResult))	{		std::cerr << "Error : IKinectSensor::get_ColorFrameSource()" << std::endl;		return -1;	}	//第六步:Color部分:从「Source」取得「Reader」。	IColorFrameReader* pColorReader;	hResult = pColorSource->OpenReader(&pColorReader);	if (FAILED(hResult))	{		std::cerr << "Error : IColorFrameSource::OpenReader()" << std::endl;		return -1;	}	//第七步:Color部分:从「Reader」取得最新的「Frame」	int width = 1920;//Color图像的尺寸(1920×1080)。 这里为了简化说明,画像尺寸用硬编码来设定,示例程序可以从Source取得着Frame信息	int height = 1080;	unsigned int bufferSize = width * height * 4 * sizeof(unsigned char);//Color图像的数据尺寸。	cv::Mat bufferMat(height, width, CV_8UC4);//为了处理Color图像,准备OpenCV的cv::Mat。「bufferMat」是原始的图像数据,「colorMat」是Resize图像数据的处理。	cv::Mat bodyMat(height / 2, width / 2, CV_8UC4);//「CV_8UC4」,是无符号8bit整数(8U),4个channel(C4)并列来表现1个像素的数据格式。	cv::namedWindow("Body");	// Color Table	cv::Vec3b color[6];	color[0] = cv::Vec3b(255, 0, 0);	color[1] = cv::Vec3b(0, 255, 0);	color[2] = cv::Vec3b(0, 0, 255);	color[3] = cv::Vec3b(255, 255, 0);	color[4] = cv::Vec3b(255, 0, 255);	color[5] = cv::Vec3b(0, 255, 255);	while (1)	{		// Color Frame  		IColorFrame* pColorFrame = nullptr;//取得Color图像的Frame接口。		hResult = pColorReader->AcquireLatestFrame(&pColorFrame);//从Reader取得最新的Frame。		if (SUCCEEDED(hResult))		{			//从Frame取得Color图像。 默认的格式是YUY2(亮度与色差表现的格式),不过可以经过简单处理变换为BGRA。			hResult = pColorFrame->CopyConvertedFrameDataToArray(bufferSize, reinterpret_cast
(bufferMat.data), ColorImageFormat_Bgra); if (SUCCEEDED(hResult)) { //缩小为长宽各一半的尺寸(960×540)。 从「Frame」取得Color图像的数据时,Kinect SDK v1是预先指定图像尺寸和格式,Kinect SDK v2不能指定图像尺寸。因此,取得数据后可以按任意形状来整理。 //取出的Color图像直接显示的话尺寸太大(1920×1080),在这里采用了OpenCV的resize命令(cv::resize()),缩小为长宽各一半的尺寸(960×540)。 //(注:阅读理解时不要受这一段缩放代码的干扰,仅仅就是为了考虑在显示器上显示的方便观察,没别的意义。) cv::resize(bufferMat, bodyMat, cv::Size(), 0.5, 0.5); } } SafeRelease(pColorFrame); //第八步:Body部分:Body Frame IBodyFrame* pBodyFrame = nullptr;//Body的Frame接口。 hResult = pBodyReader->AcquireLatestFrame(&pBodyFrame);//从Reader里取得最新的Frame。 if (SUCCEEDED(hResult)) { IBody* pBody[BODY_COUNT] = { 0 }; hResult = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, pBody);//从Frame取得Body。 后面,是从人体取得数据。 if (SUCCEEDED(hResult)) { for (int count = 0; count < BODY_COUNT; count++) { BOOLEAN bTracked = false;//确认能着追踪到人体 hResult = pBody[count]->get_IsTracked(&bTracked); if (SUCCEEDED(hResult) && bTracked) { Joint joint[JointType::JointType_Count]; hResult = pBody[count]->GetJoints(JointType::JointType_Count, joint);//取得人体Joint(关节)。 if (SUCCEEDED(hResult)) { // Left Hand State HandState leftHandState = HandState::HandState_Unknown;//取得Hand State。 hResult = pBody[count]->get_HandLeftState(&leftHandState); if (SUCCEEDED(hResult)) { //为了绘制,把Body座標向Color座標的坐标匹配。 匹配的坐标是否超出绘制范围(这里Color图像的尺寸是1920×1080)的检查。 //(注:因为两个Camera位置、FOV和分辨率的不同,在匹配时不可能完全一一对应,所以必须检查坐标的有效性) ColorSpacePoint colorSpacePoint = { 0 }; hResult = pCoordinateMapper->MapCameraPointToColorSpace(joint[JointType::JointType_HandLeft].Position, &colorSpacePoint); if (SUCCEEDED(hResult)) { int x = static_cast
(colorSpacePoint.X); int y = static_cast
(colorSpacePoint.Y); if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) { // 对应状态绘制相应颜色的○(圆型)做Hand State的可视化。用各自对应Open(打开:布),Closed(关闭:拳),Lasso(套索:剪)的颜色绘制。如果检查不出状态就不绘制。 if (leftHandState == HandState::HandState_Open) { cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(0, 128, 0), 5, CV_AA); } else if (leftHandState == HandState::HandState_Closed) { cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(0, 0, 128), 5, CV_AA); } else if (leftHandState == HandState::HandState_Lasso) { cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(128, 128, 0), 5, CV_AA); } } } } // Right Hand State /* 和左手一样,获取右手Hand State绘制状态。 */ // Joint 对应人体的Joint参照color table的颜色做绘制。 和Hand State一样,Body坐标向Color坐标坐标匹配来绘制●(圆点)。 for (int type = 0; type < JointType::JointType_Count; type++) { ColorSpacePoint colorSpacePoint = { 0 }; pCoordinateMapper->MapCameraPointToColorSpace(joint[type].Position, &colorSpacePoint); int x = static_cast
(colorSpacePoint.X); int y = static_cast
(colorSpacePoint.Y); if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) { cv::circle(bufferMat, cv::Point(x, y), 5, static_cast
(color[count]), -1, CV_AA); } } } } } cv::resize(bufferMat, bodyMat, cv::Size(), 0.5, 0.5); } } SafeRelease(pBodyFrame); // Show Window cv::imshow("Body", bodyMat); if (cv::waitKey(10) == VK_ESCAPE) { break; } } return 0;}

 

4、运行效果:

①左手能识别张开、握拳、效果,模拟了右手但是没有绘画出来

 

你可能感兴趣的文章