Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/FaceMorph/faceMorph.py
3118 views
1
#!/usr/bin/env python
2
3
import numpy as np
4
import cv2
5
import sys
6
7
# Read points from text file
8
def readPoints(path) :
9
# Create an array of points.
10
points = [];
11
# Read points
12
with open(path) as file :
13
for line in file :
14
x, y = line.split()
15
points.append((int(x), int(y)))
16
17
return points
18
19
# Apply affine transform calculated using srcTri and dstTri to src and
20
# output an image of size.
21
def applyAffineTransform(src, srcTri, dstTri, size) :
22
23
# Given a pair of triangles, find the affine transform.
24
warpMat = cv2.getAffineTransform( np.float32(srcTri), np.float32(dstTri) )
25
26
# Apply the Affine Transform just found to the src image
27
dst = cv2.warpAffine( src, warpMat, (size[0], size[1]), None, flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT_101 )
28
29
return dst
30
31
32
# Warps and alpha blends triangular regions from img1 and img2 to img
33
def morphTriangle(img1, img2, img, t1, t2, t, alpha) :
34
35
# Find bounding rectangle for each triangle
36
r1 = cv2.boundingRect(np.float32([t1]))
37
r2 = cv2.boundingRect(np.float32([t2]))
38
r = cv2.boundingRect(np.float32([t]))
39
40
41
# Offset points by left top corner of the respective rectangles
42
t1Rect = []
43
t2Rect = []
44
tRect = []
45
46
47
for i in range(0, 3):
48
tRect.append(((t[i][0] - r[0]),(t[i][1] - r[1])))
49
t1Rect.append(((t1[i][0] - r1[0]),(t1[i][1] - r1[1])))
50
t2Rect.append(((t2[i][0] - r2[0]),(t2[i][1] - r2[1])))
51
52
53
# Get mask by filling triangle
54
mask = np.zeros((r[3], r[2], 3), dtype = np.float32)
55
cv2.fillConvexPoly(mask, np.int32(tRect), (1.0, 1.0, 1.0), 16, 0);
56
57
# Apply warpImage to small rectangular patches
58
img1Rect = img1[r1[1]:r1[1] + r1[3], r1[0]:r1[0] + r1[2]]
59
img2Rect = img2[r2[1]:r2[1] + r2[3], r2[0]:r2[0] + r2[2]]
60
61
size = (r[2], r[3])
62
warpImage1 = applyAffineTransform(img1Rect, t1Rect, tRect, size)
63
warpImage2 = applyAffineTransform(img2Rect, t2Rect, tRect, size)
64
65
# Alpha blend rectangular patches
66
imgRect = (1.0 - alpha) * warpImage1 + alpha * warpImage2
67
68
# Copy triangular region of the rectangular patch to the output image
69
img[r[1]:r[1]+r[3], r[0]:r[0]+r[2]] = img[r[1]:r[1]+r[3], r[0]:r[0]+r[2]] * ( 1 - mask ) + imgRect * mask
70
71
72
if __name__ == '__main__' :
73
74
filename1 = 'hillary_clinton.jpg'
75
filename2 = 'ted_cruz.jpg'
76
alpha = 0.5
77
78
# Read images
79
img1 = cv2.imread(filename1);
80
img2 = cv2.imread(filename2);
81
82
# Convert Mat to float data type
83
img1 = np.float32(img1)
84
img2 = np.float32(img2)
85
86
# Read array of corresponding points
87
points1 = readPoints(filename1 + '.txt')
88
points2 = readPoints(filename2 + '.txt')
89
points = [];
90
91
# Compute weighted average point coordinates
92
for i in range(0, len(points1)):
93
x = ( 1 - alpha ) * points1[i][0] + alpha * points2[i][0]
94
y = ( 1 - alpha ) * points1[i][1] + alpha * points2[i][1]
95
points.append((x,y))
96
97
98
# Allocate space for final output
99
imgMorph = np.zeros(img1.shape, dtype = img1.dtype)
100
101
# Read triangles from tri.txt
102
with open("tri.txt") as file :
103
for line in file :
104
x,y,z = line.split()
105
106
x = int(x)
107
y = int(y)
108
z = int(z)
109
110
t1 = [points1[x], points1[y], points1[z]]
111
t2 = [points2[x], points2[y], points2[z]]
112
t = [ points[x], points[y], points[z] ]
113
114
# Morph one triangle at a time.
115
morphTriangle(img1, img2, imgMorph, t1, t2, t, alpha)
116
117
118
# Display Result
119
cv2.imshow("Morphed Face", np.uint8(imgMorph))
120
cv2.waitKey(0)
121
122