第四章 利用Kinect抠图和自动拍照程序
在本篇博客中,我将详细介绍Kinect的一种特殊数据源,BodyIndex(人物索引二值图),Kinect就是利用这个数据源来区分目标是人体还是其他物体,有没有觉得功能很强大。说到这里,很多朋友就应该会想到如何利用Kinect去抠图了,主要是依靠这个数据源,把 Kinect获取的图像中的人体和其他物体(主要是背景)区分开来。另外一点是关于自动拍照程序的,大概想要实现的是,自己从网上找一些比较好的图片,结合抠图技术,把自己“PS”到指定的图片。这个程序感觉很有可玩性,而且这只是一种最简单和基本的玩法,大家可以根据自己的创意做出更好玩有趣有意义的东西。
Kinect中带了一种数据源,叫做BodyIndex,简单来说就是它利用深度摄像头识别出最多6个人体,并且用数据将属于人体的部分标记,将人体和背景区别开来。利用这一特性,就可以在环境中显示出人体的轮廓而略去背景的细节。我采用了下面两种方式来实现。
一、利用Kinect抠图
还是一样的风格,先上菜,再分析
抠图程序:
#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) //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;
}
看过前面几篇博客,就会发现,Kinect程序的复用性很大,也就是说不同程序之间有很多部分是共用的,相似度非