feat(ai-cam): 增强AI摄像头人脸检测逻辑

- 引入时间范围限制配置,支持按分钟设置检测窗口
- 创建DetectResult内部类,记录人脸检测的分数和时间信息
- 优化照片筛选逻辑,先按分数排序再应用时间范围过滤
- 更新设备类型名称,将"微单"改为"AI微单"
- 增强日志记录,提供更详细的调试信息
This commit is contained in:
2025-12-05 20:03:54 +08:00
parent 125fadd6c5
commit 66775ea48b
2 changed files with 73 additions and 7 deletions

View File

@@ -81,8 +81,30 @@ public class AppAiCamServiceImpl implements AppAiCamService {
} }
} }
// 收集该设备符合阈值的faceSampleId // 获取该设备的时间范围限制(分钟)
List<Long> deviceFaceSampleIds = new ArrayList<>(); Integer timeRangeMin = null;
if (configManager != null) {
Integer range = configManager.getInteger("ai_cam_time_range_min");
if (range != null && range > 0) {
timeRangeMin = range;
log.debug("设备{}使用配置的时间范围: {}分钟", deviceId, timeRangeMin);
}
}
// 收集该设备符合阈值的faceSampleId,同时记录分数和时间信息用于后续过滤
class DetectResult {
Long faceSampleId;
Float score;
Date detectTime;
DetectResult(Long faceSampleId, Float score, Date detectTime) {
this.faceSampleId = faceSampleId;
this.score = score;
this.detectTime = detectTime;
}
}
List<DetectResult> detectResults = new ArrayList<>();
for (FaceDetectLogAiCamEntity detectLog : deviceLogs) { for (FaceDetectLogAiCamEntity detectLog : deviceLogs) {
if (detectLog.getMatchRawResult() == null) { if (detectLog.getMatchRawResult() == null) {
continue; continue;
@@ -95,7 +117,11 @@ public class AppAiCamServiceImpl implements AppAiCamService {
if (item.getScore() != null && item.getScore() >= scoreThreshold && item.getExtData() != null) { if (item.getScore() != null && item.getScore() >= scoreThreshold && item.getExtData() != null) {
try { try {
Long faceSampleId = Long.parseLong(item.getExtData()); Long faceSampleId = Long.parseLong(item.getExtData());
deviceFaceSampleIds.add(faceSampleId); detectResults.add(new DetectResult(
faceSampleId,
item.getScore(),
detectLog.getCreateTime()
));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
log.warn("解析faceSampleId失败: extData={}", item.getExtData()); log.warn("解析faceSampleId失败: extData={}", item.getExtData());
} }
@@ -108,10 +134,50 @@ public class AppAiCamServiceImpl implements AppAiCamService {
} }
// 应用照片数量限制(保留前N个) // 应用照片数量限制(保留前N个)
if (deviceFaceSampleIds.size() > photoLimit) { if (detectResults.size() > photoLimit) {
log.debug("设备{}的照片数量{}超过限制{},截取前{}张", log.debug("设备{}的照片数量{}超过限制{},截取前{}张",
deviceId, deviceFaceSampleIds.size(), photoLimit, photoLimit); deviceId, detectResults.size(), photoLimit, photoLimit);
deviceFaceSampleIds = deviceFaceSampleIds.subList(0, photoLimit); detectResults = detectResults.subList(0, photoLimit);
}
// 应用时间范围限制
List<Long> deviceFaceSampleIds;
if (timeRangeMin != null && !detectResults.isEmpty()) {
// 找到分数最高的照片
DetectResult highestScoreResult = detectResults.stream()
.max(Comparator.comparing(r -> r.score))
.orElse(null);
if (highestScoreResult != null && highestScoreResult.detectTime != null) {
Date baseTime = highestScoreResult.detectTime;
long halfRangeMillis = (long) timeRangeMin * 60 * 1000 / 2;
Date startTime = new Date(baseTime.getTime() - halfRangeMillis);
Date endTime = new Date(baseTime.getTime() + halfRangeMillis);
// 过滤出时间范围内的照片
List<DetectResult> filteredResults = detectResults.stream()
.filter(r -> r.detectTime != null
&& !r.detectTime.before(startTime)
&& !r.detectTime.after(endTime))
.collect(Collectors.toList());
log.debug("设备{}应用时间范围{}分钟过滤: {}张 -> {}张 (基准时间: {})",
deviceId, timeRangeMin, detectResults.size(), filteredResults.size(), baseTime);
deviceFaceSampleIds = filteredResults.stream()
.map(r -> r.faceSampleId)
.collect(Collectors.toList());
} else {
// 没有时间信息,不过滤
deviceFaceSampleIds = detectResults.stream()
.map(r -> r.faceSampleId)
.collect(Collectors.toList());
}
} else {
// 不限制时间范围
deviceFaceSampleIds = detectResults.stream()
.map(r -> r.faceSampleId)
.collect(Collectors.toList());
} }
if (!deviceFaceSampleIds.isEmpty()) { if (!deviceFaceSampleIds.isEmpty()) {

View File

@@ -128,7 +128,7 @@ public class GoodsServiceImpl implements GoodsService {
} else if (sourceType == 2) { } else if (sourceType == 2) {
goodsNamePrefix = "图片"; goodsNamePrefix = "图片";
} else if (sourceType == 3) { } else if (sourceType == 3) {
goodsNamePrefix = "微单"; goodsNamePrefix = "AI微单";
} else { } else {
goodsNamePrefix = "其他类型"; goodsNamePrefix = "其他类型";
} }