Java - 使用虹软人脸识别sdk记录
项目中需要使用人脸识别功能(图片vs图片),用于校验是否是用户本人操作。
思路:前端传入截取的照片(特征值),与数据库保存的用户照片(特征值)进行比对。
此处选用的是:虹软人脸识别Arcface
独立离线版SDK,拥有人脸检测、人脸跟踪、人脸比对/搜索、年龄检测、性别识别、IR/RGB活体检测等功能;
首次调用需联网激活,后续离线使用;
一年有效期,到期更新引擎继续免费使用。更新引擎只需要在开放平台重新下载引擎,将原应用工程中的引擎相关包文件、代码中所使用的APP_ID、SDK_KEY均替换成最新的即可
一、代码示例
1.提取照片特征值
将照片以base64码的形式上传,使用虹软sdk将其特征值提取并保存。
/**
* 提取人脸特征
* @param imageInfo
* @return
*/
public byte[] extractFaceFeature(ImageInfo imageInfo) throws InterruptedException {
FaceEngine faceEngine = null;
try {
// 获取引擎对象
faceEngine = faceEngineObjectPool.borrowObject();
// 人脸检测获得人脸列表 faceInfoList
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth()
, imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
if (!CollectionUtils.isEmpty(faceInfoList)) {
logger.info("faceId = {}", faceInfoList.get(0).getFaceId());
/**
* 提取人脸特征
* faceInfoList.get(0) 人脸信息(人脸框、人脸角度)
*/
FaceFeature faceFeature = new FaceFeature();
faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth()
, imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
return faceFeature.getFeatureData();
}
} catch (Exception e) {
logger.error("", e);
} finally {
if (faceEngine != null) {
//释放引擎对象
faceEngineObjectPool.returnObject(faceEngine);
}
}
return new byte[0];
}
// 校验照片是否能获取特征值
byte[] decode = cn.hutool.core.codec.Base64.decode(Base64Utils.base64Process(picture.getPictureCode()));
ImageInfo imageInfo = ImageFactory.getRGBData(decode);
//人脸特征获取
byte[] targetbytes = faceRecognitionService.extractFaceFeature(imageInfo);
if (targetbytes == null || targetbytes.length < 1) {
log.error("照片人脸读取失败");
}
2.比较特征值
// 获得对比相似值
byte[] targetbytes; // 目标特征值
byte[] sourcebytes; // 源特征值
if (targetbytes.length > 0 && sourcebytes.length > 0) {
Integer similarValue = faceRecognitionService.compareFaceFeature2(targetbytes, sourcebytes);
log.info("相似值 >>>>>>> {}%", staffId, similarValue);
}
3.工具类
/**
* base64处理工具类
*/
@Slf4j
public class Base64Utils {
// 处理图片base64码
public static String base64Process(String base64Str) {
if (!StringUtils.isEmpty(base64Str)) {
String photoBase64 = base64Str.substring(0, 30).toLowerCase();
int indexOf = photoBase64.indexOf("base64,");
if (indexOf > 0) {
base64Str = base64Str.substring(indexOf + 7);
}
return base64Str;
} else {
return "";
}
}
/**
* 计算图片的大小,返回单位为KB
* @param imageBase64Str 图片base64数据
* @return 图片大小
*/
public static Integer imageSize(String imageBase64Str){
//1.找到等号,把等号也去掉(=用来填充base64字符串长度用)
Integer equalIndex= imageBase64Str.indexOf("=");
if(imageBase64Str.indexOf("=")>0) {
imageBase64Str=imageBase64Str.substring(0, equalIndex);
}
//2.原来的字符流大小,单位为字节
Integer strLength=imageBase64Str.length();
// log.info("imageBase64Str-Length = "+strLength);
//3.计算后得到的文件流大小,单位为字节
Integer size=strLength-(strLength/8)*2;
return bytesToKB(size);
}
/**
* byte(字节)根据长度转成kb(千字节)
* @param bytes
* @return
*/
public static Integer bytesToKB(long bytes) {
BigDecimal filesize = new BigDecimal(bytes);
BigDecimal megabyte = new BigDecimal(1024 * 1024);
BigDecimal kilobyte = new BigDecimal(1024);
float returnValue = filesize.divide(kilobyte, 1, BigDecimal.ROUND_DOWN).floatValue();
return (int)returnValue ;
}
/**
* 根据图片的base64数据缩放图片
* @param base64ImagStr 原图的base64字符换
* @param imageType 图片类型
* @return
*/
public static String scaleImage(String base64ImagStr,String imageType){
BufferedImage bufferedImage = ImgUtil.toImage(base64ImagStr);
// 这块也可以直接通过传入一个image对象,
Image scaleImage = ImgUtil.scale(bufferedImage, 0.3f);
String resultBase64Str = ImgUtil.toBase64(scaleImage, imageType);
Integer imageSizeBase64 = imageSize(resultBase64Str);
if(imageSizeBase64 > 40){
log.info("当前base64图片大小为:{}kb,进行压缩 >>>>>>>>>>", imageSizeBase64);
resultBase64Str = scaleImage(resultBase64Str, imageType);
}
return resultBase64Str;
}
public static void main(String[] args){
}
}
二、参考文档
😺该文章为博主几年前写的,代码情况已经记不太清了,可能有遗漏,发布仅在此做个记录。
751c080b-1dc8-42c9-a2fd-288185d53cb6

浙公网安备 33010602011771号