您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

学习一:人脸识别

学习一:人脸识别

1.opencv

简介:  OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的IPP进行加速处理。

​ ①在Pycharm中新建一个opencv项目,选择的编译环境为[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-plRPIptJ-1651756167081)(C:\Users\艺\AppData\Roaming\Typora\typora-user-images\image-20220504212337051.png)]

​ ②安装opencv-python

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

③获取分类器位置

D:\Anaconda\Lib\sitepackages\cv2\data\haarcascade_frontalface_default.xml

④完整代码

import cv2
def detect(filename):
    ##创建⼀个级联分类器,加载⼀个 .xml⽂件
    # 这⾥路径替换成⾃⼰的'Python路径下/Lib/sitepackages/cv2/data/haarcascade_frontalface_default.xml'
    face_cascade =cv2.CascadeClassifier('D:\Anaconda\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')
  # 加载图像
    img = cv2.imread(filename)
# 转换为灰度图像
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 使⽤上⾯创建的分类器来检测⼈脸,faces为识别出脸部的矩形框向量组,⼏张脸就有⼏个矩
#形框,向量组⾥就有⼏组向量,保存⼈脸的坐标和⼤⼩。
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
# scaleFactor表示⼈脸检测过程中每次迭代时图⽚的压缩率(1.3)
# minNeighbors:每个⼈脸矩形保留近邻数⽬的最⼩值(5)
# 在原图上绘制矩形
# 遍历faces矩形框向量组⾥每⼀组矩形(即每⼀张脸)
    for (x, y, w, h) in faces:
# 通过坐标绘制矩形,x,y是左上⻆坐标;w,h分别是宽度和⾼度
# 参数:图⽚,⻓⽅形框左上⻆坐标, ⻓⽅形框右下⻆坐标, 字体颜⾊,字体粗细)
      img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
# 其中参数的含义:(255, 0, 0)表示颜⾊, 2表示线条粗细
      cv2.imshow('Person Detected!', img)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
if __name__ == '__main__':
    detect('smile.jpg')

⑤实验结果

在这里插入图片描述

2.基于face_recognition

​ 由上图可以看到opencv在识别的过程中有些人脸因为边缘性无法识别。可以通过face_recognition 提高精确度。

​ ①简介:face_recognition项目是世界上最简洁的人脸识别库,可以使用Python和命令行工具提取、识别、操作人脸。

​ ②安装环境

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
pip install CMake
pip install Boost
pip install dlib
pip install face_recognition
在这里安装的过程中,直接安装会报错需要先安装dlib,dlib依赖于boost和cmake
注意在安装dlib的时候会报错
解决方法:找到python对应的dlib安装版本:3.6——对应的版本是dlib-19.8.1
链接:https://pypi.org/project/dlib/19.8.1/#files
其他版本对应链接:https://pypi.org/project/dlib/#description

安装face_recognitiond可能需要等待一段时间

