25 行 Python 代码实现人脸检测——OpenCV 技术教程

OpenCV

OpenCV 是最流行的计算机视觉库,原本用 C 和 C++ 开发,现在也支持 Python。

它使用机器学习算法在图像中搜索人的面部。对于人脸这么复杂的东西,并没有一个简单的检测能对是否存在人脸下结论,而需要成千上万的特征匹配。算法把人脸识别任务分解成数千个小任务,每个都不难处理。这些任务也被称为分类器。

对于类似于人脸的对象,你或许需要不少于 6000 个分类器,每一个都需要成功匹配(当然,有容错率),才能检测出人脸。但这有一个问题:对于人脸识别,算法从左上角开始计算一个个数据块,不停问“这是张脸吗”。每个数据块有超过 6000 个检测,加起来的计算量会达到数百万级别,计算机很可能会让你等得花儿都谢了。

OpenCV 使用 cascades 来避免这种情况。Cascade 是什么?最佳答案已经在字典里了:一条瀑布或者连续瀑布。

好比连续瀑布,OpenCV cascade 把人脸检测问题分解为好几步。对于每个数据块,它都进行一个粗略、快速的检测。若通过,会再进行一个更仔细的检测,以此不断类推。该算法有 30 到 50 个这样的阶段,或者说 cascade。只有通过全部阶段,算法才会判断检测到人脸。这样做的好处是:大多数图形都会在头几步就产生否定反馈,算法因而不需要在它上面测试所有 6000 个特征,大大节省了时间。相对于“正常流程”耗费数个小时,这可以实时实现人脸检测。

实践中的 Cascade 

它的理论也许听起来很复杂,实际操作起来其实是很简单的。这些 cascades 只是一系列包含  OpenCV 数据的 XML 文件。你用想要的 cascade 初始化代码,它自会替你做你想要的事。

由于人脸识别的普遍性,OpenCV 有一系列能检测各种东西的内置 cascade,从眼睛到手到腿都可以检测。甚至还有针对非人体物体的 cascade。比如说,如果你经营一家卖香蕉的水果店,想要监测偷香蕉的人,就有一个家伙开发了一个针对这一场景的算法

安装 OpenCV

首选,你需要找到对应你的操作系统的正确设置文件。

我发现,安装 OpenCV 是最难的一个环节。如果你遇到奇怪的、无法解释的错误,有可能是库崩溃了、32 与 64 比特的兼容问题等等。个人经验是,只用 Linux 虚拟机,从头安装 OpenCV 最简单。

安装好之后,你可以开启一个 Python 会话,敲出下面的代码,来测试它是否能工作:

$ python

>>> import cv2

>>>

如果没弹出任何错误,你就可以到下个环节了。

理解代码

源代码可在资源库下载。记得拿好 face_detect.py 文本、abba.png 图片以及 haarcascade_frontalface_default.xml。下面,我把代码分解开来。

# Get user supplied values

imagePath = sys.argv[1]

cascPath = sys.argv[2]

 将图片和 cascade 名字作为命令行参数传入。我们会用 Abba 图片和 OpenCV 提供的默认 cascade 来人脸检测。

# Create the haar cascade

faceCascade = cv2.CascadeClassifier(cascPath)

现在,我们创建一个 cascade,并用人脸 cascade 初始化。这把人脸 cascade 导入内存,所以它随时可以使用。记住,该 cascade 只是一个包含人脸检测数据的  XML 文件。

# Read the image

image = cv2.imread(imagePath)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

读取图片把它转化到灰度格式。

# Detect faces in the image

faces = faceCascade.detectMultiScale(    

gray,    

scaleFactor=1.1,    

minNeighbors=5,    

minSize=(30, 30),   

flags = cv2.cv.CV_HAAR_SCALE_IMAGE

)

该函数做的就是检测人脸,是代码核心部分。所以,我们来过一遍选项。

DetectMultiScale 函数是一个检测物体的通用函数。我们在人脸 cascade 上调用它,它检测的就是人脸。第一个选项是灰度图片。

第二个是 scaleFactor。有的人脸离镜头近,会比其他人脸更大。ScaleFactor 对此进行补偿。

检测算法使用移动窗口来检测物体。在系统宣布检测到人脸之前,minNeighbors 会对当前其周围有多少物体进行定义。MinSize 给出每个窗口的大小。

我用的是这些领域的常用值。现实中,你会拿不同的值试验窗口尺寸、扩展因素等参数,直到找出最比较合适的那一个。

当该函数认为它找到一张人脸时,会返回一个矩形列表。下一步,我们会进行循环,直到它认为检测出了什么。

print "Found {0} faces!".format(len(faces))

# Draw a rectangle around the faces

for (x, y, w, h) in faces:

    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)   

该函数返回四个值:矩形的 x 和 y 坐标,以及它的高和宽。我们用这些值和内置的 rectangle() 函数,画出矩阵。

cv2.imshow("Faces found" ,image)

cv2.waitKey(0)

最后,我们显示该模型,等用户摁下按键。

检验结果

用 Abba 来检验。

$ python face_detect.py abba.png haarcascade_frontalface_default.xml

没有问题,试试另一张照片。

那两个东西不是脸,我们再试一次。我调整了参数,发现把 scaleFactor 调成 1.2 能去除错误检测。

发生了什么?第一张图片由高清摄像机近距离拍摄,第二章拍摄距离相对更远,而且可能是用手机拍的。这就是需要调整 scaleFactor 的原因。正如我说的,你需要按照实际场景设置算法,避免假正例。

这里,雷锋网(公众号:雷锋网)提醒大家,由于这基于机器学习,结果永远不会 100% 精确。大多数情况下,你会得到不错的结果。但算法偶尔会失误。

