Python基于Opencv来快速实现人脸识别过程详解(完整版)


Posted in Python onJuly 11, 2019

前言

随着人工智能的日益火热,计算机视觉领域发展迅速,尤其在人脸识别或物体检测方向更为广泛,今天就为大家带来最基础的人脸识别基础,从一个个函数开始走进这个奥妙的世界。

首先看一下本实验需要的数据集,为了简便我们只进行两个人的识别,选取了beyond乐队的主唱黄家驹和贝斯手黄家强,这哥俩长得有几分神似,这也是对人脸识别的一个考验:

Python基于Opencv来快速实现人脸识别过程详解(完整版)

两个文件夹,一个为训练数据集,一个为测试数据集,训练数据集中有两个文件夹0和1,之前看一些资料有说这里要遵循“slabel”命名规则,但后面处理起来比较麻烦,因为目前opencv接受的人脸识别标签为整数,那我们就直接用整数命名吧:

Python基于Opencv来快速实现人脸识别过程详解(完整版)

为了方便,我们每个人用20张照片来训练,0代表黄家驹,1代表黄家强:

Python基于Opencv来快速实现人脸识别过程详解(完整版)

开始啦:

1.检测人脸

这应该是最基本的,给我们一张图片,我们要先检测出人脸的区域,然后才能
进行操作,opencv已经内置了很多分类检测器,我们这次用haar:

def detect_face(img):
 #将测试图像转换为灰度图像,因为opencv人脸检测器需要灰度图像
 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 #加载OpenCV人脸检测分类器Haar
 face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')
 #检测多尺度图像,返回值是一张脸部区域信息的列表(x,y,宽,高)
 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)
 # 如果未检测到面部,则返回原始图像
 if (len(faces) == 0):
 return None, None
 #目前假设只有一张脸,xy为左上角坐标,wh为矩形的宽高
 (x, y, w, h) = faces[0]
 #返回图像的正面部分
 return gray[y:y + w, x:x + h], faces[0]

2.有了数据集和检测人脸的功能后,我们就可以进行预训练了

最后返回所有训练图片的人脸检测信息和标签:

# 该函数将读取所有的训练图像,从每个图像检测人脸并将返回两个相同大小的列表,分别为脸部信息和标签
def prepare_training_data(data_folder_path):
 # 获取数据文件夹中的目录(每个主题的一个目录)
 dirs = os.listdir(data_folder_path)
 # 两个列表分别保存所有的脸部和标签
 faces = []
 labels = []
 # 浏览每个目录并访问其中的图像
 for dir_name in dirs:
 # dir_name(str类型)即标签
 label = int(dir_name)
 # 建立包含当前主题主题图像的目录路径
 subject_dir_path = data_folder_path + "/" + dir_name
 # 获取给定主题目录内的图像名称
 subject_images_names = os.listdir(subject_dir_path)
 # 浏览每张图片并检测脸部,然后将脸部信息添加到脸部列表faces[]
 for image_name in subject_images_names:
 # 建立图像路径
 image_path = subject_dir_path + "/" + image_name
 # 读取图像
 image = cv2.imread(image_path)
 # 显示图像0.1s
 cv2.imshow("Training on image...", image)
 cv2.waitKey(100)
 # 检测脸部
 face, rect = detect_face(image)
 # 我们忽略未检测到的脸部
 if face is not None:
 #将脸添加到脸部列表并添加相应的标签
 faces.append(face)
 labels.append(label)
 cv2.waitKey(1)
 cv2.destroyAllWindows()
 #最终返回值为人脸和标签列表
 return faces, labels

3.有了脸部信息和对应标签后,我们就可以使用opencv自带的识别器来进行训练了

#调用prepare_training_data()函数
faces, labels = prepare_training_data("training_data")
#创建LBPH识别器并开始训练,当然也可以选择Eigen或者Fisher识别器
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.train(faces, np.array(labels))

4.训练完毕后就可以进行预测了

在这之前我们可以设定一下预测的格式,包括用矩形框框出人脸并标出其名字,当然最后别忘了建立标签与真实姓名直接的映射表:

#根据给定的(x,y)坐标和宽度高度在图像上绘制矩形
def draw_rectangle(img, rect):
 (x, y, w, h) = rect
 cv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2)
# 根据给定的(x,y)坐标标识出人名
def draw_text(img, text, x, y):
 cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
#建立标签与人名的映射列表(标签只能为整数)
subjects = ["jiaju", "jiaqiang"]

5.现在就可以定义我们的预测函数了:

