关键思想是《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));
else
tmp = 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];
}
}
}
}效果图:


版权声明:本文为skyqsdyy原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。