feat(face): 添加打印机大屏人脸识别试点功能

- 在PrinterTvController中添加tv场景参数,用于触发打印机大屏识别试点逻辑
- 在FaceMatchingScene枚举中新增PRINTER_TV_RECOGNIZE场景,支持仅执行识别补救落库建关系
- 在FaceMatchingPipelineFactory中创建打印机大屏识别试点Pipeline,包含识别补救落库建关系等阶段
- 在FaceServiceImpl中添加打印机大屏人脸识别的专门处理方法matchFaceIdForPrinterTv
- 通过scene参数区分普通人脸识别和打印机大屏识别试点流程
This commit is contained in:
2025-12-29 11:34:10 +08:00
parent 58e8189b13
commit d6780ccb7a
4 changed files with 79 additions and 3 deletions

View File

@@ -198,7 +198,7 @@ public class PrinterTvController {
@RequestParam("file") MultipartFile file, @RequestParam("file") MultipartFile file,
@PathVariable Long scenicId) { @PathVariable Long scenicId) {
// 复用 faceUpload 方法的去重逻辑 // 复用 faceUpload 方法的去重逻辑
// memberId=0L 表示打印机大屏用户,scene="print" 会触发自动添加打印逻辑并等待完成 // memberId=0L 表示打印机大屏用户,scene="tv" 为试点场景:仅执行识别/补救/落库/建关系
FaceRecognizeResp resp = pcFaceService.faceUpload(file, scenicId, 0L, "tv"); FaceRecognizeResp resp = pcFaceService.faceUpload(file, scenicId, 0L, "tv");
return ApiResponse.success(resp); return ApiResponse.success(resp);
} }

View File

@@ -21,5 +21,11 @@ public enum FaceMatchingScene {
* 仅识别 * 仅识别
* 只执行人脸识别,不处理后续业务逻辑(源文件关联、任务创建等) * 只执行人脸识别,不处理后续业务逻辑(源文件关联、任务创建等)
*/ */
RECOGNITION_ONLY RECOGNITION_ONLY,
/**
* 打印机大屏识别试点
* 仅执行:识别、补救、落库、建关系
*/
PRINTER_TV_RECOGNIZE
} }

View File