(将对应的.whl文件下载到对应到本地,在cmd中:cd+对应下载的路径;接着: pip install dlib-19.8.1-cp36-cp36m-win_amd64.whl 加安装成功了

③实验代码:使用cnn卷积神经网络

import face_recognition
import cv2
#加载图像⽂件(.jpg,.png等),返回的数据是Numpy数组,记录了图⽚的所有像素的特征向量
image = face_recognition.load_image_file("smile.jpg")
#定位图中所有的⼈脸的像素位置,返回值为列表形式,列表中每⼀⾏是⼀张⼈脸的位置信息,包括
#【top, right, bottom, left】 这是⼀组元组。
face_locations_noCNN=face_recognition.face_locations(image)
# face_locations_useCNN =
face_recognition.face_locations(image,model='cnn')
# A list of tuples of found face locations in css (top, right, bottom,
#left) order
# 因为返回值的顺序是这样⼦的,因此在后⾯的for循环⾥⾯赋值要注意按这个顺序来
print("face_location_noCNN:")
print(face_locations_noCNN)
face_num2=len(face_locations_noCNN)
print(face_num2)       # The number of faces
# 到这⾥为⽌,可以观察两种情况的坐标和⼈脸数,⼀般来说,坐标会不⼀样,但是检测出来的⼈
#脸数应该是⼀样的
# 也就是说face_num1 = face_num2; face_locations_useCNN 和
#pipface_locations_noCNN 不⼀样
org = cv2.imread("smile.jpg")
img = cv2.imread("smile.jpg")
cv2.imshow("smile.jpg",img) # 原始图⽚
for i in range(0,face_num2):
   top = face_locations_noCNN[i][0]
   right = face_locations_noCNN[i][1]
   bottom = face_locations_noCNN[i][2]
   left = face_locations_noCNN[i][3]
   start = (left, top)
   end = (right, bottom)
   color = (0,255,255)
   thickness = 2
   #参数:图⽚,⻓⽅形框左上⻆坐标, ⻓⽅形框右下⻆坐标, 字体颜⾊,字体粗细)

   cv2.rectangle(org, start, end, color, thickness)
cv2.imshow("no cnn ",org)
cv2.waitKey(0)
cv2.destroyAllWindows()

​ ④实验结果

​ 可以看到输出两个坐标,识别出两个人脸

在这里插入图片描述

3.人脸特征点检测

	Dlib有专门的函数和模型可以实现人脸68个特征点的定位。 支持更加精准的标定点。分为五点和八点,可以圈出面部和嘴鼻的位置。

​ ① 下载预训练模型

shape_predictor_68_face_landmarks.dat
链接:https://pan.baidu.com/s/1e7oyn-bc3r4USGwo4alZ5w
提取码:wppp
shape_predictor_5_face_landmarks.dat
链接:https://pan.baidu.com/s/1CxUl5NEVOFokcQb4pKry-Q
提取码:y0f3
这两个个包放在python路径下的site-packages⾥

​ ② 实验代码

import cv2
import dlib
path = "smile.jpg"
#读取图⽚
img = cv2.imread(path)
#灰度化处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#获得脸部位置检测器
detector = dlib.get_frontal_face_detector()
# 初步⼈脸检测,框出矩形。返回值是<class 'dlib.dlib.rectangle'>,即⼀个矩形,表示
#为能够唯⼀表示这个⼈脸矩形框两个点坐标:左上⻆(x1,y1)、右下⻆(x2,y2
dets = detector(gray, 1)
# 使⽤模型构建特征提取器,返回5/68个特征点的位置
#此处路径是⾃⼰的python路径下site-packages位置
predictor =dlib.shape_predictor("D:\Anaconda\Lib\site-packages\shape_predictor_68_face_landmarks.dat")
for face in dets:
   shape = predictor(img, face) # 寻找⼈脸的68个标定点
   # 遍历所有点,打印出其坐标,并圈出来
   #shape.parts() 类型为_dlib_pybind11.points,可返回检测到的关键点的位置坐标
   for pt in shape.parts():
       pt_pos = (pt.x, pt.y)
       #参数:图⽚,圆⼼, 半径, 字体颜⾊,字体粗细)
       cv2.circle(img, pt_pos, 2, (0, 255, 0), 1)
   cv2.imshow("image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

​ ③实验结果

在这里插入图片描述

4.使用人脸识别技术进行创新

​ 创新:AI换脸

​ ①使用技术:基于python的opencv和dlib

​ ②实现步骤:参考链接:(58条消息) AI换脸_hxxjxw的博客-CSDN博客_ai换脸 csdn

a. 使用dlib的shapepredictor_68_face_landmarks.dat模型获取人脸图片im1和视频中的人脸图片im2的68个人脸特征点。
b. 根据上一步获得的特征点得到两张图片的人脸掩模im1_mask和im2_mask
c. 利用68个特征点中的3个特征点,对人脸图片im1进行仿射变换使其脸部对准摄像头图片中的脸部,得到图片affine_im1
d. 对人脸图片的掩模im1_mask也进行相同的仿射变换得到affine_im1_mask。
e. 对掩模im2_mask和掩模affine_im1_mask的掩盖部分取并集得到union_mask。
f. 利用opencv里的seamlessClone函数对仿射变换后的affine_im1和摄像头图片im2进行泊松融合,掩模为union_mask,得到融合后的图像seamless_im

​ ③实验代码

# -*- coding: utf-8 -*-

import os
import cv2
import dlib
import numpy as np

here = os.path.dirname(os.path.abspath(__file__))
print(here)
models_folder_path = os.path.join(here, 'models')  # 模型保存文件夹
faces_folder_path = os.path.join(here, 'faces')  # 人脸图片保存文件夹
predictor_path = os.path.join(models_folder_path, 'shape_predictor_68_face_landmarks.dat')  # 模型路径
image_face_path = os.path.join(faces_folder_path, 'test.jpg')  # 人脸图片路径
#image_face_path = os.path.join(faces_folder_path, 'test.jpg')  # 人脸图片路径
print(image_face_path)
detector = dlib.get_frontal_face_detector()  # dlib的正向人脸检测器
predictor = dlib.shape_predictor(predictor_path)  # dlib的人脸形状检测器
#predictor = dlib.shape_predictor("./model/shape_predictor_68_face_landmarks.dat")  # dlib的人脸形状检测器
print(predictor_path)

def get_image_size(image):
    """
    获取图片大小(高度,宽度)
    :param image: image
    :return: (高度,宽度)
    """
    image_size = (image.shape[0], image.shape[1])
    return image_size


def get_face_landmarks(image, face_detector, shape_predictor):
    """
    获取人脸标志,68个特征点
    :param image: image
    :param face_detector: dlib.get_frontal_face_detector
    :param shape_predictor: dlib.shape_predictor
    :return: np.array([[],[]]), 68个特征点
    """
    dets = face_detector(image, 1)
    num_faces = len(dets)
    if num_faces == 0:
        print("Sorry, there were no faces found.")
        return None
    shape = shape_predictor(image, dets[0])
    face_landmarks = np.array([[p.x, p.y] for p in shape.parts()])
    return face_landmarks


def get_face_mask(image_size, face_landmarks):
    """
    获取人脸掩模
    :param image_size: 图片大小
    :param face_landmarks: 68个特征点
    :return: image_mask, 掩模图片
    """
    mask = np.zeros(image_size, dtype=np.uint8)
    points = np.concatenate([face_landmarks[0:16], face_landmarks[26:17:-1]])
    cv2.fillPoly(img=mask, pts=[points], color=255)

    # mask = np.zeros(image_size, dtype=np.uint8)
    # points = cv2.convexHull(face_landmarks)  # 凸包
    # cv2.fillConvexPoly(mask, points, color=255)
    return mask


def get_affine_image(image1, image2, face_landmarks1, face_landmarks2):
    """
    获取图片1仿射变换后的图片
    :param image1: 图片1, 要进行仿射变换的图片
    :param image2: 图片2, 只要用来获取图片大小,生成与之大小相同的仿射变换图片
    :param face_landmarks1: 图片1的人脸特征点
    :param face_landmarks2: 图片2的人脸特征点
    :return: 仿射变换后的图片
    """
    three_points_index = [18, 8, 25]
    M = cv2.getAffineTransform(face_landmarks1[three_points_index].astype(np.float32),
                               face_landmarks2[three_points_index].astype(np.float32))
    dsize = (image2.shape[1], image2.shape[0])
    affine_image = cv2.warpAffine(image1, M, dsize)
    return affine_image.astype(np.uint8)


def get_mask_center_point(image_mask):
    """
    获取掩模的中心点坐标
    :param image_mask: 掩模图片
    :return: 掩模中心
    """
    image_mask_index = np.argwhere(image_mask > 0)
    miny, minx = np.min(image_mask_index, axis=0)
    maxy, maxx = np.max(image_mask_index, axis=0)
    center_point = ((maxx + minx) // 2, (maxy + miny) // 2)
    return center_point


def get_mask_union(mask1, mask2):
    """
    获取两个掩模掩盖部分的并集
    :param mask1: mask_image, 掩模1
    :param mask2: mask_image, 掩模2
    :return: 两个掩模掩盖部分的并集
    """
    mask = np.min([mask1, mask2], axis=0)  # 掩盖部分并集
    mask = ((cv2.blur(mask, (5, 5)) == 255) * 255).astype(np.uint8)  # 缩小掩模大小
    mask = cv2.blur(mask, (3, 3)).astype(np.uint8)  # 模糊掩模
    return mask


def skin_color_adjustment(im1, im2, mask=None):
    """
    肤色调整
    :param im1: 图片1
    :param im2: 图片2
    :param mask: 人脸 mask. 如果存在,使用人脸部分均值来求肤色变换系数;否则,使用高斯模糊来求肤色变换系数
    :return: 根据图片2的颜色调整的图片1
    """
    if mask is None:
        im1_ksize = 55
        im2_ksize = 55
        im1_factor = cv2.GaussianBlur(im1, (im1_ksize, im1_ksize), 0).astype(np.float)
        im2_factor = cv2.GaussianBlur(im2, (im2_ksize, im2_ksize), 0).astype(np.float)
    else:
        im1_face_image = cv2.bitwise_and(im1, im1, mask=mask)
        im2_face_image = cv2.bitwise_and(im2, im2, mask=mask)
        im1_factor = np.mean(im1_face_image, axis=(0, 1))
        im2_factor = np.mean(im2_face_image, axis=(0, 1))

    im1 = np.clip((im1.astype(np.float) * im2_factor / np.clip(im1_factor, 1e-6, None)), 0, 255).astype(np.uint8)
    return im1


def main():
    print(image_face_path)
    filename = "test.jpg"
    im1=cv2.imread(filename)
    #im1 = cv2.imread(image_face_path)  # face_image

    im1 = cv2.resize(im1, (600, im1.shape[0] * 600 // im1.shape[1]))
    landmarks1 = get_face_landmarks(im1, detector, predictor)  # 68_face_landmarks
    if landmarks1 is None:
        print('{}:检测不到人脸'.format(image_face_path))
        exit(1)
    im1_size = get_image_size(im1)  # 脸图大小
    im1_mask = get_face_mask(im1_size, landmarks1)  # 脸图人脸掩模

    cam = cv2.VideoCapture("1.mp4")
    while True:
        ret_val, im2 = cam.read()  # camera_image
        landmarks2 = get_face_landmarks(im2, detector, predictor)  # 68_face_landmarks
        if landmarks2 is not None:
            im2_size = get_image_size(im2)  # 摄像头图片大小
            im2_mask = get_face_mask(im2_size, landmarks2)  # 摄像头图片人脸掩模

            affine_im1 = get_affine_image(im1, im2, landmarks1, landmarks2)  # im1(脸图)仿射变换后的图片
            affine_im1_mask = get_affine_image(im1_mask, im2, landmarks1, landmarks2)  # im1(脸图)仿射变换后的图片的人脸掩模

            union_mask = get_mask_union(im2_mask, affine_im1_mask)  # 掩模合并

            # affine_im1_face_image = cv2.bitwise_and(affine_im1, affine_im1, mask=union_mask)  # im1(脸图)的脸
            # im2_face_image = cv2.bitwise_and(im2, im2, mask=union_mask)  # im2(摄像头图片)的脸
            # cv2.imshow('affine_im1_face_image', affine_im1_face_image)
            # cv2.imshow('im2_face_image', im2_face_image)

            affine_im1 = skin_color_adjustment(affine_im1, im2, mask=union_mask)  # 肤色调整
            point = get_mask_center_point(affine_im1_mask)  # im1(脸图)仿射变换后的图片的人脸掩模的中心点
            seamless_im = cv2.seamlessClone(affine_im1, im2, mask=union_mask, p=point, flags=cv2.NORMAL_CLONE)  # 进行泊松融合

            # cv2.imshow('affine_im1', affine_im1)
            # cv2.imshow('im2', im2)
            cv2.imshow('seamless_im', seamless_im)
        else:
            cv2.imshow('seamless_im', im2)
        if cv2.waitKey(1) == 27:  # 按Esc退出
            break
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

​ ④实验结果[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tdad7ECt-1651756167091)(C:\Users\艺\AppData\Roaming\Typora\typora-user-images\image-20220505180238250.png)]

v2.imshow(‘affine_im1’, affine_im1)
# cv2.imshow(‘im2’, im2)
cv2.imshow(‘seamless_im’, seamless_im)
else:
cv2.imshow(‘seamless_im’, im2)
if cv2.waitKey(1) == 27: # 按Esc退出
break
cv2.destroyAllWindows()

if name == ‘main’:
main()


​     ④实验结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/dfc67e672850467f8c0ef0a50d69eafd.png#pic_center)






分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进