机器人视觉中物体识别实验系统设计

机器人视觉中物体识别实验系统设计

摘 要

作为机电一体化产品的典型代表,机器人在逐渐走向智能化。而通过

视觉来对周围环境中的物体进行识别的技术是机器人智能化的重要标志。具有“视觉”且能够识别物体的机器人可以获取外部世界图像,并从中识别出感兴趣的物体,根据需要作出反应。这对机器人的工作和未来机器人的发展具有重要的意义。且物体识别不仅仅可以用于机器人,其他各行各业如交通,国防等也都用到该项技术。而物体识别中最具代表的是人脸的检测,本次设计为从图像或视频中检测出人脸。

本次设计的方法为首先搜集大量正负样本,并对样本进行归一化操

作。然后用opencv 图像库根据矩形特征,Adaboost 算法训练出级联分类器,编写主程序读取图片或者从摄像头获取的视频的每一帧,对图像(帧)进行扫描,检测出人脸的个数(如果存在)、位置和大小,并标记出来予以显示。

最后需要对设计成品进行检验,将含有人脸的图片或摄像头获取的内

容提供给程序,观察程序的输出结果(对人脸的检测标记情况)是否与预期一致,确保它能够满足要求,并由此发现设计的不足之处,以便在以后的工作中予以改进。

关键字 物体识别,人脸检测,OpenCV ,训练,分类器

OBJECT RECOGNITION OF ROBOT VISION

EXPERIMENTAL SYSTEM DESIGN

ABSTRACT

As a typical of mechannical and electronics production,

robots have been going toward intelligence gradually.

The technology of recognizing objects in the environment is an important symbol of robots intelligence.The robots that have vision and recognize objects are able to get the picture of external environment,and recognize the objects that they are interested in.The they response according to

need.this is a very important meaning for the work of robot and the

development of future robot.And this technology can not only be used in robot,but also other fields such as traffic and national defense.Face

detection is a typical of objects recognition.So the content of this design is to detect faces from the image or video.

The method is as follows.First,I collect lots of positive and negtive

samples ,and normalize them.Then,I train the cascade classifier by opencv according to Haar feather and Adaboost Algorithm,and programme to read images or every frame of video from the camera.Then the programme will scan the iamge (frame),detect the number of faces(if any),the position and size,and it will mark it and show it.

At last,we should test the work.we can provide images or videos got

from the camera to the programme,then we look at and analyse what the programme show out(the result that it detect and mark faces).And the

result should be compared with the situation we expect.Having done all of these work,we can make sure that it satisfies the request well.And we can also find the shortcomings so that they can be overcome in the future work.

KEY WORDS object recognition,face detection,OpenCV,training, classifier

目 录

前言................................................1

第1章 总体方案设计..................................2

§1.1人脸检测简介及算法选取..........................2

§1.1.1 人脸检测介绍................................2

§1.1.2 人脸检测的常用方法及选取.....................2

§1.2操作系统及图像库的选取..........................3

§1.2.1操作系统...................................4

§1.2.2 图像库....................................4

第2章 Adaboost、Haar 及OpenCV 实现..................5

§2.1 Adaboost方法.................................5

§2.1.1 Boosting方法的提出和发展...................5

§2.1.2 Adaboost算法的提出........................5

§2.2 Haar特征.....................................7

§2.3 OpenCV对算法的实现...........................8

第3章 样本的采集和归一化............................9 §3.1 样本采集......................................9 §3.2 样本的归一化.................................11

第4章 分类器的训练.................................14

§4.1 创建vec 正样本...............................14

§4.2 训练分类器...................................17

第5章 编写主程序及效果检验..........................20

§5.1 编写主程序...................................21

§5.2 效果检验.....................................26

结论................................................31

致谢................................................31

参考文献............................................32

前 言

随着机电一体化技术的快速发展,作为其典型代表的机器人的智能化越来越被人们需求和受到关注。而工作在复杂环境中的机器人通过视觉来对周围环境中的物体进行识别的技术是机器人智能化的重要标志。与传统机器人不同,具有“视觉”且能够识别物体的机器人可以对外部世界进行感知(即获取图像),分析所得信息,并作出合理的决策。这种技术恰恰满足了对机器人智能化的需求,对机器人的工作和未来机器人的发展具有重要的意义。

