找工作好无趣,所以来写几篇博客玩一玩
惯例先放结果:
思路:
人脸定位——特征点——旋转
//具体实现看代码,还是有一定提升空间的,233
下面就是简单粗暴的代码了:
环境参考博客: Dlib提取人脸特征点(68点,opencv画图)
#include <dlib/opencv.h>
#include <opencv2/opencv.hpp>
#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<algorithm>
using namespace dlib;
using namespace std;
static cv::Rect dlibRectangleToOpenCV(dlib::rectangle r)
{
return cv::Rect(cv::Point2i(r.left(), r.top()), cv::Point2i(r.right() + 1, r.bottom() + 1));
}
static dlib::rectangle openCVRectToDlib(cv::Rect r)
{
return dlib::rectangle((long)r.tl().x, (long)r.tl().y, (long)r.br().x - 1, (long)r.br().y - 1);
}
int main()
{
try
{
cv::VideoCapture cap(0);
if (!cap.isOpened())
{
cerr << "Unable to connect to camera" << endl;
return 1;
}
//image_window win;
// Load face detection and pose estimation models.
frontal_face_detector detector = get_frontal_face_detector();
shape_predictor pose_model;
deserialize("shape_predictor_68_face_landmarks.dat") >> pose_model;
// Grab and process frames until the main window is closed by the user.
while (cv::waitKey(30) != 27)
{
// Grab a frame
cv::Mat temp;
cap >> temp;
cv_image<bgr_pixel> cimg(temp);
// Detect faces
std::vector<rectangle> faces = detector(cimg);
// Find the pose of each face.
std::vector<full_object_detection> shapes;
for (unsigned long i = 0; i < faces.size(); ++i)
shapes.push_back(pose_model(cimg, faces[i]));
if (!shapes.empty()) {
//for (int i = 0; i < 68; i++) {
// circle(temp, cvPoint(shapes[0].part(i).x(), shapes[0].part(i).y()), 2, cv::Scalar(255, 0, 0), -1);
// shapes[0].part(i).x();//68个
// }
int width = temp.cols;
int length = temp.rows;
double x = shapes[0].part(36).x() - shapes[0].part(45).x();
double y = shapes[0].part(36).y() - shapes[0].part(45).y();
double angle = x == 0 ? 0 : atan(y / x);
cv::Mat rotation = cv::getRotationMatrix2D(cvPoint(shapes[0].part(30).x(), shapes[0].part(30).y()), angle / 3.14 * 180, 1.0);
cv::warpAffine(temp, temp, rotation, cv::Size(width, length));
}
cimg = cv_image<bgr_pixel>(temp);
faces = detector(cimg);
if (faces.size() != 0) {
cv::Rect rect = dlibRectangleToOpenCV(faces[0]);
full_object_detection points = pose_model(cimg, faces[0]);
long xmax = points.part(0).x();
long xmin = points.part(0).x();
long ymin = points.part(0).y();
long ymax = points.part(0).y();;
for (int i = 1; i < 68; i++) {
xmax = std::max(xmax, points.part(i).x());
xmin = std::min(xmin, points.part(i).x());
ymax = std::max(ymax, points.part(i).y());
ymin = std::min(ymin, points.part(i).y());
}
rect.x = xmin ;
rect.width = xmax - xmin ;
rect.y = ymin;
rect.height = ymax - ymin ;
cv::Mat imCrop = temp(rect);
cv::resize(imCrop, imCrop, cv::Size(200, 200));
imshow("Image", imCrop);
cv::rectangle(temp, rect, cv::Scalar(255, 0, 0), 2);
}
imshow("人脸矫正", temp);
;
}
}
catch (serialization_error& e)
{
cout << "You need dlib's default face landmarking model file to run this example." << endl;
cout << "You can get it from the following URL: " << endl;
cout << " http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2" << endl;
cout << endl << e.what() << endl;
system("pause");
}
catch (exception& e)
{
cout << e.what() << endl;
system("pause");
}
}