人脸识别总感觉特别高深,但是因为Python中已经有很多前辈写好了一些库,可以直接调用,大大降低了人脸识别的难度。
之前在网上看到陈晓眼里只有陈妍希的照片,特别喜欢,想自己用python中的dlib人脸识别库实现这个功能。
所以到网上找了下资料,成功用python实现了这个功能,现在把实现方法分享给大家。
一、我的眼里只有你效果图
可以把图片放大,看下效果。
1 亲爱的热爱的—佟年眼里的韩商言
2 余生请多指教—顾魏眼里的林之校
二、安装并导入库
首先,要在电脑中安装相关的库。
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个点的位置,方便大家找到眼睛的位置。
根据点的位置和计算好的眼球大小,把一个人的照片填充到另一个人的眼睛中去,营造我的眼里只有你的效果。
os.chdir(r"F:\微信公众号\Python\33.我的眼里只有你\眼里都是你") 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。
只要把另一个人的照片缩小,放到眼球对应的位置里去,就可以营造出本文想要的效果啦。
四、把图片的背景颜色设置成眼球的颜色
有时候图片的背景颜色不一定和眼球颜色的一致,我们可以用如下代码从图像中裁剪出人,并自定义背景颜色。
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,请参考文末参考文献中的第一篇文章。
五、把放入眼睛的图片处理成圆形
一般我们见到的图片都是方形的,而眼球的形状是圆形的,故要把方形照片处理成眼球的形状。
#把图片裁剪成圆形 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)
六、把处理好的图片贴到眼球中
找到眼球的位置,并把处理好的图片贴到眼球中。
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")
至此,我的眼里只有你代码全部讲解完啦
参考文献:
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
本文分享自微信公众号 - 阿黎逸阳的代码(gh_f3910c467dfe),作者:阿黎逸阳
原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。
原始发表时间:2020-06-14
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句