Skip to content

Yanshee 人工智能 6 让机器人捕捉你的脸

UBTEDU edited this page Aug 31, 2018 · 1 revision

课程目标

本次课程将学习如何使用机器人自带树莓派摄像头基于 opencv跟踪人的正脸和基于 opencv 的检测器制作。通过本节课, 你可以学习如何进行实时跟踪目标,使用picamera第三方库打开树莓派摄像头获得实时视频流,使用opencv自带数据或是制作自己的检测分类数据,了解检测分类器制作与工作原理 ,学习一些人脸特征与快速计算方法,为日后自己建立人脸检测器打下基础。

课程引入原因

生物识别技术已广泛应用于政府,军队,银行,社会福利保障,电子商务,安全防务等领域。例如,银行可以使用摄像机扫描储户眼睛进行身份识别,快速而又精准的为客户办理业务。 又例如美国两家机场使用美国维萨格公司的脸像识别技术, 成功判断出了在人群中的恐怖分子。随着人脸识别技术更进一步的成熟与社会认同度高, 这项技术更广泛的应用于住宅管理,自助服务,信息安全等。人脸识别分为几大技术人脸图像采集与检测,人脸图像预处理,人脸图像特征提取,人脸图像匹配与识别。

在接下来的三节课我们将循序渐进地学习如何很捕捉人脸,如何模式判别物体,如何判别不同人脸。

基础概念及知识点介绍

Opencv

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和MacOS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

人脸跟踪

人脸的跟踪实际上是检测每一帧图片是否包含人脸(一个或多个),如果包含则返回人脸坐标信息和大小信息。

人脸检测

人脸检测是将提取出的人脸特征与非人脸特征,运用分类器多尺度检测。常用于人类检测的特征包含 HOG 特征(轮廓梯度特征,常用于行人检测), HAAR 特征 (人脸灰度特征,本课程将在接下来将详细介绍), LBP 特征(图像局部纹理特征)等

如有兴趣可参阅: http://dataunion.org/20584.html

Opencv中的人脸特征检测分类器

哈尔特征

哈尔特征 (HAAR) 是一种反映图像的灰度变化的,像素分模块求差值的一种特征。它分为四类:边缘特征、线性特征、中心特征和对角线特征。用黑白两种矩形框组合成特征模板,在特征模板内用黑色矩形像素和减去白色矩形像素和来表示这个模版的特征值。人脸部的一些特征能由矩形模块差值特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述在特定方向(水平、垂直、对角)上有明显像素模块梯度变化的图像结构。下图显示了一些哈尔特征。

例如一个头像的某一块区域的边缘灰度特征一号可以计算为 sum(black) - sum(white) 。

积分直方图

积分直方图是为了方便HAAR特征计算而创造的。其核心思想为将一幅图片中的像素分为一些小的像素矩形如 320 * 320 的图像分为不同的小矩形,每一个小矩形右下角坐标的灰度值为左上角所有像素灰度的和。其计算公式为

这样,一幅图片中任意大小矩形的灰度和能被快速求出。以下图片显示了一般积分图

上图中, 肉色区域灰度值即为 ii(x,y) + ii(u,v) - ii(x,v) - ii(u,y)

除了一般积分直方图还有45 度倾斜积分直方图, 此直方图用于快速计算45倾斜哈尔特征。

计算公式为

如果要计算上图中的虚线部分灰度和

级联分类器与Adaboost算法

Boosting算法涉及到两个重要的概念就是弱学习和强学习,所谓的弱学习,就是指一个学习算法对一组概念的识别率只比随机识别好一点,所谓强学习,就是指一个学习算法对一组概率的识别率很高。Kearns和Valiant提出了弱学习和强学习等价的问题 ,并证明了只要有足够的数据,弱学习算法就能通过集成的方式生成任意高精度的强学习方法。针对Boosting的若干缺陷,Freund和Schapire于1996年前后提出了一个实际可用的自适应Boosting算法AdaBoost。

下面流程显示了Adaboost算法的流程

给定训练数据集

  1. 训练数据权值初始化

  1. 多轮训练迭代m = 1,2,…,M

2.1 得到基本弱分类器

2.2 计算分类误差率

2.3 计算 G_m (x)系数a_m

