PaddleHub人臉關鍵點檢測實現貓臉人嘴特效

前段時間,下班後閒來無事,參加了百度PaddleHub的AI人像摳圖創意賽,憑藉着你們的閱讀量,得到了一個第三名,得了一個小度音響,真香啊!python

對,說的是我

PaddleHub創意賽第二期又出來了,此次要作什麼呢? git

人臉檢測主題創意賽,愛搞事的我確定是少不了搞一波事情的,想一想這能玩出什麼花樣來?github

下班路上刷知乎,看見有人用dlib + 貓臉檢測器 + 泊松融合實現了抖音貓臉人嘴的特效,瞬間……
<center>算法


</center>網絡

程序主要結合PaddleHub的人臉關鍵點模型截取人嘴位置,opencv貓臉檢測器定位貓臉(沒找到貓臉關鍵點檢測模型)和opencv泊松融合函數實現圖像的融合,共三部分。less

1、人臉關鍵點檢測

PaddleHub關鍵點檢測模型face_landmark_localization,該模型轉換自 https://github.com/lsy17096535/face-landmark ,支持同一張圖中的多我的臉檢測。它能夠識別人臉中的68個關鍵點。ide

NOTE: 若是您在本地運行該項目示例,須要首先安裝PaddleHub。若是您在線運行,能夠去底部閱讀原文的百度AI Studio fork該項目。以後按照該示例操做便可。
函數

import cv2
import paddlehub as hub
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg
import numpy as np
import math
%matplotlib inline

src_img = cv2.imread('images/youngni2.jpg')

module = hub.Module(name="face_landmark_localization")
result = module.keypoint_detection(images=[src_img])

tmp_img = src_img.copy()
for face in result[0]['data']:
    for index, point in enumerate(face):
        # print(point)
        # cv2.putText(img, str(index), (int(point[0]), int(point[1])), cv2.FONT_HERSHEY_COMPLEX, 3, (0,0,255), -1)
        cv2.circle(tmp_img, (int(point[0]), int(point[1])), 2, (0, 0, 255), -1)

res_img_path = 'face_landmark.jpg'
cv2.imwrite(res_img_path, tmp_img)

img = mpimg.imread(res_img_path) 
# 展現預測68個關鍵點結果
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

人臉關鍵點檢測結果

2、貓臉檢測

貓臉檢測使用OpenCV自帶的貓臉檢測器(感受喵星人真的是要統治世界了😀),主要經過detectMultiScale函數對圖像金字塔進行多尺度檢測。ui

import cv2
import numpy as np

# 貓臉檢測器
cat_path = "haarcascade_frontalcatface_extended.xml"
facecascade = cv2.CascadeClassifier(cat_path)

cat = cv2.imread('cat3.jpg')

cat_gray = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
cat_face_loc = facecascade.detectMultiScale(cat_gray,scaleFactor = 1.1,minNeighbors=3,minSize=(100,100),flags=cv2.CASCADE_SCALE_IMAGE)
cat_face_loc = np.array(cat_face_loc[0])
# 貓嘴中心位置
center = (int(cat_face_loc[0] + cat_face_loc[2] / 2), int(cat_face_loc[1] + cat_face_loc[3]*0.8))

cv2.rectangle(cat, (cat_face_loc[0], cat_face_loc[1]), (cat_face_loc[0] + cat_face_loc[2], cat_face_loc[1] + cat_face_loc[3]), (0, 255, 0), 2, 8)
cv2.circle(cat, center, 2,  (0, 0, 255), 3)
cv2.imwrite('cat_face.jpg', cat)
cv2.imshow('result', cat)
cv2.waitKey(0)

貓臉檢測結果

3、泊松融合

泊松融合是2004年論文《Poisson Image Editing》提出的方法,已經集成在OpenCV中,函數名:seamlessClonespa

泊松融合是將一個源圖融合到目標圖像中,放置位置根據目標圖像中P點爲中心的一個前景mask大小範圍內。融合過程會改變源圖像中顏色以及梯度,實現無縫融合效果,具體算法能夠去看論文或者文末參考文獻。

論文截圖

話很少說,下面用代碼實現將人眼貼到手心上,人眼mask沒有很精準,效果通常,膽小勿看😂

import cv2
import numpy as np

hand = cv2.imread('hand.jpg')
eye = cv2.imread('eye.jpg')
h, w, c = eye.shape
mask = np.ones((h, w, c)) * 255