# 此函数识别传递的图像中的人物并在检测到的脸部周围绘制一个矩形及其名称
def predict(test_img):
 #生成图像的副本,这样就能保留原始图像
 img = test_img.copy()
 #检测人脸
 face, rect = detect_face(img)
 #预测人脸
 label = face_recognizer.predict(face)
 # 获取由人脸识别器返回的相应标签的名称
 label_text = subjects[label[0]]
 # 在检测到的脸部周围画一个矩形
 draw_rectangle(img, rect)
 # 标出预测的名字
 draw_text(img, label_text, rect[0], rect[1] - 5)
 #返回预测的图像
 return img

6.最后使用我们test_data中的图片进行预测并显示最终效果:

#加载测试图像
test_img1 = cv2.imread("test_data/test1.jpg")
test_img2 = cv2.imread("test_data/test2.jpg")
#执行预测
predicted_img1 = predict(test_img1)
predicted_img2 = predict(test_img2)
#显示两个图像
cv2.imshow(subjects[0], predicted_img1)
cv2.imshow(subjects[1], predicted_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

来看看识别的结果:

Python基于Opencv来快速实现人脸识别过程详解(完整版)

这就是人脸识别最基本的流程,后续还会进一步的研究,下一篇我们将讨论本次实验的一些细节和注意事项,算是对本篇的一次挖掘和总结吧。

最后附上完整代码:

# # -*- coding:utf-8 -*-
import cv2
import os
import numpy as np
# 检测人脸
def detect_face(img):
 #将测试图像转换为灰度图像,因为opencv人脸检测器需要灰度图像
 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 #加载OpenCV人脸检测分类器Haar
 face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')
 #检测多尺度图像,返回值是一张脸部区域信息的列表(x,y,宽,高)
 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)
 # 如果未检测到面部,则返回原始图像
 if (len(faces) == 0):
 return None, None
 #目前假设只有一张脸,xy为左上角坐标,wh为矩形的宽高
 (x, y, w, h) = faces[0]
 #返回图像的正面部分
 return gray[y:y + w, x:x + h], faces[0]
# 该函数将读取所有的训练图像,从每个图像检测人脸并将返回两个相同大小的列表,分别为脸部信息和标签
def prepare_training_data(data_folder_path):
 # 获取数据文件夹中的目录(每个主题的一个目录)
 dirs = os.listdir(data_folder_path)
 # 两个列表分别保存所有的脸部和标签
 faces = []
 labels = []
 # 浏览每个目录并访问其中的图像
 for dir_name in dirs:
 # dir_name(str类型)即标签
 label = int(dir_name)
 # 建立包含当前主题主题图像的目录路径
 subject_dir_path = data_folder_path + "/" + dir_name
 # 获取给定主题目录内的图像名称
 subject_images_names = os.listdir(subject_dir_path)
 # 浏览每张图片并检测脸部,然后将脸部信息添加到脸部列表faces[]
 for image_name in subject_images_names:
 # 建立图像路径
 image_path = subject_dir_path + "/" + image_name
 # 读取图像
 image = cv2.imread(image_path)
 # 显示图像0.1s
 cv2.imshow("Training on image...", image)
 cv2.waitKey(100)
 # 检测脸部
 face, rect = detect_face(image)
 # 我们忽略未检测到的脸部
 if face is not None:
 #将脸添加到脸部列表并添加相应的标签
 faces.append(face)
 labels.append(label)
 cv2.waitKey(1)
 cv2.destroyAllWindows()
 #最终返回值为人脸和标签列表
 return faces, labels
#调用prepare_training_data()函数
faces, labels = prepare_training_data("training_data")
#创建LBPH识别器并开始训练,当然也可以选择Eigen或者Fisher识别器
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.train(faces, np.array(labels))
#根据给定的(x,y)坐标和宽度高度在图像上绘制矩形
def draw_rectangle(img, rect):
 (x, y, w, h) = rect
 cv2.rectangle(img, (x, y), (x + w, y + h), (128, 128, 0), 2)
# 根据给定的(x,y)坐标标识出人名
def draw_text(img, text, x, y):
 cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
#建立标签与人名的映射列表(标签只能为整数)
subjects = ["jiaju", "jiaqiang"]
# 此函数识别传递的图像中的人物并在检测到的脸部周围绘制一个矩形及其名称
def predict(test_img):
 #生成图像的副本,这样就能保留原始图像
 img = test_img.copy()
 #检测人脸
 face, rect = detect_face(img)
 #预测人脸
 label = face_recognizer.predict(face)
 # 获取由人脸识别器返回的相应标签的名称
 label_text = subjects[label[0]]
 # 在检测到的脸部周围画一个矩形
 draw_rectangle(img, rect)
 # 标出预测的名字
 draw_text(img, label_text, rect[0], rect[1] - 5)
 #返回预测的图像
 return img