机器人视觉的核心技术在于物体识别,物体识别通俗来说既是运用计算机技术使机器人具有和人类一样的,对于在任意环境下观察到的任意物体进行检测、分割和识别的能力。物体识别的作用方方面面:对汽车或车牌的识别,并附以其它处理(速度计算等),可以对交通进行智能监控;工厂中智能机器人可以识别零件种类,以对零件进行相应操作(搬运、组装等);家用机器人对各种物体的识别可以帮助人类做更多的工作,而不是像传统机器人那样只能做一些简单的重复性的事情,这会使机器人更加智能化,发挥更大的作用。在各种各样的物体识别中,人脸识别是最典型的识别之一,更准确来讲应该是人脸检测,两者的区别在于, “识别”(Recognition) 是从图像中找到能与特定人脸相匹配的部分;而“检测”(Detection) 只是识别的一部分,即在图像中检测出人脸并标记位置。而人脸检测已经满足“物体识别”的要求,它完全可以代表其他物体(如汽车、杯子等)的识别,所以下文中仅使用“人脸检测”这个名词。且人脸检测可以被应用在很多领域。比如家用机器人可以从复杂环境中判断主人的位置,数码相机可以通过人脸识别来对人脸进行准确对焦等等。

因此本次设计为实现人脸检测的功能,以此来代表各种物体的检测识别。由于本次设计为机器人视觉中的物体识别的实现,所以所有的设计工作均在个人计算机上完成。具体设计为编写程序,程序的功能为将提供给它的图片中的人脸标记出来,并且可以从摄像头中提取图像、检测出人脸并予以标记。

第1章 总体方案设计

1.1 人脸检测简介及算法选取

1.1.1 人脸检测介绍

人脸检测(Face Detection)是指在输入图像中确定所有人脸(如果存在)的位置、大小的过程。人脸检测作为人脸信息处理中的一项关键技术,今年来成为计算机(或者机器人)视觉领域内一项受到普遍重视、研究十分活跃的课题。

人脸检测(Face Detection)问题来源于人脸识别 (Face Recogni-tion) 问题。人脸检测是对给定的图像、判定其中是否有人脸,若有,将所有人脸从背景中分割提取出来,并确定每个人脸在图像中的位置和大小。人脸检测技术可以应用于人脸识别、机器人视觉、图像与视频检索等领域。

人脸检测的基本思想是建立人脸模型,比较所有可能的待检测区域与人脸模型的匹配程度,从而得到可能存在人脸的区域。

1.1.2人脸检测的常用方法及选取

随着科学技术的不断发展,人脸检测技术的方法越来越多,如早期的模块匹配法,基于特征的方法,还有中期的神经网络,统计模型,色彩信息,形状分析,还有最近的支持向量法,多模块信息融合,Adaboost 算法等。

一 基于特征的人脸检测方法

特征是人从肉眼看到的特性,我们可以从肤色,脸部,还有五官特征进行。

整体轮廓法:我们可以从人脸的形状接近于圆来开始检测,有人把人脸分割为三个轮廓区:即头顶轮廓区,左脸轮廓区和右脸轮廓区,检测任何一张图像,先进行边缘区域测试,然后提取脸部特征,最后运用评估函数来检测人脸。

肤色检测法:人脸的肤色可以在一定程度上把人脸从背景中分离出来,因此我们可以运用肤色模型来检测人脸。

器官分布法:人和人的面部各不相同,但人脸的器官分布却大致相同,即为人脸的器官分布。Mosaic 方法给出了人脸区域灰度分布的规则,依据这些规则对图像进行筛选,以样本满足这些规则的程度作为检查的依据。也可以先检测器官的位置,然后将这些位置排列组合,运用器官的分布规律进行检测,基本上找到人脸的位置。

二 模块匹配法的人脸检测

这种方法首先要把人脸的模板进行建立并保存,接着利用一些算法来计算各检测区域与标准模板的相似度,以此来判定某一区域是否为人脸。

其中包括镶嵌图法(又称马赛克图)、预定模板匹配法和变形模板法。由于这些不是本次设计所用方法,所以不再进行详细讨论。

三 基于Adaboost 算法的人脸检测方法

前面我们已经介绍了基于特征和模板匹配的方法,另外一种方法即为基于Adaboost 算法的人脸检测。Adaboost 是一种迭代算法,其核心思想是针对同一个训练集训练分类器(弱分类器),然后把这些分类器集合起来,构成一个更强的最终分类器(强分类器)。AdaBoost 算法的实现,采用的是输入图像的矩形特征,也叫Haar 特征。

经过了解知道,Adaboost+Haar特征是目前最为常用的人脸检测的方法,故决定使用该方法完成本次设计。下文中会对该方法做详细分析。

