实际上,除了深度图像、彩色图像、红外线图像这三种算是原始图像数据之外,Kinect还提供一种经过分析的图像数据——BodyIndex,直译过来是人物索引的意思。
简单来说,就是在图像中对人物相关的数据进行了标记,把人体和背景区分开来了,我们可以用这个数据还做简单的位置检测,或者抠图。
1.人体轮廓表示
BodyIndex数据的获取方法也和其他数据一样,IBodyIndexFrameSource
→ IBodyIndexFrameReader
→ IBodyIndexFrame
这样三层,但是它读取到的画面中每一个像素是一位(BYTE),代表的是这个点的人的编号。因为Kinect V2最多只能追踪6个人,所以实际上这个编号只有0-5号是有用的,超过这个范围的话,代表这个点不是人体。
效果图如下:
代码如下:
using namespace std;
using namespace cv;
int main(void)
{
// 1a.获取感应器
IKinectSensor* pSensor = nullptr;
GetDefaultKinectSensor(&pSensor);
// 1b. 打开感应器
pSensor->Open();
// 2a. 取得BodyIndex数据
IBodyIndexFrameSource* pFrameSource = nullptr;
pSensor->get_BodyIndexFrameSource(&pFrameSource);
// 2b. 取得BodyIndex数据的描述信息(宽、高)
int iWidth = 0;
int iHeight = 0;
IFrameDescription* pFrameDescription = nullptr;
pFrameSource->get_FrameDescription(&pFrameDescription);
pFrameDescription->get_Width(&iWidth);
pFrameDescription->get_Height(&iHeight);
pFrameDescription->Release();
pFrameDescription = nullptr;
// 3a. 打开BodyIndex数据阅读器
IBodyIndexFrameReader* pFrameReader = nullptr;
pFrameSource->OpenReader(&pFrameReader);
IBodyIndexFrame* pFrame = nullptr;
// 建立图像矩阵,mBodyIndexImg用来存储图像数据
Mat mBodyIndexImg(iHeight, iWidth, CV_8UC3);
namedWindow("BodyIndexImage");
// color array
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) };