本节将介绍 Haar 级联分类器,通过对比分析相邻图像区域来判断给定图像或子图像与已知对象是否匹配。

本章将考虑如何将多个  Haar 级联分类器构成一个层次结构,即一个分类器能识别整体区域(如人脸),而其他的分类器可识别小的区域(如鼻子、眼睛和嘴)。

1 Haar 级联的概念

图像会因灯光、视角、视距、摄像头抖动以及数字噪声的变化而使得细节变得不稳定。所以提取图像的细节对产生稳定分类结果和跟踪结果很有作用。这些提取的结果被称为特征。

专业的表述为:从图像数据中提取特征。虽然任意像素都可能影响多个特征,但特征应该比像素少的多,两个图像的相似程度可以通过它们对应特征的欧式距离来度量。

例如:距离可能以空间坐标或颜色坐标来定义。类 Haar 特征是一种用于实现实时人脸跟踪的特征,每个类 Haar 特征都描述了相邻图像区域的对比模式。例如,边、顶点和细线都能生成具有判别的特征。

对于给定的图像,特征可能会因区域大小(也成为窗口大小 window size)而有所不同。仅在尺度上不同的两幅图也应该有相似的特征。因此能为不同大小的窗口生成特征非常有用,这些特征几何称之为级联。

Haar 级联具有尺度不变性,也即在尺度变化上具有鲁棒性。OpenCV 提供了尺度不变 Haar 级联的分类器和跟踪器,可将其保存成指定的文件格式。

注意:OpenCV 的 Haar 级联不具有旋转不变性;如,Haar 级联不认为倒置的人脸图像和直立的人脸图像一样,而侧面的人脸图像和正面的人脸图像也不一样;更可通过多种图像变换和多种窗口大小来提高 Haar 级联的旋转鲁棒性,但这样会变得很复杂,而且会耗费更多计算资源。

2 获取 Haar 级联数据

2.1 haarcascades---各种分类器xml文件在哪里?

(小插曲,可直接跳过本节内容,没干货)

在《OpenCV 3 计算机视觉 Python语言实现》中有这样一段话:

在 OpenCV 3 源代码的副本中会有一个文件夹 data/haarcascades。

我就先找源代码,当时的思路是先找 OpenCV 包的安装源代码,方式如下

  1. C:\Users\****>python
  2. >>> import cv2
  3. >>> print(cv2.__file__)
  4. C:\Users\***\AppData\Local\Programs\Python\Python36\lib\site-packages\cv2.cp36-win_amd64.pyd

将文件路径

(C:\Users\***\AppData\Local\Programs\Python\Python36\lib\site-packages)

复制到文件地址栏,看到关于opencv的文件如下:

  • opencv_python-4.0.1.dist-info(文件夹)
  • cv.py
  • cv2.cp36-win_amd64.pyd
  • opencv.LICENSE
  • opencv.LICENSE-3RD-PARTY
  • opencv_ffmpeg401_64.dll

没有data/haarcascades文件。

查看包 packages 还可以采用下列代码

  1. >>> import sys
  2. >>> sys.path
  3. ['', 'C:\\Users\\***\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\***\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\***\\AppData\\Local\\Programs\\Python\\Python36\\lib','C:\\Users\\***\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\***\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages']

或者

  1. >>> import sys
  2. >>> module = sys.path
  3. >>> for i in module:
  4. ... print(i)
  5. ...(再敲一下回车键)
  6.  
  7. C:\Users\***\AppData\Local\Programs\Python\Python36\python36.zip
  8. C:\Users\***\AppData\Local\Programs\Python\Python36\DLLs
  9. C:\Users\***\AppData\Local\Programs\Python\Python36\lib
  10. C:\Users\***\AppData\Local\Programs\Python\Python36
  11. C:\Users\***\AppData\Local\Programs\Python\Python36\lib\site-packages

没有找到haarcasades文件夹,我想再继续看看安装的源代码 .whl 文件

先看看 OpenCV 的版本,查看方式如下:

方案一:先在命令提示符中输入python,进入python环境。

  1. python>>> import cv2
  2. >>> cv2.__version__
  3. '4.0.1'

方案二:直接在命令提示符中输入下段代码

  1. C:\Users\***>pip list
  2. Package Version
  3. --------------- ----------
  4. absl-py 0.6.1
  5. opencv-python 4.0.1
  6. ...