@@ -71,6 +71,40 @@ public class FaceMatchingPipelineFactory {
@Autowired @Autowired
private ScenicConfigFacade scenicConfigFacade; private ScenicConfigFacade scenicConfigFacade;
/**
* 创建打印机大屏识别试点Pipeline
* 仅执行:识别、补救、落库、建关系
*
* 说明:
* - “准备上下文”属于基础能力,默认包含
* - “建关系”包含构建关联与持久化两步
*/
public Pipeline<FaceMatchingContext> createPrinterTvRecognizePipeline() {
PipelineBuilder<FaceMatchingContext> builder = new PipelineBuilder<>("PrinterTvRecognize");
// 1. 准备上下文
builder.addStage(prepareContextStage);
// 2. 执行人脸识别
builder.addStage(faceRecognitionStage);
// 3. 人脸识别补救
builder.addStage(faceRecoveryStage);
// 4. 更新人脸结果(落库)
builder.addStage(updateFaceResultStage);
// 5. 构建源文件关联(建关系)
builder.addStage(buildSourceRelationStage);
// 6. 持久化关联关系(建关系)
builder.addStage(persistRelationsStage);
log.debug("创建打印机大屏识别试点Pipeline: stageCount={}", builder.build().getStageCount());
return builder.build();
}
/** /**
* 创建自动人脸匹配Pipeline * 创建自动人脸匹配Pipeline
* *
@@ -219,6 +253,7 @@ public class FaceMatchingPipelineFactory {
case AUTO_MATCHING -> createAutoMatchingPipeline(isNew); case AUTO_MATCHING -> createAutoMatchingPipeline(isNew);
case CUSTOM_MATCHING -> createCustomMatchingPipeline(); case CUSTOM_MATCHING -> createCustomMatchingPipeline();
case RECOGNITION_ONLY -> createRecognitionOnlyPipeline(); case RECOGNITION_ONLY -> createRecognitionOnlyPipeline();
case PRINTER_TV_RECOGNIZE -> createPrinterTvRecognizePipeline();
}; };
} }

View File

@@ -7,6 +7,9 @@ import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.biz.TemplateBiz; import com.ycwl.basic.biz.TemplateBiz;
import com.ycwl.basic.constant.BaseContextHandler; import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.exception.BaseException; import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.face.pipeline.core.FaceMatchingContext;
import com.ycwl.basic.face.pipeline.enums.FaceMatchingScene;
import com.ycwl.basic.face.pipeline.factory.FaceMatchingPipelineFactory;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter; import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.facebody.entity.SearchFaceResultItem; import com.ycwl.basic.facebody.entity.SearchFaceResultItem;
import com.ycwl.basic.mapper.FaceSampleMapper; import com.ycwl.basic.mapper.FaceSampleMapper;
@@ -85,6 +88,8 @@ import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl; import com.ycwl.basic.storage.enums.StorageAcl;
import com.ycwl.basic.storage.utils.StorageUtil; import com.ycwl.basic.storage.utils.StorageUtil;
import com.ycwl.basic.utils.*; import com.ycwl.basic.utils.*;
import com.ycwl.basic.pipeline.core.Pipeline;
import com.ycwl.basic.pipeline.exception.PipelineException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings; import org.apache.commons.lang3.Strings;
@@ -119,6 +124,8 @@ import static com.ycwl.basic.constant.StorageConstant.USER_FACE;
@Slf4j @Slf4j
@Service @Service
public class FaceServiceImpl implements FaceService { public class FaceServiceImpl implements FaceService {
private static final String FACE_UPLOAD_SCENE_PRINTER_TV = "tv";
@Autowired @Autowired
private FaceMapper faceMapper; private FaceMapper faceMapper;
@Autowired @Autowired
@@ -176,6 +183,8 @@ public class FaceServiceImpl implements FaceService {
// 编排器 // 编排器
@Autowired @Autowired
private FaceMatchingOrchestrator faceMatchingOrchestrator; private FaceMatchingOrchestrator faceMatchingOrchestrator;
@Autowired
private FaceMatchingPipelineFactory faceMatchingPipelineFactory;
// 防重复服务 // 防重复服务
@Autowired @Autowired
@@ -311,7 +320,7 @@ public class FaceServiceImpl implements FaceService {
resp.setUrl(faceUrl); resp.setUrl(faceUrl);
resp.setFaceId(newFaceId); resp.setFaceId(newFaceId);
resp.setScenicId(scenicId); resp.setScenicId(scenicId);
matchFaceId(newFaceId, oldFaceId == null); matchFaceId(newFaceId, oldFaceId == null, scene);
// 异步执行自动添加打印 // 异步执行自动添加打印
Long finalFaceId = newFaceId; Long finalFaceId = newFaceId;
@@ -368,9 +377,35 @@ public class FaceServiceImpl implements FaceService {
} }
@Override @Override
public SearchFaceRespVo matchFaceId(Long faceId, boolean isNew, String scene) { public SearchFaceRespVo matchFaceId(Long faceId, boolean isNew, String scene) {
if (Strings.CI.equals(FACE_UPLOAD_SCENE_PRINTER_TV, scene)) {
return matchFaceIdForPrinterTv(faceId, isNew);
}
return faceMatchingOrchestrator.orchestrateMatching(faceId, isNew, scene); return faceMatchingOrchestrator.orchestrateMatching(faceId, isNew, scene);
} }
private SearchFaceRespVo matchFaceIdForPrinterTv(Long faceId, boolean isNew) {
FaceMatchingContext context = FaceMatchingContext.builder()
.faceId(faceId)
.isNew(isNew)
.scene(FaceMatchingScene.PRINTER_TV_RECOGNIZE)
.build();
Pipeline<FaceMatchingContext> pipeline = faceMatchingPipelineFactory.createPrinterTvRecognizePipeline();
try {
boolean success = pipeline.execute(context);
if (!success) {
throw new BaseException("打印机大屏人脸识别失败");
}
return context.getSearchResult();
} catch (PipelineException e) {
Throwable rootCause = e.getCause();
if (rootCause instanceof BaseException baseException) {
throw baseException;
}
throw new BaseException("打印机大屏人脸识别失败");
}
}
/** /**
* 更新人脸实体结果信息 * 更新人脸实体结果信息
* 仅用于 handleCustomFaceMatching 方法 * 仅用于 handleCustomFaceMatching 方法