feat(face): 增加自定义人脸匹配次数限制与记录功能

- 新增常量 FACE_CUSTOM_MATCH_COUNT_PFX 用于记录自定义匹配次数
- 在人脸识别逻辑中增加对自定义匹配次数的读取与限制判断
- 实现 recordCustomMatchCount 方法用于记录自定义匹配调用次数
- 优化原有识别次数获取逻辑,避免重复代码
- 增加 Redis 过期时间设置,确保计数数据自动清理
This commit is contained in:
2025-10-23 18:17:07 +08:00
parent ea4adcdeb7
commit 3f8b911e6f
2 changed files with 57 additions and 10 deletions

View File

@@ -5,5 +5,6 @@ public class FaceConstant {
public static final String USER_FACE_DB_NAME="userFace"; public static final String USER_FACE_DB_NAME="userFace";
public static final String FACE_USER_URL_PFX="face:user:url:"; public static final String FACE_USER_URL_PFX="face:user:url:";
public static final String FACE_RECOGNITION_COUNT_PFX="face:recognition:count:"; public static final String FACE_RECOGNITION_COUNT_PFX="face:recognition:count:";
public static final String FACE_CUSTOM_MATCH_COUNT_PFX="face:custom:match:count:";
public static final String FACE_LOW_THRESHOLD_PFX="face:low:threshold:"; public static final String FACE_LOW_THRESHOLD_PFX="face:low:threshold:";
} }

View File

@@ -83,6 +83,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static com.ycwl.basic.constant.FaceConstant.FACE_CUSTOM_MATCH_COUNT_PFX;
import static com.ycwl.basic.constant.FaceConstant.FACE_LOW_THRESHOLD_PFX; import static com.ycwl.basic.constant.FaceConstant.FACE_LOW_THRESHOLD_PFX;
import static com.ycwl.basic.constant.FaceConstant.FACE_RECOGNITION_COUNT_PFX; import static com.ycwl.basic.constant.FaceConstant.FACE_RECOGNITION_COUNT_PFX;
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME; import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
@@ -987,6 +988,36 @@ public class FaceServiceImpl implements FaceService {
return false; return false;
} }
ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(face.getScenicId()); ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(face.getScenicId());
String recognitionKey = FACE_RECOGNITION_COUNT_PFX + faceId;
String recognitionCountStr = redisTemplate.opsForValue().get(recognitionKey);
long recognitionCount = 0L;
if (recognitionCountStr != null) {
try {
recognitionCount = Long.parseLong(recognitionCountStr);
} catch (NumberFormatException e) {
log.warn("识别次数解析失败,faceId={}, count={}", faceId, recognitionCountStr);
}
}
String customMatchKey = FACE_CUSTOM_MATCH_COUNT_PFX + faceId;
String customMatchCountStr = redisTemplate.opsForValue().get(customMatchKey);
long customMatchCount = 0L;
if (customMatchCountStr != null) {
try {
customMatchCount = Long.parseLong(customMatchCountStr);
} catch (NumberFormatException e) {
log.warn("自定义匹配次数解析失败,faceId={}, count={}", faceId, customMatchCountStr);
}
}
Integer faceSelectMaxCount = scenicConfig.getInteger("face_select_max_count");
if (faceSelectMaxCount != null && faceSelectMaxCount > 0 && customMatchCount > faceSelectMaxCount) {
log.debug("自定义人脸匹配次数超过限制:faceId={}, customMatchCount={}, limit={}",
faceId, customMatchCount, faceSelectMaxCount);
return false;
}
Integer maxTourTime = scenicConfig.getInteger("tour_time"); Integer maxTourTime = scenicConfig.getInteger("tour_time");
Integer minTourTime = scenicConfig.getInteger("tour_min_time"); Integer minTourTime = scenicConfig.getInteger("tour_min_time");
boolean tourMatch = false; boolean tourMatch = false;
@@ -1015,16 +1046,6 @@ public class FaceServiceImpl implements FaceService {
} }
} }
} }
String countKey = FACE_RECOGNITION_COUNT_PFX + faceId;
String countStr = redisTemplate.opsForValue().get(countKey);
long recognitionCount = 0L;
if (countStr != null) {
try {
recognitionCount = Long.parseLong(countStr);
} catch (NumberFormatException e) {
log.warn("识别次数解析失败,faceId={}, count={}", faceId, countStr);
}
}
int ruleMatched = 0; int ruleMatched = 0;
if (recognitionCount > 1) { if (recognitionCount > 1) {
ruleMatched++; ruleMatched++;
@@ -1086,6 +1107,9 @@ public class FaceServiceImpl implements FaceService {
} }
log.debug("开始自定义人脸匹配:faceId={}, faceSampleIds={}", faceId, faceSampleIds); log.debug("开始自定义人脸匹配:faceId={}, faceSampleIds={}", faceId, faceSampleIds);
// 记录自定义匹配调用次数,便于监控调用频率
recordCustomMatchCount(faceId);
try { try {
// 1. 获取基础数据 // 1. 获取基础数据
@@ -1234,6 +1258,28 @@ public class FaceServiceImpl implements FaceService {
return mergedResult; return mergedResult;
} }
/**
* 记录自定义人脸匹配次数到Redis
*
* @param faceId 人脸ID
*/
private void recordCustomMatchCount(Long faceId) {
if (faceId == null) {
return;
}
try {
String redisKey = FACE_CUSTOM_MATCH_COUNT_PFX + faceId;
Long count = redisTemplate.opsForValue().increment(redisKey);
redisTemplate.expire(redisKey, 2, TimeUnit.DAYS);
log.debug("自定义人脸匹配计数更新:faceId={}, count={}", faceId, count);
} catch (Exception e) {
log.error("记录自定义人脸匹配次数失败:faceId={}", faceId, e);
}
}
/** /**
* 记录人脸识别次数到Redis * 记录人脸识别次数到Redis
* *