隨着人臉檢測技術的不斷成熟,人臉特效也逐漸進入我們的生活中,各個美顏相機軟件,p圖軟件都能夠檢測到人臉,添加人臉特效。最近嘗試着做了一下,一種比較簡單的人臉特效,利用貼圖來實現的。
這是效果圖
思維導圖
下面根據思維導圖 講解具體的實現方法
完整代碼鏈接
製作貼圖
這個可以根據自己的需求使用ps製作,或者網上下載。
網上下載的有些貼圖,因爲有背景顏色,或則其他原因,無法獲取到想要的那部分。
比如會這樣 貼圖處理後 添加後
下面講解使用PIL消除掉背景色的具體實現方法。
利用到Alpha通道
一個圖像的每個像素都有 RGB 三個通道,後來 Alvy Ray Smith 提出每個像素再增加一個 Alpha 通道,取值爲0到1,用來儲存這個像素是否對圖片有「貢獻」,0代表透明、1代表不透明。也就是說,「Alpha 通道」儲存一個值,其外在表現是「透明度」。
把圖像中特定顏色的A值轉換爲0,就可以把背景色消除掉,應用到下一步
# #--------- This function clears the specified color to be empty
from PIL import Image
img = Image.open('maozi-1.png')
img = img.convert("RGBA") #代表Red(紅色) Green(綠色) Blue(藍色)和 Alpha的色彩空間
datas = img.getdata()
newData = []
for item in datas:
if item[0] == 0 and item[1] == 0 and item[2] == 0: #背景色爲黑色 的像素點
newData.append((0, 0, 0, 0)) # 把A值設置爲0
else:
newData.append(item)
img.putdata(newData)
img.save("img2.png", "PNG") # 保存下來
人臉檢測獲取到關鍵點
我使用到的是face_recognition 感覺效果還可以,當然也可以使用face++的效果會更好些,這裏不再介紹其他使用方法,想要研究的可以到我博客中其他文章找其他模塊獲取人臉關鍵點的方法。
image = face_recognition.load_image_file("../face_photos/yiqi.jpg")
face_landmarks_list = face_recognition.face_landmarks(image) #人臉關鍵點信息
facial_features = [
'chin', # 下巴
'left_eyebrow', # 左眉毛
'right_eyebrow', # 右眉毛
'nose_bridge', # 鼻樑
'nose_tip', # 鼻尖
'left_eye', # 左眼
'right_eye', # 右眼
'top_lip', # 上嘴脣
'bottom_lip' # 下嘴脣
] #這些參數都在face_landmarks_list 中可以找到
計算人臉傾斜角度
通過鼻樑來計算人臉傾斜角度應該算是一種比較簡單的方法,也是相對比較準確的。
但是鼻樑上的關鍵點連一塊不一定是一條直線,這裏需要用一下擬合的方法,把上面的所有關鍵點擬合成一條直線。
使用scipy中的optimize.curve_fit 來擬合直線,並計算出斜率和截距
for nose in face_landmarks['nose_bridge']:
nose_x.append(nose[0])
nose_y.append(nose[1])
A1, B1 = optimize.curve_fit(f_1, nose_x, nose_y)[0] #擬合出鼻樑所在的直線 A1爲斜率 B1爲截距
其中裏面的參數f_1 需要寫一下
def f_1(x, A, B):
return A*x + B
獲取到了斜率就可以通過斜率來計算傾斜角度
利用math.atan() 函數先計算弧度 再用公式計算角度
radian = atan(A1) # 利用反三角函數 計算出角度的弧度制
angele = radian*180/(3.14) # 計算出角度
改變貼圖的尺寸和傾斜度
貼圖的大小一定要跟人臉大小相匹配,所以貼圖的大小是由人臉的大小來決定的。
貼圖的長/人臉的長 = 貼圖的寬/人臉的寬
map_setsize_h = int(map_h/map_w)*face_w
map_set = map.resize((face_w,map_setsize_h)) #設定logo大小 寬, 高
人臉傾斜,貼圖當然也要跟着傾斜。
map_set = map_set.rotate(angele,expand = 1)
其中的參數 expend需要設置,如果不設置默認爲false ,圖片旋轉會按照原尺寸大小,會有損失,而設置爲True則圖片會隨着旋轉而改變尺寸大小。
expend爲False時,旋轉圖片就會這樣損失一部分,按照原尺寸變化。
expend=True的時候,圖片旋轉,尺寸會隨之發生變化
計算貼圖位置
這個要根據不同的貼圖要計算,不過大致思路是一樣的 。
下面以製作帽子貼圖爲例。
因爲關鍵點沒有額頭和髮際線初,所以需要計算,根據人臉比例,人臉橫着分可分爲三部分,
這樣從眉毛的中心位置和下巴的最低點可以計算出額頭的豎直高度。
獲得數值高度後,通過之前鼻樑擬合出的那條線,就可以計算出髮際正中間的點的座標。
(簡單畫的一個圖,不是很準確)
線1那條線是 根據計算得出的髮際線的數值位置 線2就是鼻樑擬合出的那條線。
兩條線相交的位置就是髮際的中心點,也就是點3.
獲取到的這個點也是貼圖旋轉後logo的斜着的中心點
上面圖中 紅色虛線是旋轉後貼圖的圖片,根據中心點位置 利用初中學的幾何知識就可以求出紅色虛線左上角點的位置。
把貼圖放到相應的位置
使用PIL庫中paste函數實現圖片的疊加。 其中mask參數要寫上,不然貼圖的背景還是會顯示出來。
pil_image.paste(map_set,(map_setx,map_sety),mask= map_set) #mask 能夠去掉掩碼
over
到這步利用貼圖實現的人臉特效就完成了! (原創)
代碼鏈接 https://github.com/niehen6174/face_detection_and_recognition/tree/master/%E4%BA%BA%E8%84%B8%E7%89%B9%E6%95%88
人臉識別模塊學習
http://niehen.cn/category/face-reco/
歡迎加入人工智能-人臉識別 技術交流羣 894243022
點擊下面圖片即可加羣
該文章有使用鏈接,如有侵權還請見諒。使用本文章或代碼還請聲明。
參考 https://github.com/niehen6174/faceai/blob/master/faceai/compose.py