1.2 操作系统及图像库的选取 一种好的算法会脱离具体的平台或者语言,可以以纯理论的形式存在。Adaboost 就是这样,它可以应用在不同的领域, 当然包括图像处理,更加可以存在于不同的操作系统,也可以通过不同的语言不同的库实现。

1.2.1 操作系统

由于linux 系统本身还有很多项目是开源的,本人有在linux 系统编程的习惯,而且linux 的终端shell 也可以大大提高编程及其他工作的效率,所以决定使用linux 系统。而Ubuntu 作为linux 系统很优秀的一个发行版(尤其是图形界面非常的友好),对于本人来讲也较为熟悉,所以本次设计的编程工作在Ubuntu 下实现。

1.2.2 图像库

在图像处理方面有四大图像库:FreeImage/CxImage/CImg/OpenCV。

以下为前辈们对着四大图像库的一些使用心得和经验和本人的一些初步了解:

FreeImage为C 语言的体系,大量使用指针运算速度可以保证,内含先进的多种插值算法。另外独有的支持meta exif 信息的读取。该库最大的特点就是比较简练,只把重点放在对各种格式图像的读取写入支持上,没有显示部分,实际编程的时候还是需要调用API 函数进行显示。

CxImage 完全开放源代码,图像封装为一个类,功能极为强大,与Windows 、MFC 支持极好,支持图像的多种操作。缺点:里面的子库很多,用起来可能较麻烦。再则它对Windows 、MFC 支持极好,对linux 支持可能逊色,所以只能放弃不用。

CImg:可以与CxImage 配合使用,但是功能上略弱于CxImage 。

OpenCV 功能十分的强大,而且支持目前先进的图像处理技术,体系十分完善,操作手册很详细,手册首先给大家补计算机视觉的知识,几乎涵盖了近10年内的主流算法;而且该库是开源项目,移植性较好,这对于我在Ubuntu 下开发是个好消息,因为设计的成果可以移植到Windows 下进行演示或者使用。

经以上分析本次设计选用OpenCV 作为图像库。在随后的了解中,发现OpenCV 对Adaboost+Haar特征支持非常好。所以更加坚定了对OpenCV 的选择。

至此设计工作任务和顺序有了大致雏形:在Ubuntu 下配置好OpenCV 环境,训练样本得到分类器,编写程序对图片或视频检测并标记人脸位置。

第2章 Adaboost 、Haar 特征及OpenCV 实现

2.1 Adaboost方法

2.1.1 Boosting方法的提出和发展

在了解Adaboost 方法之前,先了解一下Boosting 方法。 回答一个是与否的问题,随机猜测可以获得50%的正确率。如果一种方法能获得比随机猜测稍微高一点的正确率,则就可以称该得到这个方法的过程为弱学习;如果一个方法可以显著提高猜测的正确率,则称获取该方法的过程为强学习。1994年,Kearns 和Valiant 证明,在Valiant 的PAC (Probably ApproximatelyCorrect)模型中,只要数据足够多,就可以将弱学习算法通过集成的方式提高到任意精度。实际上,1990年,

SChapire 就首先构造出一种多项式级的算法,将弱学习算法提升为强学习算法,就是最初的Boosting 算法。Boosting 意思为提升、加强,现在一般指将弱学习提升为强学习的一类算法。1993年,Drucker 和Schapire 首次以神经网络作为弱学习器,利用Boosting 算法解决实际问题。前面指出,将弱学习算法通过集成的方式提高到任意精度,是Kearns 和Valiant 在1994年才证明的,虽然Boosting 方法在1990年已经提出,但它的真正成熟,也是在1994年之后才开始的。1995年,Freund 提出了一种效率更高的Boosting 算法。

2.1.2 Adaboost算法的提出

Adaboost 算法于1995年被提出,这是对Boosting 算法的一大提

升。Adaboost 是Boosting 家族的代表算法之一,全称为Adaptive

Boosting 。Adaptively ,即适应地,该方法根据弱学习的结果反馈适应地调整假设的错误率,所以Adaboost 不需要预先知道假设的错误率下限。也正因为如此,它不需要任何关于弱学习器性能的先验知识,而且和

Boosting 算法具有同样的效率,所以在提出之后得到了广泛的应用。

Adaboost 是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器) ,然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。使用Adaboost 分类器可以排除一些不必要的训练数据特征,并将关键数据特征放在关键的训练数据上面。

Adaboost 是一种基于级联分类模型的分类器。级联分类模型可以用图2-1表示。

图 2-1 级联分类模型

