我的第二程Python之路-week2 初探人脸识别

目录


  1. class 2 的实操
    • 初级人脸识别
    • 中极人脸识别
    • 究极人脸识别
    • 进阶:人脸定位和人脸核验
  2. 遇到的问题
    • 安装 Face-recognition 库
    • 图片灰度的问题
    • plt显示图片的问题
  3. 拓展一下
    • plt 图像处理基本操作
    • Haar 算法的技术逻辑和 Adaboost 级联分类器原理

写在前面

老师上课说讲人脸识别,着实把我吓了一跳。这是我第二节课就可以学到的东西么?

直到开始实操,我才发现我们站在巨人的肩膀上。程序员朋友总是调侃“瞎造轮子”,对于我们这些非专业手,不会瞎造轮子,也不需要瞎造轮子(主要是不会)。学会从错误中学习,善用百度,能够结合现有的方式实现自己的需求,就很满足了。

Eg:要学会看技术文档。


一、Class 2 实操


第二节课的上机实操,通过 OpenCV 和 Face-recognition 进行人脸识别,对卷积神经网络有一个初步的体会。

老师介绍了三种实现人脸识别的方法,分别是 OpenCV 的 CascadeClassifier 级联分类器、Face-recognition 的 HOG 算法、Face-recognition 的 CNN 算法。

三种算法就能能力相差几何?各有什么优势?三组试验,拉出来溜溜。

环境Python3.7 Jupyter Notebook 用到的库 OpenCV dlib face_recognition matplotlib.pyplot

1. 初级人脸识别


在这一组比赛中,我们先使用难度较低的一张图进行识别。这幅图的难点在于遮挡(比如墨镜和脸不全):


夕阳红舞蹈艺术团

首先使用 OpenCV,开干!

import cv2 as cv
import matplotlib.pyplot as plt

def detectFaces(image_name):
    img = cv.imread(image_name)
    face_cascade = cv.CascadeClassifier("data/haarcascade_frontalface_default.xml")    #这里可以更换模型以满足不同的需求。

    if img.ndim == 3:
        gray = cv.cvtColor(img,cv2.COLOR_BGR2GRAY)
    else:
        gray = img
        
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x, y, w, h) in faces:
            img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

    plt.imshow(img)
    plt.axis("off")
    plt.show()
    cv.imwrite('图片输出.jpg',img)

detectFaces("图片导入.jpg")

查看输出的图片,识别率 4 / 6 ,算他及格。墨镜和遮挡都没有很好的识别出来:


使用 OpenCV

继续使用 Face-recognition 的 HOG 算法和 Face-recognition 的 CNN 算法。代码如下:

# 使用 HOG 算法
import face_recognition
import cv2 as cv
import matplotlib.pyplot as plt
%matplotlib inline        #在 jupyter Notebook 中正确输出图片
image = face_recognition.load_image_file("输入.jpg")
face_locations=face_recognition.face_locations(image)

face_num2=len(face_locations)
org = cv.imread("输入.jpg")

for i in range(0,face_num2):
    top = face_locations[i][0]
    right = face_locations[i][1]
    bottom = face_locations[i][2]
    left = face_locations[i][3]

    start = (left, top)
    end = (right, bottom)

    color = (0,255,255)
    thickness = 2
    img=cv.rectangle(org, start, end, color, thickness)


    plt.axis('off')  
    plt.show()
plt.imshow(img)
cv.imwrite('输出.jpg',img)
# 使用 CNN 算法
import face_recognition
import cv2 as cv
import matplotlib.pyplot as plt

image = face_recognition.load_image_file("输入.jpg")
face_locations_useCNN = face_recognition.face_locations(image,model='cnn')  #同理可以更换不同模型

face_num1=len(face_locations_useCNN)
org = cv.imread("输入.jpg")

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
    img=cv2.rectangle(org, start, end, color, thickness)    # opencv 里面画矩形的函数
    plt.imshow(img)
    plt.axis('off')  #去掉坐标轴
plt.show()
cv.imwrite('输出.jpg',img)

对比三次的识别结果,答案显而易见:深度学习就是牛!


深度学习就是牛

2. 中级人脸识别


