非严格的签名场景,为了不让张三签上李四,我们引入了OCR手写识别验证对比,但这样的话,有些相近的字比如张目会识别为张日,朱昱大概率会识别为朱星,陈泫铃会识别为陈滋玲等,导致无法通过,由于一个人写字习惯的问题,很多相近的字,签几次都无法得到正确的结果. 测试通过率只有25%不到,有些用户甚至签了20次都过不了,销售人员压力很大,我们需要一个方案来优化这个通过率

可选方案

  • 在签字界面,显示谐体正文,让用户描
    • 前端实现有一定难度,但理论上可行,在签字div下层再放一层
    • 可能存在诱导用户签字的风险
    • 可能会导致用户反感(我写自己名字,还需要你来教我怎么写?)
  • 优化OCR手写签字
    • OCR识别技术通过不会是自己做的,比如我们这边使用的是百度的,没有看到有什么参数能优化
    • 换OCR接口供应商,未测试,理论上效果不大
  • 校验时,可以让用户错一个字
    • 理论上可行,但是这样容错率太高,张三签成张八也能通过
  • 判断字形相似度,字形相似度大于一定百分比时通过
    • 其实就是上面方案的改良版本

字形相似度判断

        <!-- nlp 汉字相似度识别 -->
        <dependency>
            <groupId>com.github.houbb</groupId>
            <artifactId>nlp-hanzi-similar</artifactId>
            <version>1.4.0</version>
        </dependency>
  • 具体代码
    public static int similarPercent(char a,char b){
        if(a == b) return 100;
        var result = similarHelper.similar(a,b);
        return Double.valueOf( result * 100).intValue();
    }

    //签名相似度百分比校验
    public static int signNameSimilarPercent(String a,String b){
        if(Objects.equals(a,b)) return 100;
        if(Objects.isNull(a) || Objects.isNull(b)) return 0;
        if(a.length() != b.length()) return 0;
        var count = a.length();
        var total = 0;
        for (int i = 0; i < count; i++) {
            var percent = similarPercent(a.charAt(i),b.charAt(i));
            //姓错的概率低,调低权重
            if(i==0 && percent>90)  percent = percent-15;
            total = total + percent;
        }
        return total/count;
    }
  • 我使用了每个字判断,然后平均的方法,现在想想不太严谨,可以考虑使用最小百分比输出
  • 根据实践测试,我使用了值是相似度大于55%即可通过,生产中通过率达80%,基本达到了预期
  • 附测试图:
    fa421319158671b0b170dd9dd2a0e68c.png