级联分类器就是将多个强分类器连接在一起进行操作。每一个强分类器都由若干个弱分类器加权组成,例如,有些强分类器可能包含多个弱分类器,一个级联用的强分类器又可包含多个强分类器,然后将强分类器级联起来,就构成了一个级联强分类器。因为每一个强分类器对负样本的判别准确度非常高,所以一旦发现检测到的目标位负样本,就不在继续调用下面的强分类器,减少了很多的检测时间。因为一幅图像中待检测的区域很多都是负样本,这样由级联分类器在分类器的初期就抛弃了很多负样本的复杂检测,所以级联分类器的速度是非常快的;只有正样本才会送到下一个强分类器进行

再次检验,这样就保证了最后输出的正样本的伪正(false positive) 的可能性非常低。

2.2 Haar特征 AdaBoost算法的实现,采用的是输入图像的矩形特征,也叫Haar 特征。影响

Adaboost 检测训练算法速度很重要的两方面是特征的选取和特征值的计算。脸部的一些特征可以由矩形特征简单地描绘。如图2-2所示:

图2-2 Haar特征描绘

常用的矩形特征有三种:两矩形特征、三矩形特征和四矩形特征,如图2-3所示。

由图表可以看出,两矩形特征反映的是边缘特征,三矩形特征反映的是线性特征、四矩形特征反映的是特定方向特征。

征模板的特征值定义为:白色矩形像素和减去黑色矩形像素和。接下来,要解决两个问题,1:求出每个待检测子窗口中的特征个数。2:求出每个特征的特征值。子窗口中的特征个数即为特征矩形的个数。训练时,将

图2-3 常用的矩形特征

每一个特征在训练图像子窗口中进行滑动计算,获取各个位置的各类矩形特征。在子窗口中位于不同位置的同一类型矩形特征,属于不同的特征。可以证明,在确定了特征的形式之后,矩形特征的数量只与子窗口的大小有关。在24×24的检测窗口中,矩形特征的数量约为160,000个。

特征模板可以在子窗口内以“任意”尺寸“任意”放置,每一种形态称为一个特征。找出子窗口所有特征,是进行弱分类训练的基础。

2.3 OpenCV对算法的实现

OpenCV 的全称是:Open Source Computer Vision Library 。OpenCV 于1999年由Intel 公司建立。它是一个基于(开源)发行的跨平台计算机视觉库。由一系列C 函数和少量C++类构成,同时提供了Python 等语言的接口,实现了图像处理和计算机视觉方面的很多算法。

由于OpenCV 强大的功能,它可以应用到多种领域。如人机互动、物体识别(其中包括人脸的检测和识别)、运动跟踪和机器人视觉等等。

OpenCV 对算法有很好的封装,这使得OpenCV 开发出的程序更加小巧和简洁,更重要的是它省去了开发人员的重复性劳动,大大提高了开发的效率。这也是吸引众多开发者使用OpenCV 的原因。

在物体识别方面(包括人脸检测),OpenCV 对Adaboost 等经典常用的算法做了更加实用的封装。所谓实用是指OpenCV 将Adaboost 算法和Haar 特征对图像的训练封装为一系列程序,并提供一些参数项,而开发者只需要提供正反样本和所需的参数,按照一定的顺序便可以训练出自己的分类器,所要关心是每个样本的质量和所有样本对各种情况的表达程度,当然样本的

数量也是需要考虑和控制的。

下面是Opencv 提供的关于训练得到分类器的程序:

opencv_createsamples创建正样本,生成的为中间数据(格式为.vec ),以便用于下一步的训练。

Opencv_haartraining:以上一步的结果作为正样本,加上不含所要识别的物体(人脸)的图片作为负样本(或者背景图)进行训练,输出的结果即为关于人脸特征的Adaboost 分类器(表现形式为.xml 文档,可以被Opencv 程序打开)。在之后的内容中,还会详细说明训练的方法。

第3章 样本的采集和归一化

3.1 样本采集

样本包括正样本和负样本(或者称为背景图),其中正样本为含有人脸的图像,而负样本或者背景图为不含人脸的图像。

正样本可以为带有背景的图像,也可以是仅含人脸的图像。由于opencv_createsamples创建正样本中间文件(.vec)时需要制定人脸的个数和在图像中的位置大小,为了减少工作量(并不影响结果),决定采集的正样本均为单张人脸且不含背景,这样图像中的人脸区域即为图像的整个区域。

由于检测人脸的环境是不确定的,光线和明暗程度也是不同的,且人的表情也是随时变化的,这些都可以引起特征的变化,所以训练所用的样本集要非常丰富,考虑到种种情况,才会使训练的分类器更加可靠。

在实际操作中,一方面我在不同环境中对不同人脸不同表情进行拍照,将所得图像中的人脸截取出来;另一方面利用互联网,获取了较多含有人脸的图像,如图3-1所示,为部分样本。

图3-1 正样本

负样本(背景图)唯一的要求是其中不能含有人脸,可以是任意图像,比如生活中的场景、动物或者各种工具等等。所以负样本的采集就非常容易。与采集正样本一样,从现实中和网络中得到一定数量的负样本,如图3-2所示。

图3-2 负样本

3.2 样本的归一化

opencv_createsamples所需的正样本必须是归一化的,所谓归一化即为图像全部是灰度图(彩色图过于复杂,信息量过大,各种特征不够明显,训练的工作量变大,时间变长,甚至无法训练出分类器),且尺寸一致。这里我们将尺寸定为20X20。每个样本的命名方式为face****.png,其中****为编号,如第一个样本为face0001.png ,第二十个样本为face0020.png 以此类推。这样命名有利于编程将样本归一化。

OpenCV 有改变图像尺寸和将图像转换为灰度图的函数。而考虑到本人有过Python 编程经验,Python 是一种简洁的脚本语言,能够轻松应对图像的命名问题,这对于C/C++来说是一大笔的代码开销,且Python 自带的PIL 模块也是较为强大易用的图像处理库,完全可以应对图像的归一化。

代码如下:

#!/usr/bin/env python

from PIL import Image

total=500

filename=''

for i in range(1,total+1):

代码解释:

第一行#!/usr/bin/env python 由于python 是一门解释型的脚本语言,所以在运行时要指定确定的解释器。/usr/bin是Linux 下的目录, env python 表示搜索可用的python 解释器。

第二句 from PIL import Image 从PIL 模块导入Image 类,这就是之前提到过的用于处理图像的python 模块。

接下来total 变量用来存放样本的数目,filename 用来存放样本图像的文件名。

第八行开始的for 循环用来逐个改变样本图片的尺寸和改变图像为灰度图。具体为:if...elif...else 语句根据样本序号来确定文件名并用filename

if i

保存。

第十八行im=Image.open(filename ) 打开样本图像并以Image 的类型保存在im 中。

第十九行 out=im.resize((20,20),Image.BILINEAR) Image 有一个resize 方法用来改变图像尺寸,返回一个Image 对象并保存在out 变量中。 后两行中,out=out.convert('L') 将out 从彩色图转换为灰度图,out.save(filename)将out 所存储的内容保存到名为filename 的文件中覆盖原来的样本图像。

经过循环每一个样本图像都得到相同的处理,即实现了正样本的归一化。所得到的归一化后的部分样本图像如图3-3所示。

图3-3 归一化的正样本

负样本对归一化没有绝对的要求,只要比正样本大就是合理的,但是转为灰度图还是很有必要的,前面已经讨论过,这会大大减少训练的工作量,提高训练速度。这里为了比较统一,也将其归一化。方法与正样本的归一化

比较相似,只是命名不同(为noface****.jpg),尺寸为100X100。归一化的部分负样本如图3-4所以。

图3-4 归一化的负样本

这些归一化的正样本和负样本图像便可以为接下来的样本创建和训练分类器做好了准备。下一章将会详细说明训练过程。

第4章 分类器的训练

这一章将会介绍训练分类器的过程。由于opencv_haartraining程序所需要的正样本为vec 文件,所以需要用opencv_createsamples程序来将正样本图像转化为vec 中间文件,即opencv_haartraining能够读取的样本形式。

4.1 创建vec 正样本

由于样本图像数目很多,被放在一个文件中,这里我们将它命名为

faces 。另外用一个正样本描述文件以描述正样本。按照要求的描述格式,举例如下:

faces/face0001.png 1 0 0 20 20

其中faces/face0001.png为样本图像的相对路径,数字1为图像中含有人脸的数目,后面四个数字为人脸的位置坐标和尺寸,由于样本图像为整个人脸,所以整个区域被描述在文件中。

创建文本文件face.idx ,用于存储样本描述内容。和样本的归一化一样,这里也写了一个python 脚本来快速的生成样本描述文件的内容,代码如下:

#!/usr/bin/env python

text=''

num=500

for i in range(1,num+1):

if i

else:

text+='faces/face0%s.png 1 0 0 20 20\n'%i

text+='faces/face%s.png 1 0 0 20 20\n'%i

f=open('face.idx','w') f.write(text) f.close()

