智慧校园
This commit is contained in:
parent
cdf5e28051
commit
1c321114b9
|
@ -226,7 +226,15 @@
|
||||||
<version>2.0.0</version>
|
<version>2.0.0</version>
|
||||||
<!--<scope>test</scope>-->
|
<!--<scope>test</scope>-->
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
<dependency>
|
||||||
|
<groupId>com.arcsoft.face</groupId>
|
||||||
|
<artifactId>arcsoft-sdk-face</artifactId>
|
||||||
|
<version>4.1.1.0</version>
|
||||||
|
<!-- <scope>system</scope>-->
|
||||||
|
<!-- <systemPath>${project.basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>-->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>${project.artifactId}</finalName>
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
|
|
@ -4,8 +4,8 @@ package net.shapelight;
|
||||||
|
|
||||||
//import net.shapelight.modules.dev.mqtt.MqttClientUtil;
|
//import net.shapelight.modules.dev.mqtt.MqttClientUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.shapelight.commons.engine.sdk.PalmSDK;
|
/*import net.shapelight.commons.engine.sdk.PalmSDK;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;*/
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
@ -29,8 +29,8 @@ public class AdminApplication {
|
||||||
SpringApplication.run(AdminApplication.class, args);
|
SpringApplication.run(AdminApplication.class, args);
|
||||||
|
|
||||||
//初始化掌静脉sdk
|
//初始化掌静脉sdk
|
||||||
int initCode = PalmSDK.init();
|
//int initCode = PalmSDK.init();
|
||||||
log.debug("掌静脉sdk初始化。。。。。。。。。。:"+initCode);
|
//log.debug("掌静脉sdk初始化。。。。。。。。。。:"+initCode);
|
||||||
// //mqtt服务启动
|
// //mqtt服务启动
|
||||||
// MqttClientUtil.createClient();
|
// MqttClientUtil.createClient();
|
||||||
//
|
//
|
||||||
|
@ -38,8 +38,8 @@ public class AdminApplication {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
int code = PalmSDK.release();
|
//int code = PalmSDK.release();
|
||||||
log.debug("掌静脉sdk释放。。。。。。。。。。:"+code);
|
//log.debug("掌静脉sdk释放。。。。。。。。。。:"+code);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,16 +346,14 @@ public class AppApiController {
|
||||||
tenPerson.setStatus(2);
|
tenPerson.setStatus(2);
|
||||||
tenPerson.setPersonType(Constant.PERSON_TYPE_GUEST);
|
tenPerson.setPersonType(Constant.PERSON_TYPE_GUEST);
|
||||||
tenPerson.setTenantId(user.getTenantId());
|
tenPerson.setTenantId(user.getTenantId());
|
||||||
int res;
|
String res;
|
||||||
try {
|
try {
|
||||||
res = tenPersonService.save(tenPerson);
|
res = tenPersonService.save(tenPerson);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return R.error(e.getMessage());
|
return R.error(e.getMessage());
|
||||||
}
|
}
|
||||||
if (res==2) {
|
if (res!=null) {
|
||||||
return R.error("照片未检测到人脸");
|
return R.error(res);
|
||||||
}else if(res == 10){
|
|
||||||
return R.error("文件不存在");
|
|
||||||
}
|
}
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
@ -566,14 +564,14 @@ public class AppApiController {
|
||||||
tenPerson.setCreateTime(new Date());
|
tenPerson.setCreateTime(new Date());
|
||||||
tenPerson.setRegisterType(Constant.RESGISTER_TYPE_APP);
|
tenPerson.setRegisterType(Constant.RESGISTER_TYPE_APP);
|
||||||
tenPerson.setStatus(Constant.PESON_SUATUS_NOMOR);
|
tenPerson.setStatus(Constant.PESON_SUATUS_NOMOR);
|
||||||
int res = 10;
|
String res;
|
||||||
try {
|
try {
|
||||||
res = tenPersonService.save(tenPerson);
|
res = tenPersonService.save(tenPerson);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return R.error(e.getMessage());
|
return R.error(e.getMessage());
|
||||||
}
|
}
|
||||||
if (res==2) {
|
if (res!=null) {
|
||||||
return R.error("照片未检测到人脸");
|
return R.error(res);
|
||||||
}
|
}
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
@ -662,14 +660,14 @@ public class AppApiController {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int res;
|
String res;
|
||||||
try {
|
try {
|
||||||
res = tenPersonService.save(tenPerson);
|
res = tenPersonService.save(tenPerson);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return R.error(e.getMessage());
|
return R.error(e.getMessage());
|
||||||
}
|
}
|
||||||
if (res==2) {
|
if (res!=null) {
|
||||||
return R.error("照片未检测到人脸");
|
return R.error(res);
|
||||||
}
|
}
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
@ -975,7 +973,12 @@ public class AppApiController {
|
||||||
.eq(TenRelation::getParentId,user.getUserId())
|
.eq(TenRelation::getParentId,user.getUserId())
|
||||||
.eq(TenRelation::getStudentId,entity.getPersonId()));
|
.eq(TenRelation::getStudentId,entity.getPersonId()));
|
||||||
if(tenRelation!=null) {
|
if(tenRelation!=null) {
|
||||||
return R.error("该学生已和您绑定");
|
if(tenRelation.getStatus()==2) {
|
||||||
|
return R.error("您已提交绑定审批,请耐心等待");
|
||||||
|
}
|
||||||
|
if(tenRelation.getStatus()==1) {
|
||||||
|
return R.error("该学生已和您绑定");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TenRelation relation = new TenRelation();
|
TenRelation relation = new TenRelation();
|
||||||
relation.setParentId(user.getUserId());
|
relation.setParentId(user.getUserId());
|
||||||
|
|
|
@ -314,10 +314,10 @@ public class AppInfoApiController {
|
||||||
//业主
|
//业主
|
||||||
else if(scope.getRoleId() == Constant.PERSON_TYPE_PARENT){
|
else if(scope.getRoleId() == Constant.PERSON_TYPE_PARENT){
|
||||||
List<TenRelation> relationList = relationService.list(new LambdaQueryWrapper<TenRelation>()
|
List<TenRelation> relationList = relationService.list(new LambdaQueryWrapper<TenRelation>()
|
||||||
.eq(TenRelation::getParentId,user.getUserId()));
|
.eq(TenRelation::getParentId,user.getUserId()).eq(TenRelation::getStatus,1));
|
||||||
if(!relationList.isEmpty()) {
|
if(!relationList.isEmpty()) {
|
||||||
List<Long> list = relationList.stream().map(TenRelation::getStudentId).collect(Collectors.toList());
|
List<Long> list = relationList.stream().map(TenRelation::getStudentId).collect(Collectors.toList());
|
||||||
params.put("cellId",scope.getCellId());
|
params.put("tenantId",user.getTenantId());
|
||||||
params.put("personIds",list);
|
params.put("personIds",list);
|
||||||
PageUtils page = tenRecordService.getByPersonIds(params);
|
PageUtils page = tenRecordService.getByPersonIds(params);
|
||||||
return R.ok().put("data", page);
|
return R.ok().put("data", page);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.shapelight.modules.app.controller;
|
package net.shapelight.modules.app.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import net.shapelight.common.utils.IpUtils;
|
import net.shapelight.common.utils.IpUtils;
|
||||||
import net.shapelight.common.utils.R;
|
import net.shapelight.common.utils.R;
|
||||||
import net.shapelight.common.utils.ServletUtils;
|
import net.shapelight.common.utils.ServletUtils;
|
||||||
|
@ -15,6 +16,8 @@ import net.shapelight.modules.app.utils.JwtUtils;
|
||||||
//import net.shapelight.modules.sys.service.PushService;
|
//import net.shapelight.modules.sys.service.PushService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import net.shapelight.modules.ten.entity.TenParent;
|
||||||
|
import net.shapelight.modules.ten.service.TenParentService;
|
||||||
import net.shapelight.modules.vo.TokenVo;
|
import net.shapelight.modules.vo.TokenVo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -37,6 +40,8 @@ public class AppLoginController {
|
||||||
private JwtUtils jwtUtils;
|
private JwtUtils jwtUtils;
|
||||||
// @Autowired
|
// @Autowired
|
||||||
// PushService pushService;
|
// PushService pushService;
|
||||||
|
@Autowired
|
||||||
|
TenParentService parentService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录
|
* 登录
|
||||||
|
@ -76,6 +81,8 @@ public class AppLoginController {
|
||||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||||
user.setLoginTime(new Date());
|
user.setLoginTime(new Date());
|
||||||
user.setLoginIp(ip);
|
user.setLoginIp(ip);
|
||||||
|
TenParent parent = parentService.getOne(new LambdaQueryWrapper<TenParent>().eq(TenParent::getUserId,user.getUserId()));
|
||||||
|
user.setParent(parent);
|
||||||
userService.saveOrUpdate(user);
|
userService.saveOrUpdate(user);
|
||||||
return R.ok().put("data", user);
|
return R.ok().put("data", user);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.shapelight.modules.app.entity;
|
package net.shapelight.modules.app.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.shapelight.modules.ten.entity.TenParent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App用户
|
* App用户
|
||||||
|
@ -76,5 +78,8 @@ public class AppUserEntity implements Serializable {
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
private Long sysUserId;
|
private Long sysUserId;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
TenParent parent;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import io.minio.PutObjectOptions;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.shapelight.common.utils.R;
|
import net.shapelight.common.utils.R;
|
||||||
import net.shapelight.common.utils.UUIDUtil;
|
import net.shapelight.common.utils.UUIDUtil;
|
||||||
import net.shapelight.commons.engine.sdk.PicSDK;
|
|
||||||
import net.shapelight.modules.excel.model.PersonModel;
|
import net.shapelight.modules.excel.model.PersonModel;
|
||||||
import net.shapelight.modules.ten.entity.*;
|
import net.shapelight.modules.ten.entity.*;
|
||||||
import net.shapelight.modules.ten.service.TenCellDeptService;
|
import net.shapelight.modules.ten.service.TenCellDeptService;
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
package net.shapelight.modules.face;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.shapelight.common.config.GlobalValue;
|
||||||
|
import net.shapelight.modules.face.entity.UserCompareInfo;
|
||||||
|
import net.shapelight.modules.face.service.FaceEngineService;
|
||||||
|
import net.shapelight.modules.face.util.Base64Util;
|
||||||
|
import net.shapelight.modules.face.util.UserInfo;
|
||||||
|
import net.shapelight.modules.face.util.UserRamGroup;
|
||||||
|
import net.shapelight.modules.sys.controller.AbstractController;
|
||||||
|
import net.shapelight.modules.ten.entity.TenCellEntity;
|
||||||
|
import net.shapelight.modules.ten.entity.TenPersonEntity;
|
||||||
|
import net.shapelight.modules.ten.service.TenCellService;
|
||||||
|
import net.shapelight.modules.ten.service.TenPersonService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Order(1)
|
||||||
|
@Slf4j
|
||||||
|
public class FaceEngineAutoRun extends AbstractController implements ApplicationRunner {
|
||||||
|
@Autowired
|
||||||
|
private FaceEngineService faceEngineService;
|
||||||
|
@Autowired
|
||||||
|
private TenPersonService tenPersonService;
|
||||||
|
@Autowired
|
||||||
|
private TenCellService tenCellService;
|
||||||
|
@Autowired
|
||||||
|
private GlobalValue globalValue;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
// 任务初始化
|
||||||
|
log.debug("服务启动。。。。。初始化人脸库");
|
||||||
|
// Map<String, String> fileMap = Maps.newHashMap();
|
||||||
|
// fileMap.put("zhao1", "赵丽颖");
|
||||||
|
// fileMap.put("yang1", "杨紫");
|
||||||
|
// fileMap.put("baixue", "白雪");
|
||||||
|
// fileMap.put("chenchuang", "陈创");
|
||||||
|
// for (String f : fileMap.keySet()) {
|
||||||
|
// ClassPathResource resource = new ClassPathResource("static/images/" + f + ".jpg");
|
||||||
|
// InputStream inputStream = resource.getInputStream();
|
||||||
|
// ImageInfo rgbData = ImageFactory.getRGBData(inputStream);
|
||||||
|
// List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
|
||||||
|
// if (CollectionUtil.isNotEmpty(faceInfoList)) {
|
||||||
|
// byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfoList.get(0), ExtractType.REGISTER);
|
||||||
|
// UserRamCache.UserInfo userInfo = new UserCompareInfo();
|
||||||
|
// userInfo.setFaceId(f);
|
||||||
|
// userInfo.setName(fileMap.get(f));
|
||||||
|
// userInfo.setFaceFeature(feature);
|
||||||
|
// //这边注册到内存缓存中,也可以根据业务,注册到数据库中
|
||||||
|
// UserRamCache.addUser(userInfo);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int count = tenPersonService.findCount();
|
||||||
|
// int pageSize = 1000;
|
||||||
|
// int page = count/pageSize;
|
||||||
|
// if(count%1000!=0){
|
||||||
|
// page = page+1;
|
||||||
|
// }
|
||||||
|
// int faceCount = 0;
|
||||||
|
// for (int i = 0; i < page; i++) {
|
||||||
|
// int start = i*1000;
|
||||||
|
// List<TenPersonEntity> listPage = tenPersonService.listPage(start,1000);
|
||||||
|
// for(TenPersonEntity personEntity: listPage){
|
||||||
|
// if(personEntity.getFeature()!=null && personEntity.getFeature().length()>0){
|
||||||
|
// UserRamCache.UserInfo userInfo = new UserCompareInfo();
|
||||||
|
// userInfo.setFaceId(personEntity.getPersonId()+"");
|
||||||
|
// userInfo.setName(personEntity.getName());
|
||||||
|
// userInfo.setFaceFeature(Base64Util.base64ToBytes(personEntity.getFeature()));
|
||||||
|
// //这边注册到内存缓存中
|
||||||
|
// UserRamCache.addUser(userInfo);
|
||||||
|
// faceCount++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
List<TenCellEntity> cellList = tenCellService.list(new QueryWrapper<TenCellEntity>()
|
||||||
|
.eq("tenant_id","1298283126102949890")
|
||||||
|
.eq("delete_flag",0));
|
||||||
|
for(TenCellEntity cellEntity: cellList){
|
||||||
|
String cellId = cellEntity.getCellId()+"";
|
||||||
|
UserRamGroup.addCell(cellId);
|
||||||
|
int count = tenPersonService.findCellCount(Long.valueOf(cellId));
|
||||||
|
int pageSize = 1000;
|
||||||
|
int page = count/pageSize;
|
||||||
|
if(count%1000!=0){
|
||||||
|
page = page+1;
|
||||||
|
}
|
||||||
|
int faceCount = 0;
|
||||||
|
for (int i = 0; i < page; i++) {
|
||||||
|
int start = i*1000;
|
||||||
|
List<TenPersonEntity> listPage = tenPersonService.listPage(start,1000, cellId);
|
||||||
|
for(TenPersonEntity personEntity: listPage){
|
||||||
|
if(personEntity.getFeature()!=null && personEntity.getFeature().length()>0){
|
||||||
|
UserInfo userInfo = new UserCompareInfo();
|
||||||
|
userInfo.setFaceId(personEntity.getPersonId()+"");
|
||||||
|
userInfo.setName(personEntity.getName());
|
||||||
|
userInfo.setFaceFeature(Base64Util.base64ToBytes(personEntity.getFeature()));
|
||||||
|
//这边注册到内存缓存中
|
||||||
|
UserRamGroup.addUser(userInfo,cellId);
|
||||||
|
faceCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug(cellEntity.getName()+":初始化人脸库完成,共 "+faceCount+" 人");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
package net.shapelight.modules.face.config;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class ArcFaceAutoConfiguration implements InitializingBean, DisposableBean {
|
||||||
|
|
||||||
|
|
||||||
|
private static final String PLATFORM;
|
||||||
|
|
||||||
|
private static final String USER_HOME;
|
||||||
|
|
||||||
|
public static String CACHE_LIB_FOLDER;
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.version}")
|
||||||
|
public String ARC_FACE_VERSION;
|
||||||
|
|
||||||
|
static {
|
||||||
|
String jvmName = System.getProperty("java.vm.name", "").toLowerCase();
|
||||||
|
String osName = System.getProperty("os.name", "").toLowerCase();
|
||||||
|
String osArch = System.getProperty("os.arch", "").toLowerCase();
|
||||||
|
String abiType = System.getProperty("sun.arch.abi", "").toLowerCase();
|
||||||
|
String libPath = System.getProperty("sun.boot.library.path", "").toLowerCase();
|
||||||
|
USER_HOME = System.getProperty("user.home");
|
||||||
|
if (jvmName.startsWith("dalvik") && osName.startsWith("linux")) {
|
||||||
|
osName = "android";
|
||||||
|
} else if (jvmName.startsWith("robovm") && osName.startsWith("darwin")) {
|
||||||
|
osName = "ios";
|
||||||
|
osArch = "arm";
|
||||||
|
} else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) {
|
||||||
|
osName = "macosx";
|
||||||
|
} else {
|
||||||
|
int spaceIndex = osName.indexOf(' ');
|
||||||
|
if (spaceIndex > 0) {
|
||||||
|
osName = osName.substring(0, spaceIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (osArch.equals("i386") || osArch.equals("i486") || osArch.equals("i586") || osArch.equals("i686")) {
|
||||||
|
osArch = "x86";
|
||||||
|
} else if (osArch.equals("amd64") || osArch.equals("x86-64") || osArch.equals("x64")) {
|
||||||
|
osArch = "x86_64";
|
||||||
|
} else if (osArch.startsWith("aarch64") || osArch.startsWith("armv8") || osArch.startsWith("arm64")) {
|
||||||
|
osArch = "arm64";
|
||||||
|
} else if ((osArch.startsWith("arm")) && ((abiType.equals("gnueabihf")) || (libPath.contains("openjdk-armhf")))) {
|
||||||
|
osArch = "armhf";
|
||||||
|
} else if (osArch.startsWith("arm")) {
|
||||||
|
osArch = "arm";
|
||||||
|
}
|
||||||
|
PLATFORM = osName + "-" + osArch;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws IOException {
|
||||||
|
CACHE_LIB_FOLDER = USER_HOME + "/.arcface/cache/" + ARC_FACE_VERSION + "/" + PLATFORM + "/";
|
||||||
|
loadLibrary();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadLibrary() throws IOException {
|
||||||
|
String baseFolder = "";
|
||||||
|
String suffix = ".dll";
|
||||||
|
if ("windows-x86_64".equals(PLATFORM)) {
|
||||||
|
baseFolder = "WIN64";
|
||||||
|
} else if ("windows-x86".equals(PLATFORM)) {
|
||||||
|
baseFolder = "WIN32";
|
||||||
|
} else if ("linux-x86_64".equals(PLATFORM)) {
|
||||||
|
baseFolder = "LINUX64";
|
||||||
|
suffix = ".so";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("".equals(baseFolder)) {
|
||||||
|
throw new RuntimeException("ArcFace不支持该操作系统");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
File file = new File(CACHE_LIB_FOLDER);
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> libList = new LinkedList<>();
|
||||||
|
libList.add("libarcsoft_face");
|
||||||
|
libList.add("libarcsoft_face_engine");
|
||||||
|
libList.add("libarcsoft_face_engine_jni");
|
||||||
|
|
||||||
|
for (String lib : libList) {
|
||||||
|
ClassPathResource resource = new ClassPathResource("libs/" + ARC_FACE_VERSION + "/" + baseFolder + "/" + lib + suffix);
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
int faceLength = inputStream.available();
|
||||||
|
File facePath = new File(CACHE_LIB_FOLDER + lib + suffix);
|
||||||
|
if (facePath.exists()) {
|
||||||
|
if (facePath.length() == faceLength) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
facePath.delete();
|
||||||
|
}
|
||||||
|
writeToLocal(CACHE_LIB_FOLDER + lib + suffix, inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeToLocal(String destination, InputStream input)
|
||||||
|
throws IOException {
|
||||||
|
int index;
|
||||||
|
byte[] bytes = new byte[1024 * 100];
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(destination);
|
||||||
|
while ((index = input.read(bytes)) != -1) {
|
||||||
|
fileOutputStream.write(bytes, 0, index);
|
||||||
|
}
|
||||||
|
fileOutputStream.flush();
|
||||||
|
fileOutputStream.close();
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shentao
|
||||||
|
* @desc
|
||||||
|
* @date 2022/3/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CompareFacesReqDTO {
|
||||||
|
private String image1;
|
||||||
|
private String image2;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FaceAddReqDTO {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String image;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FaceDetectReqDTO {
|
||||||
|
|
||||||
|
private String image;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
import com.arcsoft.face.Rect;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FaceDetectResDTO {
|
||||||
|
private Rect rect;
|
||||||
|
private int orient;
|
||||||
|
private int faceId = -1;
|
||||||
|
private int age = -1;
|
||||||
|
private int gender = -1;
|
||||||
|
private int liveness = -1;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FaceRecognitionReqDTO {
|
||||||
|
|
||||||
|
private String image;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arcsoft.face.Rect;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FaceRecognitionResDTO {
|
||||||
|
|
||||||
|
private Rect rect;
|
||||||
|
private String personId;
|
||||||
|
private String name;
|
||||||
|
private float similar;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.shapelight.modules.face.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class GetFaceListResDTO {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shapelight.modules.face.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ProcessInfo {
|
||||||
|
private int age;
|
||||||
|
private int gender;
|
||||||
|
private int liveness;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.shapelight.modules.face.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import net.shapelight.modules.face.util.UserInfo;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserCompareInfo extends UserInfo {
|
||||||
|
private Float similar;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package net.shapelight.modules.face.enums;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.shapelight.modules.face.rpc.ErrorCode;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum ErrorCodeEnum implements ErrorCode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功
|
||||||
|
*/
|
||||||
|
SUCCESS(0, "success", "成功"),
|
||||||
|
FAIL(1, "fail", "失败"),
|
||||||
|
PARAM_ERROR(2, "param error", "参数错误"),
|
||||||
|
SYSTEM_ERROR(999, "system error", "系统错误"),
|
||||||
|
|
||||||
|
;
|
||||||
|
private Integer code;
|
||||||
|
private String desc;
|
||||||
|
private String descCN;
|
||||||
|
|
||||||
|
ErrorCodeEnum(Integer code, String desc) {
|
||||||
|
this.code = code;
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCodeEnum(Integer code, String desc, String descCN) {
|
||||||
|
this.code = code;
|
||||||
|
this.desc = desc;
|
||||||
|
this.descCN = descCN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDesc() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescCN() {
|
||||||
|
return descCN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,292 @@
|
||||||
|
package net.shapelight.modules.face.face;
|
||||||
|
|
||||||
|
import com.arcsoft.face.*;
|
||||||
|
import com.arcsoft.face.enums.DetectMode;
|
||||||
|
import com.arcsoft.face.enums.ErrorInfo;
|
||||||
|
import com.arcsoft.face.enums.ExtractType;
|
||||||
|
import com.arcsoft.face.toolkit.ImageFactory;
|
||||||
|
import com.arcsoft.face.toolkit.ImageInfo;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.shapelight.modules.face.config.ArcFaceAutoConfiguration;
|
||||||
|
import net.shapelight.modules.face.factory.FaceEngineFactory;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||||
|
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FaceRecognize {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VIDEO模式人脸检测引擎,用于预览帧人脸追踪
|
||||||
|
*/
|
||||||
|
private FaceEngine ftEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸注册引擎
|
||||||
|
*/
|
||||||
|
private FaceEngine regEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于人脸识别的引擎池
|
||||||
|
*/
|
||||||
|
private GenericObjectPool<FaceEngine> frEnginePool;
|
||||||
|
|
||||||
|
|
||||||
|
private volatile ConcurrentHashMap<Integer, FaceResult> faceResultRegistry = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private ExecutorService frService = Executors.newFixedThreadPool(20);
|
||||||
|
|
||||||
|
public ConcurrentHashMap<String, byte[]> faceFeatureRegistry = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化引擎
|
||||||
|
*/
|
||||||
|
public void initEngine(String appId, String sdkKey, String activeKey, String activeFile) {
|
||||||
|
|
||||||
|
//引擎配置
|
||||||
|
ftEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER);
|
||||||
|
int activeCode;
|
||||||
|
if (StringUtils.isNotEmpty(activeFile)) {
|
||||||
|
activeCode = ftEngine.activeOffline(activeFile);
|
||||||
|
} else {
|
||||||
|
activeCode = ftEngine.activeOnline(appId, sdkKey, activeKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
EngineConfiguration ftEngineCfg = new EngineConfiguration();
|
||||||
|
ftEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_VIDEO);
|
||||||
|
ftEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).build());
|
||||||
|
int ftInitCode = ftEngine.init(ftEngineCfg);
|
||||||
|
|
||||||
|
//引擎配置
|
||||||
|
regEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER);
|
||||||
|
|
||||||
|
EngineConfiguration regEngineCfg = new EngineConfiguration();
|
||||||
|
regEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
|
||||||
|
regEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).supportFaceRecognition(true).build());
|
||||||
|
int regInitCode = regEngine.init(regEngineCfg);
|
||||||
|
|
||||||
|
|
||||||
|
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
||||||
|
poolConfig.setMaxIdle(5);
|
||||||
|
poolConfig.setMaxTotal(5);
|
||||||
|
poolConfig.setMinIdle(5);
|
||||||
|
poolConfig.setLifo(false);
|
||||||
|
EngineConfiguration frEngineCfg = new EngineConfiguration();
|
||||||
|
frEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceRecognition(true).build());
|
||||||
|
frEnginePool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey,activeFile, frEngineCfg), poolConfig);//底层库算法对象池
|
||||||
|
|
||||||
|
|
||||||
|
if (!(activeCode == ErrorInfo.MOK.getValue() || activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())) {
|
||||||
|
log.error("activeCode: " + activeCode);
|
||||||
|
throw new RuntimeException("activeCode: " + activeCode);
|
||||||
|
}
|
||||||
|
if (ftInitCode != ErrorInfo.MOK.getValue()) {
|
||||||
|
log.error("ftInitEngine: " + ftInitCode);
|
||||||
|
throw new RuntimeException("ftInitEngine: " + ftInitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regInitCode != ErrorInfo.MOK.getValue()) {
|
||||||
|
log.error("regInitEngine: " + regInitCode);
|
||||||
|
throw new RuntimeException("regInitEngine: " + regInitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void registerFace(String imagePath) {
|
||||||
|
|
||||||
|
log.info("正在注册人脸");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
if (regEngine != null) {
|
||||||
|
File file = new File(imagePath);
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
|
||||||
|
for (File file1 : files) {
|
||||||
|
ImageInfo imageInfo = ImageFactory.getRGBData(file1);
|
||||||
|
if (imageInfo != null) {
|
||||||
|
List<FaceInfo> faceInfoList = new ArrayList<>();
|
||||||
|
int code = regEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
|
||||||
|
imageInfo.getImageFormat(), faceInfoList);
|
||||||
|
|
||||||
|
if (code == 0 && faceInfoList.size() > 0) {
|
||||||
|
FaceFeature faceFeature = new FaceFeature();
|
||||||
|
int resCode = regEngine.extractFaceFeature(imageInfo, faceInfoList.get(0), ExtractType.REGISTER, 0, faceFeature);
|
||||||
|
if (resCode == 0) {
|
||||||
|
int lastIndexOf = file1.getName().lastIndexOf(".");
|
||||||
|
String name = file1.getName().substring(0, file1.getName().length() - lastIndexOf - 1);
|
||||||
|
faceFeatureRegistry.put(name, faceFeature.getFeatureData());
|
||||||
|
log.info("成功注册人脸:" + name);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("人脸注册完成,共注册:" + count + "张人脸");
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("注册失败,引擎未初始化或初始化失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerFace(Map<String, byte[]> face) {
|
||||||
|
face.forEach((k, v) -> {
|
||||||
|
faceFeatureRegistry.put(k, v.clone());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFace(String name) {
|
||||||
|
faceFeatureRegistry.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearFace() {
|
||||||
|
faceFeatureRegistry.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FaceResult getFaceResult(FaceInfo faceInfo, ImageInfo imageInfo) {
|
||||||
|
FaceResult faceResult = faceResultRegistry.get(faceInfo.getFaceId());
|
||||||
|
if (faceResult == null) {
|
||||||
|
faceResult = new FaceResult();
|
||||||
|
faceResultRegistry.put(faceInfo.getFaceId(), faceResult);
|
||||||
|
frService.submit(new FaceInfoRunnable(faceInfo, imageInfo, faceResult));
|
||||||
|
} else if (faceResult.isFlag()) {
|
||||||
|
return faceResult;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FacePreviewInfo> detectFaces(ImageInfo imageInfo) {
|
||||||
|
if (ftEngine != null) {
|
||||||
|
List<FaceInfo> faceInfoList = new ArrayList<>();
|
||||||
|
int code = ftEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
|
||||||
|
imageInfo.getImageFormat(), faceInfoList);
|
||||||
|
|
||||||
|
List<FacePreviewInfo> previewInfoList = new LinkedList<>();
|
||||||
|
for (FaceInfo faceInfo : faceInfoList) {
|
||||||
|
FacePreviewInfo facePreviewInfo = new FacePreviewInfo();
|
||||||
|
facePreviewInfo.setFaceInfo(faceInfo);
|
||||||
|
previewInfoList.add(facePreviewInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearFaceResultRegistry(faceInfoList);
|
||||||
|
return previewInfoList;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private long lastClearTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
//清理过时的人脸
|
||||||
|
private void clearFaceResultRegistry(List<FaceInfo> faceInfoList) {
|
||||||
|
if (System.currentTimeMillis() - lastClearTime > 5000) {
|
||||||
|
Iterator<Integer> iterator = faceResultRegistry.keySet().iterator();
|
||||||
|
for (; iterator.hasNext(); ) {
|
||||||
|
Integer next = iterator.next();
|
||||||
|
boolean flag = false;
|
||||||
|
for (FaceInfo faceInfo : faceInfoList) {
|
||||||
|
if (next.equals(faceInfo.getFaceId())) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
lastClearTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FaceResult {
|
||||||
|
private boolean flag = false;
|
||||||
|
private String name;
|
||||||
|
private float score;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FacePreviewInfo {
|
||||||
|
|
||||||
|
private FaceInfo faceInfo;
|
||||||
|
private int age;
|
||||||
|
private boolean liveness;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class FaceInfoRunnable implements Runnable {
|
||||||
|
private FaceInfo faceInfo;
|
||||||
|
private ImageInfo imageInfo;
|
||||||
|
private FaceResult faceResult;
|
||||||
|
|
||||||
|
public FaceInfoRunnable(FaceInfo faceInfo, ImageInfo imageInfo, FaceResult faceResult) {
|
||||||
|
this.faceInfo = faceInfo;
|
||||||
|
this.imageInfo = imageInfo;
|
||||||
|
this.faceResult = faceResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
FaceEngine frEngine = null;
|
||||||
|
try {
|
||||||
|
frEngine = frEnginePool.borrowObject();
|
||||||
|
if (frEngine != null) {
|
||||||
|
FaceFeature faceFeature = new FaceFeature();
|
||||||
|
int resCode = frEngine.extractFaceFeature(imageInfo, faceInfo, ExtractType.RECOGNIZE, 0, faceFeature);
|
||||||
|
if (resCode == 0) {
|
||||||
|
|
||||||
|
float score = 0.0F;
|
||||||
|
Iterator<Map.Entry<String, byte[]>> iterator = faceFeatureRegistry.entrySet().iterator();
|
||||||
|
for (; iterator.hasNext(); ) {
|
||||||
|
Map.Entry<String, byte[]> next = iterator.next();
|
||||||
|
FaceFeature faceFeatureTarget = new FaceFeature();
|
||||||
|
faceFeatureTarget.setFeatureData(next.getValue());
|
||||||
|
|
||||||
|
FaceSimilar faceSimilar = new FaceSimilar();
|
||||||
|
frEngine.compareFaceFeature(faceFeatureTarget, faceFeature, faceSimilar);
|
||||||
|
if (faceSimilar.getScore() > score) {
|
||||||
|
score = faceSimilar.getScore();
|
||||||
|
faceResult.setName(next.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("相似度:" + score);
|
||||||
|
if (score >= 0.8f) {
|
||||||
|
faceResult.setScore(score);
|
||||||
|
faceResult.setFlag(true);
|
||||||
|
faceResultRegistry.put(faceInfo.getFaceId(), faceResult);
|
||||||
|
} else {
|
||||||
|
faceResultRegistry.remove(faceInfo.getFaceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (frEngine != null) {
|
||||||
|
frEnginePool.returnObject(frEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package net.shapelight.modules.face.factory;
|
||||||
|
|
||||||
|
import com.arcsoft.face.EngineConfiguration;
|
||||||
|
import com.arcsoft.face.FaceEngine;
|
||||||
|
import com.arcsoft.face.enums.ErrorInfo;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.shapelight.modules.face.config.ArcFaceAutoConfiguration;
|
||||||
|
import net.shapelight.modules.face.enums.ErrorCodeEnum;
|
||||||
|
import net.shapelight.modules.face.rpc.BusinessException;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.pool2.BasePooledObjectFactory;
|
||||||
|
import org.apache.commons.pool2.PooledObject;
|
||||||
|
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FaceEngineFactory extends BasePooledObjectFactory<FaceEngine> {
|
||||||
|
|
||||||
|
private String appId;
|
||||||
|
private String sdkKey;
|
||||||
|
private String activeKey;
|
||||||
|
private String activeFile;
|
||||||
|
private EngineConfiguration engineConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
public FaceEngineFactory(String appId, String sdkKey, String activeKey, String activeFile, EngineConfiguration engineConfiguration) {
|
||||||
|
this.appId = appId;
|
||||||
|
this.sdkKey = sdkKey;
|
||||||
|
this.activeKey = activeKey;
|
||||||
|
this.activeFile=activeFile;
|
||||||
|
this.engineConfiguration = engineConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaceEngine create() {
|
||||||
|
|
||||||
|
|
||||||
|
FaceEngine faceEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER);
|
||||||
|
|
||||||
|
// FaceEngine faceEngine = new FaceEngine("/home/huangyifang/gb/咸阳师范/ArcSoft_ArcFacePro_linux_java_V4.1/libs/LINUX64/");
|
||||||
|
int activeCode;
|
||||||
|
if (StringUtils.isNotEmpty(activeFile)) {
|
||||||
|
activeCode = faceEngine.activeOffline(activeFile);
|
||||||
|
} else {
|
||||||
|
activeCode = faceEngine.activeOnline(appId, sdkKey, activeKey);
|
||||||
|
}
|
||||||
|
log.debug("引擎激活errorCode:" + activeCode);
|
||||||
|
if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
|
||||||
|
log.error("引擎激活失败" + activeCode);
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "引擎激活失败" + activeCode);
|
||||||
|
}
|
||||||
|
int initCode = faceEngine.init(engineConfiguration);
|
||||||
|
if (initCode != ErrorInfo.MOK.getValue()) {
|
||||||
|
log.error("引擎初始化失败" + initCode);
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "引擎初始化失败" + initCode);
|
||||||
|
}
|
||||||
|
log.debug("初始化引擎errorCode:" + initCode);
|
||||||
|
return faceEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PooledObject<FaceEngine> wrap(FaceEngine faceEngine) {
|
||||||
|
return new DefaultPooledObject<>(faceEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyObject(PooledObject<FaceEngine> p) throws Exception {
|
||||||
|
FaceEngine faceEngine = p.getObject();
|
||||||
|
int result = faceEngine.unInit();
|
||||||
|
super.destroyObject(p);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package net.shapelight.modules.face.rpc;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: st7251
|
||||||
|
* @Date: 2018/11/23 14:18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BusinessException extends RuntimeException {
|
||||||
|
private ErrorCode errorCode;
|
||||||
|
private String msg;
|
||||||
|
private String msgCN;
|
||||||
|
|
||||||
|
public BusinessException(Response response) {
|
||||||
|
this.errorCode = new ErrorCode() {
|
||||||
|
@Override
|
||||||
|
public Integer getCode() {
|
||||||
|
return response.getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDesc() {
|
||||||
|
return response.getMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescCN() {
|
||||||
|
return response.getMsg();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.msg=response.getMsg();
|
||||||
|
this.msgCN=response.getMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BusinessException(ErrorCode errorCode) {
|
||||||
|
super(errorCode.getDesc());
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
this.msg= errorCode.getDesc();
|
||||||
|
this.msgCN=errorCode.getDescCN();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BusinessException(ErrorCode errorCode, String msg) {
|
||||||
|
super(errorCode.getDesc());
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
this.msg = msg;
|
||||||
|
this.msgCN=msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BusinessException(Throwable cause, ErrorCode errorCode) {
|
||||||
|
super(cause);
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
this.msg= errorCode.getDesc();
|
||||||
|
this.msgCN=errorCode.getDescCN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BusinessException(Throwable cause, ErrorCode errorCode, String msg) {
|
||||||
|
super(cause);
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
this.msg = msg;
|
||||||
|
this.msgCN=msg;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shapelight.modules.face.rpc;
|
||||||
|
|
||||||
|
public interface ErrorCode {
|
||||||
|
|
||||||
|
|
||||||
|
Integer getCode();
|
||||||
|
|
||||||
|
String getDesc();
|
||||||
|
|
||||||
|
String getDescCN();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package net.shapelight.modules.face.rpc;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.shapelight.modules.face.enums.ErrorCodeEnum;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler{
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(BusinessException.class)
|
||||||
|
public Response businessException(BusinessException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
Response response = new Response();
|
||||||
|
response.setCode(e.getErrorCode().getCode());
|
||||||
|
response.setMsg(e.getMsgCN());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(IllegalArgumentException.class)
|
||||||
|
public Response handleIllegalArgumentException(IllegalArgumentException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
Response response = new Response();
|
||||||
|
response.setCode(ErrorCodeEnum.PARAM_ERROR.getCode());
|
||||||
|
response.setMsg(e.getMessage());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public Response handleException(Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
Response response = new Response();
|
||||||
|
response.setCode(ErrorCodeEnum.SYSTEM_ERROR.getCode());
|
||||||
|
response.setMsg(ErrorCodeEnum.SYSTEM_ERROR.getDescCN());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package net.shapelight.modules.face.rpc;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Response<T> {
|
||||||
|
|
||||||
|
private int code = -1;
|
||||||
|
private String msg = "success";
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
public static <T> Response<T> newSuccessResponse(T data) {
|
||||||
|
return newResponse(data, 0, "success");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> newFailedResponse(Integer code, String message) {
|
||||||
|
return newResponse(null, code, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> newFailedResponse(ErrorCode ErrorCode) {
|
||||||
|
return newResponse(null, ErrorCode.getCode(), ErrorCode.getDesc());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> newFailedResponse(ErrorCode ErrorCode, String message) {
|
||||||
|
return newResponse(null, ErrorCode.getCode(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> newResponse(T data, Integer code, String message) {
|
||||||
|
Response<T> response = new Response<T>();
|
||||||
|
response.setCode(code);
|
||||||
|
response.setMsg(message);
|
||||||
|
if (data != null && data instanceof String && "".equals(data)) {
|
||||||
|
response.setData(null);
|
||||||
|
} else {
|
||||||
|
response.setData(data);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package net.shapelight.modules.face.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arcsoft.face.FaceInfo;
|
||||||
|
import com.arcsoft.face.enums.ExtractType;
|
||||||
|
import com.arcsoft.face.toolkit.ImageInfo;
|
||||||
|
import net.shapelight.modules.face.entity.ProcessInfo;
|
||||||
|
import net.shapelight.modules.face.entity.UserCompareInfo;
|
||||||
|
import net.shapelight.modules.face.util.UserInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public interface FaceEngineService {
|
||||||
|
|
||||||
|
List<FaceInfo> detectFaces(ImageInfo imageInfo);
|
||||||
|
|
||||||
|
Float compareFace(ImageInfo imageInfo1, ImageInfo imageInfo2) ;
|
||||||
|
|
||||||
|
byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType extractType);
|
||||||
|
|
||||||
|
List<UserCompareInfo> faceRecognition(byte[] faceFeature, List<UserInfo> userInfoList, float passRate) ;
|
||||||
|
|
||||||
|
List<ProcessInfo> process(ImageInfo imageInfo, List<FaceInfo> faceInfoList);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,349 @@
|
||||||
|
package net.shapelight.modules.face.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.arcsoft.face.*;
|
||||||
|
import com.arcsoft.face.enums.DetectMode;
|
||||||
|
import com.arcsoft.face.enums.DetectOrient;
|
||||||
|
import com.arcsoft.face.enums.ExtractType;
|
||||||
|
import com.arcsoft.face.toolkit.ImageInfo;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.shapelight.modules.face.entity.ProcessInfo;
|
||||||
|
import net.shapelight.modules.face.entity.UserCompareInfo;
|
||||||
|
import net.shapelight.modules.face.enums.ErrorCodeEnum;
|
||||||
|
import net.shapelight.modules.face.factory.FaceEngineFactory;
|
||||||
|
import net.shapelight.modules.face.rpc.BusinessException;
|
||||||
|
import net.shapelight.modules.face.service.FaceEngineService;
|
||||||
|
import net.shapelight.modules.face.util.UserInfo;
|
||||||
|
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||||
|
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Service("faceEngineService")
|
||||||
|
@Slf4j
|
||||||
|
public class FaceEngineServiceImpl implements FaceEngineService {
|
||||||
|
|
||||||
|
public final static Logger logger = LoggerFactory.getLogger(FaceEngineServiceImpl.class);
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.app-id}")
|
||||||
|
public String appId;
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.sdk-key}")
|
||||||
|
public String sdkKey;
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.active-key}")
|
||||||
|
public String activeKey;
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.active-file}")
|
||||||
|
public String activeFile;
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.detect-pool-size}")
|
||||||
|
public Integer detectPooSize;
|
||||||
|
|
||||||
|
@Value("${config.arcface-sdk.compare-pool-size}")
|
||||||
|
public Integer comparePooSize;
|
||||||
|
|
||||||
|
private ExecutorService compareExecutorService;
|
||||||
|
|
||||||
|
//通用人脸识别引擎池
|
||||||
|
private GenericObjectPool<FaceEngine> faceEngineGeneralPool;
|
||||||
|
|
||||||
|
//人脸比对引擎池
|
||||||
|
private GenericObjectPool<FaceEngine> faceEngineComparePool;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
|
||||||
|
|
||||||
|
GenericObjectPoolConfig detectPoolConfig = new GenericObjectPoolConfig();
|
||||||
|
detectPoolConfig.setMaxIdle(detectPooSize);
|
||||||
|
detectPoolConfig.setMaxTotal(detectPooSize);
|
||||||
|
detectPoolConfig.setMinIdle(detectPooSize);
|
||||||
|
detectPoolConfig.setLifo(false);
|
||||||
|
EngineConfiguration detectCfg = new EngineConfiguration();
|
||||||
|
FunctionConfiguration detectFunctionCfg = new FunctionConfiguration();
|
||||||
|
detectFunctionCfg.setSupportFaceDetect(true);//开启人脸检测功能
|
||||||
|
detectFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
|
||||||
|
detectFunctionCfg.setSupportAge(true);//开启年龄检测功能
|
||||||
|
detectFunctionCfg.setSupportGender(true);//开启性别检测功能
|
||||||
|
detectFunctionCfg.setSupportLiveness(true);//开启活体检测功能
|
||||||
|
detectCfg.setFunctionConfiguration(detectFunctionCfg);
|
||||||
|
detectCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
|
||||||
|
detectCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);//人脸旋转角度
|
||||||
|
faceEngineGeneralPool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey, activeFile, detectCfg), detectPoolConfig);//底层库算法对象池
|
||||||
|
|
||||||
|
|
||||||
|
//初始化特征比较线程池
|
||||||
|
GenericObjectPoolConfig comparePoolConfig = new GenericObjectPoolConfig();
|
||||||
|
comparePoolConfig.setMaxIdle(comparePooSize);
|
||||||
|
comparePoolConfig.setMaxTotal(comparePooSize);
|
||||||
|
comparePoolConfig.setMinIdle(comparePooSize);
|
||||||
|
comparePoolConfig.setLifo(false);
|
||||||
|
EngineConfiguration compareCfg = new EngineConfiguration();
|
||||||
|
FunctionConfiguration compareFunctionCfg = new FunctionConfiguration();
|
||||||
|
compareFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
|
||||||
|
compareCfg.setFunctionConfiguration(compareFunctionCfg);
|
||||||
|
compareCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
|
||||||
|
compareCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);//人脸旋转角度
|
||||||
|
faceEngineComparePool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey, activeFile, compareCfg), comparePoolConfig);//底层库算法对象池
|
||||||
|
compareExecutorService = Executors.newFixedThreadPool(comparePooSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FaceInfo> detectFaces(ImageInfo imageInfo) {
|
||||||
|
|
||||||
|
FaceEngine faceEngine = null;
|
||||||
|
try {
|
||||||
|
faceEngine = faceEngineGeneralPool.borrowObject();
|
||||||
|
if (faceEngine == null) {
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
//人脸检测得到人脸列表
|
||||||
|
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
|
||||||
|
//人脸检测
|
||||||
|
int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
||||||
|
if (errorCode == 0) {
|
||||||
|
return faceInfoList;
|
||||||
|
} else {
|
||||||
|
log.error("人脸检测失败,errorCode:" + errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("", e);
|
||||||
|
} finally {
|
||||||
|
if (faceEngine != null) {
|
||||||
|
//释放引擎对象
|
||||||
|
faceEngineGeneralPool.returnObject(faceEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Float compareFace(ImageInfo imageInfo1, ImageInfo imageInfo2) {
|
||||||
|
|
||||||
|
List<FaceInfo> faceInfoList1 = detectFaces(imageInfo1);
|
||||||
|
List<FaceInfo> faceInfoList2 = detectFaces(imageInfo2);
|
||||||
|
|
||||||
|
if (CollectionUtil.isEmpty(faceInfoList1)) {
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "照片1未检测到人脸");
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isEmpty(faceInfoList2)) {
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "照片2未检测到人脸");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] feature1 = extractFaceFeature(imageInfo1, faceInfoList1.get(0), ExtractType.REGISTER);
|
||||||
|
byte[] feature2 = extractFaceFeature(imageInfo2, faceInfoList2.get(0), ExtractType.RECOGNIZE);
|
||||||
|
|
||||||
|
FaceEngine faceEngine = null;
|
||||||
|
try {
|
||||||
|
faceEngine = faceEngineGeneralPool.borrowObject();
|
||||||
|
if (faceEngine == null) {
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
FaceFeature faceFeature1 = new FaceFeature();
|
||||||
|
faceFeature1.setFeatureData(feature1);
|
||||||
|
FaceFeature faceFeature2 = new FaceFeature();
|
||||||
|
faceFeature2.setFeatureData(feature2);
|
||||||
|
//提取人脸特征
|
||||||
|
FaceSimilar faceSimilar = new FaceSimilar();
|
||||||
|
int errorCode = faceEngine.compareFaceFeature(faceFeature1, faceFeature2, faceSimilar);
|
||||||
|
if (errorCode == 0) {
|
||||||
|
return faceSimilar.getScore();
|
||||||
|
} else {
|
||||||
|
log.error("特征提取失败,errorCode:" + errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("", e);
|
||||||
|
} finally {
|
||||||
|
if (faceEngine != null) {
|
||||||
|
//释放引擎对象
|
||||||
|
faceEngineGeneralPool.returnObject(faceEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸特征
|
||||||
|
*
|
||||||
|
* @param imageInfo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType extractType) {
|
||||||
|
|
||||||
|
FaceEngine faceEngine = null;
|
||||||
|
try {
|
||||||
|
faceEngine = faceEngineGeneralPool.borrowObject();
|
||||||
|
if (faceEngine == null) {
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
FaceFeature faceFeature = new FaceFeature();
|
||||||
|
//提取人脸特征
|
||||||
|
int errorCode = faceEngine.extractFaceFeature(imageInfo, faceInfo, extractType, 0, faceFeature);
|
||||||
|
if (errorCode == 0) {
|
||||||
|
return faceFeature.getFeatureData();
|
||||||
|
} else {
|
||||||
|
log.error("特征提取失败,errorCode:" + errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("", e);
|
||||||
|
} finally {
|
||||||
|
if (faceEngine != null) {
|
||||||
|
//释放引擎对象
|
||||||
|
faceEngineGeneralPool.returnObject(faceEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserCompareInfo> faceRecognition(byte[] faceFeature, List<UserInfo> userInfoList, float passRate) {
|
||||||
|
List<UserCompareInfo> resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表
|
||||||
|
|
||||||
|
FaceFeature targetFaceFeature = new FaceFeature();
|
||||||
|
targetFaceFeature.setFeatureData(faceFeature);
|
||||||
|
|
||||||
|
List<List<UserInfo>> faceUserInfoPartList = Lists.partition(userInfoList, 1000);//分成1000一组,多线程处理
|
||||||
|
CompletionService<List<UserCompareInfo>> completionService = new ExecutorCompletionService(compareExecutorService);
|
||||||
|
for (List<UserInfo> part : faceUserInfoPartList) {
|
||||||
|
completionService.submit(new CompareFaceTask(part, targetFaceFeature, passRate));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < faceUserInfoPartList.size(); i++) {
|
||||||
|
List<UserCompareInfo> faceUserInfoList = null;
|
||||||
|
try {
|
||||||
|
faceUserInfoList = completionService.take().get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isNotEmpty(userInfoList)) {
|
||||||
|
resultUserInfoList.addAll(faceUserInfoList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultUserInfoList.sort((h1, h2) -> h2.getSimilar().compareTo(h1.getSimilar()));//从大到小排序
|
||||||
|
|
||||||
|
return resultUserInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProcessInfo> process(ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
|
||||||
|
FaceEngine faceEngine = null;
|
||||||
|
try {
|
||||||
|
//获取引擎对象
|
||||||
|
faceEngine = faceEngineGeneralPool.borrowObject();
|
||||||
|
if (faceEngine == null) {
|
||||||
|
throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, FunctionConfiguration.builder().supportAge(true).supportGender(true).supportLiveness(true).build());
|
||||||
|
if (errorCode == 0) {
|
||||||
|
List<ProcessInfo> processInfoList = Lists.newLinkedList();
|
||||||
|
|
||||||
|
//性别列表
|
||||||
|
List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
|
||||||
|
faceEngine.getGender(genderInfoList);
|
||||||
|
|
||||||
|
//年龄列表
|
||||||
|
List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
|
||||||
|
faceEngine.getAge(ageInfoList);
|
||||||
|
//活体结果列表
|
||||||
|
List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
|
||||||
|
faceEngine.getLiveness(livenessInfoList);
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < genderInfoList.size(); i++) {
|
||||||
|
ProcessInfo processInfo = new ProcessInfo();
|
||||||
|
processInfo.setGender(genderInfoList.get(i).getGender());
|
||||||
|
processInfo.setAge(ageInfoList.get(i).getAge());
|
||||||
|
processInfo.setLiveness(livenessInfoList.get(i).getLiveness());
|
||||||
|
processInfoList.add(processInfo);
|
||||||
|
}
|
||||||
|
return processInfoList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("", e);
|
||||||
|
} finally {
|
||||||
|
if (faceEngine != null) {
|
||||||
|
//释放引擎对象
|
||||||
|
faceEngineGeneralPool.returnObject(faceEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class CompareFaceTask implements Callable<List<UserCompareInfo>> {
|
||||||
|
|
||||||
|
private List<UserInfo> userInfoList;
|
||||||
|
private FaceFeature targetFaceFeature;
|
||||||
|
private float passRate;
|
||||||
|
|
||||||
|
|
||||||
|
public CompareFaceTask(List<UserInfo> userInfoList, FaceFeature targetFaceFeature, float passRate) {
|
||||||
|
this.userInfoList = userInfoList;
|
||||||
|
this.targetFaceFeature = targetFaceFeature;
|
||||||
|
this.passRate = passRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserCompareInfo> call() throws Exception {
|
||||||
|
FaceEngine faceEngine = null;
|
||||||
|
List<UserCompareInfo> resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表
|
||||||
|
try {
|
||||||
|
faceEngine = faceEngineComparePool.borrowObject();
|
||||||
|
for (UserInfo userInfo : userInfoList) {
|
||||||
|
FaceFeature sourceFaceFeature = new FaceFeature();
|
||||||
|
sourceFaceFeature.setFeatureData(userInfo.getFaceFeature());
|
||||||
|
FaceSimilar faceSimilar = new FaceSimilar();
|
||||||
|
faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
|
||||||
|
if (faceSimilar.getScore() > passRate) {//相似值大于配置预期,加入到识别到人脸的列表
|
||||||
|
UserCompareInfo info = new UserCompareInfo();
|
||||||
|
info.setName(userInfo.getName());
|
||||||
|
info.setFaceId(userInfo.getFaceId());
|
||||||
|
info.setSimilar(faceSimilar.getScore());
|
||||||
|
resultUserInfoList.add(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("", e);
|
||||||
|
} finally {
|
||||||
|
if (faceEngine != null) {
|
||||||
|
faceEngineComparePool.returnObject(faceEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultUserInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package net.shapelight.modules.face.util;
|
||||||
|
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class Base64Util {
|
||||||
|
public static String base64Process(String base64Str) {
|
||||||
|
if (!ObjectUtils.isEmpty(base64Str)) {
|
||||||
|
String photoBase64 = base64Str.substring(0, 30).toLowerCase();
|
||||||
|
int indexOf = photoBase64.indexOf("base64,");
|
||||||
|
if (indexOf > 0) {
|
||||||
|
base64Str = base64Str.substring(indexOf + 7);
|
||||||
|
}
|
||||||
|
base64Str = base64Str.replaceAll(" ", "+");
|
||||||
|
base64Str = base64Str.replaceAll("\r|\n", "");
|
||||||
|
return base64Str;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] base64ToBytes(String base64) {
|
||||||
|
if (ObjectUtils.isEmpty(base64)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String base64Process = base64Process(base64);
|
||||||
|
|
||||||
|
byte[] decode = Base64.getDecoder().decode(base64Process);
|
||||||
|
return decode;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,225 @@
|
||||||
|
package net.shapelight.modules.face.util;
|
||||||
|
|
||||||
|
import com.arcsoft.face.*;
|
||||||
|
import com.arcsoft.face.enums.*;
|
||||||
|
import com.arcsoft.face.toolkit.ImageFactory;
|
||||||
|
import com.arcsoft.face.toolkit.ImageInfo;
|
||||||
|
import com.arcsoft.face.toolkit.ImageInfoEx;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FaceEngineTest {
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
//激活码,从官网获取
|
||||||
|
String appId = "DEnAZa1bWXcaAxyWUg33QZaKCmMkNmrQxuKZJQGmZsHJ";
|
||||||
|
String sdkKey = "vWbvUyStZeartSaM6QoTzPYWFpSaj4uhfDmRifSzCd6";
|
||||||
|
String activeKey = "82G1-11QA-713Y-8NB4";
|
||||||
|
|
||||||
|
System.err.println("注意,如果返回的errorCode不为0,可查看com.arcsoft.face.enums.ErrorInfo类获取相应的错误信息");
|
||||||
|
|
||||||
|
//人脸识别引擎库存放路径
|
||||||
|
FaceEngine faceEngine = new FaceEngine("/home/huangyifang/gb/咸阳师范/ArcSoft_ArcFacePro_linux_java_V4.1/libs/LINUX64");
|
||||||
|
//激活引擎
|
||||||
|
int errorCode = faceEngine.activeOnline(appId, sdkKey, activeKey);
|
||||||
|
System.out.println("引擎激活errorCode:" + errorCode);
|
||||||
|
|
||||||
|
ActiveDeviceInfo activeDeviceInfo = new ActiveDeviceInfo();
|
||||||
|
//采集设备信息(可离线)
|
||||||
|
errorCode = faceEngine.getActiveDeviceInfo(activeDeviceInfo);
|
||||||
|
System.out.println("采集设备信息errorCode:" + errorCode);
|
||||||
|
System.out.println("设备信息:" + activeDeviceInfo.getDeviceInfo());
|
||||||
|
|
||||||
|
// faceEngine.activeOffline("d:\\ArcFacePro64.dat.offline");
|
||||||
|
|
||||||
|
ActiveFileInfo activeFileInfo = new ActiveFileInfo();
|
||||||
|
errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
|
||||||
|
System.out.println("获取激活文件errorCode:" + errorCode);
|
||||||
|
System.out.println("激活文件信息:" + activeFileInfo.toString());
|
||||||
|
|
||||||
|
//引擎配置
|
||||||
|
EngineConfiguration engineConfiguration = new EngineConfiguration();
|
||||||
|
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
|
||||||
|
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
|
||||||
|
engineConfiguration.setDetectFaceMaxNum(10);
|
||||||
|
//功能配置
|
||||||
|
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
|
||||||
|
functionConfiguration.setSupportAge(true);
|
||||||
|
functionConfiguration.setSupportFaceDetect(true);
|
||||||
|
functionConfiguration.setSupportFaceRecognition(true);
|
||||||
|
functionConfiguration.setSupportGender(true);
|
||||||
|
functionConfiguration.setSupportLiveness(true);
|
||||||
|
functionConfiguration.setSupportIRLiveness(true);
|
||||||
|
functionConfiguration.setSupportImageQuality(true);
|
||||||
|
functionConfiguration.setSupportMaskDetect(true);
|
||||||
|
functionConfiguration.setSupportUpdateFaceData(true);
|
||||||
|
engineConfiguration.setFunctionConfiguration(functionConfiguration);
|
||||||
|
|
||||||
|
//初始化引擎
|
||||||
|
errorCode = faceEngine.init(engineConfiguration);
|
||||||
|
System.out.println("初始化引擎errorCode:" + errorCode);
|
||||||
|
VersionInfo version = faceEngine.getVersion();
|
||||||
|
System.out.println(version);
|
||||||
|
|
||||||
|
//人脸检测
|
||||||
|
ImageInfo imageInfo = ImageFactory.getRGBData(new File("/home/huangyifang/gb/咸阳师范/10.jpg"));
|
||||||
|
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
|
||||||
|
errorCode = faceEngine.detectFaces(imageInfo, faceInfoList);
|
||||||
|
System.out.println("人脸检测errorCode:" + errorCode);
|
||||||
|
System.out.println("检测到人脸数:" + faceInfoList.size());
|
||||||
|
|
||||||
|
ImageQuality imageQuality = new ImageQuality();
|
||||||
|
errorCode = faceEngine.imageQualityDetect(imageInfo, faceInfoList.get(0), 0, imageQuality);
|
||||||
|
System.out.println("图像质量检测errorCode:" + errorCode);
|
||||||
|
System.out.println("图像质量分数:" + imageQuality.getFaceQuality());
|
||||||
|
|
||||||
|
//特征提取
|
||||||
|
FaceFeature faceFeature = new FaceFeature();
|
||||||
|
errorCode = faceEngine.extractFaceFeature(imageInfo, faceInfoList.get(0), ExtractType.REGISTER, 0, faceFeature);
|
||||||
|
System.out.println("特征提取errorCode:" + errorCode);
|
||||||
|
|
||||||
|
//人脸检测2
|
||||||
|
ImageInfo imageInfo2 = ImageFactory.getRGBData(new File("/home/huangyifang/gb/咸阳师范/10.jpg"));
|
||||||
|
List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
|
||||||
|
errorCode = faceEngine.detectFaces(imageInfo2, faceInfoList2);
|
||||||
|
System.out.println("人脸检测errorCode:" + errorCode);
|
||||||
|
System.out.println("检测到人脸数:" + faceInfoList.size());
|
||||||
|
|
||||||
|
//特征提取2
|
||||||
|
FaceFeature faceFeature2 = new FaceFeature();
|
||||||
|
errorCode = faceEngine.extractFaceFeature(imageInfo2, faceInfoList2.get(0), ExtractType.RECOGNIZE, 0, faceFeature2);
|
||||||
|
System.out.println("特征提取errorCode:" + errorCode);
|
||||||
|
|
||||||
|
//特征比对
|
||||||
|
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);
|
||||||
|
System.out.println("特征比对errorCode:" + errorCode);
|
||||||
|
System.out.println("人脸相似度:" + faceSimilar.getScore());
|
||||||
|
|
||||||
|
|
||||||
|
//人脸属性检测
|
||||||
|
FunctionConfiguration configuration = new FunctionConfiguration();
|
||||||
|
configuration.setSupportAge(true);
|
||||||
|
configuration.setSupportGender(true);
|
||||||
|
configuration.setSupportLiveness(true);
|
||||||
|
configuration.setSupportMaskDetect(true);
|
||||||
|
errorCode = faceEngine.process(imageInfo, faceInfoList, configuration);
|
||||||
|
System.out.println("图像属性处理errorCode:" + errorCode);
|
||||||
|
|
||||||
|
//性别检测
|
||||||
|
List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
|
||||||
|
errorCode = faceEngine.getGender(genderInfoList);
|
||||||
|
System.out.println("性别:" + genderInfoList.get(0).getGender());
|
||||||
|
|
||||||
|
//年龄检测
|
||||||
|
List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
|
||||||
|
errorCode = faceEngine.getAge(ageInfoList);
|
||||||
|
System.out.println("年龄:" + ageInfoList.get(0).getAge());
|
||||||
|
|
||||||
|
//活体检测
|
||||||
|
List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
|
||||||
|
errorCode = faceEngine.getLiveness(livenessInfoList);
|
||||||
|
System.out.println("活体:" + livenessInfoList.get(0).getLiveness());
|
||||||
|
|
||||||
|
//口罩检测
|
||||||
|
List<MaskInfo> maskInfoList = new ArrayList<MaskInfo>();
|
||||||
|
errorCode = faceEngine.getMask(maskInfoList);
|
||||||
|
System.out.println("口罩:" + maskInfoList.get(0).getMask());
|
||||||
|
|
||||||
|
|
||||||
|
//IR属性处理
|
||||||
|
ImageInfo imageInfoGray = ImageFactory.getGrayData(new File("/home/huangyifang/gb/咸阳师范/10.jpg"));
|
||||||
|
List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
|
||||||
|
errorCode = faceEngine.detectFaces(imageInfoGray, faceInfoListGray);
|
||||||
|
|
||||||
|
FunctionConfiguration configuration2 = new FunctionConfiguration();
|
||||||
|
configuration2.setSupportIRLiveness(true);
|
||||||
|
errorCode = faceEngine.processIr(imageInfoGray, faceInfoListGray, configuration2);
|
||||||
|
//IR活体检测
|
||||||
|
List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
|
||||||
|
errorCode = faceEngine.getLivenessIr(irLivenessInfo);
|
||||||
|
System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());
|
||||||
|
|
||||||
|
//获取激活文件信息
|
||||||
|
ActiveFileInfo activeFileInfo2 = new ActiveFileInfo();
|
||||||
|
errorCode = faceEngine.getActiveFileInfo(activeFileInfo2);
|
||||||
|
|
||||||
|
//更新人脸数据
|
||||||
|
errorCode = faceEngine.updateFaceData(imageInfo, faceInfoList);
|
||||||
|
|
||||||
|
//高级人脸图像处理接口
|
||||||
|
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);
|
||||||
|
ImageQuality imageQuality1 = new ImageQuality();
|
||||||
|
errorCode = faceEngine.imageQualityDetect(imageInfoEx, faceInfoList1.get(0), 0, imageQuality1);
|
||||||
|
FunctionConfiguration fun = new FunctionConfiguration();
|
||||||
|
fun.setSupportAge(true);
|
||||||
|
errorCode = faceEngine.process(imageInfoEx, faceInfoList1, fun);
|
||||||
|
List<AgeInfo> ageInfoList1 = new ArrayList<>();
|
||||||
|
int age = faceEngine.getAge(ageInfoList1);
|
||||||
|
FaceFeature feature = new FaceFeature();
|
||||||
|
errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), ExtractType.REGISTER, 0, feature);
|
||||||
|
errorCode = faceEngine.updateFaceData(imageInfoEx, faceInfoList1);
|
||||||
|
|
||||||
|
//设置活体测试
|
||||||
|
errorCode = faceEngine.setLivenessParam(0.5f, 0.7f, 0.3f);
|
||||||
|
System.out.println("设置活体活体阈值errorCode:" + errorCode);
|
||||||
|
|
||||||
|
LivenessParam livenessParam=new LivenessParam();
|
||||||
|
errorCode = faceEngine.getLivenessParam(livenessParam);
|
||||||
|
|
||||||
|
//注册人脸信息1
|
||||||
|
FaceFeatureInfo faceFeatureInfo = new FaceFeatureInfo();
|
||||||
|
faceFeatureInfo.setSearchId(5);
|
||||||
|
faceFeatureInfo.setFaceTag("FeatureData1");
|
||||||
|
faceFeatureInfo.setFeatureData(faceFeature.getFeatureData());
|
||||||
|
errorCode = faceEngine.registerFaceFeature(faceFeatureInfo);
|
||||||
|
|
||||||
|
//注册人脸信息2
|
||||||
|
FaceFeatureInfo faceFeatureInfo2 = new FaceFeatureInfo();
|
||||||
|
faceFeatureInfo2.setSearchId(6);
|
||||||
|
faceFeatureInfo2.setFaceTag("FeatureData2");
|
||||||
|
faceFeatureInfo2.setFeatureData(faceFeature2.getFeatureData());
|
||||||
|
errorCode = faceEngine.registerFaceFeature(faceFeatureInfo2);
|
||||||
|
|
||||||
|
//获取注册人脸个数
|
||||||
|
FaceSearchCount faceSearchCount = new FaceSearchCount();
|
||||||
|
errorCode = faceEngine.getFaceCount(faceSearchCount);
|
||||||
|
System.out.println("注册人脸个数:" + faceSearchCount.getCount());
|
||||||
|
|
||||||
|
//搜索最相似人脸
|
||||||
|
SearchResult searchResult = new SearchResult();
|
||||||
|
errorCode = faceEngine.searchFaceFeature(faceFeature, CompareModel.LIFE_PHOTO, searchResult);
|
||||||
|
System.out.println("最相似人脸Id:" + searchResult.getFaceFeatureInfo().getSearchId());
|
||||||
|
|
||||||
|
//更新人脸信息
|
||||||
|
FaceFeatureInfo faceFeatureInfo3 = new FaceFeatureInfo();
|
||||||
|
faceFeatureInfo3.setSearchId(6);
|
||||||
|
faceFeatureInfo3.setFaceTag("FeatureData2Update");
|
||||||
|
faceFeatureInfo3.setFeatureData(faceFeature2.getFeatureData());
|
||||||
|
errorCode = faceEngine.updateFaceFeature(faceFeatureInfo3);
|
||||||
|
|
||||||
|
//移除人脸信息
|
||||||
|
errorCode = faceEngine.removeFaceFeature(6);
|
||||||
|
|
||||||
|
//引擎卸载
|
||||||
|
errorCode = faceEngine.unInit();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package net.shapelight.modules.face.util;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserInfo {
|
||||||
|
private String faceId;
|
||||||
|
private String name;
|
||||||
|
private byte[] faceFeature;
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package net.shapelight.modules.face.util;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
public class UserRamCache {
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String, UserInfo> USER_INFO_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final Set<Listener> REGISTER = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
public void addUser(UserInfo userInfo) {
|
||||||
|
USER_INFO_MAP.put(userInfo.getFaceId(), userInfo);
|
||||||
|
for (Listener listener : REGISTER) {
|
||||||
|
listener.onAdd(userInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUser(String faceId) {
|
||||||
|
UserInfo userInfo = USER_INFO_MAP.remove(faceId);
|
||||||
|
for (Listener listener : REGISTER) {
|
||||||
|
listener.onRemove(userInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserInfo> getUserList() {
|
||||||
|
List<UserInfo> userInfoList = Lists.newLinkedList();
|
||||||
|
userInfoList.addAll(USER_INFO_MAP.values());
|
||||||
|
return userInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear(){
|
||||||
|
USER_INFO_MAP.clear();
|
||||||
|
REGISTER.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(Listener listener) {
|
||||||
|
REGISTER.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(Listener listener) {
|
||||||
|
REGISTER.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Data
|
||||||
|
// public class UserInfo {
|
||||||
|
//
|
||||||
|
// private String faceId;
|
||||||
|
// private String name;
|
||||||
|
// private byte[] faceFeature;
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
default void onAdd(UserInfo userInfo) {
|
||||||
|
}
|
||||||
|
|
||||||
|
default void onRemove(UserInfo userInfo) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package net.shapelight.modules.face.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class UserRamGroup {
|
||||||
|
|
||||||
|
private static final ConcurrentHashMap<String, UserRamCache> USER_RAM_GROUP_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public static void addCell(String cellId){
|
||||||
|
UserRamCache cell = new UserRamCache();
|
||||||
|
USER_RAM_GROUP_MAP.put(cellId,cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeCell(String cellId){
|
||||||
|
USER_RAM_GROUP_MAP.remove(cellId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addUser(UserInfo userInfo, String cellId) {
|
||||||
|
USER_RAM_GROUP_MAP.get(cellId).addUser(userInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeUser(String faceId, String cellId) {
|
||||||
|
USER_RAM_GROUP_MAP.get(cellId).removeUser(faceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<UserInfo> getUserList(String cellId) {
|
||||||
|
return USER_RAM_GROUP_MAP.get(cellId).getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear(){
|
||||||
|
USER_RAM_GROUP_MAP.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ public class EmpowerTask implements ITask{
|
||||||
KeysEntity.passKey = json.getString("passKey");
|
KeysEntity.passKey = json.getString("passKey");
|
||||||
KeysEntity.empowerText = json.getString("empowerText");
|
KeysEntity.empowerText = json.getString("empowerText");
|
||||||
log.debug("TokenResponse:{}", json.getString("passKey"));
|
log.debug("TokenResponse:{}", json.getString("passKey"));
|
||||||
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -426,12 +426,12 @@ public class TenPersonController extends AbstractController {
|
||||||
tenPerson.setCreateTime(new Date());
|
tenPerson.setCreateTime(new Date());
|
||||||
tenPerson.setRegisterType(Constant.RESGISTER_TYPE_WEB);
|
tenPerson.setRegisterType(Constant.RESGISTER_TYPE_WEB);
|
||||||
|
|
||||||
int res;
|
String res;
|
||||||
|
|
||||||
tenPerson.setStatus(0);
|
tenPerson.setStatus(0);
|
||||||
res = tenPersonService.save(tenPerson);
|
res = tenPersonService.save(tenPerson);
|
||||||
if (res==2) {
|
if (res!=null) {
|
||||||
return R.error("照片未检测到人脸");
|
return R.error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return R.ok();
|
return R.ok();
|
||||||
|
@ -1303,11 +1303,11 @@ public class TenPersonController extends AbstractController {
|
||||||
//----------------------------------掌静脉特征压缩包封装--------------------------------------
|
//----------------------------------掌静脉特征压缩包封装--------------------------------------
|
||||||
|
|
||||||
|
|
||||||
int res;
|
String res;
|
||||||
|
|
||||||
res = tenPersonService.save(tenPerson);
|
res = tenPersonService.save(tenPerson);
|
||||||
if (res==2) {
|
if (res!=null) {
|
||||||
return R.error("照片未检测到人脸");
|
return R.error(res);
|
||||||
}
|
}
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
@ -1361,7 +1361,7 @@ public class TenPersonController extends AbstractController {
|
||||||
AppUserScopeEntity userScopeEntity = appUserScopeService.getOne(new LambdaQueryWrapper<AppUserScopeEntity>()
|
AppUserScopeEntity userScopeEntity = appUserScopeService.getOne(new LambdaQueryWrapper<AppUserScopeEntity>()
|
||||||
.eq(AppUserScopeEntity::getUserId, params.get("userId")));
|
.eq(AppUserScopeEntity::getUserId, params.get("userId")));
|
||||||
List<TenRelation> relationList = relationService.list(new LambdaQueryWrapper<TenRelation>()
|
List<TenRelation> relationList = relationService.list(new LambdaQueryWrapper<TenRelation>()
|
||||||
.eq(TenRelation::getParentId,userScopeEntity.getUserId()));
|
.eq(TenRelation::getParentId,userScopeEntity.getUserId()).eq(TenRelation::getStatus,1));
|
||||||
if(!relationList.isEmpty()) {
|
if(!relationList.isEmpty()) {
|
||||||
List<Long> list = relationList.stream().map(TenRelation::getStudentId).collect(Collectors.toList());
|
List<Long> list = relationList.stream().map(TenRelation::getStudentId).collect(Collectors.toList());
|
||||||
params.put("cellId",userScopeEntity.getCellId());
|
params.put("cellId",userScopeEntity.getCellId());
|
||||||
|
|
|
@ -124,6 +124,8 @@ public interface TenPersonDao {
|
||||||
|
|
||||||
IPage<TenPersonEntity> getByPersonIds(Page page,@Param("personIds")List<Long> personIds, @Param("cellId")Long cellId);
|
IPage<TenPersonEntity> getByPersonIds(Page page,@Param("personIds")List<Long> personIds, @Param("cellId")Long cellId);
|
||||||
|
|
||||||
|
List<TenPersonEntity> listPage(@Param("start")int start, @Param("count")int count, @Param("cellId")String cellId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,6 +347,8 @@ public class TenPersonEntity extends BaseEntity implements Serializable {
|
||||||
|
|
||||||
//-----------------v5http-----
|
//-----------------v5http-----
|
||||||
private String thdFeature;
|
private String thdFeature;
|
||||||
|
//人脸特征
|
||||||
|
private String feature;
|
||||||
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
@ApiModelProperty("部门ID")
|
@ApiModelProperty("部门ID")
|
||||||
|
|
|
@ -27,7 +27,7 @@ public interface TenPersonService {
|
||||||
|
|
||||||
PageUtils queryVerify(Map<String, Object> params);
|
PageUtils queryVerify(Map<String, Object> params);
|
||||||
|
|
||||||
int save(TenPersonEntity entity);
|
String save(TenPersonEntity entity);
|
||||||
int save3d(TenPersonEntity entity);
|
int save3d(TenPersonEntity entity);
|
||||||
int update3d(TenPersonEntity entity);
|
int update3d(TenPersonEntity entity);
|
||||||
boolean saveOtherRoom(TenPersonEntity entity);
|
boolean saveOtherRoom(TenPersonEntity entity);
|
||||||
|
@ -154,5 +154,7 @@ public interface TenPersonService {
|
||||||
|
|
||||||
TenPersonEntity getByRyId(String ryId,Long cellId,String idCard);
|
TenPersonEntity getByRyId(String ryId,Long cellId,String idCard);
|
||||||
|
|
||||||
|
List<TenPersonEntity> listPage(int start, int count, String cellId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class TenParentServiceImpl extends ServiceImpl<TenParentMapper, TenParent
|
||||||
IPage<ParentVo> page = parentMapper.getParentVoList(pageParam,params);
|
IPage<ParentVo> page = parentMapper.getParentVoList(pageParam,params);
|
||||||
page.getRecords().forEach(item -> {
|
page.getRecords().forEach(item -> {
|
||||||
int count = relationService.count(new LambdaQueryWrapper<TenRelation>()
|
int count = relationService.count(new LambdaQueryWrapper<TenRelation>()
|
||||||
.eq(TenRelation::getParentId,item.getUserId()));
|
.eq(TenRelation::getParentId,item.getUserId()).eq(TenRelation::getStatus,1));
|
||||||
item.setCount(count);
|
item.setCount(count);
|
||||||
});
|
});
|
||||||
return new PageUtils(page);
|
return new PageUtils(page);
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
package net.shapelight.modules.ten.service.impl;
|
package net.shapelight.modules.ten.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import com.alibaba.excel.EasyExcelFactory;
|
import com.alibaba.excel.EasyExcelFactory;
|
||||||
import com.alibaba.excel.metadata.Sheet;
|
import com.alibaba.excel.metadata.Sheet;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.arcsoft.face.FaceInfo;
|
||||||
|
import com.arcsoft.face.enums.ExtractType;
|
||||||
|
import com.arcsoft.face.toolkit.ImageFactory;
|
||||||
|
import com.arcsoft.face.toolkit.ImageInfo;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.minio.MinioClient;
|
import io.minio.MinioClient;
|
||||||
import io.minio.PutObjectOptions;
|
import io.minio.PutObjectOptions;
|
||||||
|
@ -21,6 +26,8 @@ import net.shapelight.modules.app.service.AppUserService;
|
||||||
import net.shapelight.modules.app.service.impl.AppUserScopeServiceImpl;
|
import net.shapelight.modules.app.service.impl.AppUserScopeServiceImpl;
|
||||||
import net.shapelight.modules.excel.listener.PersonExcelListener;
|
import net.shapelight.modules.excel.listener.PersonExcelListener;
|
||||||
import net.shapelight.modules.excel.model.PersonModel;
|
import net.shapelight.modules.excel.model.PersonModel;
|
||||||
|
import net.shapelight.modules.face.dto.FaceRecognitionResDTO;
|
||||||
|
import net.shapelight.modules.face.service.FaceEngineService;
|
||||||
import net.shapelight.modules.job.entity.KeysEntity;
|
import net.shapelight.modules.job.entity.KeysEntity;
|
||||||
import net.shapelight.modules.nettyapi.service.ServerApiService;
|
import net.shapelight.modules.nettyapi.service.ServerApiService;
|
||||||
import net.shapelight.modules.sys.entity.SysDictEntity;
|
import net.shapelight.modules.sys.entity.SysDictEntity;
|
||||||
|
@ -106,6 +113,8 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
private String imagBaseUrl;
|
private String imagBaseUrl;
|
||||||
@Value("${global.minio.bucketName}")
|
@Value("${global.minio.bucketName}")
|
||||||
private String bucketName;
|
private String bucketName;
|
||||||
|
@Autowired
|
||||||
|
private FaceEngineService faceEngineService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -253,18 +262,17 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@CacheEvict(value = "TenPerson", allEntries = true)
|
@CacheEvict(value = "TenPerson", allEntries = true)
|
||||||
public int save(TenPersonEntity entity) {
|
public String save(TenPersonEntity entity) {
|
||||||
String userFileUrl = globalValue.getImagesDir() + "/" +
|
String userFileUrl = globalValue.getImagesDir() + "/org/";
|
||||||
entity.getCellId().toString() + "/" +
|
//保存原始图片
|
||||||
entity.getPersonId().toString() + "/";
|
String tempOrgImageFile = entity.getOrgImageTemp();
|
||||||
|
String tempIdFrontImage = entity.getIdFrontImage();
|
||||||
|
String tempIdBackImage = entity.getIdBackImage();
|
||||||
try {
|
try {
|
||||||
//保存原始图片
|
|
||||||
String tempOrgImageFile = entity.getOrgImageTemp();
|
|
||||||
String tempIdFrontImage = entity.getIdFrontImage();
|
|
||||||
String tempIdBackImage = entity.getIdBackImage();
|
|
||||||
if (tempOrgImageFile != null && !tempOrgImageFile.isEmpty()) {
|
if (tempOrgImageFile != null && !tempOrgImageFile.isEmpty()) {
|
||||||
String orgImageFileName = userFileUrl + "o_" + UUIDUtil.uuid() + ".jpg";
|
String orgImageFileName = userFileUrl + "o_" + UUIDUtil.uuid() + ".jpg";
|
||||||
String faceImageFileName = userFileUrl + "s_" + UUIDUtil.uuid() + ".jpg";
|
// String faceImageFileName = userFileUrl + "s_" + UUIDUtil.uuid() + ".jpg";
|
||||||
//MinioClient minioClient = MinioUtil.getMinioClient();
|
//MinioClient minioClient = MinioUtil.getMinioClient();
|
||||||
try {
|
try {
|
||||||
// 调用statObject()来判断对象是否存在。
|
// 调用statObject()来判断对象是否存在。
|
||||||
|
@ -275,47 +283,40 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
//判断人脸照片是否合格
|
//判断人脸照片是否合格
|
||||||
//1.保存到本地
|
//1.保存到本地
|
||||||
InputStream tempInputStream = minioClient.getObject(minioConfig.getBucketName(), tempOrgImageFile);
|
InputStream tempInputStream = minioClient.getObject(minioConfig.getBucketName(), tempOrgImageFile);
|
||||||
String tempPath = globalValue.getStaticLocations() + "/";//+globalValue.getTempDir()+"/";
|
//----------------算法检测----------------------------------------------
|
||||||
String tempOrgFilePath = tempPath + tempOrgImageFile;
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
int index;
|
byte[] buffer = new byte[1024];
|
||||||
byte[] bytes = new byte[1024];
|
int length;
|
||||||
File outFile = new File(tempOrgFilePath);
|
while ((length = tempInputStream.read(buffer)) != -1) {
|
||||||
FileOutputStream downloadFile = new FileOutputStream(outFile);
|
outputStream.write(buffer, 0, length);
|
||||||
while ((index = tempInputStream.read(bytes)) != -1) {
|
|
||||||
downloadFile.write(bytes, 0, index);
|
|
||||||
downloadFile.flush();
|
|
||||||
}
|
}
|
||||||
downloadFile.close();
|
|
||||||
tempInputStream.close();
|
|
||||||
//2.测试上传的文件
|
|
||||||
String tempFaceFileName = UUIDUtil.uuid() + ".jpg";
|
|
||||||
String tempFaceFilePath = tempPath + tempFaceFileName;
|
|
||||||
|
|
||||||
String osName = System.getProperty("os.name");//获取指定键(即os.name)的系统属性,如:Windows 7。
|
byte[] bytes = outputStream.toByteArray();
|
||||||
if (Pattern.matches("Windows.*", osName)) {
|
outputStream.close();
|
||||||
// if (Pattern.matches("Windows.*", osName)) {
|
tempInputStream.close();
|
||||||
int res = PicSDK.getFace(tempOrgFilePath, tempFaceFilePath);
|
//-------------------------------------------------------------------------
|
||||||
if (res != 0) {
|
ImageInfo rgbData = ImageFactory.getRGBData(bytes);
|
||||||
|
List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
|
||||||
|
if (CollectionUtil.isNotEmpty(faceInfoList)) {
|
||||||
|
FaceInfo faceInfo = faceInfoList.get(0);
|
||||||
|
FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
|
||||||
|
faceRecognitionResDTO.setRect(faceInfo.getRect());
|
||||||
|
byte[] featureBytes = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.REGISTER);
|
||||||
|
if (featureBytes != null) {
|
||||||
|
// UserRamCache.UserInfo userInfo = new UserCompareInfo();
|
||||||
|
// userInfo.setFaceId(faceAddReqDTO.getName());
|
||||||
|
// userInfo.setName(faceAddReqDTO.getName());
|
||||||
|
// userInfo.setFaceFeature(feature);
|
||||||
|
// //这边注册到内存缓存中,也可以根据业务,注册到数据库中
|
||||||
|
// UserRamCache.addUser(userInfo);
|
||||||
|
entity.setFeature(Base64.getEncoder().encodeToString(featureBytes));
|
||||||
|
}else{
|
||||||
log.error("图片不合格,未检测到人脸");
|
log.error("图片不合格,未检测到人脸");
|
||||||
return 2;
|
return "图片不合格,未检测到人脸";
|
||||||
}
|
}
|
||||||
//保存底片文件到oss
|
}else{
|
||||||
InputStream inputStream = new FileInputStream(tempFaceFilePath);
|
log.error("图片不合格,未检测到人脸");
|
||||||
PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
|
return "图片不合格,未检测到人脸";
|
||||||
putObjectOptions.setContentType("image/jpeg");
|
|
||||||
minioClient.putObject(
|
|
||||||
minioConfig.getBucketName(), faceImageFileName, inputStream, putObjectOptions);
|
|
||||||
inputStream.close();
|
|
||||||
} else {
|
|
||||||
minioClient.copyObject(
|
|
||||||
minioConfig.getBucketName(),
|
|
||||||
faceImageFileName,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
minioConfig.getBucketName(),
|
|
||||||
tempOrgImageFile,
|
|
||||||
null,
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
//拷贝临时文件正式文件
|
//拷贝临时文件正式文件
|
||||||
minioClient.copyObject(
|
minioClient.copyObject(
|
||||||
|
@ -329,16 +330,15 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
null);
|
null);
|
||||||
|
|
||||||
entity.setOrgImage(orgImageFileName);
|
entity.setOrgImage(orgImageFileName);
|
||||||
entity.setFaceImage(faceImageFileName);
|
entity.setFaceImage(orgImageFileName);
|
||||||
//删除临时文件oss
|
// entity.setFaceImage(faceImageFileName);
|
||||||
minioClient.removeObject(minioConfig.getBucketName(), tempOrgImageFile);
|
|
||||||
//删除本地临时文件
|
//删除本地临时文件
|
||||||
new File(tempFaceFilePath).delete();
|
// new File(tempFaceFilePath).delete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
entity.setOrgImage("");
|
entity.setOrgImage("");
|
||||||
entity.setFaceImage("");
|
entity.setFaceImage("");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return 10;
|
return "文件不存在";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
appUserService.updateById(appUser);
|
appUserService.updateById(appUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送设备通知
|
/*//发送设备通知
|
||||||
List<TenDeviceVo> devList = tenDeviceService.findByCellId(entity.getCellId());
|
List<TenDeviceVo> devList = tenDeviceService.findByCellId(entity.getCellId());
|
||||||
//状态是0正常,发送推送
|
//状态是0正常,发送推送
|
||||||
if (entity.getStatus().intValue() == Constant.PESON_SUATUS_NOMOR) {
|
if (entity.getStatus().intValue() == Constant.PESON_SUATUS_NOMOR) {
|
||||||
|
@ -498,41 +498,52 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
list.add(vo);
|
list.add(vo);
|
||||||
serverApiService.personOperation(dev.getSn(), list);
|
serverApiService.personOperation(dev.getSn(), list);
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
if(entity.getPersonType()!=Constant.PERSON_TYPE_GUEST) {
|
||||||
|
List<SysDictEntity> dictList = sysDictService.queryByType("optype");
|
||||||
|
Map<String,Object> optypeMap = new HashMap<>();
|
||||||
|
dictList.forEach(dict -> {
|
||||||
|
optypeMap.put(dict.getValue(),dict.getCode());
|
||||||
|
});
|
||||||
|
Map<String,Object> personParams = new HashMap<>();
|
||||||
|
personParams.put("operation","editUserData");
|
||||||
|
personParams.put("accountNumber",globalValue.accountNumber);
|
||||||
|
personParams.put("passKey", KeysEntity.passKey);
|
||||||
|
personParams.put("empowerText",KeysEntity.empowerText);
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
Map<String,Object> student = new HashMap<>();
|
||||||
|
student.put("objectUuid",String.valueOf(entity.getPersonId()));
|
||||||
|
student.put("userCode",entity.getRyid());
|
||||||
|
student.put("userName",entity.getName());
|
||||||
|
student.put("userType",optypeMap.get(entity.getLabelName()));
|
||||||
|
student.put("studentType","0"+entity.getLabelId());
|
||||||
|
student.put("gender",entity.getGender()==0?"WOMAN":"MAN");
|
||||||
|
student.put("cardNumber","");
|
||||||
|
student.put("idCard",entity.getIdCard());
|
||||||
|
student.put("fileUrl",imagBaseUrl+"/"+bucketName+"/"+entity.getOrgImage());
|
||||||
|
student.put("fileName",entity.getOrgImage().substring(entity.getOrgImage().lastIndexOf("/")));
|
||||||
|
jsonArray.add(student);
|
||||||
|
personParams.put("dataInfo",jsonArray);
|
||||||
|
JSONObject jsonObject = opFeignClient.submitData(personParams);
|
||||||
|
if(!jsonObject.getString("shrgStatus").equals("S")) {
|
||||||
|
log.error(jsonObject.toJSONString());
|
||||||
|
return jsonObject.getString("shrgMsg");
|
||||||
|
}
|
||||||
|
if(!jsonObject.getJSONArray("errInfo").isEmpty()) {
|
||||||
|
log.error(jsonObject.toJSONString());
|
||||||
|
return jsonObject.getJSONArray("errInfo").toJSONString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
List<SysDictEntity> dictList = sysDictService.queryByType("optype");
|
|
||||||
Map<String,Object> optypeMap = new HashMap<>();
|
|
||||||
dictList.forEach(dict -> {
|
|
||||||
optypeMap.put(dict.getValue(),dict.getCode());
|
|
||||||
});
|
|
||||||
Map<String,Object> personParams = new HashMap<>();
|
|
||||||
personParams.put("operation","editUserData");
|
|
||||||
personParams.put("accountNumber",globalValue.accountNumber);
|
|
||||||
personParams.put("passKey", KeysEntity.passKey);
|
|
||||||
personParams.put("empowerText",KeysEntity.empowerText);
|
|
||||||
JSONArray jsonArray = new JSONArray();
|
|
||||||
Map<String,Object> student = new HashMap<>();
|
|
||||||
student.put("objectUuid",String.valueOf(entity.getPersonId()));
|
|
||||||
student.put("userCode",entity.getRyid());
|
|
||||||
student.put("userName",entity.getName());
|
|
||||||
student.put("userType",optypeMap.get(entity.getLabelName()));
|
|
||||||
student.put("studentType","0"+entity.getLabelId());
|
|
||||||
student.put("gender",entity.getGender()==0?"WOMAN":"MAN");
|
|
||||||
student.put("cardNumber","");
|
|
||||||
student.put("idCard",entity.getIdCard());
|
|
||||||
student.put("fileUrl",imagBaseUrl+"/"+bucketName+"/"+entity.getOrgImage());
|
|
||||||
student.put("fileName",entity.getOrgImage().substring(entity.getOrgImage().lastIndexOf("/")));
|
|
||||||
jsonArray.add(student);
|
|
||||||
personParams.put("dataInfo",jsonArray);
|
|
||||||
JSONObject jsonObject = opFeignClient.submitData(personParams);
|
|
||||||
if(!jsonObject.getString("shrgStatus").equals("S")) {
|
|
||||||
log.error(jsonObject.toJSONString());
|
|
||||||
}
|
|
||||||
if(!jsonObject.getJSONArray("errInfo").isEmpty()) {
|
|
||||||
log.error(jsonObject.toJSONString());
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 1;
|
//删除临时文件oss
|
||||||
|
try {
|
||||||
|
minioClient.removeObject(minioConfig.getBucketName(), tempOrgImageFile);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "删除失败";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2527,4 +2538,9 @@ public class TenPersonServiceImpl implements TenPersonService {
|
||||||
IPage<TenPersonEntity> page = tenPersonDao.getByPersonIds(pageParam, list,cellId);
|
IPage<TenPersonEntity> page = tenPersonDao.getByPersonIds(pageParam, list,cellId);
|
||||||
return new PageUtils(page);
|
return new PageUtils(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TenPersonEntity> listPage(int start, int count, String cellId) {
|
||||||
|
return tenPersonDao.listPage(start, count, cellId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,8 +482,27 @@ public class TenRecordServiceImpl implements TenRecordService {
|
||||||
pageParam.setCurrent(Long.parseLong((String) params.get("page")));
|
pageParam.setCurrent(Long.parseLong((String) params.get("page")));
|
||||||
pageParam.setSize(Long.parseLong((String) params.get("limit")));
|
pageParam.setSize(Long.parseLong((String) params.get("limit")));
|
||||||
List<Long> list = (List<Long>) params.get("personIds");
|
List<Long> list = (List<Long>) params.get("personIds");
|
||||||
Long cellId = Long.parseLong(params.get("cellId").toString());
|
Long cellId = Long.parseLong(params.get("tenantId").toString());
|
||||||
IPage page = tenRecordDao.getByPersonIds(pageParam,params);
|
int during = Integer.parseInt((String)params.get("during"));
|
||||||
|
String recordTimeStart = null;
|
||||||
|
String recordTimeEnd = null;
|
||||||
|
if(during == 0){ //当天
|
||||||
|
recordTimeStart = MyDateUtils.getCurrentDayStartTime();
|
||||||
|
recordTimeEnd = MyDateUtils.getCurrentDayEndTime();
|
||||||
|
}else if(during == 1){ //本周
|
||||||
|
recordTimeStart = MyDateUtils.getCurrentWeekStartTime();
|
||||||
|
recordTimeEnd = MyDateUtils.getCurrentWeekEndTime();
|
||||||
|
}else if(during == 2){ //本月
|
||||||
|
recordTimeStart = MyDateUtils.getCurrentMonthStartTime();
|
||||||
|
recordTimeEnd = MyDateUtils.getCurrentMonthEndTime();
|
||||||
|
}
|
||||||
|
params.put("recordTimeStart",recordTimeStart);
|
||||||
|
params.put("recordTimeEnd",recordTimeEnd);
|
||||||
|
IPage<TenRecordEntity> page = tenRecordDao.getByPersonIds(pageParam,params);
|
||||||
|
page.getRecords().forEach(item-> {
|
||||||
|
TenPersonEntity person = tenPersonService.getById(item.getPersonId(),item.getCellId());
|
||||||
|
item.setPerson(person);
|
||||||
|
});
|
||||||
return new PageUtils(page);
|
return new PageUtils(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,19 @@ shapelight:
|
||||||
# token有效时长,180天,单位秒
|
# token有效时长,180天,单位秒
|
||||||
#expire: 15552000
|
#expire: 15552000
|
||||||
header: token
|
header: token
|
||||||
|
# sdk配置---------------------------------------
|
||||||
|
config:
|
||||||
|
arcface-sdk:
|
||||||
|
version: 4.1
|
||||||
|
app-id: SUQLGn78W5o7StEEbm6WTTfaMgAxSsN8HwJziApVyNN
|
||||||
|
sdk-key: 7dJ9RqEhc3mPCatuUceKjgYwRR6QtyMsxLUiL7JYAkrt
|
||||||
|
active-key: 82K1-11TT-K136-FFVW
|
||||||
|
active-file:
|
||||||
|
detect-pool-size: 16
|
||||||
|
compare-pool-size: 16
|
||||||
|
rec-face-thd: 0.8
|
||||||
|
rec-id-thd: 0.5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#mybatis
|
#mybatis
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1333,5 +1333,12 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="listPage" resultType="net.shapelight.modules.ten.entity.TenPersonEntity">
|
||||||
|
select a.* from ten_person a INNER JOIN (SELECT member_id FROM ten_person WHERE delete_flag = 0 and `status` = 0
|
||||||
|
<if test="cellId != null and cellId!=''">
|
||||||
|
and cell_id = #{cellId}
|
||||||
|
</if> ORDER BY member_id LIMIT #{start},#{count}) b on a.member_id = b.member_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -639,14 +639,22 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getByPersonIds" resultMap="tenRecordMap">
|
<select id="getByPersonIds" resultMap="tenRecordMap">
|
||||||
select * from
|
select * from ten_record_${params.tenantId} r
|
||||||
(select * from ten_record_${cellId}
|
<if test="params.name != null and params.name!=''">
|
||||||
where delete_flag = 0 and person_id in
|
left join ten_person t on r.person_id = t.person_id
|
||||||
|
</if>
|
||||||
|
where 1 = 1 and r.person_id in
|
||||||
<foreach item="params.personId" collection="params.personIds" open="(" separator="," close=")">
|
<foreach item="params.personId" collection="params.personIds" open="(" separator="," close=")">
|
||||||
#{personId}
|
#{params.personId}
|
||||||
</foreach>) a where 1=1
|
</foreach>
|
||||||
<if test="params.name != null and params.name != ''">
|
<if test="params.name != null and params.name != ''">
|
||||||
and a.name like CONCAT('%', '${params.name}', '%')
|
and t.`name` like CONCAT('%', '${params.name}', '%')
|
||||||
|
</if>
|
||||||
|
<if test="params.recordTimeStart != null and params.recordTimeStart!=''">
|
||||||
|
and `record_time` >= #{params.recordTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="params.recordTimeEnd != null and params.recordTimeEnd!=''">
|
||||||
|
and `record_time` < #{params.recordTimeEnd}
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
|
|
Loading…
Reference in New Issue