知识引入
本次我将给大家带分享如何对模型进行测试,也就是如何使用我们已经训练好的模型来测试得到我们想要的结果。本次的分享包括准备数据inference过程和对结果分析。
何为 inference ?
所谓 inference 就是将已经训练好的模型,用于测试得到我们想要的这个任务的结果,也就是一个图像分割的结果。在这个过程中,我们将给大家讲述如何准备我们的测试 test.prototxt 文件,以及如何利用 caffe 的接口来完成我们整个的 inference 这样一个过程。
关键点检测
关键点检测,也就是利用opencv 加dlib 这样的一个开源框架来获得我们嘴唇这一块区域,将这块区域切出来之后,进行测试。总的来说分为两步 : 第一步,我们要利用oencv的cascade这样的一个级联分类器的模型来做人脸检测。利用cascade模型的特点,它的优点是它的速度非常快,当然它的缺点是它的 人脸检测 的召回率会稍微低一些。如果后面对我们的场景人脸检测有更高的需求,我们可以使用更加鲁棒的人脸检测。但现在对于这个自拍这样一个场景的话,我们的cascade模型一般都能够正常地检测到我们的人脸。 dlib 是一个开源的机器学习的一个框架。我们使用dlib的一个关键点检测模型,配合我们opencv这样一个人脸检测的模型,来完成最终这样的一个任务。下面是我们的具体的代码 :
从代码上可以看出,我们需要准备两个模型文件,一个基于opencv harri 的级联模型分类器, 是xml格式的一个分类器,另一个是dlib,它的模型文件,也就是.dat这样的一个关键点的一个模型,它是一个68个关键点的模型。 当配置好这些路径之后,我们分别对cascadeclassifier以及shape_predictor进行初始化,得到了cascade和predictor这样的两个变量。得到这两个变量之后,我们再使用get_landmarks这样的一个函数。如下图所示:
之后我们输入一张图像,首先我们利用ca
scade
分类器
,在多尺度下检测出我们的人脸区域,得到rec
ts
这样的一个矩形区域,然后利用dlib的接口,以及
predictor
变量,获取到我们最终的一个包含68个关键点的结果。相关的代码就在我们
前
面
的章节
,大家可以去自行地查看使用。
ROI 获取检测
前面我们已经利用opencv的 人脸 检测和 dlib 的关键 点 检测,得到了我们68个关节点的位置。 下 面这张图就展示了68个关键点:
我们将它关键点的位置画到了我们的图像上。接下来在这68个关键点的基础之上,我们要正式获得我们的嘴唇的区域。 关键代码如下:
首先,我们可以获取嘴唇区域的关键点的序号,它是从48到67这样的一个序号,包含了20个关键点。得到这些关键点之后,我们要切出一个矩形区域。所以首先我们要获得X和Y的范围,也就是X的最大值,X的最小值,Y的最大值和Y的最小值 , 我们利用上面的代码获得它的一个矩形区域,最后因为我们直接剪裁这个嘴唇区域的话,很有可能会导致嘴唇的一部分被切除掉,所以我们需要适当的扩大我们的矩形区域。 关键代码如下:
在这里我们利用了一些算法,扩大了1.5倍。当然在这个过程中算法代码上有很多的细节,包括一些边界的补齐之类的,大家可以回头仔细的去阅读我提供的python脚本。以下就是我们 检测 出来的矩形,区域的大小, 如下图所示:
前面我们使用的是open CV的这样一个框架,来进行人类的检测和关键点的检测。他的鲁棒性会稍微差一些,在复杂的光照条件下,会有时候召回不了人脸图像。所以这里我们给大家提供了另外的一个非常鲁棒的开源框架,这是来自于CMU的这样一个openpose框架,它可以检测人脸的关键点和人体的关节点,强烈建议大家去github 上面使用 它的模型。
链接地址 :
准备测试文件
得到了我们的嘴唇的这块区域之后,我们就要开始正式的测试 。 在测试之前,我们先要准备好我们的测试文件,注意测试文件跟我们的训练文件是有差异的,它包含在以下几个方面。首先,我们的输入层有差异,左侧是我们的训练图的一个输入层 ,如下图所示:
我们前面已经给大家讲述过,我们利用这样的一个输入层获得了d ata config ,也就是获得了数据跟它的标签。同时我们要给这个 输入层 在训练的时候配置一些参数,包括他的batch size 的大小,包括它的一些数据增强操作的参数,比如说crop_size,mirror这样的一些东西。 这些东西在我们在做测试的时候,是不需要的。这就是我们做测试的时候,我们的输入的格式, 如下图所示:
从中可以看出它的输入 格式是input ,它的 type 不再是 data ,而是input,然后它的输入的参数是intpu t_param ,它其中只有一个变量,也就是 shape , 也就是说我们利用这样的一个输入input格式,我们规定了一个指定大小的blo c k。总结起来,就是当我们在做测试的时候,我们不再需要输入label,也不再需要配置一大堆数据 增强 的操作,我们只需要提供一个格式化的数据输入尺寸就可以了。
输出层也有所差异。下面是我们的一个训练网络的输出层, 如下图所示:
我们可以看到,当我们在做训练的时候,我们需要一个 loss 来指定我们的训练的迭代过程,我们需要ACC,也就是精度,来查看我们的训练的结果的好坏。当在做测试的时候,也不需要这两个网络 层 ,取而代之的直接是softmax这样的一个层,如下图所示:
softmax,就是将我们网络的输出映射到(0,1)这样的一个范围。所以总结起来就是我们去掉了 loss 层,去掉了 acc 层 ,使用 soft max 层 得到了一个最终的输出,也就是分类的结果,从而我们得到了每一个像素的分类的结果。
怎样使用配置文件?
下面我们看看怎样使用配置文件。我们采用了python的接口,因为 python 的接口 进行预测相对来说比较简单。我们下面看看我们的一些具体代码的分析。它具体来说包含四个方面的内容。首先,我们要初始化我们的网络结构,如下图所示:
就是上面的第二行代码,要输入两个文件,一个就是我们的protel
.
txt的网络配置文件,一个是
caffemodel
,也就是我们训练好的存储的模型的参数。然后我们指定caffe
的
test
.prototxt
,现在我们是测试的过程。初始化这个网络之后,我们需要定义
transformer
这样的一个变量,
它的作用就是将我们的数据真正地塞入caffe的
显存
之中。当然是否他还有要做一些预处理的操作,我们可以看看上面的代码。我们看看他做了什么,首先有一个set_mean,也就是说设置了一下我们的均值。因为我们在训练的时候减去的均值,然后还有一个transpose,它是讲我们的图像的格式转化为我们caffe输入的格式。因为我们图像使用numpy读进来的图像,是宽乘以高乘以
channel
这样的一个通道,这样的一个存储格式,而我们
caffe
,前面我们已经说过了,它是
batch
size
乘以channel乘以高乘以宽
一个格式,也就是说他的channel
是跟
caffe的输入格式是相反的。
看下transformer,
这几处没有做更多的数据增强操作,在这里我们测试的时候是不需要做数据增强操作的。然后我们利用
transformer
这样的一个接口,将我们的数据塞入到我们的网络之中。塞到网络之后,我们就可以利用for
ward
函数得到我们的结果,也就是上面的out。利用
从
out取到我们最终需要的一个输出res。res就是
一个block
,我们去掉多余的维度,然后再利用transpose函数,又得回我们的一个正常的图片。我们
使用argmax
得到最终结果
,最后把它转换成
uint
方便可视化,也就是格式化我们的结果。下面有这一套代码,我会在我的github课程中给大家提供,大家可以去关注下载。
链接地址 :
下面给大家提供一个我们的一个测试结果 ,如下图所示:
在这里我们将上嘴唇和下嘴唇都分割了出来,用不同的颜色进行表示,可以看出来结果还是不错的。
测试结果展示
最后我们给大家集中展示一下我们的结果,结果包含两个部分。首先是图片,然后是视频。我们先看一下图片的结果,如下图所示:
这是一张在训练图片中没有见过的图像,我们可以看到上 嘴唇 跟下嘴唇都正确的分割出来,尤其是对于上嘴唇,嘴唇非常的薄,但是我们仍然可以正常地分割出它的结构,这证明了我们的模型是非常鲁棒的。 为了进一步验证这个结论,我们再看看我们的视频的分割结果。
此处由于编辑器限制,请根据链接移步到公众号文章中观看,谢谢
从我们这个视频的展示结果可以看出来,对于比较薄的嘴唇,对于不同的光照条件下,对于不同的姿态,我们都能够非常好的非常平滑的得到一个视频的分割结果。因为我们在这个分割结果过程中,我们是没有使用额外的一些跟踪的策略的,这也证明了我们的模型的鲁棒性。 好了,我们的模型测试结果的分享到此 。
免费领取技术大咖分享课,加蜂口V信: fengkou-IT
感谢您的阅读,更多精彩请持续关注蜂口微信小程序!
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31553577/viewspace-2215066/,如需转载,请注明出处,否则将追究法律责任。