在上一篇使用python实现情绪识别的基础上,使用c++实现情绪识别。
这里的人脸检测模块不是使用dlib模块(使用dlib模块也可以,测试以后发现速度比较慢),这里使用另外一个开源的模块。
facedetect-dll.h,可以去我的资源里下载。里面的眉毛斜率检测模块,因为c++没有np.polyfit,所以需要自己实现(参考最小二乘)。
#include <fstream>
#include <string>
#include <iostream>
//#include <dlib/image_processing/frontal_face_detector.h>
//#include <dlib/image_processing/render_face_detections.h>
//#include <dlib/image_processing.h>
//#include <dlib/gui_widgets.h>
//#include <dlib/image_io.h>
#include <opencv2/core/core.hpp>
//#include <dlib/timer.h>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include "highgui.h"
#include "lib\facedetect-dll.h"
#include <iostream>
#include <cstdlib>
#include "lib\facedetect-dll.h"
using namespace cv;
using namespace std;
using namespace dnn;
float LineFitLeastSquares(float *data_x, float *data_y, int data_n);
// ----------------------------------------------------------------------------------------
//
#define DETECT_BUFFER_SIZE 0x20000
int main()
{
const char* path = "E:/fangtu1/1/FTA001190217537664_一寸照.jpg";
unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
//auto src = cv::imread("C:/Users/01/Desktop/face/CNN_Face_Glass_Classfy-master/face7.jpg");
auto src = cv::imread(path);
Mat gray;
cvtColor(src, gray, CV_BGR2GRAY);
auto pResults = facedetect_multiview_reinforce(pBuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step, 1.2f, 2, 48, 0, 1);
int i = 0;
short * p = ((short*)(pResults + 1)) + 142 * i;
int x = p[0];
int y = p[1];
int w = p[2];
int h = p[3];
int neighbors = p[4];
int angle = p[5];
const char *saveFilePath = "F:\\00res.jpg";
printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
//cv::rectangle(src, Rect(x-w/2, y, w, h), Scalar(0, 255, 0), 2);
cv::rectangle(src, Rect(x, y, w, h), Scalar(0, 255, 0), 2);
//cv::rectangle(src, Rect(x + w + w / 16, y + h / 3, w / 5, h / 5), Scalar(255, 0, 0), 2);
//cv::rectangle(src, Rect(x + w + w / 16, y + 4 * h / 3, w / 5, h / 5), Scalar(0, 0, 225), 2);
//cout << "hehe" << x << y << w << h << endl;
save roi image
设定感兴趣的区域ROI
//cv::Mat m_roi = src(cv::Rect(x, y, w, h));
//cv::Mat PR_m_roi = src(cv::Rect(x + w + w / 16, y + h / 3, w / 5, h / 5));
//cv::Mat FO_m_roi = src(cv::Rect(x + w + w / 16, y + 4 * h / 3, w / 5, h / 5));
//imshow("Results_multiview_reinforce", PR_m_roi);
//imshow("Results_multiview_reinforce1", FO_m_roi);
if (1)
{
for (int j = 17; j < 21; j++)
{
cv::circle(src, Point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 1, Scalar(0, 255, 0));
cout << "hehe" << p[6 + 2 * j]<<"========="<< p[6 + 2 * j + 1]<< endl;
};
/*cv::rectangle(src, Rect(p[6 + 2 * 62], p[6 + 2 * 62 + 1], 1, 1), Scalar(0, 225, 0), 2);
cv::rectangle(src, Rect(p[6 + 2 * 66], p[6 + 2 * 66 + 1], 1, 1), Scalar(0, 0, 225), 2);*/
float mouth_higth = (p[6 + 2 * 66 + 1] - p[6 + 2 * 62 + 1]) / (float) p[2]; //嘴巴张开程度
float eye_sum = ((p[6 + 2 * 41 + 1] - p[6 + 2 * 37 + 1]) + (p[6 + 2 * 40 + 1] - p[6 + 2 * 38 + 1]) + (p[6 + 2 * 47 + 1] - p[6 + 2 * 43 + 1]) + (p[6 + 2 * 46 + 1] - p[6 + 2 * 44 + 1]));
float eye_hight = (eye_sum / 4) / (float)p[2];
//计算眉毛的角度
float pX[4] = { p[6 + 2 * 17],
p[6 + 2 * 18],
p[6 + 2 * 19],
p[6 + 2 * 20] };
float pY[4] = { p[6 + 2 * 17+1],
p[6 + 2 * 18 + 1],
p[6 + 2 * 19 + 1],
p[6 + 2 * 20 + 1] };
//cout << "====" << p[6 + 2 * 17] << "====" << p[6 + 2 * 18] << "====" << p[6 + 2 * 19] << "====" << p[6 + 2 * 20] << endl;
//cout << "====" << p[6 + 2 * 17+1] << "====" << p[6 + 2 * 18 + 1] << "====" << p[6 + 2 * 19 + 1] << "====" << p[6 + 2 * 20 + 1] << endl;
//float pX[4] = { 97, 105, 115, 124 };
//float pY[4] = { 105, 101, 101, 105 };
float brow_k =-LineFitLeastSquares(pX, pY, 4);//使用最小二乘法计算眉毛的斜率。
if (mouth_higth >= 0.03)
{
if (eye_hight >= 0.056)
{
cout << "amazing" << endl;
}
else
{
cout << "happy" << endl;
}
}
else
{
if (brow_k <= -0.03)
{
cout << "angry" << endl;
}
else
{
cout << "nature" << endl;
}
}
cout << "mouth_higth" << mouth_higth << endl;
cout << "eye_hight" << eye_hight << endl;
cout << "brow_k" << brow_k << endl;
// //cv::rectangle(src, Rect(1254, 1436, 160, 160), Scalar(0, 0, 225), 2);
// //cv::rectangle(src, Rect(1407, 1422, 160, 160), Scalar(0, 225, 0), 2);
// //cv::rectangle(src, Rect(1254-1, 1436-(1407-1254)/2, (1407 - 1254), (1407 - 1254)), Scalar(0, 0, 225), 2);
// //cv::rectangle(src, Rect(1323, 1441, 160, 160), Scalar(25, 0, 0), 2);
}
检测眼镜的大小
//float rate_oc, di1, di2;
//di1 = (p[6 + 2 * 44] - p[6 + 2 * 43]) / 2 + (p[6 + 2 * 46] - p[6 + 2 * 47]) / 2;
//di2 = (p[6 + 2 * 47 + 1] - p[6 + 2 * 43 + 1]) / 2 + (p[6 + 2 * 46 + 1] - p[6 + 2 * 44 + 1]) / 2;
//rate_oc = di2 / di1;
检测眼镜的大小
检测右眼的位置
//cout << "plaese open hear" << rate_oc << endl;
//cv::Mat yanjing1 = src(cv::Rect(p[6 + 2 * 42] - 1, p[6 + 2 * 42 + 1] - (p[6 + 2 * 45] - p[6 + 2 * 42]) / 2, (p[6 + 2 * 45] - p[6 + 2 * 42]), 2 * (p[6 + 2 * 45] - p[6 + 2 * 42]) / 3));
//imshow("Results_multiview_reereinforce", yanjing1);
检测左眼的位置
//cv::Mat yanjing2 = src(cv::Rect(p[6 + 2 * 36] + 1, p[6 + 2 * 36 + 1] - (p[6 + 2 * 39] - p[6 + 2 * 36]) / 2, (p[6 + 2 * 39] - p[6 + 2 * 36]), 2 * (p[6 + 2 * 39] - p[6 + 2 * 36]) / 3));
//imshow("Results_multiview_reereinfor123ce", yanjing2);
把检测到ROI区域进行保存。
//imwrite("OPEN_CLOSE_RIGHT.jpg", yanjing1);
//imwrite("OPEN_CLOSE_LEGHT11.jpg", yanjing2);
//namedWindow("enhanced", 0);
//resizeWindow("enhanced", 640, 480);
imshow("enhanced", src);
waitKey(0);
//free(pBuffer);
return 0;
}
// ----------------------------------------------------------------------------------------
/*************************************************************************
最小二乘法拟合直线,y = a*x + b; n组数据; r-相关系数[-1,1],fabs(r)->1,说明x,y之间线性关系好,fabs(r)->0,x,y之间无线性关系,拟合无意义
a = (n*C - B*D) / (n*A - B*B)
b = (A*D - B*C) / (n*A - B*B)
r = E / F
其中:
A = sum(Xi * Xi)
B = sum(Xi)
C = sum(Xi * Yi)
D = sum(Yi)
E = sum((Xi - Xmean)*(Yi - Ymean))
F = sqrt(sum((Xi - Xmean)*(Xi - Xmean))) * sqrt(sum((Yi - Ymean)*(Yi - Ymean)))
**************************************************************************/
float LineFitLeastSquares(float *data_x, float *data_y, int data_n)
{
float A = 0.0;
float B = 0.0;
float C = 0.0;
float D = 0.0;
float E = 0.0;
float F = 0.0;
for (int i = 0; i < data_n; i++)
{
A += data_x[i] * data_x[i];
B += data_x[i];
C += data_x[i] * data_y[i];
D += data_y[i];
}
// 计算斜率a和截距b
float a, b, temp = 0;
if (temp = (data_n*A - B * B))// 判断分母不为0
{
a = (data_n*C - B * D) / temp;
b = (A*D - B * C) / temp;
}
else
{
a = 1;
b = 0;
}
// 计算相关系数r
float Xmean, Ymean;
Xmean = B / data_n;
Ymean = D / data_n;
float tempSumXX = 0.0, tempSumYY = 0.0;
for (int i = 0; i < data_n; i++)
{
tempSumXX += (data_x[i] - Xmean) * (data_x[i] - Xmean);
tempSumYY += (data_y[i] - Ymean) * (data_y[i] - Ymean);
E += (data_x[i] - Xmean) * (data_y[i] - Ymean);
}
F = sqrt(tempSumXX) * sqrt(tempSumYY);
float r;
r = E / F;
//cout << "a" << a << endl;
//cout << b << endl;
//cout << r^2 << endl;
return a;
}