序
今天的进度完成了,这会就是一些收尾工作。打开CSDN看看最新的技术新闻,看到了OpenCV-Python实战人脸识别。一直也想涉足下,了解了下OpenCV。打开官网看了下,貌似free的,可以研究下。但是好像工程有点大,这一时半会出不了效果,侧面了解了有做封装的公司了。下面就介绍下,在测试项目上集成玩下,实际上人脸识别这块公司业务中也是需求偏高的智能设备之一。
官网:https://ai.arcsoft.com.cn/
这个个人开发就可以免费提供一些的人脸相关能力的,基本上小业务量、轻量还是可以使用的。准备姿势:
这个因为不是开源的,maven上还没有jar。所以需要自行设置,设置如下:
文件放置目录:
如果同时要支持linux,也是可以下载Linux64放到这里的,后面可以通过jvm读取服务器系统信息,走不同的驱动加载引擎。
pom.xml引入依赖
<!-- 虹软人脸识别 -->
<dependency>
<groupId>com.arcsoft.face</groupId>
<artifactId>arcsoft-sdk-face</artifactId>
<version>3.0.0.0</version>
<scope>system</scope>
<systemPath>${
project.basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
</dependency>
虹软封装的引擎思路很清晰:
1、读取授权信息
2、读取驱动文件
3、加载激活引擎
4、对引擎设置功能配置
5、使用功能
后面大家看测试代码好好捋捋是不是这么个思路,我反正很细化这种思路,清晰明了,就好像要干啥先穿啥衣服,然后再干。测试代码是demo稍微改下,说实话demo演示了免费的使用基本姿势,高级姿势有pdf帮助文档和官网,还是很香的。
package face.arcsoft;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSON;
import com.arcsoft.face.*;
import com.arcsoft.face.enums.*;
import com.arcsoft.face.toolkit.ImageInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.arcsoft.face.toolkit.ImageInfoEx;
import static com.arcsoft.face.toolkit.ImageFactory.getGrayData;
import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
public class FaceEngineTest {
public static void main(String[] args) {
System.out.println("------人脸比对测试------");
//使用HuTool提供的工具类读取系统信息也很香啊
OsInfo osInfo = SystemUtil.getOsInfo();
System.out.println("--系统信息:" + JSON.toJSONString(osInfo));
System.out.println("--系统操作系统:" + osInfo.getName() + "版本:" + osInfo.getVersion());
String facePathA = "C:\\Users\\zhengwen\\Desktop\\test\\face\\old.jpg";
System.out.println("A测试图片路径:" + facePathA);
String facePathB = "C:\\Users\\zhengwen\\Desktop\\test\\face\\20211112.jpg";
//String facePathB = "C:\\Users\\zhengwen\\Desktop\\test\\face\\ldh.jpg";
System.out.println("B测试图片路径:" + facePathB);
String irPath = "C:\\Users\\zhengwen\\Desktop\\test\\face\\gg.jpg";
System.out.println("IR测试图片路径:" + irPath);
//从官网获取(这里开始可以根据操作系统用不同的id、key、驱动加载引擎)
String appId = "6mBZvzxhvmRxhHPcFkphS2BsLrsm8Xcm9M6Sc2wLXKiM";
String sdkKey = "FVQyCohAYFeN6rkA9HtVr27My2qWwrVe5WpMu1MEkTsW";
String path = System.getProperty("user.dir");
FaceEngine faceEngine = new FaceEngine(path + File.separator + "libs" + File.separator + "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 = getRGBData(new File(facePathA));
List<FaceInfo> faceInfoList = new ArrayList<>();
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("A人脸检测失败");
}
//特征提取
FaceFeature faceFeature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
//System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("A人脸特征提取失败");
}
//人脸检测2
ImageInfo imageInfo2 = getRGBData(new File(facePathB));
List<FaceInfo> faceInfoList2 = new ArrayList<>();
errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo.getImageFormat(), faceInfoList2);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("B人脸检测失败");
}
//特征提取2
FaceFeature faceFeature2 = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo.getImageFormat(), faceInfoList2.get(0), faceFeature2);
//System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("B人脸特征提取失败");
}
//特征比对
FaceFeature targetFaceFeature = new FaceFeature();
targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
FaceFeature sourceFaceFeature = new FaceFeature();
sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
FaceSimilar faceSimilar = new FaceSimilar();
errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("AB人脸特征比对失败");
}
System.out.println("AB相似度:" + faceSimilar.getScore());
//设置活体测试
errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("设置活体测试失败");
}
//A人脸属性检测
FunctionConfiguration configuration = new FunctionConfiguration();
configuration.setSupportAge(true);
configuration.setSupportFace3dAngle(true);
configuration.setSupportGender(true);
configuration.setSupportLiveness(true);
errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("A人脸属性检测失败");
}
//性别检测
List<GenderInfo> genderInfoList = new ArrayList<>();
errorCode = faceEngine.getGender(genderInfoList);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("性别检测失败");
}
System.out.println("(0男1女)性别:" + genderInfoList.get(0).getGender());
//A年龄检测
List<AgeInfo> ageInfoList = new ArrayList<>();
errorCode = faceEngine.getAge(ageInfoList);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("年龄检测失败");
}
System.out.println("A年龄:" + ageInfoList.get(0).getAge());
//B人脸属性检测
FunctionConfiguration configurationB = new FunctionConfiguration();
configurationB.setSupportAge(true);
configurationB.setSupportFace3dAngle(true);
configurationB.setSupportGender(true);
configurationB.setSupportLiveness(true);
errorCode = faceEngine.process(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2, configurationB);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("A人脸属性检测失败");
}
//A年龄检测
List<AgeInfo> ageInfoList2 = new ArrayList<>();
errorCode = faceEngine.getAge(ageInfoList2);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("年龄检测失败");
}
System.out.println("B年龄:" + ageInfoList2.get(0).getAge());
//3D信息检测
List<Face3DAngle> face3DAngleList = new ArrayList<>();
errorCode = faceEngine.getFace3DAngle(face3DAngleList);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("3D信息检测失败");
}
System.out.println("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());
//活体检测
List<LivenessInfo> livenessInfoList = new ArrayList<>();
errorCode = faceEngine.getLiveness(livenessInfoList);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("活体检测失败");
}
System.out.println("活体:" + livenessInfoList.get(0).getLiveness());
//IR属性处理
ImageInfo imageInfoGray = getGrayData(new File(irPath));
List<FaceInfo> faceInfoListGray = new ArrayList<>();
errorCode = faceEngine.detectFaces(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("IR属性处理失败");
}
FunctionConfiguration configuration2 = new FunctionConfiguration();
configuration2.setSupportIRLiveness(true);
errorCode = faceEngine.processIr(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray, configuration2);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("IR属性处理设置失败");
}
//IR活体检测
List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
errorCode = faceEngine.getLivenessIr(irLivenessInfo);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("IR活体检测失败");
}
System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());
ImageInfoEx 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});
List<FaceInfo> faceInfoList1 = new ArrayList<>();
errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("图片扩展信息读取失败");
}
FunctionConfiguration fun = new FunctionConfiguration();
fun.setSupportAge(true);
errorCode = faceEngine.process(imageInfoEx, faceInfoList1, functionConfiguration);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("图片IR属性处理合成失败");
}
List<AgeInfo> ageInfoList1 = new ArrayList<>();
int age = faceEngine.getAge(ageInfoList1);
//System.out.println("年龄:" + ageInfoList1.get(0).getAge());
System.out.println("年龄:" + age);
FaceFeature feature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), feature);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("图片IR提取人脸特征失败");
}
//引擎卸载
errorCode = faceEngine.unInit();
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("引擎卸载失败");
}
}
}
这里我找了我以前、现在、偶像的一些照片放在一个目录下,方便测试。
岁月是把杀猪刀啊,你看看这些年再我脸上雕刻的…
如果可以回去,你想回到什么时候呢?
怀恋啊我们的青春啊…
2021.1.3\lib\idea_rt.jar" face.arcsoft.FaceEngineTest
Connected to the target VM, address: '127.0.0.1:49905', transport: 'socket'
------人脸比对测试------
--系统信息:{
"aix":false,"arch":"amd64","fileSeparator":"\\","hpUx":false,"irix":false,"lineSeparator":"\r\n","linux":false,"mac":false,"macOsX":false,"name":"Windows 10","os2":false,"pathSeparator":";","solaris":false,"sunOS":false,"version":"10.0","windows":true,"windows10":true,"windows2000":false,"windows7":false,"windows8":false,"windows8_1":false,"windows95":false,"windows98":false,"windowsME":false,"windowsNT":false,"windowsXP":false}
--系统操作系统:Windows 10版本:10.0
A测试图片路径:C:\Users\zhengwen\Desktop\test\face\old.jpg
B测试图片路径:C:\Users\zhengwen\Desktop\test\face\20211112.jpg
IR测试图片路径:C:\Users\zhengwen\Desktop\test\face\gg.jpg
AB相似度:0.86731297
(0男1女)性别:0
A年龄:24
B年龄:36
3D角度:1.6797562,-0.6365518,-0.97046876
活体:1
IR活体:0
图片IR属性处理合成失败
年龄:0
Disconnected from the target VM, address: '127.0.0.1:49905', transport: 'socket'
Process finished with exit code 0
老实说,我看到这个根据照片计算出的年龄还是很伤心的,因为本尊现在根本还没到36,还差好多年呢。哎
打印出来的都有中文意思了,我也不解释了,看看相似度,还是很高的,我测了跟偶像华仔的相似度不到10%。
首先要说这个还是很不错的,底层也看了下jar里面,也是基于openCV做的。算法、训练估计是自己公司做的,看来还是很有必要好好看看OpenCV,后面有空再基于这个做下分享。
然后,简单总结下:
1、免费的也不错(基本功能都有,连1:N搜索视频流都可以,个人认证就100台终端可以激活使用)
2、需要联网(私有化部署没有网络的凉凉)
3、官方介绍的响应速度还可以
4、官方给的PDF写的很清楚规范(赞)
5、不需要再购买设备、部署
最后,我们目前有场景是用的koala做人脸比对。用上这个我不禁想到我们的通行闸机、摄像头人脸识别、摄像头人脸追踪等等似乎都可以用这个解决。其实我们也有做这块的规划的,就是人才少,留不住。
更多有趣的功能大家可以注册个人版使用,希望可以帮到大家,启迪到大家,加油技术人。