中级人脸识别难度上了一层楼。开始对 30 多人的大合影开始识别了!
由于代码基本没有调整,所以就直接上结果了。通过对比发现,结果差距不大。


深度学习就是牛

3. 究极人脸识别


就前两轮的竞争来说,CNN 算法均是略胜一筹,但是 OpenCV 和 另外两种的差距还不算明显。但是我相信下面这一组的识别绝对超出你的想象。

这一组合影照片,不光人数众多,而且分辨率有限,遮挡也比较复杂。三种方法究竟谁能更胜一筹呢?上才艺!

大吃一惊

从结果来看,表现优秀的 CNN 算法在这一轮翻车了,甚至还不如另外两种算法。相比较而言,OpenCV 对于低分辨率的人脸(比如后排同学)有着更好的识别能力;CNN 可以识别出更多的遮挡,反而 HOG 算法识别出了最多数量的人脸。

另外,CNN 算法的最大问题是运算时间比另外两种要久数倍,在一些需要快速响应的场景下就有很大的局限性了。

并不存在一劳永逸的万能算法和万能代码,各种方法实际上都各有利弊。没有最好,只有最合适。如何选择出最合适的代码,不仅要求对代码的运行原理有所了解,更重要的是对需求应用场景有一个准确的判断。

4. 进阶:人脸定位和人脸核验


人脸定位是人脸检测的前置条件。这一功能可以实现对面部器官的形状、位置等等进行识别。我们经常使用的美颜、脸部贴纸、表情等等,都是基于人脸定位开始的。
下面的代码可以对图片上的人脸进行5点或是64点定位。

import cv2 as cv
import dlib
import matplotlib.pyplot as plt

img = cv.imread("图片.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

#人脸分类器
detector = dlib.get_frontal_face_detector()
# 获取人脸检测器
#predictor = dlib.shape_predictor(r"C:\Python36\Lib\site-packages\face_recognition_models\models\shape_predictor_68_face_landmarks.dat")
predictor = dlib.shape_predictor(r"data\shape_predictor_68_face_landmarks.dat")

dets = detector(gray, 1)
for face in dets:
    shape = predictor(img, face)  # 寻找人脸的68个标定点
    # 遍历所有点,打印出其坐标,并圈出来
    for pt in shape.parts():
        pt_pos = (pt.x, pt.y)
        img=cv2.circle(img, pt_pos, 2, (0, 255, 0), 1)
        
plt.imshow(img)
plt.axis('off')  #去掉坐标轴
plt.show()

而人脸检测则可以对比不同图片中出现的脸部是否是同一人,并给出反馈。代码如下:

import cv2 as cv
import face_recognition
import matplotlib.pyplot as plt

known_image=cv.imread("ycy.jpg")
known_image = face_recognition.load_image_file("ycy.jpg")

unknown_image=cv.imread("ycy2.png")
unknown_image = face_recognition.load_image_file("ycy2.png")

known_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]

results = face_recognition.compare_faces([known_encoding],unknown_encoding,tolerance=0.6)
if results[0] == True:
    print("匹配成功,该未知图片与已有图片人脸可匹配!")
else:
    print("匹配失败!")
    
#print(known_encoding) 
#print(unknown_encoding)

plt.imshow(known_image)
plt.axis('off')  #去掉坐标轴
plt.show()

plt.imshow(unknown_image)
plt.axis('off')  #去掉坐标轴


二、遇到的问题


  • 安装 Face-recognition 库

    • 安装 Face-recognition 库需要先安装 dlib 库。而dlib 库又需要电脑有 VS C++ 的环境。所以应该先安装 VS (不是 VS Code,它只是一个编译器。)
  • plt 显示图片的问题

    • 在 jupyter 中,因为对图片进行了去色处理,所以plt.show()显示的是去色后的图片。只需要使用 OpenCV 的.imwrite命令将图片存为本地即可。

    • plt.show()默认的图片输出分辨率其实很低。在进行图片编码时,一些行列的像素会被丢弃,所以有的图片上人脸的红框会消失。可以通过下面的代码调整图片分辨率和像素:

      plt.rcParams["savefig.dpi"] = 100 # 图片像素
      plt.rcParams["figure.dpi"] = 100 # 分辨率
      

三、拓展一下



See you next time!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容