非严格的签名场景,为了不让张三签上李四,我们引入了OCR手写识别验证对比,但这样的话,有些相近的字比如张目会识别为张日,朱昱大概率会识别为朱星,陈泫铃会识别为陈滋玲等,导致无法通过,由于一个人写字习惯的问题,很多相近的字,签几次都无法得到正确的结果. 测试通过率只有25%不到,有些用户甚至签了20次都过不了,销售人员压力很大,我们需要一个方案来优化这个通过率
可选方案
- 在签字界面,显示谐体正文,让用户描
- 前端实现有一定难度,但理论上可行,在签字div下层再放一层
- 可能存在诱导用户签字的风险
- 可能会导致用户反感(我写自己名字,还需要你来教我怎么写?)
- 优化OCR手写签字
- OCR识别技术通过不会是自己做的,比如我们这边使用的是百度的,没有看到有什么参数能优化
- 换OCR接口供应商,未测试,理论上效果不大
- 校验时,可以让用户错一个字
- 理论上可行,但是这样容错率太高,张三签成张八也能通过
- 判断字形相似度,字形相似度大于一定百分比时通过
- 其实就是上面方案的改良版本
字形相似度判断
- 找到了一个比较好的nlp中文相似性库:nlp-hanzi-similar
- 引入:
<!-- 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%,基本达到了预期
- 附测试图: