下载地址:https://www.pan38.com/dow/share.php?code=JCnzE 提取密码:1133
这些代码实现了一个完整的人脸识别系统,包含眨眼检测、人脸替换和活体验证功能。您需要下载dlib的预训练模型shape_predictor_68_face_landmarks.dat才能运行。
import cv2
import dlib
import numpy as np
from scipy.spatial import distance as dist
class BlinkDetector:
def __init__(self):
self.detector = dlib.get_frontal_face_detector()
self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
self.EYE_AR_THRESH = 0.25
self.EYE_AR_CONSEC_FRAMES = 3
self.COUNTER = 0
self.TOTAL = 0
def eye_aspect_ratio(self, eye):
# 计算两组垂直方向上的欧氏距离
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
# 计算水平方向上的欧氏距离
C = dist.euclidean(eye[0], eye[3])
# 计算眼睛纵横比
ear = (A + B) / (2.0 * C)
return ear
def detect_blinks(self, frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
rects = self.detector(gray, 0)
for rect in rects:
shape = self.predictor(gray, rect)
shape = np.array([(shape.part(i).x, shape.part(i).y) for i in range(68)])
left_eye = shape[42:48]
right_eye = shape[36:42]
left_ear = self.eye_aspect_ratio(left_eye)
right_ear = self.eye_aspect_ratio(right_eye)
ear = (left_ear + right_ear) / 2.0
left_eye_hull = cv2.convexHull(left_eye)
right_eye_hull = cv2.convexHull(right_eye)
cv2.drawContours(frame, [left_eye_hull], -1, (0, 255, 0), 1)
cv2.drawContours(frame, [right_eye_hull], -1, (0, 255, 0), 1)
if ear < self.EYE_AR_THRESH:
self.COUNTER += 1
else:
if self.COUNTER >= self.EYE_AR_CONSEC_FRAMES:
self.TOTAL += 1
self.COUNTER = 0
cv2.putText(frame, "Blinks: {}".format(self.TOTAL), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
return frame
def main():
detector = BlinkDetector()
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
frame = detector.detect_blinks(frame)
cv2.imshow("Blink Detection", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
import cv2
import dlib
import numpy as np
from PIL import Image
class FaceSwapper:
def __init__(self):
self.detector = dlib.get_frontal_face_detector()
self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
def get_landmarks(self, image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
rects = self.detector(gray, 1)
if len(rects) == 0:
return None
shape = self.predictor(gray, rects[0])
landmarks = np.array([[p.x, p.y] for p in shape.parts()])
return landmarks
def create_blinking_effect(self, image, landmarks, blink_ratio=0.5):
# 获取眼睛区域
left_eye = landmarks[36:42]
right_eye = landmarks[42:48]
# 计算眼睛中心
left_eye_center = np.mean(left_eye, axis=0).astype(int)
right_eye_center = np.mean(right_eye, axis=0).astype(int)
# 创建眨眼效果
mask = np.ones_like(image) * 255
for y in range(left_eye_center[1]-5, left_eye_center[1]+5):
for x in range(left_eye[0][0], left_eye[3][0]):
if (y - left_eye_center[1])**2 / (5**2) + (x - left_eye_center[0])**2 / (10**2) <= 1:
mask[y,x] = image[y,x]
for y in range(right_eye_center[1]-5, right_eye_center[1]+5):
for x in range(right_eye[0][0], right_eye[3][0]):
if (y - right_eye_center[1])**2 / (5**2) + (x - right_eye_center[0])**2 / (10**2) <= 1:
mask[y,x] = image[y,x]
# 混合原始图像和眨眼效果
result = cv2.addWeighted(image, 1-blink_ratio, mask, blink_ratio, 0)
return result
def swap_faces(self, src_image, dst_image):
src_landmarks = self.get_landmarks(src_image)
dst_landmarks = self.get_landmarks(dst_image)
if src_landmarks is None or dst_landmarks is None:
return dst_image
# 创建凸包
hull_index = list(range(17)) + list(range(17, 27))[::-1]
hull = cv2.convexHull(src_landmarks[hull_index], False)
# 计算Delaunay三角剖分
rect = (0, 0, dst_image.shape[1], dst_image.shape[0])
subdiv = cv2.Subdiv2D(rect)
for p in dst_landmarks[hull_index]:
subdiv.insert((int(p[0]), int(p[1])))
triangles = subdiv.getTriangleList()
triangles = np.array(triangles, dtype=np.int32)
# 实现人脸交换
warped_image = np.copy(dst_image)
for t in triangles:
src_tri = []
dst_tri = []
for i in range(3):
src_tri.append(src_landmarks[hull_index][np.where(
(dst_landmarks[hull_index][:,0] == t[i*2]) &
(dst_landmarks[hull_index][:,1] == t[i*2+1]))[0][0]])
dst_tri.append([t[i*2], t[i*2+1]])
self.warp_triangle(src_image, warped_image, np.float32(src_tri), np.float32(dst_tri))
# 创建无缝克隆
mask = np.zeros(dst_image.shape, dtype=dst_image.dtype)
cv2.fillConvexPoly(mask, np.int32(hull), (255, 255, 255))
r = cv2.boundingRect(np.float32([hull]))
center = ((r[0]+r[2]//2, r[1]+r[3]//2))
output = cv2.seamlessClone(warped_image, dst_image, mask, center, cv2.NORMAL_CLONE)
return output
def warp_triangle(self, src_img, dst_img, src_tri, dst_tri):
# 计算仿射变换
warp_mat = cv2.getAffineTransform(src_tri, dst_tri)
# 应用变换
warped = cv2.warpAffine(src_img, warp_mat, (dst_img.shape[1], dst_img.shape[0]), None,
flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT_101)
# 创建mask
mask = np.zeros((dst_img.shape[0], dst_img.shape[1], 3), dtype=np.float32)
cv2.fillConvexPoly(mask, np.int32(dst_tri), (1.0, 1.0, 1.0), 16, 0)
# 混合图像
dst_img = dst_img * (1 - mask) + warped * mask
def main():
swapper = FaceSwapper()
# 加载图像
src_img = cv2.imread("source.jpg")
dst_img = cv2.imread("target.jpg")
# 人脸交换
swapped = swapper.swap_faces(src_img, dst_img)
# 添加眨眼效果
landmarks = swapper.get_landmarks(swapped)
if landmarks is not None:
blinked = swapper.create_blinking_effect(swapped, landmarks, 0.7)
cv2.imwrite("result.jpg", blinked)
else:
cv2.imwrite("result.jpg", swapped)
if __name__ == "__main__":
main()
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。