代码简单解释:变量text 用来存储描述内容(字符串),变量num 为正样本的数量。

f.write(text)将text 写入face.idx 。得到的文件内容如图4-1所示。

图4-1 正样本描述文件

在使用opencv_createsamples创建vec 文件之前先说明一下它的命

令行参数:

-vec 训练好的正样本的输出文件名。 -img原目标文件(人脸图像) -info 样本描述文件

-show 如果指定,每个样本会被显示出来,按下“esc ”会关闭这一开关,即不显示样本图片,而创建继续。

-w输出样本的宽度(以像素为单位) -h输出样本高度,以像素为单位 在终端中输入命令,如图4-2所示:

图4-2 创建样本命令

输出结果如图4-3所示:

图4-3 创建样本输出结果

可以看到共创建了500个正样本,样本宽为20,高也是20。可以发现当前工作目录中新增了一个名为face.vec 的文件,该文件包含正样本数

目,宽高以及所有样本图,即为正样本文件。

4.2 训练分类器

训练分类器需要负样本,同正样本一样,创建负样本描述文件。负样本描述格式为:

nofaces/noface0001.jpg

可以看到这里和正样本不同,后面没有几个参数来表征人脸位置,因为负样本(或背景图)是任意图片,不含人脸。

负样本有781个,所以也需要用python 脚本来快速生成负样本描述文件noface.idx 。代码如下: #!/usr/bin/env python text='' num=781

for i in range(1,num+1):

f=open('noface.idx','w') f.write(text) f.close()

由于代码与创建正样本描述文件的脚本基本相同,所以不再进行代码分

if i

text+='nofaces/noface000%s.jpg\n'%i

elif i

text+='nofaces/noface00%s.jpg\n'%i

elif i

text+='nofaces/noface%s.jpg\n'%i text+='nofaces/noface0%s.jpg\n'%i

析。生成的负样本描述文件如图4-4所示:

图4-4 负样本描述文件

正负样本均以创建完毕,接下来要训练分类器,这个过程是由opencv 提供的opencv_haartraining程序来实现的。

opencv_haartraining的命令行参数如下: -data

存放训练好的分类器的路径名 -vec

正样本文件名,即由上一节创建的face.vec 文件 -bg 背景描述文件,即nofaces.idx -npos -nneg 用来指定正负样本的数目 -nstages

训练的阶段数 -mem

预先计算的以MB 为单位的可用内存。内存越大则训练速度越快。 -mode

选择用来训练的haar 特征集的种类。Basic 仅仅使用垂直特征。All 使用垂直和45度角旋转特征。

-w -h

训练样本的尺寸,以像素为单位。必须和训练样本创建的尺寸相同,即为20X20。

在终端中输入命令,如图4-5所示:

图4-5 训练分类器命令

输出内容如图4-6所示:

图4-6 训练分类器输出内容

此时可以看到当前工作目录中生成了一个cascade 文件夹,这是训练分类器产生的中间文档。另外还生成了一个cascade.xml 文件,这便是训练得到的分类器,它能够被opencv 程序读取以检测人脸。

第5章 编写主程序及效果检验

上一章中已经训练出分类器,接下来就是要编写主程序,其功能是读取分类器的cascade.xml 文件,并将图片或者视频中的人脸检测出来予以标记显示。然后会对分类器和检测效果进行检验,确保其有可靠的性能。

5.1 编写主程序

人脸检测的主程序如下: #include #include

int main(int argc,char** argv) {

CvHaarClassifierCascade*

cascade=(CvHaarClassifierCascade*)cvLoad("cascade.xml",0,0,0);

cvNamedWindow("facedetect");

if(2==argc) {

IplImage* img=cvLoadImage(argv[1]);

IplImage* gray=cvCreateImage(cvGetSize(img),8,1); IplImage* small_img=cvCreateImage(cvSize(cvRound(img-CvMemStorage* storage=cvCreateMemStorage(0);

>width/1.3),cvRound(img->height/1.3)),8,1);

cvCvtColor(img,gray,CV_BGR2GRAY);

cvResize(gray,small_img,CV_INTER_LINEAR); cvEqualizeHist(small_img,small_img);

cvClearMemStorage(storage); CvSeq*

objects=cvHaarDetectObjects(small_img,cascade,storage,1.1,2,0,cvSize(30,30));

for(int i=0;itotal:0);i++) {

CvRect* r=(CvRect* )cvGetSeqElem(objects,i); cvRectangle(

img,

cvPoint(cvRound(r->x*1.3),cvRound(r-

>y*1.3)),

cvPoint(cvRound((r->x+r-

>width)*1.3),cvRound((r->y+r->height)*1.3)),

}

cvScalar(0,0,255), 3);

cvShowImage("facedetect",img);

cvWaitKey(0);

}