center = (hand.shape[1] // 2 + 50, hand.shape[0] // 2 + 250)
normal_clone = cv2.seamlessClone(eye, hand, mask.astype(eye.dtype), center, cv2.NORMAL_CLONE)
cv2.imwrite('res.jpg', normal_clone)
cv2.imshow('res', normal_clone)
cv2.waitKey(0)

綜合上面三部分,咱們能夠將人嘴定位並截取融合到貓臉嘴巴位置,因爲檢測視頻中貓臉會出現漏檢狀況,效果不是很好(找一隻不愛動的貓片實在太難了),因而我用了一張靜態的圖片進行替換,另外唱歌視頻也來自網絡。

import cv2
import numpy as np
import paddlehub as hub

# 人臉關鍵點檢測器
module = hub.Module(name="face_landmark_localization")
# 貓臉檢測器
cat_path = "data/model/haarcascade_frontalcatface_extended.xml"
facecascade = cv2.CascadeClassifier(cat_path)

cat = cv2.imread('data/images/cat3.jpg')
cat_gray = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
cat_face_loc = facecascade.detectMultiScale(cat_gray, scaleFactor=1.1, minNeighbors=3, minSize=(100, 100),
                                            flags=cv2.CASCADE_SCALE_IMAGE)
cat_face_loc = np.array(cat_face_loc[0])
# 貓嘴中心位置
center = (int(cat_face_loc[0] + cat_face_loc[2] / 2), int(cat_face_loc[1] + cat_face_loc[3] * 0.8))


def human_mouth_paste_to_cat(human_frame, cat_frame):
    result = module.keypoint_detection(images=[human_frame])
    landmarks = result[0]['data'][0]
    landmarks = np.array(landmarks, dtype=np.int)

    mouth_landmark = landmarks[48:, :]
    # 擴個邊
    border = 8
    mouth = human_frame[int(np.min(mouth_landmark[:, 1])) - border: int(np.max(mouth_landmark[:, 1]) + border),
            int(np.min(mouth_landmark[:, 0])) - border: int(np.max(mouth_landmark[:, 0])) + border, :]
    mouth_landmark[:, 0] -= (np.min(mouth_landmark[:, 0]) - border)
    mouth_landmark[:, 1] -= (np.min(mouth_landmark[:, 1]) - border)

    # 製做用於泊松融合的mask
    mask = np.zeros((mouth.shape[0], mouth.shape[1], 3)).astype(np.float32)
    for i in range(mouth_landmark.shape[0]):  # 先畫線
        cv2.line(mask, (mouth_landmark[i, 0], mouth_landmark[i, 1]), (
        mouth_landmark[(i + 1) % mouth_landmark.shape[0], 0], mouth_landmark[(i + 1) % mouth_landmark.shape[0], 1]),
                 (255, 255, 255), 10)
    mask_tmp = mask.copy()
    for i in range(6, mask.shape[0] - 6):  # 將線內部的範圍都算做mask=255
        for j in range(6, mask.shape[1] - 6):
            if (np.max(mask_tmp[:i, :j, :]) == 0 or np.max(mask_tmp[i:, :j, :]) == 0 or np.max(
                    mask_tmp[:i, j:, :]) == 0 or np.max(mask_tmp[i:, j:, :]) == 0):
                mask[i, j, :] = 0
            else:
                mask[i, j, :] = 255

    normal_clone = cv2.seamlessClone(mouth, cat_frame, mask.astype(mouth.dtype), center, cv2.NORMAL_CLONE)

    return normal_clone

# 合成視頻
human_video_cap = cv2.VideoCapture("data/video/human2.mp4")

fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
video_writer = cv2.VideoWriter('cat_with_humanmouth2.MP4', fourcc, 25, (1080, 2340))

index = 0
while True:
    index += 1
    human_ret, human_frame = human_video_cap.read()
    if human_ret:
        human_frame = cv2.resize(human_frame, dsize=None, fx=2, fy=2)
        cat_with_human_mouth = human_mouth_paste_to_cat(human_frame, cat)
        video_writer.write(cat_with_human_mouth.astype(np.uint8))
        # cv2.imwrite("frame/%d.jpg" % index, cat_with_human_mouth)
    else:
        break

video_writer.release()

輸出效果看文章最前面視頻,音頻是後來本身加上的。

視頻地址:PaddleHub人臉關鍵點模型實現貓臉人嘴

項目地址:PaddleHub人臉檢測:關鍵點檢測實現貓臉人嘴

參考:

  1. 貓臉人嘴特效
  2. Seamless cloning泊松克隆
  3. opencv貓臉檢測器
相關文章
相關標籤/搜索