Kinect For Windows V2开发日志六:人体的轮廓的表示

> Kinect中带了一种数据源,叫做`BodyIndex`,简单来说就是它利用深度摄像头识别出最多6个人体,并且用数据将属于人体的部分标记,将人体和背景区别开来。利用这一特性,就可以在环境中显示出人体的轮廓而略去背景的细节。我采用了下面两种方式来实现。

用OpenCV表示

代码

#include <iostream>
#include <Kinect.h>
#include <opencv2\highgui.hpp>

using	namespace	std;
using	namespace	cv;

int	main(void)
{
	IKinectSensor	* mySensor = nullptr;			    //Sensor
	GetDefaultKinectSensor(&mySensor);
	mySensor->Open();

	IBodyIndexFrameSource	* mySource = nullptr;		//Source
	mySensor->get_BodyIndexFrameSource(&mySource);

	int	height = 0, width = 0;
	IFrameDescription	* myDescription = nullptr;	
	mySource->get_FrameDescription(&myDescription);
	myDescription->get_Height(&height);
	myDescription->get_Width(&width);

	IBodyIndexFrameReader	* myReader = nullptr;		//Reader
	mySource->OpenReader(&myReader);

	IBodyIndexFrame		* myFrame = nullptr;		    //Frame
	Mat	img(height,width,CV_8UC3);
	Vec3b	color[7] = { Vec3b(0,0,255),Vec3b(0,255,255),Vec3b(255,255,255),Vec3b(0,255,0),Vec3b(255,0,0),Vec3b(255,0,255),Vec3b(0,0,0) };

	while (1)
	{
		if (myReader->AcquireLatestFrame(&myFrame) == S_OK)
		{
			UINT	size = 0;
			BYTE	* buffer = nullptr;
			myFrame->AccessUnderlyingBuffer(&size,&buffer);
			for (int i = 0; i < height; i++)
				for (int j = 0; j < width; j++)
				{
					int	index = buffer[i * width + j];		//0-5代表人体,其它值代表背景,用此将人体和背景渲染成不同颜色
					if (index <= 5)
						img.at<Vec3b>(i, j) = color[index];
					else
						img.at<Vec3b>(i, j) = color[6];

				}
			imshow("TEST",img);
			myFrame->Release();
		}
		if (waitKey(30) == VK_ESCAPE)
			break;
	}
	myReader->Release();
	myDescription->Release();
	mySource->Release();
	mySensor->Close();
	mySensor->Release();

	return	0;
}

详细说明

步骤和前面相似,不再赘述,关键在于对数据的处理。IBodyIndexFrame 里的数据分两种,值在0-5之间的点代表的是人体(因此最多识别出6个人),大于5的值代表的是背景。所以要显示人体时,只要简单的把代表人体的点渲染成一种颜色,背景渲染成另外一种颜色就可以了。值得注意的是在写颜色表color时,要用Vec3b把数据强转一下,不然会有问题。

最终的效果就是这样:


直接用数据勾画出人体

代码:

#include <iostream>
#include <Kinect.h>
#include <Windows.h>

using	namespace	std;
using	namespace	cv;

int	main(void)
{
	IKinectSensor	* mySensor = nullptr;			//Sensor
	GetDefaultKinectSensor(&mySensor);
	mySensor->Open();

	IBodyIndexFrameSource	* mySource = nullptr;		//Source
	mySensor->get_BodyIndexFrameSource(&mySource);

	int	height = 0, width = 0;
	IFrameDescription	* myDescription = nullptr;	
	mySource->get_FrameDescription(&myDescription);
	myDescription->get_Height(&height);
	myDescription->get_Width(&width);

	IBodyIndexFrameReader	* myReader = nullptr;		//Reader
	mySource->OpenReader(&myReader);

	IBodyIndexFrame		* myFrame = nullptr;		    //Frame
	while (1)
	{
		Sleep(1000);
		if (myReader->AcquireLatestFrame(&myFrame) == S_OK)
		{
			UINT	size = 0;
			BYTE	* buffer = nullptr;
			myFrame->AccessUnderlyingBuffer(&size,&buffer);
			for (int i = 50; i < 350; i++)		    //调出一个合适的尺寸
			{
				for (int j = 0; j < width; j++)
				{
					int	index = buffer[i * width + j];
					if (index <= 5)
						cout << 0;
					else
						cout << 1;
				}
				cout << endl;
			}
			cout << endl << endl;
			myFrame->Release();
		}
	}
	myReader->Release();
	myDescription->Release();
	mySource->Release();
	mySensor->Close();
	mySensor->Release();

	return	0;
}

说明

实际上,因为有可以用数字来区别人体和背景这一特性,所以甚至可以不用openCV,直接用数据来显示人体。将识别为人体的数据作为0输出,背景作为1输出,同时把控制台的窗口调大一些,字体调到最小,每秒钟输出一帧,就能直接看到数据画出的图。真是有趣。

效果如下:





posted @ 2016-02-08 15:06  Decouple  阅读(3573)  评论(0编辑  收藏  举报