回答編集履歴
1
たぶんOK
answer
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
+

|
2
|
+

|
3
|
+

|
4
|
+

|
1
|
-
|
5
|
+
※画像はwikiより。共にプログラマー界のスーパーおかあちゃんです。
|
2
6
|
|
7
|
+
コメントにも書きましたが、細かいエラーがたくさんありましたので個別には書きません。コメントと行間を察する温かい気持ちでコードを読んでください。
|
8
|
+
---
|
9
|
+
なお、fourteenlengthは「技量を証明したくて、むしゃくしゃしてやった、後悔はしていない」などと意味不明なことを供述しており…
|
3
10
|
```Python3
|
4
11
|
import argparse
|
12
|
+
|
5
13
|
import cv2
|
6
14
|
import numpy as np
|
7
15
|
import random
|
@@ -11,19 +19,18 @@
|
|
11
19
|
|
12
20
|
import sys # <--追加
|
13
21
|
from imutils import face_utils# <--追加
|
14
|
-
|
15
22
|
def Face_landmarks(image_path):
|
16
23
|
print("[INFO] loading facial landmark predictor...")
|
17
24
|
detector = dlib.get_frontal_face_detector()
|
18
25
|
|
19
|
-
path = os.
|
26
|
+
path = os.path.split(__file__)[0]+"\" # <--デバグ用に修正
|
20
27
|
print(path)
|
21
28
|
|
22
|
-
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
|
29
|
+
predictor = dlib.shape_predictor(path + "shape_predictor_68_face_landmarks.dat") # <--デバグ用に修正
|
23
30
|
|
24
|
-
image = cv2.imread(image_path)
|
31
|
+
image = cv2.imread(path + image_path)# <--デバグ用に修正
|
25
32
|
|
26
|
-
|
33
|
+
--追加
|
27
34
|
# 画像が読めないとNoneになるため
|
28
35
|
print("File loading error @Face_landmarks(image_path)")
|
29
36
|
sys.exit()
|
@@ -70,11 +77,18 @@
|
|
70
77
|
|
71
78
|
# if name == 'main': <-- 修正
|
72
79
|
if __name__ == '__main__':
|
73
|
-
# filename = 'image/MarilynMonroe.jpg'
|
74
80
|
filename = 'image/Grace_Murray_Hopper.jpg'
|
75
81
|
|
76
82
|
name,ext = os.path.splitext(filename)
|
83
|
+
|
84
|
+
path = os.path.split(__file__)[0]+"\" # <--デバグ用に
|
77
|
-
img = cv2.imread(filename)
|
85
|
+
img = cv2.imread(path + filename)# <--デバグ用に修正
|
86
|
+
|
87
|
+
if img is None:# <--追加
|
88
|
+
# 画像が読めないとNoneになるため
|
89
|
+
print("File loading error @ __name__ == '__main__'")
|
90
|
+
sys.exit()
|
91
|
+
|
78
92
|
points = Face_landmarks(filename) # failname --> filename
|
79
93
|
stringToWrite = ''
|
80
94
|
|
@@ -84,6 +98,7 @@
|
|
84
98
|
cv2.circle(img, (x, y), 1, (0, 0, 255), -1)
|
85
99
|
cv2.putText(img, str(i + 1), (x - 10, y - 10),
|
86
100
|
cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)
|
101
|
+
|
87
102
|
cv2.imwrite('%s-points.jpg' %name,img)
|
88
103
|
|
89
104
|
def Face_delaunay(rect,points1 ,points2 ,alpha ):
|
@@ -127,16 +142,15 @@
|
|
127
142
|
|
128
143
|
if rectContains(rect, pt1) and rectContains(rect, pt2) and rectContains(rect, pt3):
|
129
144
|
ind = []
|
130
|
-
|
131
145
|
for j in range(0, 3):
|
132
146
|
for k in range(0, len(points)):
|
133
147
|
if(abs(pt[j][0] - points[k][0]) < 1.0 and abs(pt[j][1] - points[k][1]) < 1.0):
|
134
148
|
ind.append(k)
|
135
149
|
if len(ind) == 3:
|
136
150
|
delaunayTri.append((ind[0], ind[1], ind[2]))
|
151
|
+
# print(delaunayTri)
|
152
|
+
pt = []
|
137
153
|
|
138
|
-
pt = []
|
139
|
-
|
140
154
|
return triangleList,delaunayTri
|
141
155
|
|
142
156
|
def rectContains(rect, point) :
|
@@ -161,7 +175,7 @@
|
|
161
175
|
tri : 画像1,2の間の三角形
|
162
176
|
alpha: 重み
|
163
177
|
"""
|
164
|
-
|
178
|
+
|
165
179
|
# 各三角形の座標を含む最小の矩形領域 (バウンディングボックス)を取得
|
166
180
|
# (左上のx座標, 左上のy座標, 幅, 高さ)
|
167
181
|
r1 = cv2.boundingRect(np.float32([tri1]))
|
@@ -177,14 +191,14 @@
|
|
177
191
|
t1Rect.append(((tri1[i][0] - r1[0]),(tri1[i][1] - r1[1])))
|
178
192
|
t2Rect.append(((tri2[i][0] - r2[0]),(tri2[i][1] - r2[1])))
|
179
193
|
|
180
|
-
|
194
|
+
# 三角形のマスクを生成
|
181
|
-
|
195
|
+
# 三角形の領域のピクセル値は1で、残りの領域のピクセル値は0になる
|
182
|
-
|
196
|
+
mask = np.zeros((r[3], r[2], 3), dtype = np.float32)
|
183
|
-
|
197
|
+
cv2.fillConvexPoly(mask, np.int32(tRect), (1.0, 1.0, 1.0), 16, 0)
|
184
198
|
|
185
|
-
|
199
|
+
# アフィン変換の入力画像を用意
|
186
|
-
|
200
|
+
img1Rect = img1[r1[1]:r1[1] + r1[3], r1[0]:r1[0] + r1[2]]
|
187
|
-
|
201
|
+
img2Rect = img2[r2[1]:r2[1] + r2[3], r2[0]:r2[0] + r2[2]]
|
188
202
|
|
189
203
|
# アフィン変換の変換行列を生成
|
190
204
|
warpMat1 = cv2.getAffineTransform( np.float32(t1Rect), np.float32(tRect) )
|
@@ -199,12 +213,10 @@
|
|
199
213
|
# 2つの画像に重みを付けて、三角形の最終的なピクセル値を見つける
|
200
214
|
imgRect = (1.0 - alpha) * warpImage1 + alpha * warpImage2
|
201
215
|
|
216
|
+
|
202
217
|
# マスクと投影結果を使用して論理AND演算を実行し、
|
203
218
|
# 三角形領域の投影されたピクセル値を取得しOutput用画像にコピー
|
204
219
|
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
|
205
|
-
|
206
|
-
# cv2.imshow("img",img)# <-- 追加
|
207
|
-
# cv2.waitKey(10) # <-- 追加
|
208
220
|
return img# <-- 追加
|
209
221
|
|
210
222
|
def betweenPoints(point1, point2, alpha) :
|
@@ -215,20 +227,17 @@
|
|
215
227
|
points.append((x,y))
|
216
228
|
return points
|
217
229
|
|
218
|
-
|
230
|
+
if __name__ == '__main__': # <-- 修正
|
219
|
-
if __name__ == '__main__':
|
220
|
-
|
221
231
|
os.makedirs("./output",exist_ok=True) # <-- 追加
|
222
232
|
|
233
|
+
path = os.path.split(__file__)[0]+"\" # <--デバグ用に追加
|
234
|
+
|
223
235
|
# モーフィングする画像取得
|
224
|
-
# filename1 = 'image/AudreyHepburn.jpg'
|
225
|
-
# filename2 = 'image/MarilynMonroe.jpg'
|
226
236
|
filename1 = 'image/Grace_Murray_Hopper.jpg'
|
227
237
|
filename2 = 'image/Frances_Elizabeth_Allen.jpg'
|
228
238
|
|
229
|
-
|
230
|
-
img1 = cv2.imread(filename1)
|
239
|
+
img1 = cv2.imread(path + filename1)
|
231
|
-
img2 = cv2.imread(filename2)
|
240
|
+
img2 = cv2.imread(path + filename2)
|
232
241
|
|
233
242
|
if img1 is None:# <--追加
|
234
243
|
# 画像が読めないとNoneになるため
|
@@ -251,26 +260,22 @@
|
|
251
260
|
rect = (0, 0, size[1], size[0])
|
252
261
|
|
253
262
|
# 顔の特徴点を取得
|
254
|
-
# points1 = face_landmarks.Face_landmarks(filename1)
|
255
|
-
# points2 = face_landmarks.Face_landmarks(filename2)
|
256
263
|
points1 = Face_landmarks(filename1) # <--修正
|
257
264
|
points2 = Face_landmarks(filename2) # <--修正
|
258
265
|
|
259
266
|
# 1~99%割合を変えてモーフィング
|
260
|
-
|
267
|
+
for cnt in range(1, 100):
|
261
|
-
for cnt in range(1, 100,10): # <--デバグ用に修正
|
262
268
|
alpha = cnt * 0.01
|
263
269
|
|
264
270
|
# 画像1,2の特徴点の間を取得
|
265
271
|
points = betweenPoints(points1,points2,alpha)
|
266
272
|
|
267
273
|
# ドロネーの三角形(座標配列とpoints要素番号)を取得
|
268
|
-
# triangles, delaunay = face_delaunay.Face_delaunay(rect,points)
|
269
274
|
triangles, delaunay = Face_delaunay(rect,points1,points2,alpha)# <--修正
|
270
275
|
|
271
276
|
# モーフィング画像初期化
|
272
277
|
imgMorph = np.zeros(img1.shape, dtype = img1.dtype)
|
273
|
-
|
278
|
+
|
274
279
|
# ドロネー三角形の配列要素番号を読込
|
275
280
|
for (i, (x, y, z)) in enumerate(delaunay):
|
276
281
|
# ドロネー三角形のピクセル位置を取得
|
@@ -278,13 +283,12 @@
|
|
278
283
|
tri2 = [points2[x], points2[y], points2[z]]
|
279
284
|
tri = [points[x], points[y], points[z]]
|
280
285
|
|
281
|
-
|
286
|
+
# モーフィング画像を作成
|
282
|
-
# Face_morph(img1, img2, imgMorph, tri1, tri2, tri, alpha)
|
283
|
-
|
287
|
+
imgMorph= Face_morph(img1, img2, imgMorph, tri1, tri2, tri, alpha) #<--修正
|
284
|
-
|
288
|
+
|
285
289
|
# モーフィング画像をint型に変換し出力
|
286
290
|
imgMorph = np.uint8(imgMorph)
|
287
|
-
cv2.imwrite('output/
|
291
|
+
cv2.imwrite(path +'output/alpha_[%s]_picture-%s.jpg' % (str(cnt).zfill(2),str(cnt).zfill(3)),imgMorph) #<--修正
|
288
292
|
cv2.imshow("imgMorph",imgMorph) # <-- 追加
|
289
293
|
cv2.waitKey(10) # <-- 追加
|
290
294
|
|