Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/FaceMorph/faceMorph.cpp
3118 views
1
#include <opencv2/imgproc/imgproc.hpp>
2
#include <opencv2/highgui/highgui.hpp>
3
#include <iostream>
4
#include <fstream>
5
#include <iomanip>
6
#include <stdlib.h>
7
8
using namespace cv;
9
using namespace std;
10
11
12
// Read points stored in the text files
13
vector<Point2f> readPoints(string pointsFileName)
14
{
15
vector<Point2f> points;
16
ifstream ifs(pointsFileName);
17
float x, y;
18
while(ifs >> x >> y)
19
{
20
points.push_back(Point2f(x,y));
21
}
22
23
return points;
24
}
25
26
// Apply affine transform calculated using srcTri and dstTri to src
27
void applyAffineTransform(Mat &warpImage, Mat &src, vector<Point2f> &srcTri, vector<Point2f> &dstTri)
28
{
29
30
// Given a pair of triangles, find the affine transform.
31
Mat warpMat = getAffineTransform( srcTri, dstTri );
32
33
// Apply the Affine Transform just found to the src image
34
warpAffine( src, warpImage, warpMat, warpImage.size(), INTER_LINEAR, BORDER_REFLECT_101);
35
}
36
37
// Warps and alpha blends triangular regions from img1 and img2 to img
38
void morphTriangle(Mat &img1, Mat &img2, Mat &img, vector<Point2f> &t1, vector<Point2f> &t2, vector<Point2f> &t, double alpha)
39
{
40
41
// Find bounding rectangle for each triangle
42
Rect r = boundingRect(t);
43
Rect r1 = boundingRect(t1);
44
Rect r2 = boundingRect(t2);
45
46
// Offset points by left top corner of the respective rectangles
47
vector<Point2f> t1Rect, t2Rect, tRect;
48
vector<Point> tRectInt;
49
for(int i = 0; i < 3; i++)
50
{
51
tRect.push_back( Point2f( t[i].x - r.x, t[i].y - r.y) );
52
tRectInt.push_back( Point(t[i].x - r.x, t[i].y - r.y) ); // for fillConvexPoly
53
54
t1Rect.push_back( Point2f( t1[i].x - r1.x, t1[i].y - r1.y) );
55
t2Rect.push_back( Point2f( t2[i].x - r2.x, t2[i].y - r2.y) );
56
}
57
58
// Get mask by filling triangle
59
Mat mask = Mat::zeros(r.height, r.width, CV_32FC3);
60
fillConvexPoly(mask, tRectInt, Scalar(1.0, 1.0, 1.0), 16, 0);
61
62
// Apply warpImage to small rectangular patches
63
Mat img1Rect, img2Rect;
64
img1(r1).copyTo(img1Rect);
65
img2(r2).copyTo(img2Rect);
66
67
Mat warpImage1 = Mat::zeros(r.height, r.width, img1Rect.type());
68
Mat warpImage2 = Mat::zeros(r.height, r.width, img2Rect.type());
69
70
applyAffineTransform(warpImage1, img1Rect, t1Rect, tRect);
71
applyAffineTransform(warpImage2, img2Rect, t2Rect, tRect);
72
73
// Alpha blend rectangular patches
74
Mat imgRect = (1.0 - alpha) * warpImage1 + alpha * warpImage2;
75
76
// Copy triangular region of the rectangular patch to the output image
77
multiply(imgRect,mask, imgRect);
78
multiply(img(r), Scalar(1.0,1.0,1.0) - mask, img(r));
79
img(r) = img(r) + imgRect;
80
81
82
}
83
84
int main( int argc, char** argv)
85
{
86
87
string filename1("hillary_clinton.jpg");
88
string filename2("ted_cruz.jpg");
89
90
//alpha controls the degree of morph
91
double alpha = 0.5;
92
93
//Read input images
94
Mat img1 = imread(filename1);
95
Mat img2 = imread(filename2);
96
97
//convert Mat to float data type
98
img1.convertTo(img1, CV_32F);
99
img2.convertTo(img2, CV_32F);
100
101
102
//empty average image
103
Mat imgMorph = Mat::zeros(img1.size(), CV_32FC3);
104
105
106
//Read points
107
vector<Point2f> points1 = readPoints( filename1 + ".txt");
108
vector<Point2f> points2 = readPoints( filename2 + ".txt");
109
vector<Point2f> points;
110
111
//compute weighted average point coordinates
112
for(int i = 0; i < points1.size(); i++)
113
{
114
float x, y;
115
x = (1 - alpha) * points1[i].x + alpha * points2[i].x;
116
y = ( 1 - alpha ) * points1[i].y + alpha * points2[i].y;
117
118
points.push_back(Point2f(x,y));
119
120
}
121
122
123
//Read triangle indices
124
ifstream ifs("tri.txt");
125
int x,y,z;
126
127
while(ifs >> x >> y >> z)
128
{
129
// Triangles
130
vector<Point2f> t1, t2, t;
131
132
// Triangle corners for image 1.
133
t1.push_back( points1[x] );
134
t1.push_back( points1[y] );
135
t1.push_back( points1[z] );
136
137
// Triangle corners for image 2.
138
t2.push_back( points2[x] );
139
t2.push_back( points2[y] );
140
t2.push_back( points2[z] );
141
142
// Triangle corners for morphed image.
143
t.push_back( points[x] );
144
t.push_back( points[y] );
145
t.push_back( points[z] );
146
147
morphTriangle(img1, img2, imgMorph, t1, t2, t, alpha);
148
149
}
150
151
// Display Result
152
imshow("Morphed Face", imgMorph / 255.0);
153
waitKey(0);
154
155
return 0;
156
}
157
158