#include "all.h"
/*******
作者:张鸿锐
浙江理工大学 15电科1班
*****/
void yuchuli(string filename)
{
Mat rgb = imread(filename, 1);
Mat output = Mat::zeros(256, 256, CV_8UC3);
resize(rgb, output, output.size());
imwrite(filename, output);
}
int face_feature(dlib::array2d<dlib::rgb_pixel>& img, Mat rgb, vector<cv::Point2f> &face)
{
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();//初始化检测器
vector<dlib::rectangle> dets = detector(img);//记录有人脸的位置
dlib::shape_predictor sp;
dlib::deserialize("shape_predictor_68_face_landmarks.dat") >> sp;//载入模型
if (dets.empty())//判断有没有检测到人脸
{
return 1;
}
// cout << dets[0] << endl;
dlib::full_object_detection shape = sp(img, dets[0]);
//先加入手工点
face.push_back(Point2f(1, 1));
face.push_back(Point2f(1, rgb.size().height / 2));
face.push_back(Point2f(1, rgb.size().height - 2));
face.push_back(Point2f(rgb.size().width / 2, 1));
face.push_back(Point2f(rgb.size().width / 2, rgb.size().height - 2));
face.push_back(Point2f(rgb.size().width - 2, 1));
face.push_back(Point2f(rgb.size().width - 2, rgb.size().height / 2));
face.push_back(Point2f(rgb.size().width - 2, rgb.size().height - 2));
for (int i = 0; i < shape.num_parts(); i++)//输出人脸68个特征点
{
if (i >= face.size() || i < 0) { cout << "vetcor下标越界" << endl; break; }
auto a = shape.part(i);
//cv::circle(rgb, cvPoint(a.x(), a.y()), 2, cv::Scalar(0, 0, 255));
face.push_back(Point2f(float(a.x()), float(a.y())));//由于后面利用opencv中的库函数进行三角剖分的时候数据类型不能为int型
}
/*for (int i = 0; i < face.size(); i++)
{
if (i >= face.size() || i < 0) { cout << "vetcor下标越界" << endl; break; }
circle(rgb, cvPoint(face[i].x, face[i].y), 2, cv::Scalar(0, 0, 255));
}
imshow(" ", rgb);
waitKey(0);*/
cout << rgb.size() << endl;
cout << rgb.rows << endl;
cout << rgb.cols << endl; ///显示用,看看是否正确
return 0;
}
void morph_feature(vector<Point2f> &face1, vector<Point2f> &face2, vector<Point2f> &face3, double a)//根据混合程度a来获得新图像的特征点
{
for (int i = 0; i < face1.size(); i++)
{
float x, y;
x = (1.0 - a) * face1[i].x + a * face2[i].x;
y = (1.0 - a) * face1[i].y + a * face2[i].y;
face3.push_back(Point2f(x, y));
}
}
void delaunayTriangulation(vector<Point2f> &face1, vector<Point2f> &face2, vector<Point2f> &face_out,
double a, vector<triangle_point>& delaunayTri, Size imgsize) //构建三角形的函数
{
morph_feature(face1, face2, face_out, a);//根据程度a,来重建新图像的特征点
Rect rect(0, 0, imgsize.width, imgsize.height);
Subdiv2D subdiv(rect);//opencv中进行三角构造的类函数,在rect这个矩形内进行三角划分
for (vector<Point2f>::iterator it = face_out.begin(); it != face_out.end(); it++)
{
Point2f a = *it;
subdiv.insert(a); //将所以点加入到subdiv中
}
vector<Vec6f> tri_list; //vec6f是6个点的结构体 x1 y1 x2 y2 x3 y3排列的
subdiv.getTriangleList(tri_list); //将所有可能的三角形存放到tri_list中
for (int i = 0; i < tri_list.size(); i++)
{
vector<Point2f> term; //存储点的中间栈
triangle_point p; //用来存储三角形三个点索引的中间变量
Vec6f t = tri_list[i];
term.push_back(Point2f(t[0], t[1]));
term.push_back(Point2f(t[2], t[3]));
term.push_back(Point2f(t[4], t[5]));//分别将三个点压栈
if (rect.contains(term[0]) && rect.contains(term[1]) && rect.contains(term[2]))//确保三角形的点在矩形区域内
{
int count = 0;
for (int j = 0; j < 3; j++)//计算三角形三个点在原特征点内的索引
{
for (int k = 0; k < face_out.size(); k++)
{
if (abs(term[j].x - face_out[k].x) < 1.0 && abs(term[j].y - face_out[k].y) < 1.0)
{
p.index.push_back(k);
count++;
}
}
}
if (count == 3)
delaunayTri.push_back(p);
}
}
}
void affine_transform_single(Mat &out, Mat &src, vector<Point2f> & srcTri, vector<Point2f> & outTri)//对一个三角形进行仿射变换
{
Mat outmat = getAffineTransform(srcTri, outTri);// 用三个点求得仿射变换,任意的变换可表示为 A*x + B outmat=(AB)
warpAffine(src, out, outmat, out.size(), INTER_LINEAR, BORDER_REFLECT_101);//将刚刚求得的仿射变换应用到源图像
}
void morphTriangle(Mat &face1, Mat &face2, Mat &face_out,
vector<Point2f> &t1, vector<Point2f> &t2, vector<Point2f> &t, double a)
//通过两张图片的三角形集,将两张图片中对应的三角形通过程度a变换为1张图片中的三角形
{
Rect r = boundingRect(t);//通过t中点的坐标,形成最小的边界。
Rect r1 = boundingRect(t1);
Rect r2 = boundingRect(t2);//rect类中的x y 指的是左上角点的坐标
vector<Point2f> t1Rect, t2Rect, tRect;
vector<Point> tRectInt;
for (int i = 0; i < 3; i++)//计算三角形的三个顶点到最小边界的距离(其实就是在新图像上的坐标),图像偏移
{
tRect.push_back(Point2f(t[i].x - r.x, t[i].y - r.y));
tRectInt.push_back(Point(t[i].x - r.x, t[i].y - r.y));
t1Rect.push_back(Point2f(t1[i].x - r1.x, t1[i].y - r1.y));
t2Rect.push_back(Point2f(t2[i].x - r.x, t2[i].y - r2.y));
}
Mat mask = Mat::zeros(r.height, r.width, CV_32FC3); //算差值的意义就在这里了 ,要转换到新图片上去
fillConvexPoly(mask, tRectInt, Scalar(1.0, 1.0, 1.0), 16, 0); //填充颜色为白色 大于等于1;通过填充三角区域获得图像的遮片,
Mat img1Rect, img2Rect;
face1(r1).copyTo(img1Rect);
face2(r2).copyTo(img2Rect);
Mat warpImage1 = Mat::zeros(r.height, r.width, img1Rect.type());
Mat warpImage2 = Mat::zeros(r.height, r.width, img2Rect.type());
affine_transform_single(warpImage1, img1Rect, t1Rect, tRect);
affine_transform_single(warpImage2, img2Rect, t2Rect, tRect);
Mat imgRect = (1.0 - a)*warpImage1 + a*warpImage2;
multiply(imgRect, mask, imgRect); //利用遮片将除三角形外的元素置零
multiply(face_out(r), Scalar(1.0, 1.0, 1.0) - mask, face_out(r));
//将三角区域置零 Scalar(1.0, 1.0, 1.0) - mask每个位置与Scalar(1.0, 1.0, 1.0)相减
face_out(r) = face_out(r) + imgRect;
}
void morph(Mat& face1, Mat& face2, Mat &face_out, double a,
vector<Point2f> &points1, vector<Point2f> &points2, vector<Point2f> &points, vector<triangle_point> &triangle)
{
face1.convertTo(face1, CV_32FC3);
face2.convertTo(face2, CV_32FC3);
int x, y, z;
for (int i = 0; i < triangle.size(); i++)
{
triangle_point val = triangle[i];
x = val.index[0];
y = val.index[1];
z = val.index[2];
vector<Point2f> t1, t2, t;
t1.push_back(points1[x]);
t1.push_back(points1[y]);
t1.push_back(points1[z]);
t2.push_back(points2[x]);
t2.push_back(points2[y]);
t2.push_back(points2[z]);
t.push_back(points[x]);
t.push_back(points[y]);
t.push_back(points[z]);
morphTriangle(face1, face2, face_out, t1, t2, t, a);
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
Face__Morph.zip (53个子文件)
Face__Morph
Face__Morph.sln 1KB
x64
Debug
Face__Morph.exe 3.05MB
Face__Morph.ilk 15.75MB
Face__Morph.pdb 19.36MB
Face__Morph.sdf 58.88MB
Face__Morph.v12.suo 21KB
Face__Morph
face.cpp 7KB
111.jpg 22KB
output.avi 455KB
11.jpg 21KB
output
output_20.jpg 23KB
output_18.jpg 22KB
output_12.jpg 21KB
output_0.jpg 18KB
output_5.jpg 20KB
output_16.jpg 22KB
output_15.jpg 22KB
output_7.jpg 20KB
output_10.jpg 21KB
output_6.jpg 20KB
output_21.jpg 22KB
output_3.jpg 19KB
output_1.jpg 18KB
output_22.jpg 22KB
output_8.jpg 21KB
output_4.jpg 20KB
output_14.jpg 22KB
output_2.jpg 19KB
output_17.jpg 22KB
output_19.jpg 22KB
output_13.jpg 21KB
output_11.jpg 21KB
output_9.jpg 21KB
Face__Morph.vcxproj.filters 1KB
222.jpg 18KB
x64
Debug
vc120.pdb 5.93MB
face.obj 14.17MB
Face__Morph.log 3KB
main.obj 3.31MB
Face__Morph.tlog
cl.command.1.tlog 1KB
CL.read.1.tlog 218KB
link.read.1.tlog 3KB
link.write.1.tlog 582B
CL.write.1.tlog 1KB
link.command.1.tlog 1KB
Face__Morph.lastbuildstate 160B
vc120.idb 4.66MB
假笑男孩.avi 437KB
main.cpp 2KB
Face__Morph.vcxproj 7KB
shape_predictor_68_face_landmarks.dat 95.08MB
123.jpg 25KB
all.h 2KB
共 53 条
- 1
资源评论
- 赵潇98802018-12-26垃圾程序啊 这么高的分rrblog2020-08-25你在这费什么话?你跑过没?
rrblog
- 粉丝: 3
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功