opencv+ArcFace人脸识别
前几天逛知乎看到有免费的工具来做人脸识别,觉得很有意思;心血来潮,想自己也搞一个人脸识别;不得不说虹软ArcFace真的是太好用了;对于我这种完全不懂人脸识别算法的人,也可以构建出人脸识别的应用;只需要调用封装好的API就行了。
环境准备:
- 1.到虹软ArcFace官网下载虹软ArcFacezip格式的压缩文件,解压后将libs文件夹copy到自己的工程下,注意libs文件下有一个:arcsoft-sdk-face-3.0.0.0.jar,添加工程对jar的路径依赖;
2.maven下载opencv;
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv-platform</artifactId>
<version>3.4.1-1.4.1</version>
</dependency>
<!-- jna:调用windows系统的API~-->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.8.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.8.0</version>
</dependency>
项目的结构:
arcFace
从官方下载的zip文件节后,samplecode文件夹下FaceEngineTest.java是官方给出的示例代码;下面是人脸特征对比部分的代码:
//从官网获取
String appId = "";
String sdkKey = "";
//加载dll文件,就是最开始准备的libs下面的dll文件路径;
FaceEngine faceEngine = new FaceEngine("E:/Project/2021/face-learning/libs/WIN64");
//激活引擎
int errorCode = faceEngine.activeOnline(appId, sdkKey);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
System.out.println("引擎激活失败");
}
ActiveFileInfo activeFileInfo=new ActiveFileInfo();
errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
System.out.println("获取激活文件信息失败");
}
//引擎配置
EngineConfiguration engineConfiguration = new EngineConfiguration();
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
engineConfiguration.setDetectFaceMaxNum(10);
engineConfiguration.setDetectFaceScaleVal(16);
//功能配置
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
functionConfiguration.setSupportAge(true);
functionConfiguration.setSupportFace3dAngle(true);
functionConfiguration.setSupportFaceDetect(true);
functionConfiguration.setSupportFaceRecognition(true);
functionConfiguration.setSupportGender(true);
functionConfiguration.setSupportLiveness(true);
functionConfiguration.setSupportIRLiveness(true);
engineConfiguration.setFunctionConfiguration(functionConfiguration);
//初始化引擎
errorCode = faceEngine.init(engineConfiguration);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("初始化引擎失败");
}
//人脸检测
ImageInfo imageInfo = ImageFactory.getRGBData(new File("C:\\Users\\Pictures\\b0488b9ed27271eab692bd0097fe67ce.jpeg"));
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
System.out.println(faceInfoList);
//特征提取
FaceFeature faceFeature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
System.out.println("特征值1大小:" + faceFeature.getFeatureData().length);
//人脸检测2
ImageInfo imageInfo2 = ImageFactory.getRGBData(new File("C:\\Users\\Pictures\\WIN_20210628_13_25_19_Pro.jpg"));
List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo.getImageFormat(), faceInfoList2);
System.out.println(faceInfoList);
//特征提取2
FaceFeature faceFeature2 = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo.getImageFormat(), faceInfoList2.get(0), faceFeature2);
System.out.println("特征值2大小:" + faceFeature2.getFeatureData().length);
//特征比对
FaceSimilar faceSimilar = new FaceSimilar();
errorCode = faceEngine.compareFaceFeature(faceFeature, faceFeature2, faceSimilar);
System.out.println("相似度:" + faceSimilar.getScore());
上面这段代码流程:
- 1.FaceEngine引擎 对象创建(加载dll文件)
- 2.激活引擎
- 3.引擎配置,功能配置
- 4.初始化引擎
- 5.分别做2张图片的:人脸检测:imageInfo(人脸信息),特征提取:faceFeatur(人脸特征)
- 6.对比2张图片的人脸特征,得出相似度FaceSimilar
opencv
用opencv调用摄像头,获取实时的人脸信息;
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
Java2DFrameConverter converter = new Java2DFrameConverter();
grabber.start(); //开始获取摄像头数据
Frame frame = grabber.grab();//获取此刻的图像数据
BufferedImage bufferedImage = converter.convert(frame);//opencv:用Java2DFrameConverter将Frame转化成BufferedImage
ImageInfo imageInfo =ImageFactory.bufferedImage2ImageInfo(bufferedImage);//ArcFace:获取到人脸信息;
opencv_ArcFace
将上面的代码整合一下
public class TestArcFace{
static String appId = "";
static String sdkKey = "";
static String enginePath ="E:/Project/2021/face-learning/libs/WIN64";
static OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
static Java2DFrameConverter converter = new Java2DFrameConverter();
public static void main(String[] args) throws Throwable{
FaceEngine faceEngine = getFaceEngine();//获取FaceEngine
grabber.start();//开启摄像头
FaceFeature bossFace = getFaceFeature(faceEngine,getImageInfoFromPicture("")).get(0);//从boss的单人照中获取boss脸部特征
boolean bossComing=false;
while(!bossComing){
//检测boss是否出现摄像头中;
List<FaceFeature> captureFaces = getFaceFeature(faceEngine,getImageInfoFromCamera());//捕获出现在镜头中的人脸特征
for (FaceFeature captureFace : captureFaces) {
//遍历list检测捕获到的人脸特征
FaceSimilar faceSimilar = getFaceSimilar(faceEngine,captureFace,bossFace);
if(samePeople(faceSimilar,0.8f)){
//boss出现
bossComing=true;
break;
}
}
Thread.sleep(100);//每隔100ms检测一次,检测boss是否出现在镜头中。。
}
User32.INSTANCE.LockWorkStation();//锁屏
grabber.stop();
faceEngine.unInit();
}
public static FaceEngine getFaceEngine(){
FaceEngine faceEngine = new FaceEngine(enginePath);
int errorCode = faceEngine.activeOnline(appId, sdkKey);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
System.out.println("引擎激活失败");
}
ActiveFileInfo activeFileInfo=new ActiveFileInfo();
errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
System.out.println("获取激活文件信息失败");
}
//引擎配置
EngineConfiguration engineConfiguration = new EngineConfiguration();
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
engineConfiguration.setDetectFaceMaxNum(10);//图片中人脸数
engineConfiguration.setDetectFaceScaleVal(30);//人脸相对于所在图片的长边的占比,建议16
//功能配置
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
functionConfiguration.setSupportAge(true);
functionConfiguration.setSupportFace3dAngle(true);
functionConfiguration.setSupportFaceDetect(true);
functionConfiguration.setSupportFaceRecognition(true);
functionConfiguration.setSupportGender(true);
functionConfiguration.setSupportLiveness(true);
functionConfiguration.setSupportIRLiveness(true);
engineConfiguration.setFunctionConfiguration(functionConfiguration);
//初始化引擎
errorCode = faceEngine.init(engineConfiguration);
if(ErrorInfo.MOK.getValue()!= errorCode){
throw new RuntimeException("初始化引擎失败。。。errorCode:"+errorCode);
}
return faceEngine;
}
/*
获取图片中人脸信息
*/
public static ImageInfo getImageInfoFromPicture(String picturePath){
return ImageFactory.getRGBData(new File(picturePath));
}
/*
从摄像头中获取到人脸信息;
*/
public static ImageInfo getImageInfoFromCamera() throws FrameGrabber.Exception {
Frame frame = grabber.grab();
BufferedImage bufferedImage = converter.convert(frame);
return ImageFactory.bufferedImage2ImageInfo(bufferedImage);
}
/*
获取ImageInfo人脸特征
*/
public static List<FaceFeature> getFaceFeature(FaceEngine faceEngine,ImageInfo imageInfo){
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
List<FaceFeature> faceFeatures = new ArrayList<>();
//提取人脸信息
faceEngine.detectFaces(imageInfo.getImageData(),imageInfo.getWidth(),imageInfo.getHeight(),imageInfo.getImageFormat(),faceInfoList);
if(!faceInfoList.isEmpty()){
//提取人脸特征
for (FaceInfo faceInfo : faceInfoList) {
FaceFeature faceFeature = new FaceFeature();
faceEngine.extractFaceFeature(imageInfo.getImageData(),imageInfo.getWidth(),imageInfo.getHeight(),imageInfo.getImageFormat(),faceInfo,faceFeature);
faceFeatures.add(faceFeature);
}
}else{
System.out.println("faceInfoList is empty");
}
return faceFeatures;
}
/*
对比FaceFeature,获取相似度
*/
public static FaceSimilar getFaceSimilar(FaceEngine faceEngine,FaceFeature captureFaceFeature,FaceFeature target){
FaceSimilar faceSimilar = new FaceSimilar();
faceEngine.compareFaceFeature(captureFaceFeature,target,faceSimilar);
return faceSimilar;
}
/*
判断是否是同一个人,
score:自定义设置 ;
当相似度超过score,判定是同一人;
*/
public static boolean samePeople(FaceSimilar faceSimilar,float score){
return faceSimilar.getScore()>score?true:false;
}
}
还没有评论,来说两句吧...