一.代码声明
下面的代码是博主参考了Intel realsense官方SDK和官方例程后写的一段较为简单的代码,实现了简单的多人脸实时检测及跟踪功能。官方的人脸检测例程功能较多,但代码量很大,阅读起来也较困难,所以博主写了一段较为精简的人脸检测代码。
二.具体代码
- #include <pxcsensemanager.h>
- #include <pxcsession.h>
- #include "util_render.h"
- #include <iostream>
- #include <string>
- #include <stdio.h>
- #include <opencv2\opencv.hpp>
- #include <windows.h>
- #define WIDTH 640
- #define HEIGHT 480
- using namespace cv;
- using namespace std;
- void DrawRectangle(Mat &img, Rect box)
- {
- rectangle(img, box, Scalar(255, 255, 0),2);
- }
- int main(int argc, char** argv)
- {
- PXCSenseManager *psm = 0;
- psm = PXCSenseManager::CreateInstance();
- if (!psm)
- {
- wprintf_s(L"Unabel to create the PXCSenseManager\n");
- return 1;
- }
- //使能人脸跟踪
- psm->EnableFace();
- // 初始化管道
- psm->Init();
- //得到一个人脸模块的实例
- PXCFaceModule *faceModule = psm->QueryFace();
- if (faceModule == NULL)
- {
- wprintf_s(L"Unabel to query FaceModule\n");
- return 3;
- }
- //创建一个人脸追踪模块动态配置的实例
- PXCFaceConfiguration *cfg = faceModule->CreateActiveConfiguration();
- if (cfg == NULL)
- {
- wprintf_s(L"Unabel to create FaceConfiguration\n");
- return 4;
- }
- cfg->detection.isEnabled = TRUE; //这句也可注释掉,不影响检测结果
- //使能所有警告
- cfg->EnableAllAlerts();
- //将任何参数的改变反馈给faceModule
- cfg->ApplyChanges();
- //创建人脸数据的实例
- PXCFaceData *facedata = faceModule->CreateOutput();
- PXCImage *colorIm;
- PXCImage::ImageData color_data;
- PXCImage::ImageInfo color_info;
- while (psm->AcquireFrame(true) >= PXC_STATUS_NO_ERROR)
- {
- if (psm->AcquireFrame(true) < PXC_STATUS_NO_ERROR) break;
- //获取最新的人脸追踪配置参数
- facedata->Update();
- PXCCapture::Sample *sample = psm->QuerySample();
- colorIm = sample->color;
- if (colorIm->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_RGB24, &color_data) < PXC_STATUS_NO_ERROR)
- wprintf_s(L"未正常获取彩色图\n");
- color_info = sample->color->QueryInfo();
- Mat color(Size(color_info.width, color_info.height), CV_8UC3, (void*)color_data.planes[0], color_data.pitches[0] / sizeof(uchar));
- //取出检测到的人脸数目
- pxcI32 nfaces = facedata->QueryNumberOfDetectedFaces();
- //对视野内每一张人脸追踪处理
- for (pxcI32 i = 0; i < nfaces; i++) {
- //按序号获取一个人脸的数据实例
- PXCFaceData::Face *trackedface = facedata->QueryFaceByIndex(i);
- PXCFaceData::DetectionData *detectiondata = trackedface->QueryDetection();
- if (detectiondata == NULL)
- {
- wprintf_s(L"Unabel to get detection data\n");
- return 5;
- }
- //将当前人脸的位置数据存在rect中
- PXCRectI32 rect;
- detectiondata->QueryBoundingRect(&rect);
- //PXCRectI32到opencv中Rect类的转化
- Rect cvrect = Rect(rect.x, rect.y, rect.w, rect.h);
- DrawRectangle(color, cvrect);
- //给当前人脸加上识别序号的文字
- stringstream ss;
- ss << i;
- string id = ss.str();
- id = "ID:" + id;
- putText(color,id, Point(rect.x+rect.w/2, rect.y-rect.h/20), CV_FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 0));
- }
- colorIm->ReleaseAccess(&color_data);
- stringstream ss;
- ss << nfaces;
- string num_faces= ss.str();
- num_faces =num_faces + " faces in the field of view.";
- putText(color, num_faces, Point(color.rows/20,color.cols/40), CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(153, 51, 250));
- psm->ReleaseFrame();
- imshow("face_detection", color);
- waitKey(1);
- }
- facedata->Release();
- cfg->Release();
- psm->Close();
- psm->Release();
- }
#include <pxcsensemanager.h>
#include <pxcsession.h>
#include "util_render.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <opencv2\opencv.hpp>
#include <windows.h>
#define WIDTH 640
#define HEIGHT 480
using namespace cv;
using namespace std;
void DrawRectangle(Mat &img, Rect box)
{
rectangle(img, box, Scalar(255, 255, 0),2);
}
int main(int argc, char** argv)
{
PXCSenseManager *psm = 0;
psm = PXCSenseManager::CreateInstance();
if (!psm)
{
wprintf_s(L"Unabel to create the PXCSenseManager\n");
return 1;
}
//使能人脸跟踪
psm->EnableFace();
// 初始化管道
psm->Init();
//得到一个人脸模块的实例
PXCFaceModule *faceModule = psm->QueryFace();
if (faceModule == NULL)
{
wprintf_s(L"Unabel to query FaceModule\n");
return 3;
}
//创建一个人脸追踪模块动态配置的实例
PXCFaceConfiguration *cfg = faceModule->CreateActiveConfiguration();
if (cfg == NULL)
{
wprintf_s(L"Unabel to create FaceConfiguration\n");
return 4;
}
cfg->detection.isEnabled = TRUE; //这句也可注释掉,不影响检测结果
//使能所有警告
cfg->EnableAllAlerts();
//将任何参数的改变反馈给faceModule
cfg->ApplyChanges();
//创建人脸数据的实例
PXCFaceData *facedata = faceModule->CreateOutput();
PXCImage *colorIm;
PXCImage::ImageData color_data;
PXCImage::ImageInfo color_info;
while (psm->AcquireFrame(true) >= PXC_STATUS_NO_ERROR)
{
if (psm->AcquireFrame(true) < PXC_STATUS_NO_ERROR) break;
//获取最新的人脸追踪配置参数
facedata->Update();
PXCCapture::Sample *sample = psm->QuerySample();
colorIm = sample->color;
if (colorIm->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_RGB24, &color_data) < PXC_STATUS_NO_ERROR)
wprintf_s(L"未正常获取彩色图\n");
color_info = sample->color->QueryInfo();
Mat color(Size(color_info.width, color_info.height), CV_8UC3, (void*)color_data.planes[0], color_data.pitches[0] / sizeof(uchar));
//取出检测到的人脸数目
pxcI32 nfaces = facedata->QueryNumberOfDetectedFaces();
//对视野内每一张人脸追踪处理
for (pxcI32 i = 0; i < nfaces; i++) {
//按序号获取一个人脸的数据实例
PXCFaceData::Face *trackedface = facedata->QueryFaceByIndex(i);
PXCFaceData::DetectionData *detectiondata = trackedface->QueryDetection();
if (detectiondata == NULL)
{
wprintf_s(L"Unabel to get detection data\n");
return 5;
}
//将当前人脸的位置数据存在rect中
PXCRectI32 rect;
detectiondata->QueryBoundingRect(&rect);
//PXCRectI32到opencv中Rect类的转化
Rect cvrect = Rect(rect.x, rect.y, rect.w, rect.h);
DrawRectangle(color, cvrect);
//给当前人脸加上识别序号的文字
stringstream ss;
ss << i;
string id = ss.str();
id = "ID:" + id;
putText(color,id, Point(rect.x+rect.w/2, rect.y-rect.h/20), CV_FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 0));
}
colorIm->ReleaseAccess(&color_data);
stringstream ss;
ss << nfaces;
string num_faces= ss.str();
num_faces =num_faces + " faces in the field of view.";
putText(color, num_faces, Point(color.rows/20,color.cols/40), CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(153, 51, 250));
psm->ReleaseFrame();
imshow("face_detection", color);
waitKey(1);
}
facedata->Release();
cfg->Release();
psm->Close();
psm->Release();
}
运行结果和丑照:
三.心得体会
说实话,研究realsense的sdk是略痛苦的,因为可参考的资料实在有限,除了官方sdk就只有一个开发者论坛了。当你上网搜索kinect的相关资料时,可以发现大批大神的研究例程和心得。反过来看realsense,新闻很多,都是说它怎么怎么厉害,但是并没有多少对开发者有参考价值的资料。realsense毫无疑问比kinect强悍,体积又小,但因为发布时间较短,所以大部分人都还在研究这玩意怎么用。
就像上面这个程序,博主在看完sdk关于人脸检测的介绍之后,按照它的框架去码代码,码的时候自己都有点迷糊每一步的意思。最后程序闪退,得不到任何结果,人脸都没有,还检测什么。无奈之下只有看example了,天哪噜,代码量实在大,还有一堆写窗口和按钮的,只能慢慢从里面探索出对自己有用的东西。
看久了也就能看出一些门道了,比如ApplyChanges到底有什么用, 原来FaceConfiguration这个接口一旦创建了,就和FaceModule独立了,使用ApplyChanges是为了在模块配置参数发生变化时能通过update来将最新的配置参数传递给FaceModule。然而一开始,我并有理解这些,所以代码里连update都没有,结果只能是gg。
甚至在刚开始的时候,我的enableface还有配置实例的创建代码都是写在while获取每一帧里面的,后面才理解了人脸模块的使能以及人脸追踪的配置应该在获取图片帧之前完成,然后获取一帧图片之后,更新人脸配置参数,对该帧图片检测人脸,对每一个检测到的人脸进行处理。
总之,路漫漫,博主继续研究去了。