该方法会显示出基于 pip 安装的所有 packages 列表。

打开安装的 .whl 文件,找到当时我的安装文件

opencv_python-4.0.1-cp36-cp36m-win_amd64.whl,

将.whl后缀修改为.zip,即

opencv_python-4.0.1-cp36-cp36m-win_amd64.zip

再将其解压,也没有发现书中所述文件,在data文件下下有 opencv_ffmpeg401_64.dll 文件。

2.2 haarcascades---各种分类器xml文件在这里

直接打开OpenCV(官网https://opencv.org/最下方有GitHub的代码超链接)在GitHub上的官方文件即可。文件地址:

https://github.com/opencv/opencv/tree/master/data/haarcascades

在这里( opencv / data / haarcascades / )有所有 OpenCV haarcascades 文件,这些文件可用于检测静止图像、视频和摄像头所得到的图像中的人脸。

首先创建一个项目文件夹,然后再创建一个子文件(命名为 cascade),将 haarcascades 文件夹中的所有文件复制到 cascades 文件夹中。

为方便下载,可以直接下载 haarcascdes 文件夹【点击我

其文件目录如下:

  1. └─cascades
  2. haarcascade_eye.xml
  3. haarcascade_eye_tree_eyeglasses.xml
  4. haarcascade_frontalcatface.xml
  5. haarcascade_frontalcatface_extended.xml
  6. haarcascade_frontalface_alt.xml
  7. haarcascade_frontalface_alt2.xml
  8. haarcascade_frontalface_alt_tree.xml
  9. haarcascade_frontalface_default.xml
  10. haarcascade_fullbody.xml
  11. haarcascade_lefteye_2splits.xml
  12. haarcascade_licence_plate_rus_16stages.xml
  13. haarcascade_lowerbody.xml
  14. haarcascade_profileface.xml
  15. haarcascade_righteye_2splits.xml
  16. haarcascade_russian_plate_number.xml
  17. haarcascade_smile.xml
  18. haarcascade_upperbody.xml

从文件名可知,这些级联是用于人脸、眼睛、鼻子和嘴的跟踪(人脸检测器),这些文件需要正面、直立的人脸图像。

接下来我们创造自己的级联,并训练这些级联来检测各种对象。

2019年03月10日更新

今天发现不同的安装方式,其包含的内容是由区别的,因为要学习书中第六节内容SIFT,结果采用重新安装 opencv。

  1. pip install opencv_contrib_python

发现文件中就含有data/***.xml 检测器文件。

而采用在python非官方第三方库中下载安装,就没有data/.xml 文件。

3 使用 OpenCV 进行人脸检测

人脸检测的图像来源可分为:

  • 静态图像
  • 视频

静态图像和视频中检测人脸的操作非常相似,基本理论也是一致的;实际上,视频人脸检测是从摄像头中读取每帧图像,然后采用静态图像中的人脸检测方法进行检测;不过视频人脸检测还涉及诸如跟踪等静态图像中没有的概念。

3.1 静态图像中的人脸检测

图像识别内容及其分析详见下代码

  1. import cv2
  2.  
  3. filename = './pic.jpg'
  4.  
  5. def detect(filename):
  6. # 声明一个变量,该变量为级联分类器CascadeClassifier对象,它负责人脸检测
  7. face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
  8.  
  9. # 加载文件并将其转为灰度图,因人脸检测需要这样的色彩空间
  10. img = cv2.imread(filename)
  11. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  12. # detectMultiScale函数检测操作返回人脸矩形数组
  13. # scaleFactor=1.15 - 人脸检测过程中每次迭代时图像的压缩率
  14. # minNeighbors=5 - 人脸检测过程中每次迭代时每个人脸矩形保留近邻数目的最小值,   # 调节这两个参数可以实现人脸的有效识别
  15. faces = face_cascade.detectMultiScale(gray,1.15, 5)
  16. # print(faces.shape) # (16,4)
  17. # 这里面会出现 16 行 4 列,代表16个矩形
  18. # 每个矩形为(x,y,w,h)
  19. print(faces)
  20.  
  21. # 通过依次提取faces变量中的值来找人脸,并在人脸周围绘制蓝色矩形(255,0,0)
  22. # cv2.rectangle通过坐标绘制矩形(x和y表示左上角,w和h表示人脸矩形的宽度和高度
  23. # 注意这是在原始图像而不是灰度图上进行绘制
  24. for (x,y,w,h) in faces:
  25. img = cv2.rectangle(img, (x,y),(x+w,y+h),(255,0,0),2)
  26. # 最后创建nameWindow的实例,并显示处理后的图像。
  27. cv2.namedWindow('Detected')
  28. cv2.imshow('Detected',img)
  29. cv2.imwrite('./Detected.jpg', img)
  30. # 加入waitKey函数,这样在按下任意键时才可关闭窗口
  31. cv2.waitKey(0)
  32.  
  33. detect(filename)

运行

  1. [[1916 781 121 121]
  2. [1524 804 122 122]
  3. [2308 796 132 132]
  4. [2788 1305 292 292]
  5. [2917 848 162 162]
  6. [ 165 1172 241 241]
  7. [3366 1182 246 246]
  8. [1181 851 135 135]
  9. [2663 853 138 138]
  10. [ 604 869 158 158]
  11. [ 797 1194 240 240]
  12. [ 884 905 144 144]
  13. [3132 935 155 155]
  14. [ 385 978 196 196]
  15. [3579 1029 230 230]
  16. [1544 1312 249 249]]

输出图像 【原图像

3.2 视频中的人脸检测

3.1 的章节内容可以实现静态图像上的人脸检测;实际上,在视频的帧上重复3.1 章节中的过程就能完成视频(摄像头的输入或视频文件)中的人脸检测。

在书中的其他地方一直出现报错,后来 参考 视频人脸检测——OpenCV版(三),两者结合学习才将问题解决。同时觉得课本上的代码结构没有 王磊 博客中那个合理,书中将人脸检测和视频流读入有部分杂糅。下图是可以运行的代码。

  1. import cv2
  2.  
  3. # 图片识别方法封装,
  4. def discern(img):
  5. # 将图img转为灰度图,因opencv中的人脸检测是基于灰度的色彩空间
  6. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  7. # 实例化级联分类器
  8. face_cascade = cv2.CascadeClassifier('D:/project/opencv3/c5/cascades/haarcascade_frontalface_default.xml')
  9. # 调用图像中的对象,并返回矢量矩形
  10. faceRects = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=3, minSize=(50, 50))
  11. # 只要视频存在,就输出人脸识别框
  12. if len(faceRects):
  13. # 框出人脸,分开写
  14. # for faceRect in faceRects:
  15. # x, y, w, h = faceRect
  16. # cv2.rectangle(img, (x, y), (x + h, y + w), (0, 255, 0), 2)
  17. # 框出人脸,合并写
  18. for (x,y,w,h) in faceRects:
  19. # 在原彩色图img上绘制识别的人脸矩形
  20. cv2.rectangle(img, (x, y), (x + h, y + w), (0, 255, 0), 2)
  21. # 将绘制有矩形框的img显示输出
  22. cv2.imshow("Image", img)
  23.  
  24. # 打开一个VideoCapture目标(初始化摄像头)
  25. # 参数为摄像头ID,0表获取第一个摄像头
  26. cap = cv2.VideoCapture(0)
  27. while(True):
  28. # 将视频逐帧显示
  29. ret, img = cap.read()
  30. # 调用discern函数
  31. discern(img)
  32. if cv2.waitKey(1) & 0xFF == ord('q'):
  33. break
  34. # 释放摄像头
  35. cap.release()
  36. # 释放窗口资源
  37. cv2.destroyAllWindows()

运行输出

可以识别出人物。

3.3 视频中的人脸和人眼检测

将3.2 章节中的内容进行丰富,人脸识别的同时,增加人眼识别。代码如下:

  1. import cv2
  2.  
  3. # 图片识别方法封装,
  4. def discern(img):
  5. # 将图img转为灰度图,因opencv中的人脸检测是基于灰度的色彩空间
  6. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  7. # 实例化级联分类器
  8. face_cascade = cv2.CascadeClassifier('D:/project/opencv3/c5/cascades/haarcascade_frontalface_default.xml')
  9. eye_cascade = cv2.CascadeClassifier('D:/project/opencv3/c5/cascades/haarcascade_eye.xml')
  10. # 调用图像中的对象,并返回矢量矩形
  11. faceRects = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=3, minSize=(50, 50))
  12. # 只要视频存在,就输出人脸识别框
  13. if len(faceRects):
  14. # 框出人脸,分开写
  15. # for faceRect in faceRects:
  16. # x, y, w, h = faceRect
  17. # cv2.rectangle(img, (x, y), (x + h, y + w), (0, 255, 0), 2)
  18. # 框出人脸,合并写
  19. for (x,y,w,h) in faceRects:
  20. # 在原彩色图img上绘制识别的人脸矩形
  21. cv2.rectangle(img, (x, y), (x + h, y + w), (0, 255, 0), 2)
  22. # 将眼睛区域限制在人脸范围内,不过这种方式不太好用
  23. # roi_gray = gray[y:y+h, x:x+w]
  24. # eyes = eye_cascade.detectMultiScale(roi_gray,scaleFactor=1.03,minNeighbors=5,flag=0,minSize=(40,40))
  25. eyes = eye_cascade.detectMultiScale(img,scaleFactor=1.03,minNeighbors=5,minSize=(40,40))
  26.  
  27. # 框出人眼
  28. for (ex,ey,ew,eh) in eyes:
  29. cv2.rectangle(img,(ex,ey),(ex+ew,ey+eh),(0,0,255),2)
  30.  
  31. # 将绘制有矩形框的img显示输出
  32. cv2.imshow("Image", img)
  33.  
  34. # 打开一个VideoCapture目标(初始化摄像头)
  35. # 参数为摄像头ID,0表获取第一个摄像头
  36. cap = cv2.VideoCapture(0)
  37. while(True):
  38. # 将视频逐帧显示
  39. ret, img = cap.read()
  40. # 调用discern函数
  41. discern(img)
  42. if cv2.waitKey(1) & 0xFF == ord('q'):
  43. break
  44.  
  45. # 释放摄像头
  46. cap.release()
  47. # 释放窗口资源
  48. cv2.destroyAllWindows()

在眼睛检测中增加了参数,增加的主要原因是detectMultiScale有许多参数;在人脸检测时,默认的选项足以完成人脸检测,但是眼睛是一个比较小的人脸特征,且还存在胡子、鼻子等本身阴影(self-casting shadow)以及帧的随机阴影都会产生假阳性(false positive)

通过限制对眼睛搜索的最小尺寸为 40 * 40 像素,可去掉所有的假阳性。然后调试这些参数,直到程序可满足预期(例如,可以尝试指定特征的最大尺寸,或增加比例因子以及邻近的数量)。


关于 cv2.waitKey(1) & 0xFF == ord('q') 的理解

Opencv中使用waitKey(10) & 0xFF的原因

cv2.waitKey

用python opencv 调用摄像头之if cv2.waitKey(1) & 0xFF == ord('q')分析

3.4 人脸识别

人脸检测是OpenCV的一个不错的功能,它是人脸识别的基础。

人脸识别就是程序能识别给定图像或视频中的人脸;可通过一系列分好类的图像(人脸数据库)来 ” 训练 “ 程序。并基于这些图像进行识别。

人脸识别所需的人脸获取方式

  • 自己获得图像
  • 从人脸数据库免费获得可用的人脸图像

3.4.1 生成人脸识别数据

人脸识别模块的一项重要特征:每个识别都具有转置信(confidence)评分。所以在实际应用中通过对其设置阈值来进行筛选。

下段代码可制定样本,依据代码可知,样本具有如下特征:

  • 图像为灰度格式,后缀名为.pgm
  • 图像为正方形
  • 图像大小要一样(这里保存为200*200,大多是免费图像集都比这个小)

具体代码如下:

  1. import cv2
  2. import time
  3.  
  4. # 图像名编号
  5. count = 1
  6. # 记录循环次数
  7. i = 1
  8. # 控制图片保存频率,间隔10次保存一次图像
  9. FREQUENCY = 5
  10. # 拟制备样本数量
  11. MAX = 20
  12.  
  13. # 图片识别方法封装,
  14. def discern(img):
  15. global count
  16. global i
  17. global FREQUENCY
  18.  
  19. # 将图img转为灰度图,因opencv中的人脸检测是基于灰度的色彩空间
  20. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  21. # 实例化级联分类器
  22. face_cascade = cv2.CascadeClassifier('D:/project/opencv3/c5/cascades/haarcascade_frontalface_default.xml')
  23. eye_cascade = cv2.CascadeClassifier('D:/project/opencv3/c5/cascades/haarcascade_eye.xml')
  24. # 调用图像中的对象,并返回矢量矩形
  25. faceRects = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
  26. # 只要视频存在,就输出人脸识别框
  27. if len(faceRects):
  28. # 框出人脸
  29. for (x,y,w,h) in faceRects:
  30. # 在原彩色图img上绘制识别的人脸矩形
  31. cv2.rectangle(img, (x, y), (x + h, y + w), (255, 0, 0), 2)
  32. # 裁剪灰度帧的区域,将其调整为200*200像素
  33. f = cv2.resize(gray[y:y+h, x:x+w],(200,200))
  34.  
  35. # 控制输出频率,如果没有控制,则输出的非常快
  36. i += 1
  37. if i % FREQUENCY == 0:
  38. # 将裁剪区域保存到指定文件夹中,文件后缀名为.pgm
  39. cv2.imwrite('D:/project/opencv3/c5/%s.pgm' %str(count),f)
  40. count += 1
  41.  
  42. # 将绘制有矩形框的img显示输出
  43. cv2.imshow("camera",img)
  44.  
  45. # 打开一个VideoCapture目标(初始化摄像头)
  46. # 参数为摄像头ID,0表获取第一个摄像头
  47. cap = cv2.VideoCapture(0)
  48. while(True):
  49. # 将视频逐帧显示
  50. ret, img = cap.read()
  51. # 调用discern函数
  52. discern(img)
  53.  
  54. if cv2.waitKey(1) & 0xFF == ord('q'):
  55. break
  56. # 如果大于所需样本数量,则推出循环程序
  57. if count > MAX:
  58. break
  59.  
  60. # 释放摄像头
  61. cap.release()
  62. # 释放窗口资源
  63. cv2.destroyAllWindows()

注意:

如果不加图像保存速率,则会短时间内保存大量图片;同时图像保存速率可以人为控制,实验中发现,时间间隔愈大,运行速度越慢。

3.4.2 人脸识别

OpenCV 3 有三种人脸识别的方式,对应于三种不同的算法:

  • Eigenfaces - Eigenfaces 是通过 PCA 来处理的,PCA 是计算机视觉中提到最多的数学概念。PCA 的本质是识别某个训练集上(比如人脸数据库)的主成分,并计算出训练集(图像或帧中检测到的人脸)相对于数据库的发散程度,并输出一个值。该值越小,表明人脸数据库和检测到的人脸之间的差别就越小;0 值表示完全匹配。
  • Fisherfaces - Fisherfaces 是从PCV 衍生并发展起来的概念,它采用更复杂的逻辑。尽管计算更加密集,但比Eigenfaces 更容易得到准确的效果。
  • Local Binary Pattern Histogram(LBPH) - LBPH粗略地(在非常高的层次上)将检测到的人脸分成小单元,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图。由于这种方法的灵活性,LBPH 是唯一允许模型样本人脸和检测到的人脸在形状、大小上可以不同的人脸识别算法。书中作者认为这种是最准确的算法,但是每个算法都有其长处和缺点。

备注:所有的方法都有类似的过程,即都使用了分好类的训练数据集(人脸数据库,每个人都有很多样本)来进行 " 训练 “ ,对图像或视频中检测到的人脸进行分析,并从两方面来确定:

  • 是否识别到目标
  • 目标真正被识别到的置信度的度量,这也称为置信度评分

2.4.3 准备训练数据

将已有的样本图像加载到人脸识别算法中。

一般而言,人脸识别算法在它们的 train() 函数中都有两个参数:

  • 图像数组
  • 标签数组

基于上述要求创建一个 逗号分隔值(comma-separated value,CSV)的文件,并用ID记录样本图像的路径。CSV文件内容如下所示

jm/1.pgm; 0

jm/2.pgm; 0

jm/3.pgm; 0

...

jm - 文件夹

1.pgm、2.pgm - 样本图像

0 - 人脸ID,假如 A 的人脸ID为0,B 的人脸 ID 为 1 。标签。

2.4.4 加载数据并识别人脸

本段代码会将 图像数组 和 CSV 文件加载到人脸识别的算法中,以训练人脸识别算法。

1、需要创建函数用来逐行读取 CSV 文件。

2、将对应路径的图像加载到图像数组中。

3、将 ID 加载到标签数组中。

4、基于 Eigenfaces 的人脸识别

详细代码如下所示:

  1. import cv2
  2. import os
  3. import numpy as np
  4.  
  5. # 建立标签
  6. label_num = [0, 1, 2]
  7. label_name = ["gengyi", "cat", "gengniu"]
  8. images = []
  9. labels = []
  10.  
  11. # 将图像数组和CSV文件加载到人脸识别的算法中
  12. def read_images(path):
  13. # 定义数据和标签
  14. # 获取path文件下的文件及文件夹并返回名称列表
  15. for dir_item in os.listdir(path):
  16. # 返回path规范化的绝对路径
  17. path_abs = os.path.abspath(os.path.join(path, dir_item))
  18. # 判断path_abs是文件还是文件还是文件夹
  19. try:
  20. # str.endswith()是判断文件str后缀是否为指定格式
  21. # 本图像指定为.png格式
  22. if(path_abs.endswith('.png')):
  23. # print("try:", path_abs)
  24. # 读取训练数据
  25. img = cv2.imread(path_abs)
  26. # 统一输入文件的尺寸大小
  27. img = cv2.resize(img, (200, 200))
  28. # 统一图像文件的元素dtype,并将其加入images中
  29. images.append(np.asarray(img, dtype=np.uint8))
  30. # 为训练数据赋标签
  31. # 简单地可以用,当文件夹为me时,标签设置为0
  32. # if(dir_item.endswith('gengyi')):
  33. # labels.append(0)
  34. # 为了代码更具有实用性,拟以下处理
  35. # 先将path_abs分割,注意分割线\\,而不是//
  36. path_piece = path_abs.split('\\')
  37. # 为训练数据赋标签,较多标签通过elif追加即可
  38. if label_name[0] in path_piece:
  39. labels.append(label_num[0])
  40. elif label_name[1] in path_piece:
  41. labels.append(label_num[1])
  42. elif label_name[2] in path_piece:
  43. labels.append(label_num[2])
  44. else:
  45. # 没有对应标签则删除训练数据
  46. images.pop()
  47. # pass
  48. # 若为文件夹则递归调用,循环读取子子文件内容
  49. elif os.path.isdir(path_abs):
  50. read_images(path_abs)
  51. # 若为其他情况则循环运行
  52. else:
  53. continue
  54. # 当发生异常时则抛出异常信息e
  55. except Exception as e:
  56. print("REASON:", e)
  57. print('labels:',labels)
  58. print("images:",images)
  59. return images, labels
  60.  
  61. # 基于Eigenfaces的模型训练
  62. def face_model():
  63.  
  64. # 使用label_num作为全局变量
  65. # 每当脚本识别出一个ID,就会将相应名称数组中的名字打印到人脸上
  66. global label_num
  67. # 获取文件所在文件夹的绝对路径
  68. path = os.getcwd()
  69. # 调用图像读入函数,获取训练数据及标签
  70. images, labels = read_images(path)
  71. # print("face_model_images:", images)
  72.  
  73. # 实例化人脸识别模型
  74. model = cv2.face.EigenFaceRecognizer_create()
  75. # 通过图像数组和标签来训练模型
  76. model.train(np.asarray(images), np.asarray(labels))
  77.  
  78. return model
  79.  
  80. def face_rec():
  81. # 调用训练好的模型
  82. face_model_trained = face_model()
  83. # 初始化摄像头
  84. camera = cv2.VideoCapture(0)
  85. # 实例化人脸识别级联分类器
  86. face_cascade = cv2.CascadeClassifier('D:/project/opencv3/c5/cascades/haarcascade_frontalface_default.xml')
  87. while(True):
  88. read, img = camera.read()
  89. faces = face_cascade.detectMultiScale(img, 1.3, 5)
  90. for (x, y, w, h) in faces:
  91. img = cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
  92. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  93. roi = gray[x:x+w, y:y+h]
  94. try:
  95. roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
  96. # predict()预测函数,返回预测标签和置信度
  97. params = face_model_trained.predict(roi)
  98. print("Label: %s, confidence: %0.2f" % (label_name[params[0]], params[1]))
  99. cv2.putText(img, label_name[params[0]], (x, y-20), cv2.FONT_HERSHEY_SIMPLEX, 3, (255, 0, 0), 2)
  100. except Exception as e:
  101. print("face_rec_REASON:", e)
  102.  
  103. cv2.imshow('camera', img)
  104. if cv2.waitKey(10) & 0xff == ord('q'):
  105. break
  106.  
  107. cv2.destroyAllWindows()
  108.  
  109. if __name__ == '__main__':
  110. face_rec()

注意:上述代码是基于被训练的图片与该文件在同一个文件夹下。

备注:代码一直识别错误。查找不出原因。

附:

2.4.5 基于 Fisherfaces 的人脸识别

Fisherfaces 的实现过程并没有太大变化,只需要采用不同的算法。模型变量的声明如下:

  1. model = cv2.face.FisherFaceRecognizer_create()

备注:该函数与 《 OpenCV 3 计算机视觉 Python 语言实现》中的函数有差别。该函数参数与 Eigenfaces 参数相同,保留 Fisherfaces 的参数以及置信度阈值;置信度高于该阈值的人脸将被丢弃。

2.4.6 基于 LBPH 的人脸识别

该运算过程与前面的识别过程很类似;该算法的参数有点复杂,这些参数依次表示 radius、neighbors、grid_x、grid_y 以及置信度阈值;如果不指定这些值,这些参数就会取默认值:1,8,8,8,123.0。模型声明如下。

  1. model = cv2.face.createLBPHFaceRecognizer()

备注:

对于 LBPH 不需要调整图像大小,因为网格中的分割允许在每个单元中比较识别到的模式。

对于上面的话,纯书中的内容,没有验证!

2.4.7 通过置信度评分来丢弃结果

predict() 函数返回值含有两个元素的数组:

  • 被识别个体的标签
  • 置信度评分

所有的算法都有一个置信度评分阈值,置信度评分用来衡量所识别人脸与原模型的差距,0 表示完全匹配。

可能有时不想保留所有的识别结果,则需进一步处理,因此可用自己的算法来估算识别的置信度评分。

例如:如果正在试图识别视频中的人,则可能要分析后续帧的置信度评分来评估识别是否成功,在这种情况下,可通过算法来检查得到的置信度评分,然后得出自己的结论。

Eigenfaces / Fisherfaces 和 LBPH 的置信度评分值完全不同。Eigenfaces 和 Fisherfaces 将产生 0 到 20000 的值,而任意低于 4000 到 5000 的评分都是相当可靠的识别。

LBPH 有类似的工作方式,但是一个好的识别参考值要低于 50 ,任何高于 80 的参考值都会被认为是低的置信度评分。

Python中 sys.argv[]的用法简明解释

os.walk和os.listdir遍历目录比较

python os.path模块常用方法详解

Python endswith()方法

Python List 删除元素

os.getcwd()、sys.path[0]、sys.argv[0]和__file__的区别

  1. import os
  2.  
  3. print(os.path.abspath('C:/Downloads/Machine Learning for OpenCV - 2017.pdf'))
  4.  
  5. # C:\Downloads\Machine Learning for OpenCV - 2017.pdf

Python 3.2

  1. os.makedirs(path, exist_ok=True)

python 3.2创建目录新增了可选参数existok,把existok设置True,创建目录如果已经存在则不会往外抛出异常。exist_ok默认值为False

OpenCV 学习笔记 05 人脸检测和识别的更多相关文章

  1. OpenCV 学习笔记 05 人脸检测和识别 AttributeError: module 'cv2' has no attribute 'face'

    1 环境设置: win10 python 3.6.8 opencv 4.0.1 2 尝试的方法 在学习人脸识别中,遇到了没有 cv2 中没有 face 属性.在网上找了几个方法,均没有成功解决掉该问题 ...

  2. OpenCV 学习笔记 07 目标检测与识别

    目标检测与识别是计算机视觉中最常见的挑战之一.属于高级主题. 本章节将扩展目标检测的概念,首先探讨人脸识别技术,然后将该技术应用到显示生活中的各种目标检测. 1 目标检测与识别技术 为了与OpenCV ...

  3. OpenCV 学习笔记 05 级联分类器CascadeClassifier类

    在人脸检测中,CascadeClassifier 是一个类,该类的作用是(基于官方已经训练好的数据文件 .xml)实例化一个检测器. 1 类 CascadeClassifier 的概述 首先看一下该类 ...

  4. OpenCV学习代码记录——人脸检测

    很久之前学习过一段时间的OpenCV,当时没有做什么笔记,但是代码都还在,这里把它贴出来做个记录. 代码放在码云上,地址在这里https://gitee.com/solym/OpenCVTest/tr ...

  5. opencv学习笔记霍夫变换——直线检测

    参考大佬博文:blog.csdn.net/jia20003/article/details/7724530 lps-683.iteye.com/blog/2254368 openCV里有两个函数(比较 ...

  6. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  7. 基于OpenCv的人脸检测、识别系统学习制作笔记之三

    1.在windows下编写人脸检测.识别系统.目前已完成:可利用摄像头提取图像,并将人脸检测出来,未进行识别. 2.在linux下进行编译在windows环境下已经能运行的代码. 为此进行了linux ...

  8. 基于OpenCV读取摄像头进行人脸检测和人脸识别

    前段时间使用OpenCV的库函数实现了人脸检测和人脸识别,笔者的实验环境为VS2010+OpenCV2.4.4,opencv的环境配置网上有很多,不再赘述.检测的代码网上很多,记不清楚从哪儿copy的 ...

  9. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

随机推荐

  1. [转] nginx配置HTTPS

    使用ssl模块配置同时支持http和https并存 一,生成证书 # 1.首先,进入你想创建证书和私钥的目录,例如: cd /etc/nginx/ # 2.创建服务器私钥,命令会让你输入一个口令: o ...

  2. jQuery如何退出each循环 和如何退出function函数

    1.在函数内部使用return false是跳出function; 2.在each的回调函数中使用return false,是跳出each循环;return true 进入下一个循环: 3.break ...

  3. this关键字的用法(包括this语句)

    一:概述 this代表它所在函数所属对象的引用. 简单说:哪个对象在调用this所在的函数,this就代表哪个对象. 二:关于运用的程序 同龄人的比较. 三:关于this语句的使用 用于构造函数之间进 ...

  4. 003 将spark源码导入到IDEA中

    1.解压源代码 2.进入IDEA的首界面 3.使用open将解压的工程加载 4.将文件的形式改成maven项目 5.使用

  5. kms可用激活服务器地址|kms可用激活服务器分享

    kms可用激活服务器地址|kms可用激活服务器分享   kms可用激活服务器地址都有哪些呢?使用kms激活服务器激活windows和office是微软提供的激活方式之一.kms激活服务器普遍由个人或企 ...

  6. mongoDB的配置以及运行

    干嘛的:数据库,nosql(非关系型)   场景:解决大规模数据集合多重数据种类 一.mongoDb安装: 下载地址: https://www.mongodb.com/download-center ...

  7. go语言爬虫 - TapTap用户都喜欢些什么游戏

    前面的废话 说到爬虫,首先想到的当然是python~ 它在机器学习.爬虫数据分析领域可谓是如日中天,十分热门.但我最近在学习go语言,所以就用go写了 TapTap社区 这是一个高品质的游戏分享社区, ...

  8. socket.io的用户认证

    一直专心于写代码,遇到问题便看别人的博客来解决问题,突然感觉自己也应该写点东西帮助别人来解决问题.废话不多说了,直接切入正题~ 最近在写一个聊天室来学习node和socket相关知识.遇到的问题描述: ...

  9. anaconda虚拟环境管理,从此Python版本不用愁

    1 引言 在前几篇博文中介绍过virtualenv.virtualenvwrapper等几个虚拟环境管理工具,本篇要介绍的anaconda也有很强大的虚拟环境管理功能,甚至相比virtualenv.v ...

  10. 【原创】ABP之IConventionalDependencyRegistra接口分析

    类图: 作用: abp中默认把对象的注册分为5中约定注册方式: 1.AbpAspNetCoreConventionalRegistrar public class AbpAspNetCoreConve ...