Python人脸识别—我的眼里只有你

2020-09-08 10:55:55 浏览数 (1)

人脸识别总感觉特别高深,但是因为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

0 人点赞