#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include
#include "OpenNI.h"
#include
#include
#include
#include
#include
#include
#include
#include "mtcnn.hpp"
#include "utils.hpp"
#include
#include "RGBDCamera.h"
#include "RGB-D_calibration_sample_code.h"
using namespace std;
using namespace cv;
using namespace openni;
static VideoCapture capture;
static Device device;
static VideoStream depth;
static VideoStream color;
static VideoStream ir;
static VideoFrameRef depthFrame;
static VideoFrameRef colorFrame;
static VideoFrameRef irFrame;
#define CAMERA_PARAMS_INI "./camera_params.ini"
#define CONFIG_INI "./config.ini"
const static int MAX_DEPTH_VALUE = 0xffff;
const static int OPENNI_READ_WAIT_TIMEOUT = 500;
static int mirrorColor = 0;
Mat depthImg(480, 640, CV_8UC3);
Mat depthRaw(480, 640, CV_16UC1, Scalar(0));
Mat irImg(480, 640, CV_8UC3, Scalar(0));
Mat colorImg(480, 640, CV_8UC3);
Mat CaliDepth(480, 640, CV_8UC3);
float mat[16] = { 0 };
static bool quit = false;
static int openAllStream = 0;
static bool isUvcCamera = true;
int num = 0;
string dirname = "./";
const char *type = "tensorflow";
mtcnn * p_mtcnn = mtcnn_factory::create_detector(type);
std::vector face_info;
int save_chop = 0;
typedef struct {
float x;
float y;
float z;
} vector3f;
void screenshot(vector point,string dirname,string filenames)
{
ofstream outfile (dirname +"/"+ filenames + ".txt");
//string file = dirname +"/"+ filenames + ".xyz";
// outfile.open(file);
if (outfile.is_open())
{
for (int ii = 0; ii < 640 * 400; ii++)
{
if (point[ii].z != 0 && point[ii].z < 800)
{
outfile << point[ii].x << " " << point[ii].y << " " << point[ii].z << std::endl;
}
}
}
outfile.close();
cout << dirname << "/" < type_list = mtcnn_factory::list();
for (unsigned int i = 0; i < type_list.size(); i++)
std::cerr << " " << type_list[i];
std::cerr << std::endl;
return 1;
}
p_mtcnn->load_model(model_dir);
}
int do_mtcnn()//检测人脸
{
if (!colorImg.data) {
std::cerr << "failed to read image file "<< std::endl;
return 1;
}
face_info.clear();
p_mtcnn->detect(colorImg,face_info);
if (face_info.size() > 0)
{
return 1;
}
return 0;
}
void FramFace(Mat &rgbImg,int mode,int move_x,int move_y)//显示人脸边框及关键点
{
for(unsigned int i = 0; i < face_info.size(); i++) {
face_box& box = face_info[i];
printf("face %d: x0,y0 %2.5f %2.5f x1,y1 %2.5f %2.5f conf: %2.5f\n",i,
box.x0,box.y0,box.x1,box.y1, box.score);
printf("landmark: ");
for(unsigned int j = 0; j < 5; j++)
printf(" (%2.5f %2.5f)",box.landmark.x[j], box.landmark.y[j]);
printf("\n");
if (save_chop) {
cv::Mat corp_img=rgbImg(cv::Range(box.y0,box.y1),cv::Range(box.x0,box.x1));
char title[128];
sprintf(title,"id%d.jpg",i);
cv::imwrite(title,corp_img);
}
/*draw box */
cv::rectangle(rgbImg, cv::Point(box.x0 + move_x, box.y0 + move_y), cv::Point(box.x1 + move_x, box.y1 + move_y), cv::Scalar(0, 255, 0), 1);
/* draw landmark */
for (int l = 0; l < 5; l++) {
cv::circle(rgbImg,cv::Point(box.landmark.x[l],box.landmark.y[l]),1,cv::Scalar(0, 0, 255),1.8);
}
}
// if (mode == 0)
// {
// cv::imwrite("color.jpg",rgbImg);
// }
// else
// {
// cv::imwrite("depth.jpg",rgbImg);
// }
}
int waitForColorFrame()//获取彩色照片
{
capture >> colorImg;
cv::flip(colorImg, colorImg, 1);
if (colorImg.empty()){
printf("Capture UVC color failed.\n");
return -1;
}
return 0;
}
int waitForOpenNIFrame()//获取深度图片
{
int streamIndex;
VideoFrameRef frame;
VideoStream* pStream[] = {&depth, &color, &ir};
Status rc = OpenNI::waitForAnyStream(pStream, 3, &streamIndex, OPENNI_READ_WAIT_TIMEOUT);
if (rc != STATUS_OK)
{
printf("Wait failed! (timeout is %d ms)\n%s\n", OPENNI_READ_WAIT_TIMEOUT, OpenNI::getExtendedError());
return 1;
}
// printf ("streamIndex = %d\n",streamIndex);
switch(streamIndex) {
case 0:
rc = depth.readFrame(&depthFrame);
break;
case 1:
rc = color.readFrame(&colorFrame);
break;
case 2:
rc = ir.readFrame(&irFrame);
break;
default:
printf("Wait frame error. Stream index:%d\n", streamIndex);
return 1;
}
if (rc != STATUS_OK)
{
printf("Read failed!\n%s\n", OpenNI::getExtendedError());
return 2;
}
// printf ("depthFrame.isValid() = %d\n",depthFrame.isValid());
if(depthFrame.isValid()) {
if (depthFrame.getVideoMode().getPixelFormat() != PIXEL_FORMAT_DEPTH_1_MM && depthFrame.getVideoMode().getPixelFormat() != PIXEL_FORMAT_DEPTH_100_UM)
{
printf("Unexpected depthFrame format\n");
return 3;
}
DepthPixel* pDepth = (DepthPixel*)depthFrame.getData();
// vector3f xyzdata;
// vector point;
// float x = 0.0, y = 0.0, z = 0.0, depthv = 0.0;
// float i, j;
// for (i = 0; i < depthFrame.getHeight(); i++)
// {
// for (j = 0; j < depthFrame.getWidth(); j++)
// {
// int k = i;
// int m = j;
// depthv = pDepth[k*depthFrame.getWidth() + m];
// CoordinateConverter::convertDepthToWorld(depth, j, i, depthv, &x, &y, &z);
// xyzdata.x = x;
// xyzdata.y = y;
// xyzdata.z = z;
// point.push_back(xyzdata);
// }
// }
string filenames = std::to_string(num);
// screenshot(point,dirname,filenames);
//printf ("pDepth = %s\n",*pDepth);
depthRaw = Mat(depthFrame.getVideoMode().getResolutionY(), depthFrame.getVideoMode().getResolutionX(), CV_16UC1, (unsigned char*)pDepth);
float* pDepthHist = NULL;
if (pDepthHist == NULL) {
pDepthHist = new float[MAX_DEPTH_VALUE];
}
memset(pDepthHist, 0, MAX_DEPTH_VALUE * sizeof(float));
int numberOfPoints = 0;
openni::DepthPixel nValue;
int totalPixels = depthFrame.getVideoMode().getResolutionY() * depthFrame.getVideoMode().getResolutionX();
for (int i = 0; i < totalPixels; i ++) {
nValue = pDepth[i];
if (nValue != 0) {
pDepthHist[nValue] ++;
numberOfPoints ++;
}
}
for (int i = 1; i < MAX_DEPTH_VALUE; i ++) {
pDepthHist[i] += pDepthHist[i - 1];
}
for (int i = 1; i < MAX_DEPTH_VALUE; i ++) {
if (pDepthHist[i] != 0) {
pDepthHist[i] = (numberOfPoints - pDepthHist[i]) / (float)numberOfPoints;
}
}
// printf ("pDepthHist = %s\n",pDepthHist);
int height = depthFrame.getVideoMode().getResolutionY();
int width = depthFrame.getVideoMode().getResolutionX();
for (int row = 0; row < height; row++) {
DepthPixel* depthCell = pDepth + row * width;
uchar * showcell = (uchar *)depthImg.ptr(row);
for (int col = 0; col < width; col++)
{
char depthValue = pDepthHist[*depthCell] * 255;
*showcell++ = 0;
*showcell++ = depthValue;
*showcell++ = depthValue;
depthCell++;
}
}
}
// // printf ("irFrame.isValid() = %d\n",irFrame.isValid());
// if(irFrame.isValid()) {
// int height = irFrame.getVideoMode().getResolutionY();
// int width = irFrame.getVideoMode().getResolutionX();
// const openni::RGB888Pixel* pImageRow = (const openni::RGB888Pixel*)irFrame.getData();
// memcpy(irImg.data, pImageRow, height * width * 3);
// }
// // printf ("colorFrame.isValid() = %d\n",colorFrame.isValid());
// if(colorFrame.isValid()) {
// int height = colorFrame.getVideoMode().getResolutionY();
// int width = colorFrame.getVideoMode().getResolutionX();
// const openni::RGB888Pixel* pImageRow = (const openni::RGB888Pixel*)colorFrame.getData();
// memcpy(colorImg.data, pImageRow, height * width * 3);
// cv::cvtColor(colorImg, colorImg, COLOR_RGB2BGR);
// }
return 0;
}
long long current_timestamp() {
struct timeval te;
gettimeofday(&te, NULL); // get current time
long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds
return milliseconds;
}
void captureImage(int flag, Mat& img, int num)
{
std::vector png_params;
png_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
png_params.push_back(0); // 无损
char csName[512];
char fileName[64] = {0};
if (flag == 0) {
strcpy(fileName, "Depth");
}
else if (flag == 1){
strcpy(fileName, "Color");
}
else {
strcpy(fileName, "IR");
}
sprintf(csName, "./Capture/%s_%d.png", fileName, num);
cv::imwrite(csName, img, png_params);
}
int isLiveFace()
{
for(unsigned int i = 0; i < face_info.size(); i++)
{
face_box& box = face_info[i];
// float x = box.x0 - 9 > 0 ? box.x0 - 9 : 0;
// float y = box.y0 - 10 > 0 ? box.y0 - 10 :0;
float x = box.x0 > 0 ? box.x0 : 0;
float y = box.y0 > 0 ? box.y0 : 0;
float w = box.x1 - box.x0 > 0 ? box.x1 - box.x0 : box.x0 - box.x1;
float h = box.y1 - box.y0 > 0 ? box.y1 - box.y0 : box.y0 - box.y1;
w = x + w < depthImg.cols ? w : depthImg.cols - x;
h = y + h < depthImg.rows ? h : depthImg.rows - y;
Mat out = depthImg(Rect(x, y, w, h));
Mat means, stddev, covar;
meanStdDev(out, means, stddev);
double stddev_sum = 0;
double stddev_avg = 0;
for (int row = 0; row < means.rows; row++)
{
stddev_sum = stddev_sum + stddev.at(row);
}
stddev_avg = stddev_sum / means.rows;
stringstream ss,sss;
ss << "real_" << stddev_avg;
sss << "unreal_" << stddev_avg;
int font = cv::FONT_HERSHEY_COMPLEX;
if (stddev_avg > 58)
{
printf("真人!标准差 = %.3f\n", stddev_avg);
cv::rectangle(depthImg, cv::Point(box.x0 , box.y0 ), cv::Point(box.x1, box.y1 ), cv::Scalar(0, 255, 0), 1);
cv::putText(depthImg, ss.str(), cvPoint(box.x0, box.y0),font,1.5, cv::Scalar(255, 0, 0),2);
}
else
{
printf("假人!标准差 = %.3f\n", stddev_avg);
cv::rectangle(depthImg, cv::Point(box.x0, box.y0), cv::Point(box.x1, box.y1 ), cv::Scalar(0, 255, 0), 1);
cv::putText(depthImg, sss.str(), cvPoint(box.x0, box.y0), font, 1.5, cv::Scalar(0, 255, 0),2);
}
}
}
int waitForFrame(Mat& previewImg)
{
if(isUvcCamera) {
waitForColorFrame();
}
int is_has_face = do_mtcnn();
if (is_has_face)
{
FramFace(colorImg,0,0,0);
}
else
return 0;
waitForOpenNIFrame();
static long long lastTimeStamp = 0;
long long currentTimeStamp = current_timestamp();
long timepast = currentTimeStamp - lastTimeStamp;
static int num = 0;
if (mirrorColor != 0) {
cv::flip(colorImg, colorImg, 1);
}
// printf("timepast = %ld \n",timepast);
// if (timepast > 100.0) {
// captureImage(0, depthRaw, num);
// captureImage(1, colorImg, num);
// if(irFrame.isValid()) {
// captureImage(2, irImg, num);
// }
// lastTimeStamp = currentTimeStamp;
// num ++;
// }
previewImg = colorImg.clone();
FramFace(depthImg,1,0,0);
hconcat(previewImg, depthImg, previewImg);
int is_live_face = isLiveFace();
if (is_has_face && is_live_face)
{
/* code */
}
if(irFrame.isValid()) {
hconcat(previewImg, irImg, previewImg);
}
return 0;
}
int keyboardEvent(int key)
{
if(key == 27) {
quit = true;
}
return 0;
}
bool checkFile(char * file)
{
bool r = false;
if (access(file, 0) != -1)
{
cout << "-- find " << file << endl << endl;
r = true;
}
else
{
cout << "-- Didn't find " << file << endl << endl;
}
cout<<"r "<= 2) {
sscanf(argv[1], "%d", &openAllStream);
}
if(argc >= 3) {
sscanf(argv[2], "%d", &camNum);
}
if(argc >= 4) {
sscanf(argv[3], "%d", &mirrorColor);
}
Status rc;
rc = openni::OpenNI::initialize();
if(rc != STATUS_OK) {
printf("init failed:%s\n", OpenNI::getExtendedError());
return 1;
}
rc = device.open(ANY_DEVICE);
if(rc != STATUS_OK) {
printf("Couldn't open device\n%s\n", OpenNI::getExtendedError());
return 2;
}
if (device.getSensorInfo(SENSOR_DEPTH) != NULL)
{
rc = depth.create(device, SENSOR_DEPTH);
if (rc != STATUS_OK)
{
printf("Couldn't create depth stream\n%s\n", OpenNI::getExtendedError());
return 3;
}
}
rc = depth.start();
if (rc != STATUS_OK)
{
printf("Couldn't start the depth stream\n%s\n", OpenNI::getExtendedError());
return 4;
}
// printf("isUvcCamera = %d \n",isUvcCamera);
// printf("openAllStream = %d \n",openAllStream);
//bool hasOpenNIColor = device.hasSensor(openni::SENSOR_COLOR);
const SensorInfo* colorSensorInfo = device.getSensorInfo(openni::SENSOR_COLOR);
if (colorSensorInfo != NULL){
isUvcCamera = false;
rc = color.create(device, SENSOR_COLOR);
if (rc != STATUS_OK)
{
printf("Couldn't create ir stream\n%s\n", OpenNI::getExtendedError());
return 3;
}
rc = color.start();
if (rc != STATUS_OK)
{
printf("Couldn't start the ir stream\n%s\n", OpenNI::getExtendedError());
return 4;
}
}
if (isUvcCamera && openAllStream) {
if (device.getSensorInfo(SENSOR_IR) != NULL)
{
rc = ir.create(device, SENSOR_IR);
if (rc != STATUS_OK)
{
printf("Couldn't create ir stream\n%s\n", OpenNI::getExtendedError());
return 3;
}
}
rc = ir.start();
if (rc != STATUS_OK)
{
printf("Couldn't start the ir stream\n%s\n", OpenNI::getExtendedError());
return 4;
}
}
if (isUvcCamera) {
capture.set(6, CV_FOURCC('M', 'J', 'P', 'G'));
if (!capture.open(1))
{
capture.open(0);
}
if (!capture.isOpened())
{
return -1;
}
}
Status result = STATUS_OK;
cout << " *********** Astra Viewer v1.1*********" << endl << endl;
cout << " O - RGBD Over display" << endl;
cout << " R - toggle register" << endl;
cout << " C - increase the Color proportion (after 'O')" << endl;
cout << " D - increase the Depth proportion (after 'O')" << endl;
cout << " Esc - Exit" << endl << endl;
int REC_WIDTH = 640;
int REC_HEIGHT = 480;
if (checkFile(CONFIG_INI))
{
int Scale = 2;//GetPrivateProfileInt(TEXT("Resolution"), TEXT("RES"), 2, TEXT(CONFIG_INI));
if (Scale == 2)
{
REC_WIDTH = 640;
REC_HEIGHT = 480;
}
if (Scale == 3)
{
REC_WIDTH = 1280;
REC_HEIGHT = 1024;
}
}
cout<<"REC_WIDTH: "<= 0) {
keyboardEvent(key);
}
// num++;
}
if (isUvcCamera) {
capture.release();
}
device.close();
openni::OpenNI::shutdown();
return 0;
}
先把代码撸上来,注释慢慢加,基本思想是先获得摄像头的ir,rgb图像,对齐,在rgb图像上进行检测,通位置一致,将特征点平移到ir图像上,再通过算法,对ir图像上的点进行活体判别。