人脸识别总感觉特别高深,但是因为Python中已经有很多前辈写好了一些库,可以直接调用,大大降低了人脸识别的难度。
之前在网上看到陈晓眼里只有陈妍希的照片,特别喜欢,想自己用python中的dlib人脸识别库实现这个功能。
所以到网上找了下资料,成功用python实现了这个功能,现在把实现方法分享给大家。
一、我的眼里只有你效果图
可以把图片放大,看下效果。
1 亲爱的热爱的—佟年眼里的韩商言
2 余生请多指教—顾魏眼里的林之校
二、安装并导入库
首先,要在电脑中安装相关的库。
代码语言:javascript复制import cv2
import numpy as np
from PIL import Image
import os
import dlib
这些库除了dlib库,安装都比较顺利。只有安装dlib库时踩了很多坑,折腾了比较久。
建议直接下载whl文件,并用pip install dlib-19.17.99-cp37-cp37m-win_amd64.whl安装dlib库。
注意:要根据你自己的python版本下载对应版本的whl,我的是python3.7,windows64位所以我下载的是cp37,amd64版本的whl。
具体步骤如下:
step1: 下载whl文件
step2:在下载好whl文件的目录下打开cmd,并pip install xxx.whl,这个xxx就是你电脑对应版本的whl文件。
step3:在python中import dlib即可。
三、标记人脸中68个点的位置
我用一张肖战的硬照,标记五官中68个点的位置,方便大家找到眼睛的位置。
根据点的位置和计算好的眼球大小,把一个人的照片填充到另一个人的眼睛中去,营造我的眼里只有你的效果。
代码语言:javascript复制os.chdir(r"F:微信公众号Python33.我的眼里只有你眼里都是你")
bg = '肖战.jpg' #背景图片
img = cv2.imdecode(np.fromfile(bg,dtype=np.uint8),-1)
detector = dlib.get_frontal_face_detector() #用它来检测人脸,返回图中人脸的个数和坐标位置:
faces = detector(img,1)
points = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
if (len(faces) > 0):
for k,d in enumerate(faces):
print(k,d)
cv2.rectangle(img,(d.left(),d.top()),(d.right(),d.bottom()),(255,0,0))
pts = points(img,d)
for i in range(68):
cv2.circle(img, (pts.part(i).x,pts.part(i).y),3,(0,255,0), -1, 3)
cv2.putText(img,str(i),(pts.part(i).x,pts.part(i).y), cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,255))
cv2.imwrite('xiaozhan_68point.png', img)
运行以上程序,可得到如下结果:
从上图知,用68个点标记的五官,左眼球位置对应的数字是:37、38、40、41,右眼球位置对应的数字是43、44、46、47。
只要把另一个人的照片缩小,放到眼球对应的位置里去,就可以营造出本文想要的效果啦。
四、把图片的背景颜色设置成眼球的颜色
有时候图片的背景颜色不一定和眼球颜色的一致,我们可以用如下代码从图像中裁剪出人,并自定义背景颜色。
代码语言:javascript复制from removebg import RemoveBg
from PIL import Image
#把图片背景设置成眼球的颜色
def Change_img_bg(old_img, bg_color):
rmbg = RemoveBg("UQ7x2hmLXxv8XXXXXXXXX###", "error.log") # 引号内是你获取的API
rmbg.remove_background_from_img_file(old_img) #图片地址
old_no_bg = old_img '_no_bg.png'
im = Image.open(old_no_bg)
x, y = im.size
# 填充背景
p = Image.new('RGBA', im.size, bg_color)
p.paste(im, (0, 0, x, y), im)
# 保存填充后的图片
p.save("new_black_pg_img.png")
如需函数中的API,请参考文末参考文献中的第一篇文章。
五、把放入眼睛的图片处理成圆形
一般我们见到的图片都是方形的,而眼球的形状是圆形的,故要把方形照片处理成眼球的形状。
代码语言:javascript复制#把图片裁剪成圆形
def img_deal(ori_img):
img = cv2.imread(ori_img, cv2.IMREAD_UNCHANGED)
h, w, channel = img.shape
img_deal = np.zeros((h, w, 4), np.uint8)
img_deal[:, :, 0:3] = img[:, :, 0:3]
img_circle = np.zeros((h, w, 1), np.uint8)
img_circle[:, :, :] = 0
center = (int(w / 2), int(h / 2))
radius = int(min(h, w) / 2)
img_circle = cv2.circle(img_circle,center ,radius , 255, -1)
img_deal[:, :, 3] = img_circle[:, :, 0]
cv2.imwrite('eye_circle.png', img_deal)
六、把处理好的图片贴到眼球中
找到眼球的位置,并把处理好的图片贴到眼球中。
代码语言:javascript复制for face in faces:
face_68point = predictor(gray, face)
#获取左眼球位置信息
left_eye_x1 = min(face_68point.part(37).x, face_68point.part(41).x)
left_eye_x2 = min(face_68point.part(38).x, face_68point.part(40).x)
left_eye_y1 = min(face_68point.part(37).y, face_68point.part(48).y)
left_eye_y2 = min(face_68point.part(40).y, face_68point.part(41).y)
left_eye_midx = int((left_eye_x1 left_eye_x2)/2)
left_eye_midy = int((left_eye_y1 left_eye_y2)/2)
#获取右眼球位置信息
right_eye_x1 = min(face_68point.part(43).x, face_68point.part(47).x)
right_eye_x2 = min(face_68point.part(44).x, face_68point.part(46).x)
right_eye_y1 = min(face_68point.part(43).y, face_68point.part(44).y)
right_eye_y2 = min(face_68point.part(47).y, face_68point.part(46).y)
right_eye_midx = int((right_eye_x1 right_eye_x2)/2)
right_eye_midy = int((right_eye_y1 right_eye_y2)/2)
#左眼球大小
left_eye_r = abs(int(min(left_eye_x1-left_eye_x2,left_eye_y1-left_eye_y2)/2))
left_eye_d = left_eye_r*2
#右眼球大小
right_eye_r = abs(int(min(right_eye_x1-right_eye_x2,right_eye_y1-right_eye_y2)/2))
right_eye_d = right_eye_r*2
#设置眼球中图片直径
eye_img_d = min(int(left_eye_d/1.2),int(right_eye_d/1.2))
#把图像贴到左眼
left_ori = cv2.resize(src_img, (eye_img_d, eye_img_d), interpolation=cv2.INTER_AREA)
cv2.imwrite("left_eye.png", left_ori)
img_deal("left_eye.png")
left_eye = Image.open("eye_circle.png")
im = Image.open(back_graph)
im.paste(left_eye,(left_eye_midx-int(eye_img_d/3), left_eye_midy-int(eye_img_d/2)),left_eye)
#把图像贴到右眼
right_ori = cv2.resize(src_img, (eye_img_d, eye_img_d), interpolation=cv2.INTER_AREA)
cv2.imwrite("right_eye.png", right_ori)
img_deal("right_eye.png")
right_eye = Image.open("eye_circle.png")
im.paste(right_eye,(right_eye_midx-int(eye_img_d/3),right_eye_midy-int(eye_img_d/2)),right_eye)
#保存最终图形
im.save("you_in_my_eye.png")
至此,我的眼里只有你代码全部讲解完啦
参考文献:
代码语言:javascript复制1. https://blog.csdn.net/qq_42374697/article/details/106202744
2. https://www.cnblogs.com/darkknightzh/p/6117528.html
3. https://blog.csdn.net/weixin_40632944/article/details/81.698508?utm_medium=distributepc_relevant.none-task-blog-baidujs-1