cvReleaseImage(&img); cvReleaseImage(&gray); cvReleaseImage(&small_img); cvDestroyWindow("facedetect"); return 0;

else {

CvCapture* capture=cvCreateCameraCapture(-1); IplImage* img; while(1) {

img=cvQueryFrame(capture); if(!img) break;

IplImage* gray=cvCreateImage(cvGetSize(img),8,1); IplImage*

small_img=cvCreateImage(cvSize(cvRound(img->width/1.3),cvRound(img->height/1.3)),8,1);

cvClearMemStorage(storage); CvSeq*

cvCvtColor(img,gray,CV_BGR2GRAY);

cvResize(gray,small_img,CV_INTER_LINEAR); cvEqualizeHist(small_img,small_img);

objects=cvHaarDetectObjects(small_img,cascade,storage,1.1,2,0,cvSize(30,30));

for(int i=0;itotal:0);i++) {

CvRect* r=(CvRect* )cvGetSeqElem(objects,i); cvRectangle(

img,

cvPoint(cvRound(r-

>x*1.3),cvRound(r->y*1.3)),

cvPoint(cvRound((r->x+r-

>width)*1.3),

cvRound((r->y+r-

>height)*1.3)), }

程序解释:

前两行为opencv 提供的头文件。其中cv.h 包含了opencv 对图像处理的算法函数。Highgui.h 则包含的是与操作系统、文件系统和摄像机之类的硬件进行交互的一些函数。

CvHaarClassifierCascade*cascade=(CvHaarClassifierCascade*)cvLoad("cascade.xml",0,0,0);

CvHaarClassifierCascade是opencv 用来存储分类器的数据结构,分类器.xml 文件是由函数cvLoad ()读取的。

CvMemStorage*storage=cvCreateMemStorage(0); CvMemStorage是一个用来存储诸如序列轮廓,图形等动态增长数据结构的底层结构。它由cvCreateMemStorage ()函数创建。

cvNamedWindow()为GUI 函数,它创建一个窗口,用来显示图片

}

cvScalar(0,0,255), 3);

}

cvShowImage("facedetect",img); char c=cvWaitKey(33); if(27==c)

break;

}

cvReleaseCapture(&capture); cvDestroyWindow("facedetect"); return 0;

或者视频。

下面的if...else... 语句的判定条件为2==argc,即如果命令行有两个参数(第一个是程序本身),则执行第一部分,否则为第二部分。

IplImage*img=cvLoadImage(argv[1]);IplImage是opencv 存储图像的数据结构,由函数cvLoadImage ()创建,参数为命令行的第二个参数。 变量gray 是由函数cvCreateImage ()创建的,它同样为IplImage 的指针。cvGetSize (img )表示它与img 有相同的尺寸,参数8说明图像为8位,参数1表示单通道,即为灰度图。

同样small_img也为8位单通道,尺寸为img 的1/1.3。

cvCvtColor()将img 复制给gray ,由彩色图转换为灰度图。 cvRsize()将gray 复制给small_img,尺寸为small_img的尺寸。 cvClearMemStorage(storage );清空storage ;

CvSeq*objects=cvHaarDetectObject

(small_img,cascade,storage,1.1,2,0,cvSize(30,30)); 作用是对图片中的人脸进行检测,并将检测到的人脸和位置和大小存储在objects 中。

cvHaarDetectObject()的原型为:

CvSeq* cvHaarDetectObject(

const CvArr* image,

CvHaarClassifierCascade* cascade,

CvMemStorage*

double

int

int

Cvsize

);

其中参数CvArr*image为灰度图像。分类器cascade 是cvLoad ()加载的Haar 特征级联。参数storage 是这个函数的工作缓存。该函数以不同的窗口扫描图像寻找人脸,设置scale_factor参数可以决定每连个不同大小的窗口之间有多大的跳越。参数min_neighbors控制着误检测。现时图像中的脸会被多次检测到,因为周围的像素和不同大小的窗口也会检测到人

storage, scale_factor=1.1, min_neighbors=3, flags=0, min_size=cvSize(0,0)

脸。默认值3表示至少有3次重叠检测,才被判定为人脸。min_size为寻找人脸的最小区域。

接下来的for 循环即为检测出人脸的区域在原图像相应的位置画出矩形以表示此处为人脸。

cvShowImage ()在窗口中显示图像。

