- 作 者
- 黄福珍,苏剑波 [1]
- 定 价
- 12.00元
- 书 名
- 人脸检测
- 出版时间
- 2006-4-1
- 出版社
- 上海交通大学出版社
- ISBN
- 9787313043665 [1]
-
人脸检测
2018-03-10 17:55:30人脸检测 人脸检测目的就是在一张图中找到所有的人脸。本次分享只针对人脸检测,不涉及到人脸识别。 人脸检测几种常用的方法: ①早期的人脸检测方法是利用人工提取特征,训练分类器,进行人脸检测。例如...人脸检测
人脸检测目的就是在一张图中找到所有的人脸。本次分享只针对人脸检测,不涉及到人脸识别。
人脸检测几种常用的方法:
① 早期的人脸检测方法是利用人工提取特征,训练分类器,进行人脸检测。例如opencv源码中自带的人脸检测器就是利用haar特征进行的人脸检测。这类方法的缺点就是在环境变化强烈的时候检测效果不理想,例如弱光条件,人脸不全。
② 从通用的目标检测算法中继承过来的人脸检测算法。例如利用faster-RCNN来检测人脸。效果不错,可以适应环境变化和人脸不全等问题,但是时间消耗很高。
③ 鉴于以上两种方法的优劣势,就有人专门研究了人脸检测的算法,同时规避了以上两种的劣势,兼具时间和性能两个优势。级联结构的卷积神经网络,例如,cascadeCNN,MTCNN。MTCNN效果要比cascadeCNN要好。
目前人脸检测任务主要是有两个方面的挑战:
① 召回率:复杂背景下的人脸的尺度变化和光照等外部因素变化导致的人脸分类困难。
(在CNN方法下解决此类问题一般都是通过加入此类样本进行训练解决问题。)
② 耗时:人脸多尺度位置定位导致的时间消耗。
MTCNN算法介绍
MTCNN(多任务级联卷积神经网络)由三个部分组成,P-Net(proposal Network),R-Net(refineNet),O-Net(outputNet)。这三个部分是相互独立的三个网络结构,相互串联的关系。每个阶段的网络都是一个多任务网络,处理的任务有三个:人脸/非人脸的判断、人脸框回归、特征点定位。
流程说明:
原始待检测图像经过resize,生成不同尺寸的图像构建图像金字塔作为网络的输入。
构建的图像金字塔,其层数由两个因素决定,第一个是设置的最小人脸minSize,第二个是缩放因子factor,最小人脸表示min(w,h),论文中说明最小人脸不能小于12,给出的缩放因子0.709可以根据公式计算图像金字塔的层数
minL=org_L*(12/minsize)*factor^(n),n={0,1,2,3,...,N}
其中n就是金字塔的层数,org_L是输入原始图像的最小边min(W,H),minisize是人为根据应用场景设定,在保证minL大于12的情况下,所有的n就构成金字塔的层。所以minsize的值越小,n的取值范围就越大,计算量就相应地增加,能够检测到的人脸越小。
第一阶段,通过浅层的CNN(P-Net)快速生成候选窗口,该网络全部由卷积层实现,获取到候选人脸窗和人脸窗的回归向量,基于人脸窗的回归向量对人脸窗进行校正,然后对所有人脸窗进行NMS(非极大值抑制),合并高度重叠的人脸窗。其具体过程就是通过图像金字塔生成的各种尺寸大小的图片,每一张图都进行一次前向传播,在每个图上得到的结果之后利用设置的阈值去掉一部分,剩下的根据缩放尺度还原到原图上的坐标,将所有的坐标信息汇总,然后NMS去除一部分冗余。
第二阶段,通过一个更复杂的CNN来处理第一阶段中被误认为人脸的“人脸窗”从而精细化人脸窗,第一阶段的输出作为第二阶段的输入,第一阶段最后产生了大量的bbox,将这些bbox根据缩放因子回推到原图上之后,将他们全部resize到24x24大小,作为第二阶段的输入。第二阶段经过网络之后同样产生大量的bbox,同样的根据阈值去掉一部分,再利用nms去掉一部分。
第三阶段,使用第二阶段中最后留下来的bbox,还原到原来的图片上之后,全部resize到48x48大小,然后输入到第三阶段,使用更为复杂的CNN进一步精细化结果并输出人脸上的5个特征点。
通过三阶的级联卷积神经网络对任务进行从粗到细的处理,并提出一种新的在线困难样本生成策略提升性能,最终输出人脸框位置和五个特征点位置。整个过程中会用到三次人脸窗回归和NMS,三个网络独立工作。
关于NMS
简单来说,输入一个图片,分类器会产生多个候选框,每个候选框会有一个得分,分数就是此框是人脸的概率。
例如这张图,一共产生了4个候选框,每个候选框都有一个得分。右下角的框得分最低,如果我们这是NMS阈值为0.6,那么这个框直接被干掉,然后川普脸上还有两个框,有一定重叠,要想去掉一个框那就得用上NMS了。一般有两种种计算方式。IOU交/并,IOM交/max。如果比值大于阈值,那么直接干掉得分低的那个框。这里手上的框没有与其他框有交集,所以它不会被NMS干掉。
其实这样传统的NMS直接干掉分数低的有点简单粗暴了,有一篇论文专门针对NMS进行了改进优化,称之为soft-nms。如果某一个框的分数较低,那么不直接将这个框干掉而是降低其置信度,通过高斯加权的方式再进行排除。文章中指出在常规算法(faster-RCNN, MTCNN)中MAP值上升一个百分点。
文章链接: 《Improving Object Detection With One Line of Code》
Github链接: https://github.com/bharatsingh430/soft-nms
MTCNN方法在FDDB数据库上测试的结果是0.95。(在1000次误检情况下的准确率)
但是,MTCNN仍然具有一些缺点。
① MTCNN的检测速度跟待检测人脸的数量有很大关系,当人脸数量变多之后,检测耗时上升会非常明显。
② 在CPU上时间消耗比较严重
③ 侧脸进行人脸对齐的时候,特征点位置不准确。
针对MTCNN的优化版本已经有很多了,例如我用过两种
1,MTCNN-light,作者将caffemodel文件转成了txt,不再依赖caffe框架,只依赖openmp,在cpu平台下运行,多线程处理速度不错,但是检测效果略有下降。
2,MTCNN-AccelerateONet,专门针对最后的ONet网络进行了加速,在GPU上加速很明显。但是速度依然会受人脸数量的影响。
MTCNN,MTCNN-light,MTCNN-Accelerate三者实验对比
方法
输入分辨率
硬件平台
1个人脸耗时
8人脸耗时
MTCNN
VGA
GTX1070
13ms
23ms
MTCNN-Acce
VGA
GTX1070
8ms
14ms
MTCNN-light
VGA
i5 CPU
33ms
45ms
方法
输入分辨率
硬件平台
20人脸脸耗时
MTCNN
5184*3456
GTX1070
1.25 s
MTCNN-Acce
5184*3456
GTX1070
570 ms
MTCNN-light
5184*3456
I5CPU
3.66 s
经过对比三种方法,MTCNN-light适合应用于没有gpu的硬件平台,在VGA分辨率情况下,适当调整minSize,可以做到实时检测。
对比MTCNN和MTCNN-Acce,后者的时间消耗几乎是前者的一半,在FDDB上进行测试,后者的检测效果略差于前者。如下图所示:
上面两种方法本质都是一样的,只不过加速版在最后O-Net网络结构上面进行了修改,然后重新训练得到一个新模型。在网络结构方面,加速版只是在原始版本上将第五个卷积层后面的dropout层去掉了,然后在前面卷积层的输出参数上进行了缩减,前5个卷积层的num_output都减少了一半,从而减少了计算量。如下图所示:
dropout层在神经网络中的应用目的就是防止网络层数过多出现过拟合,根据设置的dropout_ratio参数随机停止部分神经元工作,然后输出多种情况下的平均值,这样防止出现训练过拟合。这里的改动直接将卷积层输出参数去掉一半,然后不要dropout,重新训练就可以得到和原网络差不多的效果。这种方法可以值得我们借鉴。
由于MTCNN系列的方法耗时都对待检测人脸数量敏感,并且在CPU上的表现不好。所以,faceBoxes这个方法就出现了。论文中说使用的方法可以很大幅度提高检测速度,并且不受人脸数量的影响。在FDDB上准确率0.96,但是没有人脸对齐。
faceBoxes介绍
faceBoxes主要包含两个部分:RDCL和MSCL
RDCL的全名是 Rapidly Digested Convolutional Layers,主要负责快速性
MSCL的全名是 Multiple Scale Convolutional Layers,主要负责多尺度检测
如上图所示,输入一张图,会在三个分支检测人脸,这样解决多尺度的问题。
在网络的前半部分,RDCL主要是加速,快速缩小特征图。
① Conv1,Pool1, Conv2 和 Pool2 的stride分别是4,2, 2 和 2。这样整个RDCL的stride就是32,就是说原始的输入尺寸被缩小了32次。
② 另外,通过设计合适的核尺寸来加速计算。卷积核或者池化核尺寸太大就会导致计算量增加,尺寸太小又会导致覆盖的信息不足,所以文章中直接选择了7×7,5×5 , 3×3, 3×3分别对应 Conv1, Conv2 ,Pool1,Pool2 。
③ 最后,由于为了减少计算量,减少了卷积核的数量。为了保证输出维度不变,通过使用CReLU来保持输出维度不变。
关于CReLU,CReLU论文的大致意思是在神经网络中靠前的部分,参数的分布具有很强的负相关性,随着网络的变深,这种负相关性越来越弱。在网络的前部,网络更加倾向于同时捕捉正负相位的信息,但是由于ReLU的特性将负响应抹掉了,这样造成了卷积核会存在一定冗余。
上图中,红色曲线是假设随机高斯分布生成的卷积核得到的相似度统计。蓝色的直方图是对所有的卷积核寻找其pair filter,按照相似度和数量画出的。这个图说明了随着网络深度加深,负相关性越来越小。
在网络的后半部分,MSCL主要是解决人脸多尺度的问题,这种方法增加了小人脸的召回率。
① 在网络的不同层进行检测,类似于SSD。
② 采用Inception模块。由于Inception包含多个不同的卷积分支,因此可以进一步使得感受野多样化。
Faster-RCNN中RPN对小目标检测效果不好,一定程度上是因为RPN中的anchor只跟卷积层后面几层有关系,并且小目标所能对应的anchor比较少。
最后采用增加anchor密度的方法来提高多尺度人脸的召回率
根据计算anchor密度的方法,密度=anchor大小/stride,原始Inception3网络结构中anchor大小分别为32,64,128,stride为32,所以其密度为1,2,4。Conv3_2和Conv4_2的密度都是4。为了anchor的密度均衡,所以对密度不足的anchor进行均衡化。
论文的效果还没有复现出来,目前github上开源的代码,FDDB上的检测效果只有0.91,在cpu上的时间消耗在180ms左右,640X480分辨率。
关注我的公众号,分享资源
公众号搜索: 卡本特
扫码关注
 -
