人脸识别与大模型问答
This commit is contained in:
parent
aa74d0d128
commit
fb47f5554c
|
|
@ -18,7 +18,7 @@ public class FaceResultVo implements Serializable {
|
||||||
/**
|
/**
|
||||||
* 人脸库表id
|
* 人脸库表id
|
||||||
*/
|
*/
|
||||||
private String faceId;
|
private Long faceId;
|
||||||
/**
|
/**
|
||||||
* 服务id
|
* 服务id
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ package com.bonus.ai.service;
|
||||||
import com.bonus.ai.domain.vo.FaceResultVo;
|
import com.bonus.ai.domain.vo.FaceResultVo;
|
||||||
import com.bonus.common.core.web.domain.AjaxResult;
|
import com.bonus.common.core.web.domain.AjaxResult;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author bonus
|
* @author bonus
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ public class AiFaceRecognizeResultServiceImpl implements AiFaceRecognizeResultSe
|
||||||
public AjaxResult selectAllAiFaceRecognizeResults() {
|
public AjaxResult selectAllAiFaceRecognizeResults() {
|
||||||
try {
|
try {
|
||||||
List<FaceResultVo> faceResultVos = aiFaceRecognizeResultMapper.selectAllAiFaceRecognizeResults();
|
List<FaceResultVo> faceResultVos = aiFaceRecognizeResultMapper.selectAllAiFaceRecognizeResults();
|
||||||
return ObjectUtils.isNotEmpty(faceResultVos) ? AjaxResult.success(faceResultVos) : AjaxResult.error();
|
return AjaxResult.success(faceResultVos);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return AjaxResult.error();
|
return AjaxResult.error();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
package com.bonus.ai.service.impl;
|
package com.bonus.ai.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.unit.DataUnit;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.bonus.ai.domain.vo.FaceResultVo;
|
||||||
import com.bonus.ai.domain.vo.FaceVo;
|
import com.bonus.ai.domain.vo.FaceVo;
|
||||||
|
import com.bonus.ai.mapper.AiFaceRecognizeResultMapper;
|
||||||
import com.bonus.ai.mapper.FaceMapper;
|
import com.bonus.ai.mapper.FaceMapper;
|
||||||
import com.bonus.ai.service.FaceService;
|
import com.bonus.ai.service.FaceService;
|
||||||
import com.bonus.ai.utils.FaceUtils;
|
import com.bonus.ai.utils.FaceUtils;
|
||||||
import com.bonus.common.core.domain.R;
|
import com.bonus.common.core.domain.R;
|
||||||
|
import com.bonus.common.core.utils.DateUtils;
|
||||||
import com.bonus.common.core.web.domain.AjaxResult;
|
import com.bonus.common.core.web.domain.AjaxResult;
|
||||||
import com.bonus.common.security.utils.SecurityUtils;
|
import com.bonus.common.security.utils.SecurityUtils;
|
||||||
import com.bonus.system.api.RemoteFileService;
|
import com.bonus.system.api.RemoteFileService;
|
||||||
|
|
@ -17,16 +21,8 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.File;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author bonus
|
|
||||||
* 人脸识别服务层
|
|
||||||
*/
|
|
||||||
@Service
|
@Service
|
||||||
public class FaceServiceImpl implements FaceService {
|
public class FaceServiceImpl implements FaceService {
|
||||||
|
|
||||||
|
|
@ -35,20 +31,18 @@ public class FaceServiceImpl implements FaceService {
|
||||||
@Resource
|
@Resource
|
||||||
private RemoteFileService remoteFileService;
|
private RemoteFileService remoteFileService;
|
||||||
|
|
||||||
/**
|
@Resource
|
||||||
* 查询全部人脸信息
|
private AiFaceRecognizeResultMapper aiFaceRecognizeResultMapper;
|
||||||
*/
|
|
||||||
|
private static final Set<String> VALID_IMAGE_TYPES = new HashSet<>(Arrays.asList("image/jpeg", "image/png"));
|
||||||
|
private static final String BASE64_PREFIX = "data:";
|
||||||
|
private static final String BASE64_SUFFIX = ";base64,";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult getList() {
|
public AjaxResult getList() {
|
||||||
return AjaxResult.success(faceMapper.getList());
|
return AjaxResult.success(faceMapper.getList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 插入人脸信息
|
|
||||||
*
|
|
||||||
* @param face 人脸信息对象
|
|
||||||
* @return 受影响的行数
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult insertFace(MultipartFile file, FaceVo face) {
|
public AjaxResult insertFace(MultipartFile file, FaceVo face) {
|
||||||
if (isFileOrFaceInvalid(file, face)) {
|
if (isFileOrFaceInvalid(file, face)) {
|
||||||
|
|
@ -57,159 +51,153 @@ public class FaceServiceImpl implements FaceService {
|
||||||
try {
|
try {
|
||||||
String base64WithMimeType = getBase64WithMimeType(file);
|
String base64WithMimeType = getBase64WithMimeType(file);
|
||||||
String response = FaceUtils.updateDb(base64WithMimeType, "add", face.getIdCardNumber());
|
String response = FaceUtils.updateDb(base64WithMimeType, "add", face.getIdCardNumber());
|
||||||
return handleInsertResponse(file, response, face, base64WithMimeType);
|
return handleInsertResponse(file, response, face);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return AjaxResult.error("插入人脸信息失败");
|
return AjaxResult.error("插入人脸信息失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 人脸识别
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult recognition(MultipartFile file) {
|
public AjaxResult recognition(MultipartFile file) {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
if (ObjectUtils.isEmpty(file)) {
|
if (ObjectUtils.isEmpty(file)) {
|
||||||
return AjaxResult.error("文件不能为空, 请选择文件");
|
return AjaxResult.error("文件不能为空, 请选择文件");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String base64WithMimeType = getBase64WithMimeType(file);
|
String base64WithMimeType = getBase64WithMimeType(file);
|
||||||
String response = FaceUtils.faceRecognition(base64WithMimeType);
|
String response = FaceUtils.faceRecognition(base64WithMimeType);
|
||||||
return handleRecognitionResponse(response);
|
return handleRecognitionResponse(response, startTime);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return AjaxResult.error("人脸识别失败");
|
return AjaxResult.error("人脸识别失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 识别结果统计
|
|
||||||
*
|
|
||||||
* @return 结果
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult resultStatistics() {
|
public AjaxResult resultStatistics() {
|
||||||
return AjaxResult.success(faceMapper.resultStatistics());
|
return AjaxResult.success(faceMapper.resultStatistics());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断文件的 MIME 类型是否为图片类型
|
|
||||||
*/
|
|
||||||
private boolean isImageMimeType(String mimeType) {
|
private boolean isImageMimeType(String mimeType) {
|
||||||
Set<String> validMimeTypes = new HashSet<>();
|
return VALID_IMAGE_TYPES.contains(mimeType);
|
||||||
validMimeTypes.add("image/jpeg");
|
|
||||||
validMimeTypes.add("image/png");
|
|
||||||
return mimeType != null && validMimeTypes.contains(mimeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查文件和人员信息是否为空
|
|
||||||
*/
|
|
||||||
private boolean isFileOrFaceInvalid(MultipartFile file, FaceVo face) {
|
private boolean isFileOrFaceInvalid(MultipartFile file, FaceVo face) {
|
||||||
return ObjectUtils.isEmpty(file) ||
|
return ObjectUtils.isEmpty(file) ||
|
||||||
ObjectUtils.isEmpty(face.getName()) ||
|
ObjectUtils.isEmpty(face.getName()) ||
|
||||||
ObjectUtils.isEmpty(face.getIdCardNumber());
|
ObjectUtils.isEmpty(face.getIdCardNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取Base64编码的文件内容,并添加MIME类型
|
|
||||||
*/
|
|
||||||
private String getBase64WithMimeType(MultipartFile file) throws Exception {
|
private String getBase64WithMimeType(MultipartFile file) throws Exception {
|
||||||
String mimeType = file.getContentType();
|
String mimeType = file.getContentType();
|
||||||
if (!isImageMimeType(mimeType)) {
|
if (!isImageMimeType(mimeType)) {
|
||||||
throw new IllegalArgumentException("文件类型不支持,请上传图片文件");
|
throw new IllegalArgumentException("文件类型不支持,请上传图片文件");
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] fileBytes = file.getBytes();
|
byte[] fileBytes = file.getBytes();
|
||||||
String base64String = Base64.getEncoder().encodeToString(fileBytes);
|
String base64String = Base64.getEncoder().encodeToString(fileBytes);
|
||||||
return "data:" + mimeType + ";base64," + base64String;
|
return BASE64_PREFIX + mimeType + BASE64_SUFFIX + base64String;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private AjaxResult handleInsertResponse(MultipartFile file, String response, FaceVo face) {
|
||||||
* 处理插入人脸信息的响应
|
|
||||||
*/
|
|
||||||
private AjaxResult handleInsertResponse(MultipartFile file, String response, FaceVo face, String base64WithMimeType) {
|
|
||||||
if (response == null) return AjaxResult.error();
|
|
||||||
JSONObject jsonObject = JSON.parseObject(response);
|
|
||||||
String code = jsonObject.getString("code");
|
|
||||||
switch (code) {
|
|
||||||
case "30002":
|
|
||||||
face.setCreateTime(new Date());
|
|
||||||
face.setCreateBy(SecurityUtils.getUsername());
|
|
||||||
face.setUpdateBy(SecurityUtils.getUsername());
|
|
||||||
face.setUpdateTime(new Date());
|
|
||||||
try {
|
|
||||||
R<SysFile> upload = remoteFileService.upload(file);
|
|
||||||
if (upload.getCode() == 200) {
|
|
||||||
face.setFaceAddress(upload.getData().getUrl().replaceFirst("http://[^/]+", ""));
|
|
||||||
return faceMapper.insertFace(face) > 0 ? AjaxResult.success() : AjaxResult.error();
|
|
||||||
} else {
|
|
||||||
return AjaxResult.error();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
return AjaxResult.error();
|
|
||||||
}
|
|
||||||
case "30006":
|
|
||||||
return AjaxResult.error("文件类型不支持");
|
|
||||||
case "30007":
|
|
||||||
return AjaxResult.error("不支持的操作类型");
|
|
||||||
case "30008":
|
|
||||||
return AjaxResult.error("存在多张人脸");
|
|
||||||
case "30009":
|
|
||||||
return AjaxResult.error("光照条件差");
|
|
||||||
case "30016":
|
|
||||||
return AjaxResult.error("人脸图片不清晰");
|
|
||||||
case "30010":
|
|
||||||
case "30011":
|
|
||||||
return AjaxResult.error("人脸不全");
|
|
||||||
case "30019":
|
|
||||||
return AjaxResult.error("人员信息已存在");
|
|
||||||
case "30018":
|
|
||||||
return AjaxResult.error("未检测到人脸");
|
|
||||||
default:
|
|
||||||
return AjaxResult.error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理人脸识别的响应
|
|
||||||
*/
|
|
||||||
private AjaxResult handleRecognitionResponse(String response) {
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
return AjaxResult.error();
|
return AjaxResult.error();
|
||||||
}
|
}
|
||||||
JSONObject jsonObject = JSON.parseObject(response);
|
JSONObject jsonObject = JSON.parseObject(response);
|
||||||
String code = jsonObject.getString("code");
|
String code = jsonObject.getString("code");
|
||||||
switch (code) {
|
|
||||||
case "30000":
|
if ("30002".equals(code)) {
|
||||||
JSONArray dataArray = jsonObject.getJSONArray("data");
|
face.setCreateTime(new Date());
|
||||||
String idCardNumber = dataArray.getString(0);
|
face.setCreateBy(SecurityUtils.getUsername());
|
||||||
List<FaceVo> faceByIdCardNumber = faceMapper.getFaceByIdCardNumber(idCardNumber);
|
face.setUpdateBy(SecurityUtils.getUsername());
|
||||||
return faceByIdCardNumber != null && !faceByIdCardNumber.isEmpty()
|
face.setUpdateTime(new Date());
|
||||||
? AjaxResult.success(faceByIdCardNumber.get(0))
|
|
||||||
: AjaxResult.error("人员不存在");
|
try {
|
||||||
case "30001":
|
return handleFileUpload(file, face);
|
||||||
return AjaxResult.error("人员不存在");
|
} catch (Exception e) {
|
||||||
case "30006":
|
|
||||||
return AjaxResult.error("文件类型不支持");
|
|
||||||
case "30007":
|
|
||||||
return AjaxResult.error("不支持的操作类型");
|
|
||||||
case "30008":
|
|
||||||
return AjaxResult.error("存在多张人脸");
|
|
||||||
case "30009":
|
|
||||||
return AjaxResult.error("光照条件差");
|
|
||||||
case "30010":
|
|
||||||
case "30011":
|
|
||||||
return AjaxResult.error("人脸不全");
|
|
||||||
case "30019":
|
|
||||||
return AjaxResult.error("人员信息已存在");
|
|
||||||
case "30018":
|
|
||||||
return AjaxResult.error("未检测到人脸");
|
|
||||||
default:
|
|
||||||
return AjaxResult.error();
|
return AjaxResult.error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return handleCommonErrors(code, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AjaxResult handleFileUpload(MultipartFile file, FaceVo face) throws Exception {
|
||||||
|
R<SysFile> upload = remoteFileService.upload(file);
|
||||||
|
if (upload.getCode() == 200) {
|
||||||
|
face.setFaceAddress(upload.getData().getUrl().replaceFirst("http://[^/]+", ""));
|
||||||
|
return faceMapper.insertFace(face) > 0 ? AjaxResult.success() : AjaxResult.error();
|
||||||
|
}
|
||||||
|
return AjaxResult.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AjaxResult handleCommonErrors(String code, FaceResultVo faceResultVo, long startTime) {
|
||||||
|
Map<String, String> errorMessages = new HashMap<>();
|
||||||
|
errorMessages.put("30006", "文件类型不支持");
|
||||||
|
errorMessages.put("30007", "不支持的操作类型");
|
||||||
|
errorMessages.put("30008", "存在多张人脸");
|
||||||
|
errorMessages.put("30009", "光照条件差");
|
||||||
|
errorMessages.put("30016", "人脸图片不清晰");
|
||||||
|
errorMessages.put("30010", "人脸不全");
|
||||||
|
errorMessages.put("30011", "人脸不全");
|
||||||
|
errorMessages.put("30019", "人员信息已存在");
|
||||||
|
errorMessages.put("30018", "未检测到人脸");
|
||||||
|
if (ObjectUtils.isEmpty(faceResultVo)) {
|
||||||
|
faceResultVo.setResultStatus("1");
|
||||||
|
faceResultVo.setFailureReason(errorMessages.get(code));
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long elapsedTime = endTime - startTime;
|
||||||
|
faceResultVo.setResponseLong(String.valueOf(elapsedTime));
|
||||||
|
aiFaceRecognizeResultMapper.insertAiFaceRecognizeResult(faceResultVo);
|
||||||
|
}
|
||||||
|
return errorMessages.containsKey(code)
|
||||||
|
? AjaxResult.error(errorMessages.get(code))
|
||||||
|
: AjaxResult.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AjaxResult handleRecognitionResponse(String response, long startTime) {
|
||||||
|
if (response == null) {
|
||||||
|
return AjaxResult.error();
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = JSON.parseObject(response);
|
||||||
|
String code = jsonObject.getString("code");
|
||||||
|
FaceResultVo faceResultVo = buildFaceResultVo();
|
||||||
|
if ("30000".equals(code)) {
|
||||||
|
return handleRecognitionSuccess(jsonObject, faceResultVo, startTime);
|
||||||
|
}
|
||||||
|
return handleCommonErrors(code, faceResultVo, startTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FaceResultVo buildFaceResultVo() {
|
||||||
|
FaceResultVo faceResultVo = new FaceResultVo();
|
||||||
|
faceResultVo.setInvokeIp("192.168.0.14");
|
||||||
|
faceResultVo.setServiceId("4");
|
||||||
|
faceResultVo.setResultType("0");
|
||||||
|
faceResultVo.setDelFlag("0");
|
||||||
|
faceResultVo.setUpdateBy(SecurityUtils.getUsername());
|
||||||
|
faceResultVo.setUpdateTime(DateUtils.getTime());
|
||||||
|
faceResultVo.setRecognizeTime(DateUtils.getTime());
|
||||||
|
return faceResultVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AjaxResult handleRecognitionSuccess(JSONObject jsonObject, FaceResultVo faceResultVo, long startTime) {
|
||||||
|
JSONArray dataArray = jsonObject.getJSONArray("data");
|
||||||
|
String idCardNumber = dataArray.getString(0);
|
||||||
|
List<FaceVo> faceByIdCardNumber = faceMapper.getFaceByIdCardNumber(idCardNumber);
|
||||||
|
if (faceByIdCardNumber != null && !faceByIdCardNumber.isEmpty()) {
|
||||||
|
faceResultVo.setFaceId(faceByIdCardNumber.get(0).getFaceId());
|
||||||
|
faceResultVo.setFaceAddress(faceByIdCardNumber.get(0).getFaceAddress());
|
||||||
|
faceResultVo.setResultStatus("0");
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long elapsedTime = endTime - startTime;
|
||||||
|
faceResultVo.setResponseLong(String.valueOf(elapsedTime));
|
||||||
|
aiFaceRecognizeResultMapper.insertAiFaceRecognizeResult(faceResultVo);
|
||||||
|
return AjaxResult.success(faceByIdCardNumber.get(0));
|
||||||
|
}
|
||||||
|
faceResultVo.setResultStatus("1");
|
||||||
|
faceResultVo.setFailureReason("人员不存在");
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
long elapsedTime = endTime - startTime;
|
||||||
|
faceResultVo.setResponseLong(String.valueOf(elapsedTime));
|
||||||
|
aiFaceRecognizeResultMapper.insertAiFaceRecognizeResult(faceResultVo);
|
||||||
|
return AjaxResult.error("人员不存在");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
result_status = #{resultStatus},
|
result_status = #{resultStatus},
|
||||||
failure_reason = #{failureReason}
|
failure_reason = #{failureReason}
|
||||||
WHERE result_id = #{resultId}
|
WHERE result_id = #{resultId}
|
||||||
|
AND del_flag = '0'
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<!-- 根据主键ID查询记录 -->
|
<!-- 根据主键ID查询记录 -->
|
||||||
|
|
@ -57,6 +58,7 @@
|
||||||
failure_reason AS failureReason
|
failure_reason AS failureReason
|
||||||
FROM ai_facerecognize_result
|
FROM ai_facerecognize_result
|
||||||
WHERE result_id = #{resultId}
|
WHERE result_id = #{resultId}
|
||||||
|
AND del_flag = '0'
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 查询所有记录 -->
|
<!-- 查询所有记录 -->
|
||||||
|
|
@ -76,6 +78,7 @@
|
||||||
result_status AS resultStatus,
|
result_status AS resultStatus,
|
||||||
failure_reason AS failureReason
|
failure_reason AS failureReason
|
||||||
FROM ai_facerecognize_result
|
FROM ai_facerecognize_result
|
||||||
|
WHERE del_flag = '0'
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue