??不論是對(duì)face進(jìn)行morph,還是swap,Delaunay Triangulation都是一個(gè)重要基礎(chǔ)角溃。其道理是廓俭,替換、變形等說(shuō)到底是重新繪制盔腔,即將source的某部分經(jīng)過(guò)變形繪制到target上來(lái)。就人臉來(lái)說(shuō),當(dāng)然不能整個(gè)的復(fù)制過(guò)來(lái)辜伟,那樣會(huì)造成圖像的扭曲和失真氓侧。 Delaunay Triangulation就對(duì)人臉進(jìn)行了切分,切分后形成了一個(gè)個(gè)對(duì)應(yīng)的無(wú)重疊的三角區(qū)域导狡,然后在每對(duì)之間基于仿射變換去做一些有趣的事情约巷。
-
什么是Delaunay Triangulation?
??給定一個(gè)平面和其上的若干點(diǎn)旱捧,通過(guò)某種形式地連接點(diǎn)独郎,把平面切分成若干三角形,使得任一點(diǎn)都不在某個(gè)三角形的內(nèi)部枚赡。該算法不傾向于產(chǎn)生“瘦小”的三角形氓癌。
WX20190115-144015.png -
結(jié)合facial landmark的Delaunay Triangulation
??將人臉上68個(gè)landmark標(biāo)好后,基于這些點(diǎn)進(jìn)行Delaunay Triangulation贫橙,就能將人臉?lè)指铋_(kāi)贪婉,便于之后在對(duì)應(yīng)三角形間進(jìn)行仿射變換。
delaunay.png - demo
def draw_delaunay(img, subdiv, delaunay_color ) :
triangleList = subdiv.getTriangleList(); #do Delaunay Triangulation
size = img.shape
r = (0, 0, size[1], size[0])
for t in triangleList :
pt1 = (t[0], t[1])
pt2 = (t[2], t[3])
pt3 = (t[4], t[5])
if rect_contains(r, pt1) and rect_contains(r, pt2) and rect_contains(r, pt3) :
cv2.line(img, pt1, pt2, delaunay_color, 1, cv2.LINE_AA, 0)
cv2.line(img, pt2, pt3, delaunay_color, 1, cv2.LINE_AA, 0)
cv2.line(img, pt3, pt1, delaunay_color, 1, cv2.LINE_AA, 0)
img = cv2.imread("obama.jpg");
size = img.shape
rect = (0, 0, size[1], size[0])
subdiv = cv2.Subdiv2D(rect);
keypoints =[(a[0], a[1]) for a in utils.get_facial_landmarks(img)]
for p in keypoints:
subdiv.insert(p)
draw_delaunay(img, subdiv, (255, 255, 255))