最近公司有个业务场景是需要用到人脸识别功能的,正好趁此机会写下这篇文章,以巩固自己不精的技能~
话不多说,开干!
1.环境准备:JDK1.8 + SpringBoot + Maven
2.下载虹软SDK
前往虹软开发者中心
新建应用--填写一些基本信息,完成后如下图
点击下载,然后解压文件,你会得到下图
我们主要是需要libs文件夹下的文件
3.引入jar包
虹软并没有为spring boot 提供 maven 的引入方式,所以你需要手动将他的jar包集成到本地
3.1src 同级目录下创建libs 文件夹,将虹软的jar包放到这个文件中
3.2其次在 pom.xml 文件中将这个jar包引入到项目中
<dependency>
<groupId>com.arcsoft.face</groupId>
<artifactId>arcsoft-sdk-face</artifactId>
<version>3.0.0.0</version>
<scope>system</scope>
<systemPath>${basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
</dependency>
3.3允许你的项目在打包发布后仍然可以调用本地路径下的jar包
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 加入下面这一行 -->
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
4.集成到项目
4.1application.yml配置
arcsoft: appid: *********#你注册应用后所对应的APP_ID sdkkey: ********#你注册应用后所对应的SDK_KEY libpath: *******#libs目录下的dll文件夹路径,如D:\\libs\\WIN64 engine-configuration: #引擎配置 detectMode: IMAGE detectFaceOrientPriority: ASF_OP_ALL_OUT detectFaceScale: 32 detectFaceMaxNum: 8 function-configuration: #功能配置 supportAge: true supportFace3dAngle: true supportFaceDetect: true supportFaceRecognition: true supportGender: true supportLiveness: true supportIRLiveness: true
4.2引擎类
@Data
@ConfigurationProperties(prefix = "arcsoft.engine-configuration")
public class EngineConfigurationProperty {
private String detectMode;
private String detectFaceOrientPriority;
private Integer detectFaceScale;
private Integer detectFaceMaxNum;
}
4.3功能类
@Data
@ConfigurationProperties(prefix = "arcsoft.function-configuration")
public class FunConfigurationProperty {
private boolean supportFace3dAngle = true;
private boolean supportFaceDetect = true;
private boolean supportFaceRecognition = true;
private boolean supportGender = true;
private boolean supportAge = true;
private boolean supportLiveness = true;
private boolean supportIRLiveness = true;
}
4.4初始化配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "arcsoft")
@EnableConfigurationProperties({ FunConfigurationProperty.class,EngineConfigurationProperty.class})
public class ArcSoftConfig {
@Autowired
private FunConfigurationProperty funConfigurationProperty;
@Autowired
private EngineConfigurationProperty engineConfigurationProperty;
private String appid;
private String sdkkey;
private String libpath;
@Bean
public FaceEngine faceEngine(){
FaceEngine faceEngine = new FaceEngine(libpath);
int errorCode = faceEngine.activeOnline(appid, sdkkey);
if (errorCode != ErrorInfo.MOK.getValue() &&
errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())
throw new RuntimeException("引擎注册失败");
EngineConfiguration engineConfiguration = getFaceEngineConfiguration();
//初始化引擎
errorCode = faceEngine.init(engineConfiguration);
if (errorCode != ErrorInfo.MOK.getValue())
throw new RuntimeException("初始化引擎失败");
return faceEngine;
}
/**
* 初始化引擎配置
* @return
*/
private EngineConfiguration getFaceEngineConfiguration() {
EngineConfiguration engineConfiguration = new EngineConfiguration();
//配置引擎模式
if ("IMAGE".equals(engineConfigurationProperty.getDetectMode()))
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
else
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_VIDEO);
//配置人脸角度 全角度 ASF_OP_ALL_OUT 不够准确且检测速度慢
switch (engineConfigurationProperty.getDetectFaceOrientPriority()){
case "ASF_OP_0_ONLY":
engineConfiguration
.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);
break;
case "ASF_OP_90_ONLY":
engineConfiguration
.setDetectFaceOrientPriority(DetectOrient.ASF_OP_90_ONLY);
break;
case "ASF_OP_270_ONLY":
engineConfiguration
.setDetectFaceOrientPriority(DetectOrient.ASF_OP_270_ONLY);
break;
case "ASF_OP_180_ONLY":
engineConfiguration
.setDetectFaceOrientPriority(DetectOrient.ASF_OP_180_ONLY);
break;
case "ASF_OP_ALL_OUT":
engineConfiguration
.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
break;
default:
engineConfiguration
.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
}
//设置识别的最小人脸比
engineConfiguration
.setDetectFaceScaleVal(engineConfigurationProperty.getDetectFaceScale());
engineConfiguration
.setDetectFaceMaxNum(engineConfigurationProperty.getDetectFaceMaxNum());
//功能配置
initFuncConfiguration(engineConfiguration);
return engineConfiguration;
}
/**
* 功能配置
* @param engineConfiguration
*/
private void initFuncConfiguration(EngineConfiguration engineConfiguration){
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
//是否支持年龄检测
functionConfiguration.setSupportAge(funConfigurationProperty.isSupportAge());
//是否支持3d 检测
functionConfiguration
.setSupportFace3dAngle(funConfigurationProperty.isSupportFace3dAngle());
//是否支持人脸检测
functionConfiguration
.setSupportFaceDetect(funConfigurationProperty.isSupportFaceDetect());
//是否支持人脸识别
functionConfiguration
.setSupportFaceRecognition(funConfigurationProperty.isSupportFaceRecognition());
//是否支持性别检测
functionConfiguration
.setSupportGender(funConfigurationProperty.isSupportGender());
//是否支持活体检测
functionConfiguration
.setSupportLiveness(funConfigurationProperty.isSupportLiveness());
//是否至此IR活体检测
functionConfiguration
.setSupportIRLiveness(funConfigurationProperty.isSupportIRLiveness());
engineConfiguration.setFunctionConfiguration(functionConfiguration);
}
}
4.5对图片对象封装的工具类
public class ArcSoftUtils {
/**
* 处理 File 的图片流
* @param img
* @return
*/
public static ImageInfoMeta packImageInfoEx(File img){
ImageInfo imageInfo = getRGBData(img);
return packImageInfoMeta(imageInfo);
}
/**
* 处理 byte[] 的图片流
* @param img
* @return
*/
public static ImageInfoMeta packImageInfoMeta(byte[] img){
ImageInfo imageInfo = getRGBData(img);
return packImageInfoMeta(imageInfo);
}
/**
* 处理 InpuStream 的图片流
* @param img
* @return
*/
public static ImageInfoMeta packImageInfoMeta(InputStream img){
ImageInfo imageInfo = getRGBData(img);
return packImageInfoMeta(imageInfo);
}
/**
* 打包生成 ImageInfoMeta
* @param imageInfo
* @return
*/
private static ImageInfoMeta packImageInfoMeta(ImageInfo imageInfo){
ImageInfoMeta imageInfoMeta = new ImageInfoMeta(imageInfo);
return imageInfoMeta;
}
/**
* 对imageInfo 和 imageInfoEx 的打包对象
* @return
*/
@Data
public static class ImageInfoMeta{
private ImageInfo imageInfo;
private ImageInfoEx imageInfoEx;
public ImageInfoMeta(ImageInfo imageInfo) {
this.imageInfo = imageInfo;
imageInfoEx = new ImageInfoEx();
imageInfoEx.setHeight(imageInfo.getHeight());
imageInfoEx.setWidth(imageInfo.getWidth());
imageInfoEx.setImageFormat(imageInfo.getImageFormat());
imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
}
}
}
4.6封装的常用方法工具类
@Component
public class ArcSoftMothodUtils {
@Autowired
private FaceEngine faceEngine;
/**
* 人脸检测
*/
public List<FaceInfo> detectFace(ImageInfoEx imageInfoEx) {
if (imageInfoEx == null)
return null;
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
int i = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList);
checkEngineResult(i, ErrorInfo.MOK.getValue(), "人脸检测失败");
return faceInfoList;
}
/**
* 特征提取
*/
public FaceFeature extractFaceFeature(
List<FaceInfo> faceInfoList, ImageInfoEx imageInfoEx) {
if (faceInfoList == null || imageInfoEx == null)
return null;
FaceFeature faceFeature = new FaceFeature();
int i = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList.get(0), faceFeature);
checkEngineResult(i, ErrorInfo.MOK.getValue(), "人脸特征提取失败");
return faceFeature;
}
/**
* 特征比对
*/
public FaceSimilar compareFaceFeature(
FaceFeature target, FaceFeature source, CompareModel compareModel) {
FaceSimilar faceSimilar = new FaceSimilar();
int i = faceEngine
.compareFaceFeature(target, source, compareModel, faceSimilar);
checkEngineResult(i, ErrorInfo.MOK.getValue(), "人脸特征对比失败");
return faceSimilar;
}
/**
* 错误检测
*/
private void checkEngineResult(int errorCode, int sourceCode, String errMsg) {
if (errorCode != sourceCode)
throw new RuntimeException(errMsg);
}
}
4.7测试
@RestController
@RequestMapping("/arcsoft")
public class FaceController {
@Autowired
private ArcSoftMothodUtils arcSoftMothodUtils;
@GetMapping("/detectFace")
public Result detectFace(String imgPath) {
List<FaceInfo> faceInfo = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath)).getImageInfoEx());
return Result.succ(faceInfo);
}
@GetMapping("/extractFaceFeature")
public Result extractFaceFeature(String imgPath) {
List<FaceInfo> faceInfo = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath)).getImageInfoEx());
FaceFeature faceFeature = arcSoftMothodUtils.extractFaceFeature(faceInfo, ArcfaceUtils.packImageInfoEx(new File(imgPath)).getImageInfoEx());
return Result.succ(faceFeature);
}
@GetMapping("/compareFaceFeature")
public Result compareFaceFeature(String imgPath1,String imgPath2) {
List<FaceInfo> faceInfo1 = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath1)).getImageInfoEx());
FaceFeature faceFeature1 = arcSoftMothodUtils.extractFaceFeature(faceInfo1, ArcfaceUtils.packImageInfoEx(new File(imgPath1)).getImageInfoEx());
List<FaceInfo> faceInfo2 = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath2)).getImageInfoEx());
FaceFeature faceFeature2 = arcSoftMothodUtils.extractFaceFeature(faceInfo2, ArcfaceUtils.packImageInfoEx(new File(imgPath2)).getImageInfoEx());
FaceSimilar faceSimilar = arcSoftMothodUtils.compareFaceFeature(faceFeature1, faceFeature2, CompareModel.LIFE_PHOTO);
return Result.succ(faceSimilar);
}
}
到这里整个流程就结束了,其实虹软的几个方法的使用有两种方式,我使用的是第二种,也就是下图红圈中的
最后,附上文档中心--虹软AI-虹软AI开放平台