车车 8 сар өмнө
parent
commit
a906181dbc

+ 106 - 0
ktg-iscs/src/main/java/com/ktg/iscs/config/FingerprintComparisonByImg.java

@@ -0,0 +1,106 @@
+package com.ktg.iscs.config;
+
+
+import cn.hutool.core.util.ObjectUtil;
+import com.google.common.collect.Lists;
+import com.ktg.iscs.domain.vo.cabinet.VerificationVO;
+import com.machinezoo.sourceafis.FingerprintImage;
+import com.machinezoo.sourceafis.FingerprintImageOptions;
+import com.machinezoo.sourceafis.FingerprintMatcher;
+import com.machinezoo.sourceafis.FingerprintTemplate;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * <p>
+ * FingerprintComparison<br>
+ * 指纹比对算法(图片)
+ * </p>
+ *
+ * @author CGJ
+ * @version 1.0
+ * @since 2025年03月07日 11:51
+ */
+@Slf4j
+public class FingerprintComparisonByImg {
+
+    // 相似度门槛
+    private static final double THRESHOLD = 40; // 相当于错误率是0.01%,THRESHOLD越高,错误率越低
+    private static final ExecutorService THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool(4); // 线程池
+
+    public static VerificationVO completableFutureComparison(final String inputImg, final Set<String> matcherImg) {
+        // 转成list
+        List<String> matcherImgList = new ArrayList<>(matcherImg);
+        // 切分四等份
+        List<List<String>> averageMatcherImgList = Lists.partition(matcherImgList, matcherImgList.size() / 4);
+        // 构建四个线程进行处理,防止人员过多对比速度太慢
+        CompletableFuture<VerificationVO>[] completableFutureArray = averageMatcherImgList.stream().map(
+                partitionFingerprint -> CompletableFuture.supplyAsync(
+                        () -> comparison(inputImg, new ArrayList<>(partitionFingerprint)), THREAD_POOL_EXECUTOR)
+        ).toArray(CompletableFuture[]::new);
+        // 等待所有任务执行完
+        CompletableFuture.allOf(completableFutureArray).join();
+        List<VerificationVO> verificationList = new ArrayList<>();
+        for (CompletableFuture<VerificationVO> completableFuture : completableFutureArray) {
+            try {
+                VerificationVO verification = completableFuture.get();
+                if (ObjectUtil.isNotEmpty(verification)) {
+                    verificationList.add(verification);
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        // 找出最匹配的指纹(匹配度最高)
+        if (ObjectUtil.isNotEmpty(verificationList)) {
+            VerificationVO max = verificationList.stream().max(Comparator.comparing(VerificationVO::getScore)).get();
+            log.info("相似值最佳的的指纹:{},分数{}", max.getFingerprintImg(), max.getScore());
+            return max;
+        }
+        return null;
+    }
+
+    public static VerificationVO comparison(final String inputImg, final List<String> matcherImgList) {
+        try {
+            // 开始解析输入的指纹到指纹模板
+            byte[] bytes = Files.readAllBytes(Paths.get(inputImg));
+            FingerprintImageOptions dpi = new FingerprintImageOptions().dpi(500);
+            FingerprintImage fingerprintImage = new FingerprintImage(bytes, dpi);
+            FingerprintTemplate fingerprintTemplate = new FingerprintTemplate(fingerprintImage);
+
+            if (!matcherImgList.isEmpty()) {
+                // 输入的被验证指纹
+                FingerprintMatcher matcher = new FingerprintMatcher(fingerprintTemplate);
+                // 最匹配的指纹
+                String match = null;
+                // 峰值
+                double high = 0;
+                for (String matcherImg : matcherImgList) {
+                    // 输入的指纹和指纹库中的指纹进行对比,找到当前线程中的分数最高的指纹
+                    double score = matcher.match(new FingerprintTemplate(new FingerprintImage(Files.readAllBytes(Paths.get(matcherImg)), dpi)));
+                    if (score > high) {
+                        high = score;
+                        match = matcherImg;
+                    }
+                }
+                return high >= THRESHOLD ? new VerificationVO().setFingerprintImg(match).setScore(high) : null;
+            }
+        } catch (Exception e) {
+            log.error("指纹比对异常:{}", e.getMessage());
+        }
+        return null;
+    }
+
+}
+
+

+ 39 - 0
ktg-iscs/src/main/java/com/ktg/iscs/domain/vo/cabinet/VerificationVO.java

@@ -0,0 +1,39 @@
+package com.ktg.iscs.domain.vo.cabinet;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@EqualsAndHashCode(callSuper = false)
+@Data
+@Accessors(chain = true)
+public class VerificationVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "人员编号")
+    private Long userId;
+
+    @ApiModelProperty(value = "指纹图片地址")
+    private String fingerprintImg;
+
+    @ApiModelProperty(value = "指纹信息")
+    private String fingerprint;
+
+    @ApiModelProperty(value = "指纹模板信息")
+    private byte[] fingerprintTemplate;
+
+    @ApiModelProperty(value = "指纹信息")
+    private String fingerprintHex;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
+    @ApiModelProperty(value = "得分")
+    private Double score;
+
+}
+