最终代码在这里

用网络摄像头

如果你想要用网络摄像头呢?OpenCV 从摄像头读取每一帧,你可以通过处理每一帧进行人脸检测。你需要一个性能强大的 PC,不过我的五岁大的笔记本用着还行。

====================================分割线================================

本文作者:三川

本文转自雷锋网禁止二次转载,原文链接

时间: 2024-11-01 08:32:20

25 行 Python 代码实现人脸检测——OpenCV 技术教程的相关文章

3行Python代码完成人脸识别

Face Recognition软件包 这是世界上最简单的人脸识别库了.你可以通过Python引用或者命令行的形式使用它,来管理和识别人脸. 该软件包使用dlib中最先进的人脸识别深度学习算法,使得识别准确率在<Labled Faces in the world>测试基准下达到了99.38%. 它同时提供了一个叫face_recognition的命令行工具,以便你可以用命令行对一个文件夹中的图片进行识别操作. 特性 在图片中识别人脸 找到图片中所有的人脸 找到并操作图片中的脸部特征 获得图片中

一篇文章教你用 11 行 Python 代码实现神经网络

声明:本文是根据英文教程 A Neural Network in 11 lines of Python(用 11 行 Python 代码实现的神经网络)学习总结而来,关于更详细的神经网络的介绍可以参考我的另一篇博客:从感知机到人工神经网络. 如果你读懂了下面的文章,你会对神经网络有更深刻的认识,有任何问题,请多指教.   Very simple Neural Network 首先确定我们要实现的任务: 输出的为样本为 X 为 4*3,有 4 个样本 3 个属性,每一个样本对于这一个真实值 y,为

仅用500行Python代码实现一个英文解析器的教程_python

语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理.自然语言引入了很多意外的歧义,以我们对世界的了解可以迅速地发现这些歧义.举一个我很喜欢的例子: 正确的解析是连接"with"和"pizza",而错误的解析将"with"和"eat"联系在了一起: 过去的一些年,自然语言处理(NLP)社区在语法分析方面取得了很大的进展.现在,小小的 Python 实现可能比广泛应用的 Stanford 解析器表现得更出色. 文章剩下

50行Python代码制作一个计算器

简介 在这篇文章中,我将向大家演示怎样向一个通用计算器一样解析并计算一个四则运算表达式.当我们结束的时候,我们将得到一个可以处理诸如 1+2*-(-3+2)/5.6+3样式的表达式的计算器了.当然,你也可以将它拓展的更为强大. 我本意是想提供一个简单有趣的课程来讲解 语法分析 和 正规语法(编译原理内容).同时,介绍一下 PlyPlus,这是一个我断断续续改进了好几年的语法解析 接口.作为这个课程的附加产物,我们最后会得到完全可替代eval()的一个安全的四则运算器. 如果你想在自家的电脑上试试

使用70行Python代码实现一个递归下降解析器的教程_python

 第一步:标记化 处理表达式的第一步就是将其转化为包含一个个独立符号的列表.这一步很简单,且不是本文的重点,因此在此处我省略了很多. 首先,我定义了一些标记(数字不在此中,它们是默认的标记)和一个标记类型:   token_map = {'+':'ADD', '-':'ADD', '*':'MUL', '/':'MUL', '(':'LPAR', ')':'RPAR'} Token = namedtuple('Token', ['name', 'value']) 下面就是我用来标记 `expr`

仅利用30行Python代码来展示X算法_python

假如你对数独解法感兴趣,你可能听说过精确覆盖问题.给定全集 X 和 X 的子集的集合 Y ,存在一个 Y 的子集 Y*,使得 Y* 构成 X 的一种分割. 这儿有个Python写的例子.   X = {1, 2, 3, 4, 5, 6, 7} Y = { 'A': [1, 4, 7], 'B': [1, 4], 'C': [4, 5, 7], 'D': [3, 5, 6], 'E': [2, 3, 6, 7], 'F': [2, 7]} 这个例子的唯一解是['B', 'D', 'F']. 精确覆

400多行Python代码实现了一个FTP服务器_python

Python版本 实现了比之前的xxftp更多更完善的功能 1.继续支持多用户 2.继续支持虚拟目录 3.增加支持用户根目录以及映射虚拟目录的权限设置 4.增加支持限制用户根目录或者虚拟目录的空间大小 xxftp的特点 1.开源.跨平台 2.简单.易用 3.不需要数据库 4.可扩展性超强 5.你可以免费使用xxftp假设自己的私人FTP服务器 测试地址 ftp://xiaoxia.org 匿名帐号可以使用! 匿名根目录只读,映射了一个虚拟目录,可以上传文件但不允许更改! 使用方法 跟之前用C语言

仅用50行Python代码实现一个简单的代理服务器_python

之前遇到一个场景是这样的: 我在自己的电脑上需要用mongodb图形客户端,但是mongodb的服务器地址没有对外网开放,只能通过先登录主机A,然后再从A连接mongodb服务器B. 本来想通过ssh端口转发的,但是我没有从机器A连接ssh到B的权限.于是就自己用python写一个.   原理很简单. 1.开一个socket server监听连接请求 2.每接受一个客户端的连接请求,就往要转发的地址建一条连接请求.即client->proxy->forward.proxy既是socket服务端

10行Python代码创建可视化地图

import vincent  world_countries = r'world-countries.json'  world = vincent.Map(width=1200, height=1000)  world.geo_data(projection='winkel3', scale=200, world=world_countries)  world.to_json(path)    当我开始建造Vincent时, 我的一个目的就是使得地图的建造尽可能合理化. 有一些很棒的pytho