admin管理员组

文章数量:815327

opencv+c++实现的瘦脸算法

关键思想是《Image Deformation Using Moving Least Squares》这篇论文中提到的方法。
 

实现:

1>实现人脸关键点定位
 

2>实现论文中像素点的坐标变换

坐标变换源码:

void face_lift(Mat &src,const vector<Point2f>& landmarks,int change,const Rect &face)
{vector<Point2f> control_p = {landmarks[0],landmarks[5],								            Point2f(face.x,face.y+face.height),Point2f(face.x+face.width,face.y+face.height),landmarks[11],landmarks[16],landmarks[33],landmarks[62]};vector<Point2f> control_q = { landmarks[0],	landmarks[5],								              Point2f(landmarks[5].x + change,landmarks[5].y),					      Point2f(face.x,face.y + face.height),Point2f(face.x + face.width,face.y + face.height),Point2f(landmarks[11].x-change,landmarks[11].y ),landmarks[16],landmarks[33],landmarks[62],};Mat pic=src.clone();for (int i =face.x; i <=face.x+face.width; ++i){for (int j = landmarks[0].y;j< landmarks[8].y; ++j){{vector<float> weight_p;								        vector<Point2f>::iterator itcp = control_p.begin();while (itcp != control_p.end()){double tmp;if (itcp->x != i || itcp->y != j)tmp = 1 / ((itcp->x - i)*(itcp->x - i) + (itcp->y - j)*(itcp->y - j));elsetmp = MAXNUM;weight_p.push_back(tmp);++itcp;}double px = 0, py = 0, qx = 0, qy = 0, tw = 0;itcp = control_p.begin();vector<float>::iterator itwp = weight_p.begin();vector<Point2f>::iterator itcq = control_q.begin();while (itcp != control_p.end()){px += (*itwp)*(itcp->x);py += (*itwp)*(itcp->y);qx += (*itwp)*(itcq->x);qy += (*itwp)*(itcq->y);tw += *itwp;++itcp;++itcq;++itwp;}px = px / tw;py = py / tw;qx = qx / tw;qy = qy / tw;Mat A = Mat::zeros(2, 1, CV_32FC1);Mat B = Mat::zeros(1, 2, CV_32FC1);Mat C = Mat::zeros(1, 2, CV_32FC1);Mat sumL = Mat::zeros(2, 2, CV_32FC1);Mat sumR = Mat::zeros(2, 2, CV_32FC1);Mat M, pos;for (int i = 0; i < weight_p.size(); ++i){A.at<float>(0, 0) = (control_p[i].x - px);A.at<float>(1, 0) = (control_p[i].y - py);B.at<float>(0, 0) = weight_p[i] * ((control_p[i].x - px));B.at<float>(0, 1) = weight_p[i] * ((control_p[i].y - py));sumL += A * B;C.at<float>(0, 0) = weight_p[i] * (control_q[i].x - qx);C.at<float>(0, 1) = weight_p[i] * (control_q[i].y - qy);sumR += A * C;}M = sumL.inv()*sumR;B.at<float>(0, 0) = i - px;B.at<float>(0, 1) = j - py;C.at<float>(0, 0) = qx;C.at<float>(0, 1) = qy;pos = B * M + C;int row = pos.at<float>(0, 0);int col = pos.at<float>(0, 1);pic.at<Vec3b>(col, row)[0] = src.at<Vec3b>(j, i)[0];pic.at<Vec3b>(col, row)[1] = src.at<Vec3b>(j, i)[1];pic.at<Vec3b>(col, row)[2] = src.at<Vec3b>(j, i)[2];}}}
}

效果图:

本文标签: opencvc实现的瘦脸算法