#加载测试图像
test_img1 = cv2.imread("test_data/test1.jpg")
test_img2 = cv2.imread("test_data/test2.jpg")
#执行预测
predicted_img1 = predict(test_img1)
predicted_img2 = predict(test_img2)
#显示两个图像
cv2.imshow(subjects[0], predicted_img1)
cv2.imshow(subjects[1], predicted_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python操作使用MySQL数据库的实例代码
May 25 Python
python矩阵/字典实现最短路径算法
Jan 17 Python
python3实现指定目录下文件sha256及文件大小统计
Feb 25 Python
python3.x提取中文的正则表达式示例代码
Jul 23 Python
python 图像处理画一个正弦函数代码实例
Sep 10 Python
Django REST Framework之频率限制的使用
Sep 29 Python
python中with语句结合上下文管理器操作详解
Dec 19 Python
Django 设置多环境配置文件载入问题
Feb 25 Python
Python基于Hypothesis测试库生成测试数据
Apr 29 Python
Windows下PyCharm配置Anaconda环境(超详细教程)
Jul 31 Python
PyQt5多线程防卡死和多窗口用法的实现
Sep 15 Python
再谈python_tkinter弹出对话框创建
Mar 20 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
Jul 11 #Python
PowerBI和Python关于数据分析的对比
Jul 11 #Python
pow在python中的含义及用法
Jul 11 #Python
Python简单处理坐标排序问题示例
Jul 11 #Python
如何使用Python自动控制windows桌面
Jul 11 #Python
python字典嵌套字典的情况下找到某个key的value详解
Jul 10 #Python
如何安装并使用conda指令管理python环境
Jul 10 #Python
You might like
flash用php连接数据库的代码
2011/04/21 PHP
解析php防止form重复提交的方法
2013/07/01 PHP
Javascript 面向对象 继承
2010/05/13 Javascript
chrome浏览器不支持onmouseleave事件的解决技巧
2013/05/31 Javascript
jquery阻止冒泡事件使用模拟事件
2013/09/06 Javascript
了不起的node.js读书笔记之mongodb数据库交互
2014/12/22 Javascript
JavaScript截取、切割字符串的技巧
2016/01/07 Javascript
Bootstrap基本组件学习笔记之下拉菜单(7)
2016/12/07 Javascript
关于iframe跨域POST提交的方法示例
2017/01/15 Javascript
Bootstrap3下拉菜单的实现
2017/02/22 Javascript
js读取json文件片段中的数据实例
2017/03/09 Javascript
初识 Vue.js 中的 *.Vue文件
2017/11/22 Javascript
使用Angular CLI生成 Angular 5项目教程详解
2018/03/18 Javascript
vue 根据数组中某一项的值进行排序的方法
2018/08/30 Javascript
TypeScript类型声明书写详解
2019/08/28 Javascript
vue实现树形结构样式和功能的实例代码
2019/10/15 Javascript
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
Django中实现一个高性能计数器(Counter)实例
2014/07/09 Python
Python编写Windows Service服务程序
2018/01/04 Python
python生成密码字典的方法
2018/07/06 Python
python如何获取列表中每个元素的下标位置
2019/07/01 Python
Python+PyQt5+MySQL实现天气管理系统
2020/06/16 Python
Python+kivy BoxLayout布局示例代码详解
2020/12/28 Python
浅谈matplotlib默认字体设置探索
2021/02/03 Python
HTML5之SVG 2D入门12—SVG DOM及DOM操作介绍
2013/01/30 HTML / CSS
TCP/IP的分层模型
2013/10/27 面试题
C#面试常见问题
2013/02/25 面试题
写自荐信的七个技巧
2013/10/15 职场文书
求职信模板标准格式范文
2014/02/23 职场文书
经典团队口号大全
2014/06/21 职场文书
教育局党的群众路线教育实践活动整改方案
2014/09/20 职场文书
交通事故委托书范本精选
2014/10/04 职场文书
小学教师2014年度工作总结
2014/12/03 职场文书
2015年预备党员自我评价
2015/03/04 职场文书
幼师求职自荐信
2015/03/26 职场文书
2015年城管个人工作总结范文
2015/04/20 职场文书