[Python图像处理] 二十八.OpenCV快速实现人脸识别及视频中的人脸

该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。希望文章对您有所帮助,如果有不足之处,还请海涵~

前面一篇文章详细讲解了Python和OpenGL的入门知识,包括安装、语法、基本图形绘制等。本篇文章将通过OpenCV快速实现人脸识别,涉及图像、视频、摄像头。基础性文章,希望对你有所帮助。同时,该部分知识均为杨秀璋查阅资料撰写,转载请署名CSDN+杨秀璋及原地址出处,谢谢!!

该系列在github所有源代码:
https://github.com/eastmountyxz/ImageProcessing-Python
https://github.com/eastmountyxz/CSDNBlog-ImageProcessing-Python

前文参考:
[Python图像处理] 一.图像处理基础知识及OpenCV入门函数
[Python图像处理] 二.OpenCV+Numpy库读取与修改像素
[Python图像处理] 三.获取图像属性、兴趣ROI区域及通道处理
[Python图像处理] 四.图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
[Python图像处理] 五.图像融合、加法运算及图像类型转换
[Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移
[Python图像处理] 七.图像阈值化处理及算法对比
[Python图像处理] 八.图像腐蚀与图像膨胀
[Python图像处理] 九.形态学之图像开运算、闭运算、梯度运算
[Python图像处理] 十.形态学之图像顶帽运算和黑帽运算
[Python图像处理] 十一.灰度直方图概念及OpenCV绘制直方图
[Python图像处理] 十二.图像几何变换之图像仿射变换、图像透视变换和图像校正
[Python图像处理] 十三.基于灰度三维图的图像顶帽运算和黑帽运算
[Python图像处理] 十四.基于OpenCV和像素处理的图像灰度化处理
[Python图像处理] 十五.图像的灰度线性变换
[Python图像处理] 十六.图像的灰度非线性变换之对数变换、伽马变换
[Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
[Python图像处理] 十八.图像锐化与边缘检测之Scharr算子、Canny算子和LOG算子
[Python图像处理] 十九.图像分割之基于K-Means聚类的区域分割
[Python图像处理] 二十.图像量化处理和采样处理及局部马赛克特效
[Python图像处理] 二十一.图像金字塔之图像向下取样和向上取样
[Python图像处理] 二十二.Python图像傅里叶变换原理及实现
[Python图像处理] 二十三.傅里叶变换之高通滤波和低通滤波
[Python图像处理] 二十四.图像特效处理之毛玻璃、浮雕和油漆特效
[Python图像处理] 二十五.图像特效处理之素描、怀旧、光照、流年以及滤镜特效
[Python图像处理] 二十六.图像分类原理及基于KNN、朴素贝叶斯算法的图像分类案例
[Python图像处理] 二十七.OpenGL入门及绘制基本图形(一)


一.OpenCV基础

首先调用"pip install opencv-python"安装OpenCV库,如下图所示,显示“Successfully installed opencv-python-4.2.0.32”表示安装成功。

在这里插入图片描述

下面代码是读入图片并显示保存。

读入图像
OpenCV读图像主要调用下面函数实现:

img = cv2.imread(文件名,[,参数])
参数(1) cv2.IMREAD_UNCHANGED (图像不可变)
参数(2) cv2.IMREAD_GRAYSCALE (灰度图像)
参数(3) cv2.IMREAD_COLOR (读入彩色图像)
参数(4) cv2.COLOR_BGR2RGB (图像通道BGR转成RGB)

显示图像
显示图像调用函数如下:

cv2.imshow(窗口名, 图像名)

窗口等待
调用函数如下:

cv2.waitKey(delay)
键盘绑定函数,共一个参数,表示等待毫秒数,将等待特定的几毫秒,看键盘是否有输入,返回值为ASCII值。如果其参数为0,则表示无限期的等待键盘输入;参数>0表示等待delay毫秒;参数<0表示等待键盘单击。

删除所有窗口
调用函数如下:

cv2.destroyAllWindows() 删除所有窗口
cv2.destroyWindows() 删除指定的窗口

写入图片
调用函数如下:

retval = cv2.imwrite(文件地址, 文件名)

下面代码是读入图片并显示保存。

# -*- coding:utf-8 -*-
import cv2

#读取图片
img = cv2.imread("test.jpg")

#显示图像
cv2.imshow("Demo", img)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

#写入图像
cv2.imwrite("testyxz.jpg", img)

输出结果如下图所示,并且在文件夹下保存了一张名为“testyxz.jpg”的图像。

在这里插入图片描述

同样,OpenCV可以实现各种图像处理效果,前面的文章我们也进行了详细的讲解。

图像素描特效
它会将图像的边界都凸显出来,通过边缘检测及阈值化处理能实现该功能。一幅图像的内部都具有相似性,而在图像边界处具有明显的差异,边缘检测利用数学中的求导来扩大这种变化。但是求导过程中会增大图像的噪声,所以边缘检测之前引入了高斯滤波降噪处理。本文的图像素描特效主要经过以下几个步骤:

  • 调用cv2.cvtColor()函数将彩色图像灰度化处理;
  • 通过cv2.GaussianBlur()函数实现高斯滤波降噪;
  • 边缘检测采用Canny算子实现;
  • 最后通过cv2.threshold()反二进制阈值化处理实现素描特效。

其运行代码如下所示。

#coding:utf-8
import cv2
import numpy as np

#读取原始图像
img = cv2.imread('yxz.png')

#图像灰度处理
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#高斯滤波降噪
gaussian = cv2.GaussianBlur(gray, (5,5), 0)
 
#Canny算子
canny = cv2.Canny(gaussian, 50, 150)

#阈值化处理
ret, result = cv2.threshold(canny, 100, 255, cv2.THRESH_BINARY_INV)

#显示图像
cv2.imshow('src', img)
cv2.imshow('gray', gray)
cv2.imshow('result', result)
cv2.waitKey()
cv2.destroyAllWindows()

最终输出结果如下图所示,它将彩色图像灰度素描处理。

在这里插入图片描述

在这里插入图片描述



二.图像单人脸识别

人脸识别的常见步骤如下,如果想要将人脸准确地找出来,需要通过建立人脸模型,获取准确区分人脸的分类器,这里我们使用网上公开的扩展包或已经训练好的分类器。

在这里插入图片描述


第一步,下载人脸识别算法,这里使用OpenCV发布在github上的代码。

在这里插入图片描述

下载地址:
https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml

我们将“haarcascade_frontalface_default.xml”文件下载至本地,后续调用它辅助我们进行人脸识别。

在这里插入图片描述


第二步,调用cv2.CascadeClassifier()和detectMultiScale()函数,根据人脸特征进行识别。

  • CascadeClassifier:是OpenCV中人脸检测的一个级联分类器,既可以使用Haar,也可以使用LBP特征。以Haar特征分类器为基础的对象检测技术是一种非常有效的技术。它是基于机器学习且使用大量的正负样本训练得到分类器。
  • Haar-like矩形特征:是用于物体检测的数字图像特征。这类矩形特征模板由两个或多个全等的黑白矩形相邻组合而成,而矩形特征值是白色矩形的灰度值的和减去黑色矩形的灰度值的和,矩形特征对一些简单的图形结构,如线段、边缘比较敏感。如果把这样的矩形放在一个非人脸区域,那么计算出的特征值应该和人脸特征值不一样,所以这些矩形就是为了把人脸特征量化,以区分人脸和非人脸。
  • LBP:是一种特征提取方式,能提取出图像的局部的纹理特征,最开始的LBP算子是在3X3窗口中,取中心像素的像素值为阀值,与其周围八个像素点的像素值比较,若像素点的像素值大于阀值,则此像素点被标记为1,否则标记为0。这样就能得到一个八位二进制的码,转换为十进制即LBP码,于是得到了这个窗口的LBP值,用这个值来反映这个窗口内的纹理信息。LBPH是在原始LBP上的一个改进,在opencv支持下我们可以直接调用函数直接创建一个LBPH人脸识别的模型。比如:cv2.face.LBPHFaceRecognizer_create()。
  • detectMultiScale:检测人脸算法,其参数:
    – image表示要检测的输入图像
    – objects表示检测到的人脸目标序列
    – scaleFactor表示每次图像尺寸减小的比例
    – minNeighbors表示每一个目标至少要被检测到3次才算是真的目标,因为周围的像素和不同的窗口大小都可以检测到人脸
    – minSize表示目标的最小尺寸
    – minSize表示目标的最大尺寸

在这里插入图片描述

在这里插入图片描述


第三步,绘制矩形或圆形检测人脸,并将人脸识别的最终图像显示出来。


完整代码如下所示:

#coding:utf-8
import cv2

# 读取原始图像
img = cv2.imread('yxz.png')

# 调用熟悉的人脸分类器 识别特征类型
# 人脸 - haarcascade_frontalface_default.xml
# 人眼 - haarcascade_eye.xm
# 微笑 - haarcascade_smile.xml
face_detect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 检查人脸 按照1.1倍放到 周围最小像素为5
face_zone = face_detect.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5)
print ('识别人脸的信息:',face_zone)

# 绘制矩形和圆形检测人脸
for x, y, w, h in face_zone:
    # 绘制矩形人脸区域 thickness表示线的粗细
    cv2.rectangle(img, pt1=(x, y), pt2=(x+w, y+h),color=[0,0,255], thickness=2)
    # 绘制圆形人脸区域 radius表示半径
    cv2.circle(img, center=(x+w//2, y+h//2), radius=w//2, color=[0,255,0], thickness=2)

# 设置图片可以手动调节大小
cv2.namedWindow("Easmount-CSDN", 0)

# 显示图片
cv2.imshow("Easmount-CSDN", img)

# 等待显示 设置任意键退出程序
cv2.waitKey(0)
cv2.destroyAllWindows()

识别人脸如下图所示,同时输出“识别人脸的信息: [[318 115 151 151]]”。作者大一在北京十渡的照片,笑容灿烂啊!哈哈~

在这里插入图片描述

在这里插入图片描述

注意,此时的算法只能检测正脸,比如下图就无法检测。

在这里插入图片描述



三.图像多人脸识别

检测图像多张人脸,其方法和前面非常类似,基本流程如下:

  • 将图像转换为灰度图像
  • 调用cv2.CascadeClassifier()和detectMultiScale()函数,根据人脸特征进行识别
  • 绘制矩形或圆形检测人脸,并将人脸识别的最终图像显示出来

完整代码如下图所示:

#coding:utf-8
import cv2

# 读取原始图像
img = cv2.imread('test01.jpg')

# 调用熟悉的人脸分类器 识别特征类型
# 人脸 - haarcascade_frontalface_default.xml
# 人眼 - haarcascade_eye.xm
# 微笑 - haarcascade_smile.xml
face_detect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 灰度处理
gray = cv2.cvtColor(img, code=cv2.COLOR_BGR2GRAY)

# 检查人脸 按照1.1倍放到 周围最小像素为5
face_zone = face_detect.detectMultiScale(gray, scaleFactor = 1.1, minNeighbors = 4) # maxSize = (55,55)
print ('识别人脸的信息:\n',face_zone)

# 绘制矩形和圆形检测人脸
for x, y, w, h in face_zone:
    # 绘制矩形人脸区域
    cv2.rectangle(img, pt1 = (x, y), pt2 = (x+w, y+h), color = [0,0,255], thickness=2)
    # 绘制圆形人脸区域 radius表示半径
    cv2.circle(img, center = (x + w//2, y + h//2), radius = w//2, color = [0,255,0], thickness = 2)

# 设置图片可以手动调节大小
cv2.namedWindow("Easmount-CSDN", 0)

# 显示图片
cv2.imshow("Easmount-CSDN", img)

# 等待显示 设置任意键退出程序
cv2.waitKey(0)
cv2.destroyAllWindows()

如下图所示,将两人的脸庞识别出来。注意,该算法会根据人脸的不同尺寸,绘制不同人脸的矩形或圆形框出。

识别人脸的信息: 
[[479 281 154 154]
 [314 359 129 129]]

在这里插入图片描述

再举一个北影毕业照的示例,可以看到人脸被成功的识别。

识别人脸的信息:
 [[166  38  26  26]
 [366  80  30  30]
 [273  83  30  30]
 [117  40  29  29]
 [ 71  44  28  28]
 [210 127  30  30]
 [376  45  27  27]
 [ 39  89  29  29]
 [285 126  30  30]
 [329 128  29  29]
 [196  48  30  30]
 [366 129  32  32]
 [306  82  31  31]
 [135 123  32  32]
 [134  76  29  29]
 [ 92 102  32  32]
 [341  22  26  26]
 [140  25  28  28]
 [305  30  30  30]
 [244  35  27  27]
 [250 109  31  31]
 [174 111  30  30]
 [336  75  29  29]]

在这里插入图片描述

同样,任何算法都不会100%识别准确,由于噪声、误差、算法、训练集等影响,某些时候也会出现错误识别。一方面OpenCV无法识别侧脸,另一方面某些花被识别成人脸。



四.识别视频人脸

这里需要调用cv2.VideoCapture()函数导入视频,然后读取视频中的数据,最后调用之前的算法识别人脸。核心代码如下:

读取视频数据

  • cap = cv2.VideoCapture(‘shipin.mp4’) #导入视频
  • flag, frame = cap.read()
  • flag:返回值为True和False,True和图片一起返回,当读完视频后返回False
  • frame:接受返回来的图片

人脸像素检测识别

  • face_zone = face_detect.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3)
  • scaleFactor:检测像素点扩散的面积
  • minNeighbors:像素点邻近值

设置视频展示频度
为了让视频的展示速度和原视频一致,我们需要调用 “cap.get(propId = cv2.CAP_PROP_FPS)” 函数将其设置为25,即每秒25帧。


完整代码如下:

#coding:utf-8
import cv2
import numpy as np

# 加载视频
cap = cv2.VideoCapture('shipin01.mp4')

# 调用熟悉的人脸分类器 识别特征类型
# 人脸 - haarcascade_frontalface_default.xml
# 人眼 - haarcascade_eye.xm
# 微笑 - haarcascade_smile.xml
face_detect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

while True:
    # 读取视频片段
    flag, frame = cap.read()
    if flag == False:
        break

    # 灰度处理
    gray = cv2.cvtColor(frame, code=cv2.COLOR_BGR2GRAY)

    # 检查人脸 按照1.1倍放到 周围最小像素为5
    face_zone = face_detect.detectMultiScale(gray, scaleFactor = 1.1, minNeighbors = 4)

    # 绘制矩形和圆形检测人脸
    for x, y, w, h in face_zone:
        cv2.rectangle(frame, pt1 = (x, y), pt2 = (x+w, y+h), color = [0,0,255], thickness=2)
        cv2.circle(frame, center = (x + w//2, y + h//2), radius = w//2, color = [0,255,0], thickness = 2)

    # 显示图片
    cv2.imshow('video', frame)
    
    # 设置退出键和展示频率
    if ord('q') == cv2.waitKey(40):
        break

# 释放资源
cv2.destroyAllWindows()
cap.release()

女神跳舞输出视频如下图所示,能够实时获取人脸并显示。但是当人物跳舞运动时,由于抖动会导致识别的人脸不准确,这也是更多算法要进行优化的原因。本文当前仅分享基础知识,后续随着自己深入研究,可能会分享更深更好的文章。

在这里插入图片描述



五.摄像头人脸识别

识别电脑摄像头的流程和识别视频中的是一样的,只是加载源的方式不一样。当VideoCapture(0)时,自动调用摄像头捕捉视频。

#coding:utf-8
import cv2

# 识别电脑摄像头并打开
cap = cv2.VideoCapture(0)

# 调用熟悉的人脸分类器 识别特征类型
# 人脸 - haarcascade_frontalface_default.xml
# 人眼 - haarcascade_eye.xm
# 微笑 - haarcascade_smile.xml
face_detect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

while True:
    # 读取视频片段
    flag, frame = cap.read()
    if flag == False:
        break

    # 灰度处理
    gray = cv2.cvtColor(frame, code=cv2.COLOR_BGR2GRAY)

    # 检查人脸 按照1.1倍放到 周围最小像素为5
    face_zone = face_detect.detectMultiScale(gray, scaleFactor = 1.2, minNeighbors = 5)

    # 绘制矩形和圆形检测人脸
    for x, y, w, h in face_zone:
        cv2.rectangle(frame, pt1 = (x, y), pt2 = (x+w, y+h), color = [0,0,255], thickness=2)
        cv2.circle(frame, center = (x + w//2, y + h//2), radius = w//2, color = [0,255,0], thickness = 2)

    # 显示图片
    cv2.imshow('video', frame)
    
    # 设置退出键和展示频率
    if ord('q') == cv2.waitKey(40):
        break

# 释放资源
cv2.destroyAllWindows()
cap.release()

输出结果如下图所示,同样需要注意识别正脸和静止状态效果更好。

在这里插入图片描述



六.总结

本篇文章主要讲解Python和OpenCV基础知识,主要调用github算法进行人脸识别,包括识别图像、视频和摄像头等。但该算法也存在缺陷,比如侧脸识别效果不佳、抖动视频识别不好等,后续随着作者深入,希望能够分享更好的代码。希望这篇基础性文章对读者有一定帮助,也希望这些知识点为读者从事Python图像处理相关项目实践或科学研究提供一定基础。

这篇文章参考了杨友学生的分享,作为老师,最开心的事是看到学生不断成长,分享这么好的文章、撰写高质量的论文、找到编程相关的工作。也希望更多学生能从我的文章、故事、课堂中学到有用的知识或一些感受,我会继续努力,争取早日博士毕业,回贵州那篇土地继续教书育人。一起加油~

推荐大家阅读学生的博客:https://blog.csdn.net/ayouleyang

在这里插入图片描述

(By:Eastmount 2020-02-23 深夜10点夜于贵阳 http://blog.csdn.net/eastmount/ )


参考文献:
[1] 图像处理之opencv识别图片和视频中人脸 - 阿优乐扬
[2] https://github.com/opencv/opencv/blob/master/data/haarcascades
[3] cv2级联分类器CascadeClassifier - cchangcs
[4] OpenCV实践之路——人脸检测(C++/Python) - 冰不语
[5] 10分钟手把手教你运用Python实现简单的人脸识别 - 短短的路走走停停

发布了432 篇原创文章 · 获赞 5506 · 访问量 461万+

猜你喜欢

转载自blog.csdn.net/Eastmount/article/details/104463173