else 中的代码为使用摄像头获取视频并检测人脸显示。

CvCapture* capture=cvCreateCameraCapture(-1); 检测可用的摄像

头,并将得到视频图像存储在CvCapture 数据结构中。

由于视频是由一帧一帧图像构成,所以经while 循环中

img=cvQueryFrame(capture);;将每一帧图像提取出来之后,处理方法便和单个的图像一致。所以不再赘述。

5.2 效果检验

上一节中主程序已经完成,现在将它编译成可执行程序,首先将源程序命名为facedetect.cpp 编译的指令为:

g++ -ggdb `pkg-config --cflags opencv` -o facedetect facedtect.cpp `pkg-config --libs opencv`

在当前工作目录中产生了一个可执行文件,文件名为facedetect 。 先检验对图像的中人脸检测的效果,所用到的图像如图所示:

图5-1 lihong.jpg

图5-2 cjk.jpg

图5-3 zhaol.jpg

执行指令以此为:

./facedetect lihong.jpg

./facedetect cjk.jpg

./facedetect zhaol.jpg

检测结果如图所示:

图5-4 检测后的lihong.jpg

图5-5 检测后的 cjk.jpg

图5-6 检测后的 zhaol.jpg

可以看到lihong.jpg zhaol.jpg中的人脸均被检测出来,只有cjk.jpg 中的四张人脸中的两个没有检测出来,这是受到了人脸角度的影响。总体效果还是满足要求的。

对摄像头拍摄的视频中的人脸检测不仅考验检测的准确度,还对检测的速度有要求,输入以下指令执行并观察:

./facedetect

检测结果如下:

5-7 摄像头人脸检测结果1

图5-8 摄像头人脸检测结果2

视频中的人脸可以被检测出来,但也有误检的情况,但均在可接受的范围。

通过上述现象,可以认为训练出的分类器和主程序能够满足检测识别的要求。

结 论

经过两个多月的工作,我从毫无头绪到作出人脸检测,非常有成就感。但是它还有不完善的地方,比如这里没有考虑人脸有其他物品的情况(比如戴眼镜等),致使它的通用性降低。其次样本数量不够多,检测效果不是很强,稳定性也有待提高。但总体来说,满足了物体识别的设计要求。 将来还可以将它移植到机器人上,通过机器人接口来使机器人更加智能,做更多的事情。也能其他机电一体化产品有更完善的功能。

致 谢

在设计过程中,需要向同学们获取脸部图片,完成后也要拿他们进行测试,所以感谢同学们无私的帮助。设计更加离不开指导老师田老师从头到尾认真负责地对我们的指导,在这里表示衷心的感谢。

河南科技大学毕业设计(论文)

参考文献

[1]Gary Bradski.学习OpenCV (中文版). 北京. 清华大学出版社. 2009:01-570

[2]克来格. 机器人学导论. 北京. 机械工业出版社.2006:01-198

[3]卡尔斯曼. 数字图像处理. 北京. 电子工业出版社.1998:35-78

[4]冈萨雷斯. 数字图像处理. 第二版. 北京. 电子工业出版社.2009:01-300

[5]张铮. 数字图像处理与机器视觉. 北京. 人民邮电出版社.2010:125-198

[6]桑卡. 图像处理分析与机器视觉. 第三版. 北京. 清华大学出版社. 2011:01-14

[7]赵鹏. 机器视觉理论及应用. 北京. 电子工业出版社.2011:35-62

[8]赵鹏. 机器视觉研究与发展. 北京. 科学出版社.2012:15-27

[9]戴维斯等. 机器视觉:理论、算法与实践. 北京. 人民邮电出版社. 2009:03-18

[10]徐国华. 移动机器人的发展现状及其趋势. 机器人技术与应用,2001, 第 3期,12-15

[11]李磊. 移动机器人技术研究现状与未来. 机器人,2002, 第5期,05-07

[12]蔡自兴. 未知环境中移动机器人导航控制研究的若干问题. 控制与决 策,2002,第4期,23-25

[13]王涛. 傅里叶描述子识别物体的形状. 计算机研究与发展,2002, 第12 期,19-22

[14]杨淑莹. 基于图像纹理分析的目标物体识别方法. 天津理工学院学报, 2001,第4期,6-10

[15]李庆. 三维物体识别研究进展. 中国图像图形学报,2000,第12期, 30-34

[16]程义民. 基于广义Hough 变换的部分遮挡物体识别. 中国科学技术大学 学报,1997,第4期,18-22


© 2024 实用范文网 | 联系我们: webmaster# 6400.net.cn