一.代碼聲明
下面的代碼是博主參考了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獲取每一幀里面的,后面才理解了人臉模塊的使能以及人臉追蹤的配置應該在獲取圖片幀之前完成,然后獲取一幀圖片之后,更新人臉配置參數,對該幀圖片檢測人臉,對每一個檢測到的人臉進行處理。
總之,路漫漫,博主繼續研究去了。