2.4 更新权值分布

3 建立强分类器

建立完每个强分类器后,我们将各个强分类器级联起来得到级联分类器。下图显示了级联分类器的工作情况。

环境准备

Opencv自带训练数据配置

正如背景介绍说的那样,我们需要使用训练好的数据进行人脸检测。Opencv自带训练好的检测数据,如人眼,左右眼,人正脸,全身,上下半身等。点击下面的压缩文件并解压到你的树莓派文件系统中。

下载地址: https://github.com/UBTEDU/YanShee-Curriculum/blob/master/img/project16/haarcascades.zip

解压后,你会看到(例)

训练自己的检测分类器

如果你觉得opencv自带的检测数据不够好,Opencv也提供了检测分类器训练程序。你可以通过它的训练程序去训练自己的检测分类器。因为树莓派Arm架构算力不足,我们需要在桌面或移动笔记本端进行模型训练。 以下步骤将以windows为例讲解如何进行数据训练。如果你使用的是Linux系统,请自行上网查阅资料进行训练。

下载并安装Windows版Opencv-3.4.1

下载地址: https://sourceforge.net/projects/opencvlibrary/

正样本制作

将正样本照片放入一个空文件夹,在此文件夹命令行输入

E:\project\face_head_train_images\train_pos>dir *.jpg */b>pos_route.txt

用写字板打开刚刚生成的文本文件(pos_route.txt), 替换文件内容并保存

其中 jpg 后面的参数对应为(本照片, 左,右,宽,高), 本例子的宽与高为20

负样本制作

负样本制作同正样本制作,但是无需替换文本文件照片描述。

训练

新建一个文件夹放入opencv中的可执行文件与动态链接库,动态链接库与可执行文件在以下路径: D:\opencv_3.4.1\opencv\build\x64\vc15\bin 。因为没有涉及windowsc++编程,所以无需进行环境变量设置。我是将opencv安装在D盘opncv_3.4.1 目录下。以下图片显示了你需要复制的可执行文件与动态链接库。

将正样本与负样本文件夹中的所有文件放入此文件中。在命令行输入如下命令获得正样本.vec文件

在命令行输入如下命令开始训练

E:\project\face_head_train_images\train>opencv_traincascade.exe -data head_face.xml -vec pos.vec -bg neg_route.txt -numPos 3500 -numNeg 9000 -numStages 20 -w 20 -h 20 -minHitRage 0.99 -maxFalseAlarmRate 0.5 -mode ALL 

其中两个重要参数 -minHitRate最小识别率 -maxFalseAlarmRate最大误识率

详细程序参数请参阅: http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html

程序流程

程序指引

#coding=utf-8
#############################################################################
		############Author: Xuyang Jie####################

		############Date: 13/03/2018######################
#############################################################################
import cv2
import time
import os
from picamera import PiCamera
from picamera.array import PiRGBArray


# Initialization 
camera = PiCamera()
camera.resolution = (320,240)
camera.framerate = 40
rawCapture = PiRGBArray(camera, size = (320, 240))
time_start = time.time()
counter = 0


# Load the cascade files for detecting faces
face_cascade = cv2.CascadeClassifier("/home/pi/data/haarcascades/haarcascadefrontalface.xml")


# Capture frames from camera
for capture in camera.capture_continuous(rawCapture,format = "bgr", use_video_port = True):
	image = capture.array

	#Frame pre-process
	grayimage = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

	#Comparison
	face = face_cascade.detectMultiScale(grayimage,scaleFactor = 2.0)

	#Mark the face
	for (x,y,w,h) in face:
		cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
		cv2.putText(image,"Found face",(x,y-2),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0),2)

    #Use Green text to show FPS at the left image corner
	counter = counter + 1
	fps = counter / ( time.time() - time_start )
	cv2.putText(image,str(fps),(15,15),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,0),2)

	#Show Frame
	cv2.imshow('Camera Capture',image)

	# Press 'q' to quit 
	if cv2.waitKey(1) & 0xFF == ord('q'):
		break

	#Wait for next frame
	rawCapture.truncate(0)

#Close window and camera
camera.close()
cv2.destroyAllWindows()

扩展实验

利用opencv自带检测器训练脸程序训练模型捕捉人头。