昨天情人节,写了个表白的小代码,将女友照片进行缩放,自动贴到我照片眼球处,表达“我的眼里只有你”。
思路
Python可以直接调用dlib库进行人脸识别,其中也包含了准度较高的眼部识别。利用dlib面部识别库定位照片中眼球位置,将女友照片进行相应缩放,最终通过PIL将其贴图到眼球处。
dlib
dlib是一个高质量的机器学习、图像处理、深度学习、人脸识别 C++/Python库。Python中可以直接调用dlib库进行面部识别,其中也包含了准度较高的眼部识别,如下图:
通过37、38、40、41来确定左眼球位置,43、44、48、47来确定右眼球位置。获取点在照片中的坐标,计算距离来获取眼球区域信息。
裁剪处理眼球中贴图
因为眼球的形状,贴图最好处理成略小于眼球的圆形图,所以代码中先将女友照片缩小成眼球区域大小的矩形图,再进行边缘透明处理和裁剪生成。
def img_deal(input_img):
img = cv2.imread(input_img, cv2.IMREAD_UNCHANGED)
rows, cols, channel = img.shape
img_new = np.zeros((rows, cols, 4), np.uint8)
img_new[:, :, 0:3] = img[:, :, 0:3]
img_circle = np.zeros((rows, cols, 1), np.uint8)
img_circle[:, :, :] = 0
img_circle = cv2.circle(img_circle, (int(cols / 2), int(rows / 2)), int(min(rows, cols) / 2), 255, -1)
img_new[:, :, 3] = img_circle[:, :, 0]
cv2.imwrite('src_circle.png', img_new)
将女友照片缩放成小于该区域的图片,通过PIL将其贴到眼球位置上。
回顾
你可能会说,这很简单啊,PS一下就搞定,比你这还好看。
是的,有点杀鸡用牛刀的鸡肋感。但代码的好处是,设计好的程序高效地自动执行,我就可以专注于提升操作步骤之外的事情了。对于批量化生成图片也是很方便的。此外,除了图片,还可以通过摄像头在视频中进行操作。
- 完整代码
# -*- coding:utf-8 -*-
import cv2,dlib
import numpy as np
from PIL import Image
"""
Python眼部识别参考链接:https://pysource.com/2019/01/07/eye-detection-gaze-controlled-keyboard-with-python-and-opencv-p-1/
"""
def img_deal(input_img):
img = cv2.imread(input_img, cv2.IMREAD_UNCHANGED)
rows, cols, channel = img.shape
img_new = np.zeros((rows, cols, 4), np.uint8)
img_new[:, :, 0:3] = img[:, :, 0:3]
img_circle = np.zeros((rows, cols, 1), np.uint8)
img_circle[:, :, :] = 0
img_circle = cv2.circle(img_circle, (int(cols / 2), int(rows / 2)), int(min(rows, cols) / 2), 255, -1)
img_new[:, :, 3] = img_circle[:, :, 0]
cv2.imwrite('./img/src_circle.png', img_new)
#背景图片
bg = 'haoran.jpg'
img = cv2.imread(bg)
#眼睛内容图片
src_img = "qianxi.jpg"
src = cv2.imread(src_img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
faces = detector(gray)
for face in faces:
landmarks = predictor(gray, face)
areaX1 = max(landmarks.part(37).x, landmarks.part(41).x)
areaX2 = min(landmarks.part(38).x, landmarks.part(40).x)
areaY1 = max(landmarks.part(37).y, landmarks.part(38).y)
areaY2 = min(landmarks.part(41).y, landmarks.part(40).y)
r = int(min(areaX2-areaX1,areaY2-areaY1)/2)
d=2*r
midx = int((areaX1 + areaX2)/2)
midy = int((areaY1 + areaY2)/2)
left = cv2.resize(src, (d, d), interpolation=cv2.INTER_AREA)
cv2.imwrite("./img/left_eye.png", left)
img_deal("./img/left_eye.png")
im = Image.open(bg)
eye = Image.open("./img/src_circle.png")
im.paste(eye,(midx-r,midy-r),eye)
#im.save("temp.png")
area2X1 = max(landmarks.part(43).x,landmarks.part(47).x)
area2X2 = min(landmarks.part(44).x,landmarks.part(46).x)
area2Y1 = max(landmarks.part(43).y,landmarks.part(44).y)
area2Y2 = min(landmarks.part(47).y,landmarks.part(46).y)
r2 = int(min(area2X2-area2X1,area2Y2-area2Y1)/2)
d2=2*r2
midx2 = int((area2X1 + area2X2)/2)
midy2 = int((area2Y1 + area2Y2)/2)
right = cv2.resize(src, (d2, d2), interpolation=cv2.INTER_AREA)
cv2.imwrite("./img/right_eye.png", right)
img_deal("./img/right_eye.png")
#im = Image.open('temp.png')
eye = Image.open("./img/src_circle.png")
im.paste(eye,(midx2-r2,midy2-r2),eye)
im.save("./img/result.png")
Python眼部识别参考链接:https://pysource.com/2019/01/07/eye-detection-gaze-controlled-keyboard-with-python-and-opencv-p-1/
参考:https://zhuanlan.zhihu.com/p/56769993
https://github.com/pengfexue2/Eye