攝像頭實時換臉,上網課老師都不認識我了,哈哈
# -*- coding: utf-8 -*-
import cv2
import dlib
import numpy as np
detector = dlib.get_frontal_face_detector() # dlib 的正向人臉檢測器
predictor = dlib.shape_predictor(r'shape_predictor_68_face_landmarks.dat') # dlib 的人臉形狀檢測器
def get_image_size(image):
"""
獲取圖片大小(高度 , 寬度)
:param image: image
:return: (高度 , 寬度)
"""
image_size = (image.shape[0], image.shape[1])
return image_size
def get_face_landmarks(image, face_detector, shape_predictor):
"""
獲取人臉標誌, 68 個特徵點
:param image: image
:param face_detector: dlib.get_frontal_face_detector
:param shape_predictor: dlib.shape_predictor
:return: np.array([[],[]]), 68 個特徵點
"""
dets = face_detector(image, 1)
shape = shape_predictor(image, dets[0])
face_landmarks = np.array([[p.x, p.y] for p in shape.parts()])
return face_landmarks
def get_face_mask(image_size, face_landmarks):
"""
獲取人臉掩模
:param image_size: 圖片大小
:param face_landmarks: 68 個特徵點
:return: image_mask, 掩模圖片
"""
mask = np.zeros(image_size, dtype=np.uint8)
points = np.concatenate([face_landmarks[0:16], face_landmarks[26:17:-1]])
cv2.fillPoly(img=mask, pts=[points], color=255)
return mask
def get_affine_image(image1, image2, face_landmarks1, face_landmarks2):
"""
獲取圖片 1 仿射變換後的圖片
:param image1: 圖片 1, 要進行仿射變換的圖片
:param image2: 圖片 2, 外匯跟單gendan5.com 只要用來獲取圖片大小,生成與之大小相同的仿射變換圖片
:param face_landmarks1: 圖片 1 的人臉特徵點
:param face_landmarks2: 圖片 2 的人臉特徵點
:return: 仿射變換後的圖片
"""
three_points_index = [18, 8, 25]
M = cv2.getAffineTransform(face_landmarks1[three_points_index].astype(np.float32),
face_landmarks2[three_points_index].astype(np.float32))
dsize = (image2.shape[1], image2.shape[0])
affine_image = cv2.warpAffine(image1, M, dsize)
return affine_image.astype(np.uint8)
def get_mask_center_point(image_mask):
"""
獲取掩模的中心點座標
:param image_mask: 掩模圖片
:return: 掩模中心
"""
image_mask_index = np.argwhere(image_mask > 0)
miny, minx = np.min(image_mask_index, axis=0)
maxy, maxx = np.max(image_mask_index, axis=0)
center_point = ((maxx + minx) // 2, (maxy + miny) // 2)
return center_point
def get_mask_union(mask1, mask2):
"""
獲取兩個掩模掩蓋部分的並集
:param mask1: mask_image, 掩模 1
:param mask2: mask_image, 掩模 2
:return: 兩個掩模掩蓋部分的並集
"""
mask = np.min([mask1, mask2], axis=0) # 掩蓋部分並集
mask = ((cv2.blur(mask, (5, 5)) == 255) * 255).astype(np.uint8) # 縮小掩模大小
mask = cv2.blur(mask, (3, 3)).astype(np.uint8) # 模糊掩模
return mask
def skin_color_adjustment(im1, im2, mask=None):
"""
膚色調整
:param im1: 圖片 1
:param im2: 圖片 2
:param mask: 人臉 mask. 如果存在,使用人臉部分均值來求膚色變換系數;否則,使用高斯模糊來求膚色變換系數
:return: 根據圖片 2 的顏色調整的圖片 1
"""
if mask is None:
im1_ksize = 55
im2_ksize = 55
im1_factor = cv2.GaussianBlur(im1, (im1_ksize, im1_ksize), 0).astype(np.float)
im2_factor = cv2.GaussianBlur(im2, (im2_ksize, im2_ksize), 0).astype(np.float)
else:
im1_face_image = cv2.bitwise_and(im1, im1, mask=mask)
im2_face_image = cv2.bitwise_and(im2, im2, mask=mask)
im1_factor = np.mean(im1_face_image, axis=(0, 1))
im2_factor = np.mean(im2_face_image, axis=(0, 1))
im1 = np.clip((im1.astype(np.float) * im2_factor / np.clip(im1_factor, 1e-6, None)), 0, 255).astype(np.uint8)
return im1
def main():
im1 = cv2.imread('1.png') # face_image
im1 = cv2.resize(im1, (600, im1.shape[0] * 600 // im1.shape[1]))
landmarks1 = get_face_landmarks(im1, detector, predictor) # 68_face_landmarks
if landmarks1 is None:
print('{}: 檢測不到人臉 '.format(image_face_path))
exit(1)
im1_size = get_image_size(im1) # 臉圖大小
im1_mask = get_face_mask(im1_size, landmarks1) # 臉圖人臉掩模
cam = cv2.VideoCapture(0)
while True:
ret_val, im2 = cam.read() # camera_image
landmarks2 = get_face_landmarks(im2, detector, predictor) # 68_face_landmarks
if landmarks2 is not None:
im2_size = get_image_size(im2) # 攝像頭圖片大小
im2_mask = get_face_mask(im2_size, landmarks2) # 攝像頭圖片人臉掩模
affine_im1 = get_affine_image(im1, im2, landmarks1, landmarks2) # im1 (臉圖)仿射變換後的圖片
affine_im1_mask = get_affine_image(im1_mask, im2, landmarks1, landmarks2) # im1 (臉圖)仿射變換後的圖片的人臉掩模
union_mask = get_mask_union(im2_mask, affine_im1_mask) # 掩模合併
affine_im1 = skin_color_adjustment(affine_im1, im2, mask=union_mask) # 膚色調整
point = get_mask_center_point(affine_im1_mask) # im1 (臉圖)仿射變換後的圖片的人臉掩模的中心點
seamless_im = cv2.seamlessClone(affine_im1, im2, mask=union_mask, p=point, flags=cv2.NORMAL_CLONE) # 進行泊松融合
cv2.imshow('seamless_im', seamless_im)
else:
cv2.imshow('seamless_im', im2)
if cv2.waitKey(1) == 27: # 按 Esc 退出
break
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2872576/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 超模臉、網紅臉、萌娃臉...換頭像不重樣?我開源了5款人臉生成器
- 專訪模組廠商:人臉識別中單攝像頭和雙攝像頭該如何選型
- 海康威視攝像頭-chrome谷歌瀏覽器高版本區域網下海康攝像頭web網頁實時播放Chrome谷歌瀏覽器Web網頁
- 滑坡監測識別攝像頭
- HSmartWindowControl 之 攝像頭實時顯示( 使用 WPF )
- 上著課呢,老師臉皮突然被「掀起來」了,DeepFake這次搞笑了
- 純前端如何在網頁端播放攝像頭的實時畫面前端網頁
- iphone 4 攝像頭是前後切換iPhone
- shodan秒破網路攝像頭
- Maui Blazor 使用攝像頭實現UIBlazor
- 溺水識別攝像頭防溺水系統
- 1000個網路攝像頭如何組網?
- AndroidCamera2拍照(三)——切換攝像頭,延時拍攝和閃光模式Android模式
- 【音影片】攝像頭
- 攝像頭操作指南
- uniapp H5人臉採集帶前後攝像頭APPH5
- ToDesk勾上攝像頭會看到我嗎?如何關閉攝像頭
- AI安全帽監測識別攝像頭AI
- vue如何實時展示海康威視攝像頭多畫面?Vue
- 我的慕課實戰課程上線了
- .NET 攝像頭採集
- android opencv 前置攝像頭AndroidOpenCV
- android 開啟攝像頭Android
- Android呼叫攝像頭拍照Android
- 基於人工智慧的摔倒識別攝像頭人工智慧
- Camera開發系列之一 顯示攝像頭實時畫面
- Win10攝像頭如何開啟_WIN10攝像頭在哪裡Win10
- 搭建一個攝像頭應用程式 應用程式內部攝像頭
- 樹莓派上安裝USB網路攝像頭樹莓派
- UVC 攝像頭在 RK3399 上的應用
- YouGov:4/10的英國PC使用者遮蔽了網路攝像頭Go
- WPF呼叫攝像頭,對圖片相似度識別 1.0
- 何時能不被黑客魚肉?D-Link 智慧攝像頭又出事了黑客
- 大華攝像頭 ZLMediaKit JavaJava
- WebRTC開啟本地攝像頭Web
- 如何使用PYTHON操作攝像頭Python
- Android提供的攝像頭拍照Android
- 某CCTV攝像頭漏洞分析