利用MTCNN和facenet实现人脸检测和人脸识别
2018-12-09 14:29:07利用MTCNN和facenet实现人脸检测和人脸识别 人脸检测和人脸识别技术算是目前人工智能方面应用最成熟的技术了。本博客将利用mtcnn和faceNet搭建一个实现人脸检测和人脸识别的系统。基本思路也很简单,先利用mtcnn的...利用MTCNN和facenet实现人脸检测和人脸识别
人脸检测和人脸识别技术算是目前人工智能方面应用最成熟的技术了。本博客将利用mtcnn和faceNet搭建一个实现人脸检测和人脸识别的系统。基本思路也很简单,先利用mtcnn的进行人脸检测,当然也可以使用其他的人脸检测方法,如Dilb,OpenCV,OpenFace人脸检测等等,然后再利用faceNet进行人脸识别,faceNet可简单看成是提取人脸特征的CNN网络,这个特征就是embadding了,有了人脸特征embadding,最后一步,就只需要与数据库人脸特征进行相似性比较,即可完成人脸识别的任务。
老规矩,先上Github源码:记得给个“Star”哦,不然,对不起我的苦劳!!!!
本博客Github源码: https://github.com/PanJinquan/Face_Detection_Recognition/tree/master/faceRecognition
FaceNet的人脸识别效果并不算好,相比InsightFace模型,就差很多。目前使用InsightFace模型测试,在开数据集可以达到99.6%,在自建的数据集可以达到93%的准确率,比虹软的人脸识别率还高一点,关于InsightFace模型的项目,我还在整理,网友慢慢期待哈,不急!
目录
一、项目结构:
打开FaceNet Github地址: https://github.com/davidsandberg/facenet,把我们需要的文件拷贝到自己独立的工程中,(1)align文件夹,(2)facenet.py文件:
align:这个文件夹是从facenet中拷贝的,https://github.com/davidsandberg/facenet/tree/master/src/align,主要是MTCNN人脸检测的相关文件
facenet.py:这个Python文件也是从facenet中拷贝的,https://github.com/davidsandberg/facenet/blob/master/src/facenet.py
其他文件介绍
dataset:这个文件夹主要存放数据,如人脸数据库
utils:这个文件是工具类文件,用于文件读写,图像相关操作的函数方法等
models:存放facenet预训练模型,百度网盘下载地址:链接: https://pan.baidu.com/s/1hAK9ylURkbeH52BtSSGWsw 提取码: jf1n
Pre-trained models:
Model name LFW accuracy Training dataset Architecture 20180408-102900 0.9905 CASIA-WebFace Inception ResNet v1 20180402-114759 0.9965 VGGFace2 Inception ResNet v1 NOTE: If you use any of the models, please do not forget to give proper credit to those providing the training dataset as well.
二、实现流程
1.通过MTCNN人脸检测模型,从照片中提取人脸图像。
2.把人脸图像输入到FaceNet,计算Embedding的特征向量。
3.比较特征向量间的欧式距离,判断是否为同一人,例如当特征距离小于1的时候认为是同一个人,特征距离大于1的时候认为是不同人。
三、Multi-task CNN(MTCNN)人脸检测
人脸检测方法很多,如Dilb,OpenCV,OpenFace人脸检测等等,这里使用MTCNN进行人脸检测,一方面是因为其检测精度确实不错,另一方面facenet工程中,已经提供了用于人脸检测的mtcnn接口。 MTCNN是多任务级联CNN的人脸检测深度学习模型,该模型中综合考虑了人脸边框回归和面部关键点检测。在facenet工程中的位置是
align/detect_face.py
,它的参数模型也保存在align文件夹下,分别是det1.npy,det2.npy,det3.npy
。参考资料:
MTCNN一个深度卷积多任务的框架,这个框架利用了检测和对准之间固有的关系来增强他们的性能。特别是,在预测人脸及脸部标记点的时候,通过3个CNN级联的方式对任务进行从粗到精的处理。
Stage 1:使用P-Net是一个全卷积网络,用来生成候选窗和边框回归向量(bounding box regression vectors)。使用Bounding box regression的方法来校正这些候选窗,使用非极大值抑制(NMS)合并重叠的候选框。全卷积网络和Faster R-CNN中的RPN一脉相承。
Stage 2:使用R-Net改善候选窗。将通过P-Net的候选窗输入R-Net中,拒绝掉大部分false的窗口,继续使用Bounding box regression和NMS合并。
Stage 3:最后使用O-Net输出最终的人脸框和特征点位置。和第二步类似,但是不同的是生成5个特征点位置。
这里提供一个使用MTCNN进行人脸检测的方法:
def detection_face(img): minsize = 20 # minimum size of face threshold = [0.6, 0.7, 0.7] # three steps's threshold factor = 0.709 # scale factor print('Creating networks and loading parameters') with tf.Graph().as_default(): # gpu_memory_fraction = 1.0 # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_memory_fraction) # sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess = tf.Session() with sess.as_default(): pnet, rnet, onet = detect_face.create_mtcnn(sess, None) bboxes, landmarks = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor) landmarks = np.transpose(landmarks) bboxes = bboxes.astype(int) bboxes = [b[:4] for b in bboxes] landmarks_list=[] for landmark in landmarks: face_landmarks = [[landmark[j], landmark[j + 5]] for j in range(5)] landmarks_list.append(face_landmarks) return bboxes,landmarks_list
当然,实际应用中,建议还是封装成一个类吧,方面初始化和单独调用:
注意:mtcnn人脸检测获得bboxes并不一定是正方形的矩形框,参数fixed指定等宽或者等高的bboxes,其实现方法可以参考get_square_bboxes()方法。当然啦,你也可以不调用get_square_bboxes()方法,直接resize成指定大小,也是OK的。
class Facedetection: def __init__(self): self.minsize = 30 # minimum size of face self.threshold = [0.6, 0.7, 0.7] # three steps's threshold self.factor = 0.709 # scale factor print('Creating networks and loading parameters') with tf.Graph().as_default(): # gpu_memory_fraction = 1.0 # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_memory_fraction) # sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess = tf.Session() with sess.as_default(): self.pnet, self.rnet, self.onet = detect_face.create_mtcnn(sess, None) def detect_face(self,image,fixed=None): ''' mtcnn人脸检测, PS:人脸检测获得bboxes并不一定是正方形的矩形框,参数fixed指定等宽或者等高的bboxes :param image: :param fixed: :return: ''' bboxes, landmarks = detect_face.detect_face(image, self.minsize, self.pnet, self.rnet, self.onet, self.threshold, self.factor) landmarks_list = [] landmarks=np.transpose(landmarks) bboxes=bboxes.astype(int) bboxes = [b[:4] for b in bboxes] for landmark in landmarks: face_landmarks = [[landmark[j], landmark[j + 5]] for j in range(5)] landmarks_list.append(face_landmarks) if fixed is not None: bboxes,landmarks_list=self.get_square_bboxes(bboxes, landmarks_list, fixed) return bboxes,landmarks_list def get_square_bboxes(self, bboxes, landmarks, fixed="height"): ''' 获得等宽或者等高的bboxes :param bboxes: :param landmarks: :param fixed: width or height :return: ''' new_bboxes = [] for bbox in bboxes: x1, y1, x2, y2 = bbox w = x2 - x1 h = y2 - y1 center_x, center_y = (int((x1 + x2) / 2), int((y1 + y2) / 2)) if fixed == "height": dd = h / 2 elif fixed == 'width': dd = w / 2 x11 = int(center_x - dd) y11 = int(center_y - dd) x22 = int(center_x + dd) y22 = int(center_y + dd) new_bbox = (x11, y11, x22, y22) new_bboxes.append(new_bbox) return new_bboxes, landmarks
四、faceNet人脸识别
FaceNet Github地址: https://github.com/davidsandberg/facenet
参考资料:https://blog.csdn.net/fire_light_/article/details/79592804
Google工程师Florian Schroff,Dmitry Kalenichenko,James Philbin提出了人脸识别FaceNet模型,该模型没有用传统的softmax的方式去进行分类学习,而是抽取其中某一层作为特征,学习一个从图像到欧式空间的编码方法,然后基于这个编码再做人脸识别、人脸验证和人脸聚类等。
FaceNet主要用于验证人脸是否为同一个人,通过人脸识别这个人是谁。FaceNet的主要思想是把人脸图像映射到一个多维空间,通过空间距离表示人脸的相似度。同个人脸图像的空间距离比较小,不同人脸图像的空间距离比较大。这样通过人脸图像的空间映射就可以实现人脸识别,FaceNet中采用基于深度神经网络的图像映射方法和基于triplets(三联子)的loss函数训练神经网络,网络直接输出为128维度的向量空间。
FaceNet的网络结构如下图所示,其中Batch表示人脸的训练数据,接下来是深度卷积神经网络,然后采用L2归一化操作,得到人脸图像的特征表示,最后为三元组(Triplet Loss)的损失函数。
下面是鄙人已经封装好的facenetEmbedding类,其中类函数get_embedding(self,images)方法用于提取facenet的人脸特征embadding,有了人脸embadding特征,就可以比较人脸相似性啦!
class facenetEmbedding: def __init__(self,model_path): self.sess = tf.InteractiveSession() self.sess.run(tf.global_variables_initializer()) # Load the model facenet.load_model(model_path) # Get input and output tensors self.images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0") self.tf_embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0") self.phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0") def get_embedding(self,images): feed_dict = {self.images_placeholder: images, self.phase_train_placeholder: False} embedding = self.sess.run(self.tf_embeddings, feed_dict=feed_dict) return embedding def free(self): self.sess.close()
五、产生数据库
既然是人脸识别,数据库肯定要有已知人脸的数据库,不然怎么知道被检测的人脸是哪位大神,所以先制作人脸数据库。
(1)制作人脸数据图库:
把相关大神的人像收集放在dataset/images文件夹下:
特别说明:
- 这里只收集了4张胡歌和4张周杰伦的单人照片,
- 注意制作人脸数据图库时,所使用的照片必须是单人照片!!!
- 若需要新增图库,只需在dataset/images下,新建一个文件夹,如,新增“xietingfeng”(谢霆锋)的文件夹,然后把谢霆锋的单人照片放在里面即可,图片名称可以是任意
- 函数image_list,names_list=file_processing.gen_files_labels(images_dir,postfix='jpg')可以获取目录images_dir下所有文件,包括子目录下的所有文件路径(image_list),其中names_list就是子目录的文件名,一般子目录作为样本的标签。
(2)生成embedding数据库
有了人脸数据图库,就可以使用create_dataset.py生成embedding数据库(人脸特征),后面待检测识别的人脸,只需要与这些embedding数据库(人脸特征)进行相似性比较,就可以识别人脸啦!!!!
opencv-python的imread()函数并不支持中文路径,这里在提供一个函数read_image_gbk()方便读取中文路径的图像。详细请看image_processing.py文件
# -*-coding: utf-8 -*- """ @Project: faceRecognition @File : create_dataset.py @Author : panjq @E-mail : pan_jinquan@163.com @Date : 2018-12-07 11:31:09 """ import numpy as np from utils import image_processing , file_processing,debug import face_recognition import cv2 import os resize_width = 160 resize_height = 160 def get_face_embedding(model_path,files_list, names_list): ''' 获得embedding数据 :param files_list: 图像列表 :param names_list: 与files_list一一的名称列表 :return: ''' # 转换颜色空间RGB or BGR colorSpace="RGB" # 初始化mtcnn人脸检测 face_detect = face_recognition.Facedetection() # 初始化facenet face_net = face_recognition.facenetEmbedding(model_path) embeddings=[] # 用于保存人脸特征数据库 label_list=[] # 保存人脸label的名称,与embeddings一一对应 for image_path, name in zip(files_list, names_list): print("processing image :{}".format(image_path)) # image_path='E:/Face/dataset/bzl/subjectphoto_with_name/谢伟林_179_180.jpg' image = image_processing.read_image_gbk(image_path, colorSpace=colorSpace) # 进行人脸检测,获得bounding_box bboxes, landmarks = face_detect.detect_face(image) bboxes, landmarks =face_detect.get_square_bboxes(bboxes, landmarks,fixed="height") # image_processing.show_image_boxes("image",image,bboxes) if bboxes == [] or landmarks == []: print("-----no face") continue if len(bboxes) >= 2 or len(landmarks) >= 2: print("-----image have {} faces".format(len(bboxes))) continue # 获得人脸区域 face_images = image_processing.get_bboxes_image(image, bboxes, resize_height, resize_width) # 人脸预处理,归一化 face_images = image_processing.get_prewhiten_images(face_images,normalization=True) # 获得人脸特征 pred_emb = face_net.get_embedding(face_images) embeddings.append(pred_emb) # 可以选择保存image_list或者names_list作为人脸的标签 # 测试时建议保存image_list,这样方便知道被检测人脸与哪一张图片相似 # label_list.append(image_path) label_list.append(name) return embeddings,label_list def create_face_embedding(model_path,dataset_path,out_emb_path,out_filename): ''' :param model_path: faceNet模型路径 :param dataset_path: 人脸数据库路径,每一类单独一个文件夹 :param out_emb_path: 输出embeddings的路径 :param out_filename: 输出与embeddings一一对应的标签 :return: None ''' files_list,names_list=file_processing.gen_files_labels(dataset_path,postfix='jpg') embeddings,label_list=get_face_embedding(model_path,files_list, names_list) print("label_list:{}".format(label_list)) print("have {} label".format(len(label_list))) embeddings=np.asarray(embeddings) np.save(out_emb_path, embeddings) file_processing.write_data(out_filename, label_list, model='w') if __name__ == '__main__': model_path = 'models/20180408-102900' dataset_path='dataset/images' out_emb_path = 'dataset/emb/faceEmbedding.npy' out_filename = 'dataset/emb/name.txt'
六、人脸识别过程
(1)加载人脸数据库
把上面制作的,已知的人脸数据库加载进来:
def load_dataset(dataset_path,filename): ''' 加载人脸数据库 :param dataset_path: embedding.npy文件(faceEmbedding.npy) :param filename: labels文件路径路径(name.txt) :return: ''' compare_emb=np.load(dataset_path) names_list=file_processing.read_data(filename,split=False) return compare_emb,names_list
(2)进行人脸检测
def face_recognition_image(model_path,dataset_path, filename,image_path): # 加载数据库的数据 dataset_emb,names_list=load_dataset(dataset_path, filename) # 初始化mtcnn人脸检测 face_detect=face_recognition.Facedetection() # 初始化facenet face_net=face_recognition.facenetEmbedding(model_path) image = image_processing.read_image_gbk(image_path) # 获取 判断标识 bounding_box crop_image bboxes, landmarks = face_detect.detect_face(image) bboxes, landmarks = face_detect.get_square_bboxes(bboxes, landmarks, fixed="height") if bboxes == [] or landmarks == []: print("-----no face") exit(0) print("-----image have {} faces".format(len(bboxes))) face_images = image_processing.get_bboxes_image(image, bboxes, resize_height, resize_width) face_images = image_processing.get_prewhiten_images(face_images) pred_emb=face_net.get_embedding(face_images) pred_name,pred_score=compare_embadding(pred_emb, dataset_emb, names_list) # 在图像上绘制人脸边框和识别的结果 show_info=[ n+':'+str(s)[:5] for n,s in zip(pred_name,pred_score)] image_processing.show_image_text("face_recognition", image,bboxes,show_info)
(3)人脸识别(比较相似性)
比较特征向量间的欧式距离
def compare_embadding(pred_emb, dataset_emb, names_list,threshold=0.65): # 为bounding_box 匹配标签 pred_num = len(pred_emb) dataset_num = len(dataset_emb) pred_name = [] pred_score=[] for i in range(pred_num): dist_list = [] for j in range(dataset_num): dist = np.sqrt(np.sum(np.square(np.subtract(pred_emb[i, :], dataset_emb[j, :])))) dist_list.append(dist) min_value = min(dist_list) pred_score.append(min_value) if (min_value > threshold): pred_name.append('unknow') else: pred_name.append(names_list[dist_list.index(min_value)]) return pred_name,pred_score
(4)人脸识别效果
一切准备好了,开始run:
if __name__=='__main__': model_path='models/20180408-102900' dataset_path='dataset/emb/faceEmbedding.npy' filename='dataset/emb/name.txt' image_path='dataset/test_images/1.jpg' face_recognition_image(model_path, dataset_path, filename,image_path)
说明:
为了方便测试, 这里以文件的路径作为人脸label,这样方便知道被检测人脸与哪一张图片最相似
./dataset/emb_face\huge\huge_1.jpg
./dataset/emb_face\huge\huge_2.jpg
./dataset/emb_face\huge\huge_3.jpg
./dataset/emb_face\huge\huge_4.jpg
./dataset/emb_face\zhoujielun\zhoujielun_1.jpg
./dataset/emb_face\zhoujielun\zhoujielun_2.jpg
./dataset/emb_face\zhoujielun\zhoujielun_3.jpg
./dataset/emb_face\zhoujielun\zhoujielun_4.jpg对应的label是:
huge
huge
huge
huge
zhoujielun
zhoujielun
zhoujielun
zhoujielun七、模型测评
为了对faceNed性能进行测评,这里提供一个测评文件:evaluation_test.py,该文件会绘制测试文件的ROC曲线,并给出最优阈值,以及FPR, TPR, AUC等参数。
这里的测试数据集是agedb_30,该数据集共有12000张,分为6000对照片,每对照片有一个label,即True和False,对应1和0,表示该对照片是否是同一个人;利用该数据集,就可以绘制模型的ROC曲线了
# -*- coding: utf-8 -*- import os import pickle from utils import image_processing,file_processing,evaluation import cv2 import PIL.Image as Image import numpy as np import matplotlib.pyplot as plt from sklearn import metrics import face_recognition def load_npy(dir_path): issames_path=os.path.join(dir_path,"issames.npy") pred_score_path=os.path.join(dir_path,"pred_score.npy") issames=np.load(issames_path) pred_score=np.load(pred_score_path) return pred_score,issames def load_bin(path, image_size=[112,112]): ''' 加载人脸bin文件数据,bin_files = ['agedb_30', 'cfp_fp', 'lfw', 'calfw', 'cfp_ff', 'cplfw', 'vgg2_fp'] :param path: :param image_size: :return: ''' bins, issame_list = pickle.load(open(path, 'rb'), encoding='bytes') data=[] for i in range(len(bins)): _bin = bins[i] img = cv2.imdecode(_bin, -1) # opencv image is bgr img = image_processing.resize_image(img,resize_height=image_size[0],resize_width=image_size[1]) # image_processing.show_image("src",img) data.append(img) i += 1 if i % 1000 == 0: print('loading bin', i) data = np.array(data) issames = np.array(issame_list) return data, issames def split_data(data): ''' 按照奇偶项分割数据 :param data: :return: ''' data1 = data[0::2] data2 = data[1::2] return data1,data2 def get_pair_scores(faces_data, issames_data, model_path, save_path=None): ''' 计算分数 :param faces_data: :param issames_data: :param model_path: insightFace模型路径 :param save_path: :return: ''' faces_list1,faces_list2 = split_data(faces_data) face_net=face_recognition.facenetEmbedding(model_path) pred_score=[] i=0 for face1,face2,issame in zip(faces_list1, faces_list2, issames_data): # pred_id, pred_scores = faceRec.predict(faces) # 或者使用get_faces_embedding()获得embedding,再比较compare_embedding() face_images1 = image_processing.get_prewhiten_images([face1],normalization=False) face_images2 = image_processing.get_prewhiten_images([face2],normalization=False) face_emb1=face_net.get_embedding(face_images1) face_emb2=face_net.get_embedding(face_images2) # face_emb1 = face_net.get_faces_embedding([face1]) # face_emb2 = face_net.get_faces_embedding([face2]) dist = np.sqrt(np.sum(np.square(np.subtract(face_emb1, face_emb2)))) pred_score.append(dist) i += 1 if i % 100 == 0: print('processing data :', i) pred_score=np.array(pred_score).reshape(-1) issames_data= issames_data + 0 # 将true和false转为1/0 if save_path is not None: issames_path = os.path.join(save_path, "issames.npy") pred_score_path = os.path.join(save_path, "pred_score.npy") np.save(issames_path, issames_data) np.save(pred_score_path,pred_score) return pred_score, issames_data if __name__=='__main__': # bin_files = ['agedb_30', 'cfp_fp', 'lfw', 'calfw', 'cfp_ff', 'cplfw', 'vgg2_fp'] bin_path='./dataset/faces_emore/agedb_30.bin' model_path = './models/20180408-102900' # 加载bin测试数据 faces_data, issames_data=load_bin(bin_path,image_size=[160,160]) # 计算分数 save_path="./dataset/faces_emore" pred_score, issames_data=get_pair_scores(faces_data, issames_data, model_path, save_path=save_path) pred_score, issames_data=load_npy(dir_path=save_path) # 计算roc曲线 fpr, tpr, roc_auc, threshold, optimal_idx=evaluation.get_roc_curve(y_true=issames_data, y_score=pred_score, invert=True, plot_roc=True) print("fpr:{}".format(fpr)) print("tpr:{}".format(tpr)) print("threshold:{}".format(threshold)) print("roc_auc:{}".format(roc_auc)) print("optimal_idx :{},best_threshold :{} ".format(optimal_idx,threshold[optimal_idx])) # 测评数据保存 evaluation.save_evaluation(fpr, tpr, roc_auc, "evaluation.npz") # 加载测评数据 fpr, tpr, roc_auc=evaluation.load_evaluation("evaluation.npz") evaluation.plot_roc_curve(fpr_list=[fpr], tpr_list=[tpr], roc_auc_list=[roc_auc], line_names=["FaceNet"])
对应的ROC曲线如下:optimal_idx :1038,最佳阈值:best_threshold :1.1444087028503418
FaceNet的人脸识别效果并不算好,相比InsightFace模型,就差很多。目前使用InsightFace模型测试,在开数据集可以达到99.6%,在自建的数据集可以达到93%的准确率,比虹软的人脸识别率还高一点,关于InsightFace模型的项目,我还在整理,网友慢慢期待哈,不急!
八、参考资料:
【1】《如何应用MTCNN和FaceNet模型实现人脸检测及识别》http://www.uml.org.cn/ai/201806124.asp
如果你觉得该帖子帮到你,还望贵人多多支持,鄙人会再接再厉,继续努力的~
-
人脸检测
2008-04-14 23:57:00人脸检测的任务是在复杂的背景下检测图像中有无人脸,从而判断人是否存在,并提取出人脸面部图像信息.欧式距离:在二维和三维空间中的欧式距离的就是两点之间的距离,二维的公式是 d = sqrt((x1-x2)^+(y1-y2)^)三前一阵子的工作已经告一段落了,新的挑战即将开始,既然选择了它,就要无悔,开弓没有回头箭,努力吧!!
人脸检测的任务是在复杂的背景下检测图像中有无人脸,从而判断人是否存在,并提取出人脸面部图像信息.
欧式距离:
在二维和三维空间中的欧式距离的就是两点之间的距离,二维的公式是
d = sqrt((x1-x2)^+(y1-y2)^)
三维的公式是
d=sqrt(x1-x2)^+(y1-y2)^+z1-z2)^)
推广到n维空间,欧式距离的公式是
d=sqrt( ∑(xi1-xi2)^ ) 这里i=1,2..n
xi1表示第一个点的第i维坐标,xi2表示第二个点的第i维坐标隐马尔科夫模型
隐马尔科夫模型(hidden Markov model, HMM, 被我亲切的称为黑妹妹)于20世纪70年代在语音识别领域取得巨大的成功,之后被广泛应用到自然语言处理的各个领域,成为基于统计的自然语言处理的重要方法.
先来看看基础的知识–随机过程, 或许需要复习复习大学的<概率统计>了. 随机过程是在同一样本空间Ω下的一个随机变量序列ε1,ε2,ε3,…,εn.这些变量可能出现的结果称为这个随机过程的状态.例如以掷骰子,不断掷出的骰子所形成的序列就可以看作是一个随机过程.
随机过程按照时间的连续与否可以分为连接随机过程和离散随机过程.上面举的例子就是一个离散随机过程. 离散随机过程完全可以用以下两个条件刻画:
- 初始时刻的任意状态的初始概率为
;
- 此后任意时刻的条件概率为
, 其中 t∈N
了解了离散随机过程,接着我们看一下马尔科夫链和马尔科夫性.马尔科夫链是一种特殊的离散随机过程,这种随机过程的下一时刻的状态完全由当前时刻的状态来决定,而与从前的状态无关,即”未来”只与”现在”有关,而与”过去”无关.即:
称具有以上性质的随机过程为马尔科夫过程,具有马尔科夫性.如果随机过程的马尔科夫性成时间t无关,则这个随机过程被称为齐次马尔科夫过程.下面讨论的都是齐次马尔科夫过程.
概率转移矩阵是描述马尔科夫链的重要工具.给定一个具有n个状态s1,s2,…,sn的马尔科夫链,设从状态si到sj的概率为pij,即:
,则概率转移矩阵定义为
通过根据转移矩阵可以直观地看到从状态si到状态sj的概率pij,方便地计算出一个马尔科夫链的概率.也可以通过概率转移矩阵算出从状态si出发,经过n个时刻到达状态sj的概率
:
再来看一下马尔科科夫模型,实际的马尔科夫模型是在马尔科夫链的基础上发展起来的.现实世界十分复杂, 实际问题往往不能直接转换成马尔科夫链来处理,观察到的事件也不能与马尔科夫链的状态一一对应,而是通过某种概率分布来与状态保持联系.这种实际事件与状态由某种概率分布来联系的马尔科夫链就是马尔科夫模型.实际上,马尔科夫模型是一个双重随机过程.其中的一重随机过程是描述基本的状态转移,而另一重随机过程是描述状态与观察值之间的对应关系.下面是马尔科夫模型的形式定义:
马尔科夫模型是一个五元组M={Ω,Σ,P,A,Θ},其中Ω={s1,s2,…,sn}是所有状态的集合;Σ={σ1,σ2,…σm}是所有观察序列的集合;
是概率转移矩阵;
称为发射概率矩阵,其中
是在状态si观察到σj的概率,Θ={π1,π2,…,πn}是初始概率向量,其中πi是在状态i的初始概率.
隐马尔科夫模型(HMM)
当马尔科夫模型中的”状态”对于外界来说是不可见的时候,就转换成了隐马尔科夫模型.其实马尔科夫模型和隐马尔科夫模型的数据模型都是相同的,只是因为现实问题的情况不同,对模型的限定条件不同以及要解决的问题不同而分为两个模型.
黑妹妹模型有三个基本的问题要解决:
- 对于给定的观察序列,它出现的概率是多大.
- 对于给定的观察序列,在状态序列未知的情况下,根据现有的黑妹妹模型,它最有可能的隐含状态序列是什么.
- 给定观察序列,怎样调整现在的黑妹妹的模型参数,使得此观察序列的概率最大,即最好地”解释”了这一观察序列,也就是HMM的训练问题.
计算机人脸识别的主要方法
人脸识别方法的分类,根据研究角度的不同,可以有不同的分类方法。根据输入图像中人脸的角度,可以分为基于正面,侧面,倾斜人脸图像的人脸识别;根据图像来源的不同,可以分为静态和动态的人脸识别;根据图像的特点,可以分为灰度图像和彩色图像的人脸识别。本文的研究就是基于正面,静态的灰度图像的。根据对灰度图像的特征提取方式的不同,人脸识别方法大致可以分成三种:基于局部特征的人脸识别方法,基于整体的人脸识别方法和基于将局部和整体结合起来的人脸识别方法。
(1)结构匹配的方法
早期的人脸识别方法有检测人脸的眼睛,眉毛,鼻子和嘴巴等各种几何特征。特征点的位置,距离和角度等的各个特征和相互的联系就用作人脸识别的描述符。这种方法的主要缺点在于识别效果取决于特征定位算法的准确性。另外一种结构匹配的方法是从人脸边缘图中提取一种线性边缘图(Line edge map简称LEM)(来进行特征提取。它是基于结合模板匹配和几何特征匹配来进行的。先利用Sobel边缘算子来提取人脸二值图象,然后用人脸几何特征的提取方法来量度人脸之间的相似性。这种方法的优点在于光照不变性,存储量小和基于模板匹配的高识别率;主要缺点在于对于人脸面部的大的表情变化很敏感。
(2)隐马尔可夫模型(Hidden Markov Model,简称HMM)的方法
隐马尔可夫模型是采用概率统计的方法描述时变信号。 HMM原来是应用在语音识别领域的,并取得了相当的成功,但是由于语音信号是一维信号,而图像是二维信号,为了把HMM应用于二维的图像,就要在图像上取一个采样窗口,该窗口的宽度就是图像的宽度,高度可能只有几个像素,然后将在图像上由上至下滑动,相邻窗口之间允许重叠,这样就把人脸垂直分成了五个区域:前额,眼睛,鼻子,嘴巴,下领,然后用一个五状态的HMM模型来表达人脸。基于离散马尔可夫模型和奇异值特征的人脸检测方法.其实质是将奇异值特征转化为向量序列.再利用HMM对其进行识别,这种方法鲁棒性较好,对不同角度和不同光照条件的人脸图像都可以取得较好的识别效果。
(3)弹性图匹配(Elastic Bunch Graph Matching简称EBGM)的方法
该方法采用网格作为模板,将图像间的比较变为网格间的比较。使用一种基于动态链接结构的弹性匹配法来定位人脸,并根据人脸数据库进行匹配识别。将人脸用格状的稀疏图形描述(图1-3),图中的节点用图像位置的Gabor小波分解得到的特征向量标记,记录人脸在该顶点位置的分布信息,图的边用连接节点的距离向量标记,表示拓扑连接关系。匹配时,首先寻找与输入图像的最相似的模型图,再对图中的每个节点位置进行最佳匹配,寻找最近的己知图形。弹性匹配方法提取了人脸图像的局部特征,保留了人脸图像的空间信息,可以在一定程度上容忍人脸从三维到二维投影引起的变形。因此,对人脸变形和光照变化等具有较好的适应性,整体识别性能优于特征脸法。但是计算量大,识别速度慢。
(1)基于主成分分析(Principal Component Analysis简称PCA)的方法
PCA是一种经典的算法,它根据图像的统计特征进行正交变换,以消除原有向量各个分量之间的相关性。变换得到对应特征值依次递减的特征向量。即特征脸。利用特征脸可以重建和识别人脸。PCA方法是统计最优的,速度快,实现方便,对正面图像识别率高。但是容易受光照、人脸旋转和小形变,光照改变及位移改变等因素的影响。因此许多学者在此基础上又作了不少改进。其中一种就是基于线性鉴别分析(LDA.Linear Discrirninant Analysis) , Belhumeur等的Fisherfaces方法。它能充分利用类别的信息。Bartlett等采用独立分量分析(ICA, Independent Component Analysis)的方法识别人脸,获得了比PCA方法更好的识别效果。与PCA相比,ICA有两个优势:一是ICA获得的独立分量不需要满足正交关系,能够消除象素间的高阶统计相关性,而PCA只能消除象素间的二阶统计相关性;二是ICA获得的一组矢量比本征矢量更具空间局部描述性,具有更好的人脸描述能力。现在还出现很多其他子空间的人脸识别方法。借鉴SVM的Kernel方法,PCA, LDA等都被扩展到Kernel PCA和Kernel ICA。与线性子空间方法相比,基于Kernel的方法获得了更好的识别效果,然而计算量较大。
(2)基于人工神经网络(Artificial Neural Networks简称ANN)的方法
人工神经网络(ANN)是以对大脑的生理研究成果为基础,用机器来模拟大脑的某些机理与机制,实现某方面功能的方法,具有强大的非线性逼近能力,它既是特征提取器,又是分类器。神经网络中的神经元是人类大脑神经单元的简化,神经网络以这些具有非线性映射能力的神经元为节点,神经元之间通过加权系数连接。目前比较有代表性的方法有:混合型神经网络、卷积神经网络、基于概率决策的神经网络,主元神经网络等。与前几类方法比起来,由于对人脸识别的许多规律或规则进行显性的描述相当困难,而神经网络方法则可以通过学习的过程获得对这些规律和规则的隐性表达,因此它的适应性更强,一般也比较容易实现。但是由于人类对自身思维机理认识的不足及对人工神经元作了极度的简化,这种模拟还是极其肤浅和简单的。
(3) 支持向量机(Support Vector Machine简称SVM)的方法
SVM起源于统计学习理论,它研究如何构造学习机,实现模式分类问题。其基本思想是通过非线性变换将输入空间变换到一个高维空间,在高维空间求取最优线性分类面,以解决那些线性不可分的分类问题。而这种非线性变换是通过定义适当的内积函数(即核函数)来实现的。SVM技术中核函数及其参数的选取难度较大。由于它基于结构风险最小化原理,而不是传统计学的经验风险最小化,因而表现出很多优于己有方法的性能。由于SVM的训练需要大量的存储空问,非线性SVM 分类器需要较多的支持向量,所以速度很慢。
(4) 小波变换(Wavelet Transform)的方法
小波变换是一种时间和频率的局域变换,通过伸缩、平移等运算对图像作多尺度细化分析,可以有效地从图像中提取信息,其作用原理是使用一系列不同带宽的滤波函数,将图分为4个子图:LL, LH, HL, HH.小波变换中,将图像“主信息”映射成低频分量LL,将噪音和细节映射成高频分量HH,通过对高频分量的舍弃和对低频分量的分析实现降维和图像滤波。同时过滤掉人脸的表情因数,可以提高识别精度。小波变换的优点是能同时在时域和频域描述人脸的局部信息,并能逐步聚焦到分析对象的任何细节。同时对细微的表情不敏感,可以在一定程度上容忍光线和角度的干扰。还可以考虑人脸的局部细节,保留人脸的空间信息。国内外应用该方法取得了众多的研究成果。
现有的每一种方法都是针对某一类问题提出的,都有自己的优缺点。基于局部特征识别方法的识别结果取决于特征定位的准确性,这类的方法现在已经发展到了弹性图匹配,总体来说识别率较高。然而,其缺点在于要求图像的像素较高,一般要128*128的像素大小。因此,只有在人脸与摄像机离得很近时才可能利用这种方法。基于整体的识别方法中,每一种都有自己的特点。近年来,很多研究者尝试采取将多分类器结合的方法来提取较稳定、受人脸姿态变化和光照条件等因素影响小的识别特征,取得了良好的识别效果。虽然多分类器组合还有很多问题值得进一步深入研究,但是却预示了人脸识别技术今后的发展方向。
在实验室待了一段时间了,在实验室的报告及小组会议中,深刻的体会到了HMM算法 ,SVM等的重要性.
这几天翻译了一篇使用隐马尔科夫模型(HMM)进行语音识别的论文的部分.
这篇论文是通过google的学术搜索搜到的,通过在互联网上的查找,发现这篇论文引用率很高。(排在google的第一位),并且没发现对其的汉语翻译。或许这篇是对该文的第一篇汉语翻译。原文一共有25页,由于时间的原因,只翻译其中部分内容。并对翻译较多的部分贴上原文对照。原文内容见网址:http://www.jstor.org/view/00401706/ap040131/04a00020/0使用隐马尔科夫进行语音识别作者:B.H.Juang,L.R.Rabiner语言语音研究所,Bell实验室Murray Hill,NJ 07974摘要:在近几年发表的论文和大型语言语音会议上中,隐马尔科夫定律已经成为语音识别研究的主导方法。这个方法之所以如此流行就在于其固有的统计框架:从有限语音训练集数据中训练出模型近似参数的简单易行;模型可根据特殊的词汇、声音等改变认知系统的大小、种类或模型的架构的灵活多变;实现整个认知系统的简单方便。在这篇解释性的文章中,我们将讲解应用在语音识别中的非常重要的统计方法,并讨论一系列尚未解决的原理性的和实际性的问题,因为他们很重要并对不同系统实现的性能有很大影响。关键词:Baum-Welch算法,Incomplete data problem ,Maximum a posteriori decoding;极大似然度机器语音识别已经达到了可以投入到实际使用的水平了。大量的语音识别系统已经应用在众多应用领域如语音拨号、语音应答、语音查询股价、语音报价等。导致这些有用的技术能够应用于实际是因为最近技术的进步使得语音认知系统能辨别不同的说话者并达到了一定量的认知词汇。其中的一项进步就是统计方法的使用,马尔科夫模型就是其中一个很有趣的方法。使用HMM来进行语音识别在过去的一段时间内很流行。虽然报告过的大量基于HMM的语音认知系统不易在此深入地讨论,列出其中最重要的部分和这些系统的成功之处仍然是值得的。其中包括在卡内基梅隆大学早期进行的Dragon System的工作,IBM公司在语音系统方面进行的长期的工作,在Bell实验室的工作,MIT林肯实验室的工作,Philips在使用HMM进行的整词识别的工作,DARPA资源管理任务,及其它在该相关领域的众多的工作。HMM的广泛流行可以归功于它简单的算法结构和它相对于其它语音识别方法的清晰高效性。性能,特别是精度,是评价一个语音认知系统实际价值的关键因素。语音识别任务经常根据它的需求,如是处理特定的还是非特定说话者,处理单个词汇的输入还是连续的一个句子的输入,来进行分类。如今,该技术能够轻松达到对非特定说话者的精确识别,当识别由非特定说话者说出的连续数字字串时,错误率仅有2-3%.更进一步,但在非特定说话者以特定的语法限制说出连续1000个词时,一些使用HMM的系统证实可以达到96%的识准率。这些结果说明了自动语音识别系统在指定的应用中的有用性和可用性。虽然隐马尔科夫模型显著地改善了当前语音识别系统的性能。完全流利的、非特定说话者的语音识别仍是一个普遍存在并等待着解决的问题。例如,没有一个系统能够识别没有限制(话题)的对话语音,也没有一个好的方法使用借助于有限语料库的统计方法去推断语言的结构。这篇解释性的文章的目的是提供HMM的原理的一个概述,讨论统计方法的作用,并指出一系列值得注意和理解的原理性和实践性问题,以便于推动语音识别这一领域的发展。1.语音的度量和建模语音是不稳定的信号量。当我们说话时,我们的发音器官(嘴唇、下颚、舌头,如图1所示)调节空气压力并影响气流产生一系列的声音。虽然任何一个声音的范围会是在几千赫兹的范围内,我们的关节配置(声道形状,舌头移动等)经常不能忍受每秒超过10次的动态变化。语音建模包括两个方面:(1)以10毫秒采样分析不同声音的短时间的范围属性,(2)根据关节配置的不同,以100毫秒采样去分析长时间声音的变化特征。2.隐马尔科夫模型统计方法在HMM 方法发展的过程中,如下问题显得特别有意思。首先,给出一个观察序列O和一个模型λ,我们怎么样有效的度量模型λ产生观察序列O的概率,即Pr (O|λ)?第二,给出观察序列O,反过来我们怎么解决估算模型λ中的参数?虽然(8)中的概率不完全依赖于q,(译者注:(8)是在论文前出现的一个公式),关于导致观察序列O的最可能的状态序列q的信息在很多的应用中都是需要的。第三个问题就是怎么有效地从观察序列O中推出最有可能的状态序列q.通常我们将这三个问题称为(1)评估问题(2)估计问题(3)解释问题。在下面的段落中,我们将描述几个对这三个问题通用的解决方法。2.1 评估问题在评估问题中主要关注的是计算的效率。如果没有复杂度约束,可以直接简单的直接计算出Pr(O|λ).在公式(8)中,一共有个可能的q序列。总共的计算需要2*T*个操作。计算公式(8)同时没有指数级增长的计算量,是HMM技术实现的第一个挑战。幸运的是,使用著名的前向-后向算法,这个昂贵的计算开销可以轻松的减轻。2.2 估计问题给出一个观察序列(或一个序列的集合)O.估计问题包括找到合适的模型参数使模型最可能产生给定的序列。在语音识别中,这经常被称为“训练”。我们用来获取模型参数的给定序列,被成为训练序列,即使这儿的准则是统计的。2.3 解释问题正如前面所说的,我们经常对找到产生观察序列O极大似然度的状态序列感兴趣。虽然HMM的概率度量定义中没有涉及到状态序列,在很多的应用场合中仍然需要知道极大似然度的状态序列。举个例来说,如果我们使用一个词汇模型的状态来代表该词汇中的特定的声音,就有必要知道语音片段和词的声音之间的关系,因为单独的语音片段为语音识别提供了有用信息。2.4 使用HMM进行语音识别HMM在语音识别中的应用和其他传统的模式匹配方法差不多。成功的使用HMM算法包括一下步骤:1.定义一个用来建模的L声音类的集合。例如音素或词汇,定义声音类V={v1,v2,..,v3};2. 对于每一个类,积累一定量的已知的标记语音集合。3.在训练集合的基础上,解决估计问题,为每个类Vi获取一个最好的模型λi.4. 在认识的过程中,对每个未知观察序列O估计Pr(O|λi)(i=1,2,…,L)),并为每个类Vi确定产生O的语音.其满足:Pr(O|λi) = Pr(O|λi)本文将不详细地描述如何实现一个HMM识别器。感兴趣的读者可以阅读Jelinek,Bahl,Mercer(1975)及Levinson,Rabiner,Sondhi(1983)的文章。3.使用隐马尔科夫模型进行语音识别的优点HMM方法的优点体现在两个大的方面:(1)它的数学框架和(2)它的实现结构。在数学框架方面,我们讨论问题的连续统计方法学和它为相关问题提供的直接的解决方案。在实现结构方面,我们讨论它在处理不同的、复杂的语音认知任务的灵活性和实现的简单性,这些都是在实际工程领域中需要考虑的关键问题。3.1 HMM方法学的连续统计框架3.2 HMM的训练算法3.3 模型灵活性4.进一步考虑隐马尔科夫定理的问题5.总结在这篇文章中,我们复习了HMM的统计学方法,展示了这个方法的统计学框架及由其带来的灵活性和通用性,特别是在语音识别方面,以及其实现的简单性,使其在工程实现方面显出优势。我们还指出了在一般的HMM方法中值得注意的方面,希望有人能在这些方面取得进步,这些进步将会大大提高性能。这些领域包括建模标准,特别是最小分类错误,将新的特征和之前的语言学知识的融合,对状态的建模和其在语音识别领域中的应用。根据我们现在的理解,HMM系统识别非特定说话者在一定量词汇量的语音识别率已经高达95%。随着技术的发展,不难预料到基于HMM模型的语音识别系统将能应用到我们的日常生活中去。(版权归原作者所有,我转贴是方便自己学习) - 初始时刻的任意状态的初始概率为
-
python+opencv 实现图像人脸检测及视频中的人脸检测
2020-09-01 17:13:38python+opencv 实现图像人脸检测及视频中的人脸检测,首先下载人脸检测要用到的分类器,熟悉opencv相关API的使用,然后利用python+opencv实现图像单人脸检测、图像多人脸检测、视频中人脸检测和摄像头人脸检测。执着于理想,纯粹于当下。
文章目录
原文链接:https://yetingyun.blog.csdn.net/article/details/108153075
创作不易,未经作者允许,禁止转载,更勿做其他用途,违者必究。一、数据和知识准备
1. 下载HAAR与LBP数据
人脸检测的常见步骤如下,如果想要将人脸准确地检测出来,需要通过建立人脸模型,获取准确区分人脸的分类器,这里我们使用网上公开的扩展包或已经训练好的分类器。
将haarcascades与lbpcascades里面的相关xml文件下载到本地,便于之后调用,辅助进行人脸检测。
下载地址:https://github.com/opencv/opencv/tree/master/data
2. opencv相关知识
- cv.CascadeClassifier():是OpenCV中人脸检测的一个级联分类器,既可以使用Haar特征,也可以使用LBP特征。以Haar特征分类器为基础的对象检测技术是一种非常有效的技术,它是基于机器学习且使用大量的正负样本训练得到分类器。
- detectMultiScale函数:检测人脸算法,其参数如下:
image:要检测的输入图像
scaleFactor:表示每次图像尺寸减小的比例
minNeighbors:表示每一个目标至少要被检测到多少次才算是真的人脸,因为周围的像素和不同的窗口大小都可能检测成人脸
minSize:表示目标的最小尺寸
maxSize:表示目标的最小尺寸 - Haar-like矩形特征:是用于物体检测的数字图像特征。这类矩形特征模板由两个或多个全等的黑白矩形相邻组合而成,而矩形特征值是白色矩形的灰度值的和减去黑色矩形的灰度值的和,矩形特征对一些简单的图形结构,如线段、边缘比较敏感。如果把这样的矩形放在一个非人脸区域,那么计算出的特征值应该和人脸特征值不一样,所以这些矩形就是为了把人脸特征量化,以区分人脸和非人脸。
- LBP:是一种特征提取方式,能提取出图像的局部的纹理特征,最开始的LBP算子是在3X3窗口中,取中心像素的像素值为阀值,与其周围八个像素点的像素值比较,若像素点的像素值大于阀值,则此像素点被标记为1,否则标记为0。这样就能得到一个八位二进制的码,转换为十进制即LBP码,于是得到了这个窗口的LBP值,用这个值来反映这个窗口内的纹理信息。LBPH是在原始LBP上的一个改进,在opencv支持下可以直接调用函数直接创建一个LBPH人脸识别的模型。
比如:cv2.face.LBPHFaceRecognizer_create()。
二、python+opencv实现人脸检测
1. 图像单人脸检测
import cv2 as cv def face_detection(image): # 创建一个级联分类器 加载一个.xml分类器文件 它既可以是Haar特征也可以是LBP特征的分类器 face_detecter = cv.CascadeClassifier(r'./face_detection/haarcascades/haarcascade_frontalface_default.xml') # 多个尺度空间进行人脸检测 返回检测到的人脸区域坐标信息 faces = face_detecter.detectMultiScale(image=image, scaleFactor=1.1, minNeighbors=5) print('检测人脸信息如下:\n', faces) for x, y, w, h in faces: # 在原图像上绘制矩形标识 cv.rectangle(img=image, pt1=(x, y), pt2=(x+w, y+h), color=(0, 0, 255), thickness=2) cv.imshow('result', image) src = cv.imread(r'./test/036.jpg') cv.imshow('input image', src) face_detection(src) cv.waitKey(0) cv.destroyAllWindows()
运行效果如下:
检测人脸信息如下: [[ 61 53 110 110]] Process finished with exit code 0
2. 图像多人脸检测
import cv2 as cv def face_detection(image): # 转成灰度图像 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 创建一个级联分类器 加载一个.xml分类器文件 它既可以是Haar特征也可以是LBP特征的分类器 face_detecter = cv.CascadeClassifier(r'./face_detection/haarcascades/haarcascade_frontalface_default.xml') # 多个尺度空间进行人脸检测 返回检测到的人脸区域坐标信息 faces = face_detecter.detectMultiScale(image=gray, scaleFactor=1.1, minNeighbors=5) print('检测人脸信息如下:\n', faces) for x, y, w, h in faces: # 在原图像上绘制矩形标识 cv.rectangle(img=image, pt1=(x, y), pt2=(x+w, y+h), color=(0, 0, 255), thickness=2) cv.imshow('result', image) src = cv.imread(r'./test/044.jpg') cv.imshow('input image', src) face_detection(src) cv.waitKey(0) cv.destroyAllWindows()
运行效果如下:
检测人脸信息如下: [[329 157 49 49] [ 88 156 44 44] [157 158 54 54] [240 159 50 50] [ 86 370 68 68] [ 79 254 54 54] [339 250 58 58] [155 254 59 59] [251 247 59 59] [199 371 80 80] [308 370 69 69]] Process finished with exit code 0
3. 视频中人脸检测
import cv2 # 加载视频 cap = cv2.VideoCapture('test.mp4') # 创建一个级联分类器 加载一个.xml分类器文件 它既可以是Haar特征也可以是LBP特征的分类器 face_detect = cv2.CascadeClassifier(r'./face_detection/haarcascades/haarcascade_frontalface_default.xml') while True: # 读取视频片段 ret, frame = cap.read() if not ret: # 读完视频后falg返回False break frame = cv2.resize(frame, None, fx=0.5, fy=0.5) # 灰度处理 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 多个尺度空间进行人脸检测 返回检测到的人脸区域坐标信息 face_zone = face_detect.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=8) # 绘制矩形和圆形检测人脸 for x, y, w, h in face_zone: cv2.rectangle(frame, pt1=(x, y), pt2=(x + w, y + h), color=[0, 0, 255], thickness=2) cv2.circle(frame, center=(x + w // 2, y + h // 2), radius=w // 2, color=[0, 255, 0], thickness=2) # 显示图片 cv2.imshow('video', frame) # 设置退出键和展示频率 if ord('q') == cv2.waitKey(40): break # 释放资源 cv2.destroyAllWindows() cap.release()
截取新版倚天屠龙记某一集36:35到36:39的片段,简单实现实时检测人脸并显示,运行效果如下:
任何算法都不会100%识别准确,由于噪声、误差、算法、训练集等影响,某些时候也会出现一些错误识别。自己进行简单测试时也会发现,人物动作、视频中镜头切换过快、背景变化等因素,可能会造成对视频中人脸检测不准确。4. 摄像头人脸检测
import cv2 as cv # 识别电脑摄像头并打开 cap = cv.VideoCapture(0, cv.CAP_DSHOW) # 创建一个级联分类器 加载一个.xml分类器文件 它既可以是Haar特征也可以是LBP特征的分类器 face_detect = cv.CascadeClassifier(r'./face_detection/haarcascades/haarcascade_frontalface_default.xml') while True: # 读取视频片段 flag, frame = cap.read() frame = cv.flip(frame, 1) if not flag: # 读完视频后falg返回False break # 灰度处理 gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) # 多个尺度空间进行人脸检测 返回检测到的人脸区域坐标信息 face_zone = face_detect.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5) # 绘制矩形和圆形检测人脸 for x, y, w, h in face_zone: cv.rectangle(frame, pt1=(x, y), pt2=(x + w, y + h), color=[0, 0, 255], thickness=2) cv.circle(frame, center=(x + w // 2, y + h // 2), radius=w // 2, color=[0, 255, 0], thickness=2) # 显示图片 cv.imshow('video', frame) # 设置退出键q 展示频率 if ord('q') == cv.waitKey(30): break # 释放资源 cv.destroyAllWindows() cap.release()
程序运行,即可调用电脑的摄像头识别面对摄像头的人脸,正脸和静止状态检测人脸的效果好。
作者:叶庭云
CSDN:https://blog.csdn.net/fyfugoyfa
本文仅用于交流学习,未经作者允许,禁止转载,更勿做其他用途,违者必究。
文章对你有所帮助的话,欢迎给个赞或者 star 呀,你的支持是对作者最大的鼓励,不足之处可以在评论区多多指正,交流学习呀。 -
2017年人脸检测、人脸对齐、人脸识别源码
2017-11-23 10:27:43人脸检测 人脸对齐 人脸识别工程,五点人脸特征识别 实时性好 -
人脸检测:人脸检测算法综述
2018-06-01 21:17:52问题描述人脸检测的目标是找出图像中所有的人脸对应的位置,算法的输出是人脸外接矩形在图像中的坐标,可能还包括姿态如倾斜角度等信息。下面是一张图像的人脸检测结果:虽然人脸的结构是确定的,由眉毛、眼睛、鼻子... -
代码C++, opencv实现人脸识别,人脸检测,人脸匹配,视频中的人脸检测,摄像头下的人脸检测等
2018-01-22 19:59:20前一段时间写了一个人脸相关的算法,包括视频中的人脸检测,相机的人脸检测,图像中人脸检测,还有人脸识别。 使用的是VS2013和opencv。 首先创建头文件common.h #ifndef _COMMON_H #define _COMMON_H #include #... -
人脸检测MTCNN进行人脸检测的过程
2018-04-16 11:02:34MTCNN可实现两个任务——人脸检测与人脸关键点检测——由三个级联的轻量级CNN完成:PNet,RNet和Onet。图像数据先后经这三个网络的处理,最终输出人脸检测和关键点检测结果。 检测的过程可见于detect_face... -
3分钟内实现人脸检测
2019-10-09 09:44:03人脸检测是人工智能最常见的应用之一。从智能手机的摄像头应用到Facebook的标签建议(Tag Suggestions),人脸检测的应用每天都在增加。 人脸检测是计算机程序在数字图像中识别和定位人脸的能力。 随着应用对人脸检测... -
深度学习_人脸检测_人脸检测与目标检测的区别
2020-04-24 10:23:48人脸检测是目标检测的一种特殊情形。目标检测(通用物体检测)针对的是多类别,人脸检测是二分类,只检测人脸这个类别。 通用物体检测算法都可以直接拿来做人脸检测,只需要改一下输出类别就可以。但是如果直接拿来... -
基于Python的OpenCV人脸检测
2020-07-23 19:56:32本文将要讲述的是Python环境下如何用OpenCV检测人脸,本文的主要内容分为: 1、检测图片中的人脸 2、实时检测视频中出现的人脸 3、用运设备的摄像头实时检测人脸 提前做的准备: 安装好Python3 下载安装OpenCV库... -
人脸检测和识别:人脸检测(Python)
2019-06-04 16:25:47视频人脸检测只是从摄像头读出每帧图像,然后采用静态图像中的人脸检测方法进行检测。至于视频人脸检测涉及到的其他处理过程,例如轨迹跟踪,将在以后完善。本文只介绍视频人脸检测,对于静态人脸检测,可通过本文... -
AdaBoost人脸检测程序
2012-06-04 16:54:43利用opencv2.3.1 开发的adaboost人脸检测,使用了正面人脸分类器,当摄像头检测到的正面人脸消失三秒钟后记录摄像头照片。项目开始的时候会有记录十张用户图片计算平均人脸面积。 -
人脸检测算法
2019-03-26 16:29:261级联CNN人脸检测方法 2 OpenCV人脸检测方法 ok 3 Seetaface人脸检测方法 山世光 4libfacedetect人脸检测方法 5 FaceNet 人脸检测(MTCNN) + 人脸比对(FaceNet) ... -
人脸检测(十九)--人脸检测综述(2018.2)
2018-06-01 14:45:08这篇文章,偏工程实用...《人脸检测背景介绍和常用数据库》,介绍人脸检测的背景,常用数据库和评价指标,重点介绍各类算法的发展现状和各数据库上目前算法的性能速度水平; 《非深度学习的人脸检测》,介绍以VJ为... -
Jetson Nano 从入门到实战(案例:Opencv配置、人脸检测、二维码检测)
2020-01-02 11:59:28目录 1.Jetson Nano简介 2. Jetson Nano环境配置 2.1 开箱配件介绍 2.2 烧录系统 2.3 开机和基本设置 2.4 开发环境配置 2.4.1 更新源和软件 2.4.2 关屏时间设置 ...3.1 人脸检测 3.1.1 安装pip 3.1.2... -
如何用 200 行 JavaScript 代码实现人脸检测?
2019-06-19 18:20:31在超市、地铁、车站等很多场景中,人脸识别已经被广泛应用,但是这个功能究竟是怎么实现的? 在本文中,将以pico.js 库为例,分享实现轻量级人脸...pico.js 是一个只有 200 行纯 JavaScript 代码的人脸检测库,具备... -
java 人脸检测 人脸抓拍
2019-04-24 11:07:27最近对人脸识别很感兴趣,就自己钻研学习了一下,历时一个月,终于实现了用摄像头自动人脸检测和抓拍,后期准备继续研究人脸比对。用java+opencv实现的,用的是opencv自带的人脸检测器。 主要步骤: 1、打开... -
人脸算法系列:MTCNN人脸检测详解
2020-03-21 09:25:34人脸检测是一种在多种应用中使用的计算机技术,可以识别数字图像中的人脸。人脸检测还指人类在视觉场景中定位人脸的过程。 人脸检测可以视为目标检测的一种特殊情况。在目标检测中,任务是查找图像中给定类的所有... -
大数据:深度学习项目实战-人脸检测视频教程
2017-03-27 22:01:54进军深度学习佳项目实战:人脸检测项目视频培训课程,从数据的收集以及预处理开始,一步步带着大家完成整个人脸检测的项目,其中涉及了如何使用深度学习框架Caffe完成整个项目的架构,对于每一个核心步骤详细演示... -
人脸系列:人脸检测、人脸关键点定位、人脸优选、人脸对齐、人脸特征提取、人脸跟踪、人脸活体检测
2019-06-21 15:43:57过程:本系列包括从人脸检测、人脸关键点检测、人脸优选、人脸对齐、再到人脸特征提取的一系系列过程,每个模块都有尝试一些网络结构和方法,因为自己主要部署在嵌入式平台、移动端等设备,所以都是采用轻量级的网络... -
OpenCV人脸检测 人脸打码
2017-01-08 21:39:39利用opencv提供的级联分类器,实现人脸检测,并对人脸部位做打码处理