人脸识别算法初稿..
#include <stdio.h>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include "src/facedetectcnn.h"
#include "time.h"
#include <dlib/opencv.h>
#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 <vector>
#include <math.h>
//define the buffer size. Do not change the size!
#define DETECT_BUFFER_SIZE 0x20000
using namespace cv;
using namespace dlib;
using namespace std;
CvPoint getPointAffinedPos(const CvPoint src, const Point center, double angle)
{
CvPoint dst;
int x = src.x - center.x;
int y = src.y - center.y;
dst.x = cvRound(x * cos(angle) + y * sin(angle) + center.x);
dst.y = cvRound(-x * sin(angle) + y * cos(angle) + center.y);
return dst;
}
Mat face_alignment(Mat &face, CvPoint& left, CvPoint& right, Rect roi) {
int offsetx = roi.x;
int offsety = roi.y;
// 计算中心位置
int cx = roi.width / 2;
int cy = roi.height / 2;
// 计算角度
int dx = right.x - left.x;
int dy = right.y - left.y;
double degree = 180 * ((atan2(dy, dx)) / CV_PI);
Point2f center(cx, cy);
// 旋转矩阵计算
Mat M = getRotationMatrix2D(center, degree, 1.0);
Rect bbox = RotatedRect(center, face.size(), degree).boundingRect();
M.at<double>(0, 2) += (bbox.width / 2.0 - center.x);
M.at<double>(1, 2) += (bbox.height / 2.0 - center.y);
// 对齐
Mat result;
warpAffine(face, result, M, bbox.size());//仿射变换
int length = (result.cols - face.cols) / 2;
left = getPointAffinedPos(left, center, degree*CV_PI / 180);
right = getPointAffinedPos(right, center, degree*CV_PI / 180);
left.x += length;
left.y += length;
right.x += length;
right.y += length;
imshow("face-alignment", result);
imwrite("face_alignment.jpg", result);
return result;
}
int main(int argc, char* argv[])
{
// Load pose estimation models.
shape_predictor pose_model;
deserialize("model\\shape_predictor_5_face_landmarks.dat") >> pose_model;
//usb camera
Mat image = imread("images/test1.jpg");
//VideoCapture cam(0);
Mat mb = imread("model/mb.jpg");
Mat result_image;
if (image.empty())
{
//fprintf(stderr, "Can not open camera.\n");
return -1;
}
resize(image, image, Size(640, 360));
cv_image<bgr_pixel> cimg(image);
time_t start = clock();
int * pResults = NULL;
//pBuffer is used in the detection functions.
//If you call functions in multiple threads, please create one buffer for each thread!
unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
if (!pBuffer)
{
fprintf(stderr, "Can not alloc buffer.\n");
return -1;
}
///
// CNN face detection
// Best detection rate
pResults = facedetect_cnn(pBuffer, (unsigned char*)(image.ptr(0)), image.cols, image.rows, (int)image.step);
printf("%d faces detected.\n", (pResults ? *pResults : 0));
Mat result_cnn = image.clone();
//print the detection results
if (*pResults)
{
//short * p = ((short*)(pResults + 1)) + 142 * i;
short *p = (short*)(pResults + 1);
int x = p[0];
int y = p[1];
int w = p[2];
int h = p[3];
int neighbors = p[4];
int angle = p[5];
printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
cv::rectangle(result_cnn, Rect(x - 20, y - 40, w + 40, h + 40), Scalar(0, 255, 0), 2);
Rect roi(x - 20, y - 40, w + 40, h + 40);
Mat roi_image = result_cnn(Rect(x - 20, y - 40, w + 40, h + 40));
//circle(roi_image, cvPoint(roi_image.cols / 2, roi_image.rows / 2), 3, cv::Scalar(0, 0, 255), -1);
//Find the pose of each face.
dlib::rectangle face;
//std::vector<dlib::rectangle> faces;
std::vector<full_object_detection> shapes;
face.set_left(x);
face.set_top(y);
face.set_right(x + w);
face.set_bottom(y + h);
//faces.push_back(face);
/*for (unsigned long i = 0; i < faces.size(); ++i)
shapes.push_back(pose_model(cimg, faces[i]));*/
shapes.push_back(pose_model(cimg, face));
//draw 5 points
if (!shapes.empty())
{
std::vector<CvPoint> keypoints;
for (int i = 0; i < 5; i++)
{
circle(image, cvPoint(shapes[0].part(i).x(), shapes[0].part(i).y()), 3, cv::Scalar(0, 0, 255), -1);
CvPoint p(shapes[0].part(i).x(), shapes[0].part(i).y());
cout << p.x << " " << p.y << endl;
keypoints.push_back(p);
//putText(image, to_string(i), cvPoint(shapes[0].part(i).x(), shapes[0].part(i).y()), cv::FONT_HERSHEY_PLAIN, 1, Scalar(0, 0, 255));
}
CvPoint p1, p2;
p1.x = (keypoints[0].x + keypoints[1].x) / 2 - (x - 20);
p1.y = (keypoints[0].y + keypoints[1].y) / 2 - (y - 40);
p2.x = (keypoints[2].x + keypoints[3].x) / 2 - (x - 20);
p2.y = (keypoints[2].y + keypoints[3].y) / 2 - (y - 40);
/*circle(roi_image, p2, 3, cv::Scalar(0, 255, 255), -1);
circle(roi_image, p1, 3, cv::Scalar(0, 255, 255), -1);*/
imshow("roi_img", roi_image);
Mat face_result = face_alignment(roi_image, p2, p1, roi);
/*circle(face_result, p2, 2, cv::Scalar(255, 255, 255), -1);
circle(face_result, p1, 2, cv::Scalar(255, 255, 255), -1);*/
Mat mask = Mat::zeros(face_result.cols, face_result.rows, CV_8UC3);
Mat mb2roi(mask, Rect(p2.x - 55, p2.y - 77, 200, 200));
mb.copyTo(mb2roi);
imshow("mask", mask);
/*double alpha = 0.8;
double beta = 1 - alpha;
addWeighted(face_result, alpha, mask, beta, 0.0, result_image);*/
//cout << "result_image size is: " << result_image.cols << " " << result_image.rows << endl;
Mat Image_Forehead = Mat::zeros(face_result.cols, face_result.rows, CV_8UC3);//额头
Mat Image_Eyelid = Mat::zeros(face_result.cols, face_result.rows, CV_8UC3);//眼眶
Mat Image_Cheek = Mat::zeros(face_result.cols, face_result.rows, CV_8UC3);//脸颊
Mat Image_Nose = Mat::zeros(face_result.cols, face_result.rows, CV_8UC3);//鼻子
Mat Image_Mouth = Mat::zeros(face_result.cols, face_result.rows, CV_8UC3);//嘴巴
for (int i = 0; i < mask.rows; i++)
{
uchar* p = mask.ptr<uchar>(i);
for (int j = 0; j < mask.cols; j++)
{
uchar b = p[3 * j + 0];
uchar g = p[3 * j + 1];
uchar r = p[3 * j + 2];
if (b == 0 && g == 0 && r == 255)//额头 红
{
Image_Forehead.at<cv::Vec3b>(i, j) = face_result.at<cv::Vec3b>(i, j);
}
else if(b == 255 && g == 0 && r == 0)//眼眶 蓝
{
Image_Eyelid.at<cv::Vec3b>(i, j) = face_result.at<cv::Vec3b>(i, j);
}
else if (b == 0 && g == 255 && r == 255)//脸颊 黄
{
Image_Cheek.at<cv::Vec3b>(i, j) = face_result.at<cv::Vec3b>(i, j);
}
else if (b == 0 && g == 255 && r == 0)//鼻子 绿
{
Image_Nose.at<cv::Vec3b>(i, j) = face_result.at<cv::Vec3b>(i, j);
}
else if (b == 255 && g == 255 && r == 0)//嘴巴 青色
{
Image_Mouth.at<cv::Vec3b>(i, j) = face_result.at<cv::Vec3b>(i, j);
}
else
{
continue;
}
}
}
imshow("Image_Forehead", Image_Forehead);
imshow("Image_Eyelid", Image_Eyelid);
imshow("Image_Cheek", Image_Cheek);
imshow("Image_Nose", Image_Nose);
imshow("Image_Mouth", Image_Mouth);
}
}
time_t end = clock();
imshow("landmark", image);
imshow("result_cnn", result_cnn);
//imshow("result_image", result_image);
//imwrite("result_image.jpg", result_image);
//release the buffer
free(pBuffer);
//calculate running time
double total_time = (double)(end - start) / CLOCKS_PER_SEC * 1000;
cout << "total_time:" << total_time << "ms" << endl;
waitKey(0);
return 0;
}
未完待续...