前言
上篇文章我们讲到了OpenCV的安装和简单使用,OpenCV简介及使用(一)。
这篇文章我们来看下如何使用OpenCV进行图像的识别与训练。
正文
由于OpenCV自带人脸识别及检测功能,我们来看下如何使用OpenCV来分辨人脸。
如果要进行人脸识别及训练,需要用到人脸灰度图,且有一定的数量,图片宽高需要保持一致。
上篇文章已经说到如何寻找并裁剪人脸,然后我们将它置灰即可,需要调用org.bytedeco.opencv.global.opencv_imgproc.cvtColor
方法,如代码所示cvtColor(image,image,COLOR_BGR2GRAY)
。
其中第一个image是原Mat图,第二个image是生成的Mat图,两个设置成一样则生成的灰度图会覆盖原图,COLOR_BGR2GRAY
表示生成的图片颜色。
则生成灰度图代码大致如下:
1 | public static Mat detectFace(String sourceImage, String targetImage,int width,int height){ |
上述方法里主要使用了OpenCV中org.bytedeco.opencv.global.opencv_imgcodecs
和org.bytedeco.opencv.global.opencv_imgproc
两个包中的方法。
然后我们开始进行人脸识别训练。
人脸识别器(FaceRecognizer)这个类目前包含三种人脸识别方法:基于PCA变换的人脸识别(EigenFaceRecognizer)、基于Fisher变换的人脸识别(FisherFaceRecognizer)、基于局部二值模式的人脸识别(LBPHFaceRecognizer)。
这儿我们以基于PCA变换的人脸识别(EigenFaceRecognizer)来进行举例。
我们想识别两张不同的人脸,需要首先准备若干样本,这儿我准备了胡歌和刘亦菲的照片各10张来作为训练样本(想要更好的训练效果,训练图片至少要在数百张左右),如下图:
其中胡歌的图片以0-开头,刘亦菲的图片以1-开头,对测试图片进行测试时,识别器的label(识别标签)返回0认为属于胡歌的照片,1认为属于刘亦菲的图片,-1认为不属于他们的照片。
训练时需要使用灰度图,我们使用上面的方法处理下生成宽高相等的灰度图。
其相关代码如下:
1 | public static void faceRecognize(String baseImagePath,String testImage){ |
其关键部分代码为faceRecognizer.train(matVector,labels)
,matVector接受生成的灰度图,labels为图片所属的标签,我们可以通过faceRecognizer.save(baseImagePath+”/face.xml”)
保存训练后的xml。
在训练之前,通过灰度图处理(detectFace方法),如果训练图片选择落地的话,会在文件夹下生成train文件夹,里面就是存放宽高相等的待训练的样本。如下图:
我们取一张测试照片test.jpg,来进行测试,如下:
其测试的主要代码就是上面代码的这部分:
1 | //处理待识别的图片 |
识别时也是需要使用灰度图进行识别,调用faceRecognizer.predict(tempMat, label, confidence)
来对测试图片进行测试,同时也会返回置信度。
我们构建Main运行代码:
1 | public static void main(String[] args) throws Exception { |
运行后可以看到输出结果:
可以看到符合我们的预期。
这儿只使用了少量训练样本来展示图像训练的方法,其实在进行识别训练时,样本越大精确度越高。
我们之前用到的haarcascade_frontalface_alt.xml
,就是使用大量人脸样本进行训练生成的。
总结
今天我们使用了OpenCV自带的人脸识别器(FaceRecognizer)来进行了人脸的识别与训练,后续我们会在了解下OpenCV在图像应用方面的一些其它功能。