基于opencv,face_recognition和dlib的人脸识别的入门学习

近期课程学习了一些入门级别的人脸识别技术实现,所以借此机会整理整理

何为人脸识别

1.人脸识别,是基于人的脸部特征信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相关技术,通常也叫做人像识别、面部识别。

2.人脸识别系统根据输入的图片,识别出人物信息,应用到不同的任务场景中。具体,这个复杂的人脸识别系统负责哪些工作呢?

resnet算法人脸识别 人脸识别技术csdn_python

resnet算法人脸识别 人脸识别技术csdn_python_02

opencv

通过命令pip3 install opencv-python快速安装

然后由于我使用的是macos
在macos系统中,需要将haarcascade_frontalface_default.xml的路径找到并写入代码中。

一般路径:"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml"

demo

import cv2

def detect(filename):
    face_cascade = cv2.CascadeClassifier('/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml')
    #加载haar数据
    img=cv2.imread(filename)
    #加载图片,读进来直接是BGR格式
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #cv2.cvtColor(p1,p2) 是颜色空间转换函数,p1是需要转换的图片,p2是转换成何种格式。
    #cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    # 识别图像中的人脸,返回所有人脸的矩形框向量组
    # scaleFactor=1.3 为了检测到不同大小的目标,通过scalefactor参数把图像长宽同时按照一定比例1.3逐步缩小,
    # 然后检测,这个参数设置的越大,计算速度越快,但可能会错过了某个大小的人脸。
    # minNeighbors=5 构成检测目标的相邻矩形的最小个数,此处设置为5

    for(x,y,w,h) in faces:
        img=cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    
    #在图像中画上矩形框
    cv2.imshow('Person Detected!',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    #显示结果

if __name__ == '__main__':
    detect('1.jpeg')

识别结果

resnet算法人脸识别 人脸识别技术csdn_python_03

可以看到,虽然有一些人脸能够被正确识别到,但还是有一些人脸(例如侧脸)不能够识别,甚至有一些错误的识别。这就要求我们使用更高级的算法来识别人脸

face_recognition

GitHub项目:face_recognition

  • 该项目目前star数超过3万,是GitHub上最主流的人脸识别工具包之一。
  • Face_recognition主要参考了OpenFace项目以及谷歌的facenet。
  • 世界上最简洁的人脸识别库,可以使用Python和命令行工具提取、识别、操作人脸。
  • 本项目的人脸识别是基于业内领先的C++开源库dlib中的深度学习模型,用Labeled Faces in the Wild人脸数据集进行测试,有高达99.38%的准确率。但对小孩和亚洲人脸的识别准确率尚待提升。

安装dlib和face_recognition

在安装dlib时,可能会因为没有安装依赖包而出现错误,所以在安装dlib之前,我们先用brew安装openblas和cmake

  1. brew install openblas
  2. brew install cmake
  3. pip install dlib
  4. pip install face_recognition

demo

import face_recognition
import cv2

def detect(filename):
    image=face_recognition.load_image_file(filename)
    #加载图片到image
    face_locations_noCNN=face_recognition.face_locations(image)
    #Returns an array of bounding boxes of human faces in a image
    #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("I found {} face(s) in this photograph.".format(face_num2))
    # 到这里为止,可以观察两种情况的坐标和人脸数,一般来说,坐标会不一样,但是检测出来的人脸数应该是一样的
    # 也就是说face_num1 = face_num2; face_locations_useCNN 和 face_locations_noCNN 不一样

    org=cv2.imread(filename)
    img=cv2.imread(filename)
    #cv2.imshow(filename,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.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → None
        #img:图片   pt1&pt2:矩形的左上角和右下角    color:矩形边框的颜色(rgb)   thickness:参数表示矩形边框的厚度

    cv2.imshow("no cnn",org)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    # # use CNN
# face_locations_useCNN = face_recognition.face_locations(image,model='cnn')
# model – Which face detection model to use. “hog” is less accurate but faster on CPUs.
# “cnn” is a more accurate deep-learning model which is GPU/CUDA accelerated (if available). The default is “hog”.

# print("face_location_useCNN:")
# print(face_locations_useCNN)
# face_num1=len(face_locations_useCNN)
# print(face_num1)       # The number of faces


# for i in range(0,face_num1):
#     top = face_locations_useCNN[i][0]
#     right = face_locations_useCNN[i][1]
#     bottom = face_locations_useCNN[i][2]
#     left = face_locations_useCNN[i][3]
#
#     start = (left, top)
#     end = (right, bottom)
#
#     color = (0,255,255)
#     thickness = 2
#     cv2.rectangle(img, start, end, color, thickness)    # opencv 里面画矩形的函数

# # Show the result
# cv2.imshow("useCNN",img)

if __name__ =='__main__':
    detect('1.png')

识别结果

resnet算法人脸识别 人脸识别技术csdn_python_04


可以看到,相比较第一次识别的结果,这一次的准确度提高了,但是在这次识别中,侧脸依旧无法识别,所以我们要找到人脸特征点。

人脸特征点

Dlib有专门的函数和模型,能够实现人脸68个特征点的定位。
找到特征点后,就可以通过图像的几何变换(仿射、旋转、缩放),使各个特征点对齐(将眼睛、嘴等部位移到相同位置)。

下载和安装

需要下载包:shape_predictor_68_face_landmarks.dat
并添加到路径"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages"中(Mac用户)

demo

import cv2
import dlib

def detect(filename):
    img=cv2.imread(filename)
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #人脸分类器
    detector=dlib.get_frontal_face_detector()
    #获取人脸检测器
    predictor=dlib.shape_predictor(r"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/shape_predictor_68_face_landmarks.dat")
    #dets保存的是图像中人脸的矩形框,可以有多个
    dets=detector(gray,1)
    
    for face in dets:
        shape=predictor(img,face)# 寻找人脸的68个标定点
        # 遍历所有点,打印出其坐标,并圈出来
        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()

if __name__=='__main__':
    detect('1.png')

resnet算法人脸识别 人脸识别技术csdn_python_05


虽然这次依旧没有能够把侧脸识别出,这说明了我们的算法依然待提升,但是成功将几个人脸的特征点提取出来了,这也为我们之后对人脸进行对齐等操作提供了数据。