简介 
笔者最近在从事文本纠错的相关工作,颇有收获,因此记录于此。
文本纠错很大一部分工作在于纠正同音字、形近字,所谓形近字,是指字形相近的汉字。本文将介绍如何获取形近字。
获取形近字的算法如下:
获取汉字库,将所有汉字转化为黑白图片; 
获取每个汉字的向量表示(即将图片转化为向量); 
计算两个汉字的向量的余弦相似度,得到它们的字形相似度。 
 
下面将详细演示如何获取形近字。
获取形近字 
我们从网上得到3500个汉字的txt文件(all_3500_chars.txt),通过pygame将汉字转化为100*100的黑白图片,Python程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 import  pygamewith  open ("all_3500_chars.txt" , "r" , encoding="utf-8" ) as  f:for  char in  chars:"C://Windows/Fonts/simkai.ttf" , 100 )True , (0 , 0 , 0 ), (255 , 255 , 255 ))"{}.png" .format (char))
前10个汉字为一乙二十丁厂七卜人入,其对应的黑白图片如下:
前10个汉字图片 
 
接着我们获取每个汉字的向量表示,并将这两个向量的余弦相似度作为对应汉字的余弦相似度,Python程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import  numpy as  npimport  cv2import  osfrom  operator import  itemgetterdef  read_img_2_list (img_path ):1 )1 , 1 )return  [_[0 ] for  _ in  img.tolist()]def  get_all_char_vectors ():for  _ in  os.listdir("." ) if  _.endswith("png" )]for  image_path in  image_paths:0 ]] = read_img_2_list(img_path=image_path)return  img_vector_dictdef  cosine_similarity (vector1, vector2 ):0.0 0.0 0.0 for  a, b in  zip (vector1, vector2):2 2 if  normA == 0.0  or  normB == 0.0 :return  0 else :return  dot_product / ((normA**0.5 )*(normB**0.5 ))if  __name__ == '__main__' :while  True :input ("输入汉字: " )for  char, vector in  img_vector_dict.items():sorted (similarity_dict.items(), key=itemgetter(1 ), reverse=True )print ([(char, round (similarity, 4 ))for  char, similarity in  sorted_similarity[:10 ]])
我们尝试着输入国、填、博这三个字,得到的相近字形的汉字如下:
输入汉字: 国 [('国', 1.0), ('固', 0.9493), ('团', 0.9432), ('困',
0.9405), ('因', 0.9369), ('围', 0.9357), ('门', 0.9334), ('园', 0.9326),
('同', 0.929), ('圆', 0.9261)] 输入汉字: 填 [('填', 1.0), ('慎',
0.9522), ('坞', 0.9238), ('培', 0.9149), ('坎', 0.9133), ('块', 0.9101),
('币', 0.9092), ('镇', 0.9077), ('埠', 0.9074), ('了', 0.9044)]
输入汉字: 博 [('博', 1.0), ('傅', 0.9306), ('协', 0.9115), ('搏',
0.907), ('惰', 0.9046), ('膊', 0.9029), ('愕', 0.9019), ('侯', 0.8999),
('悴', 0.8997), ('怜', 0.8989)]
 
opencv读取文件名为汉字的图片 
在使用opencv读物文件名为汉字的图片时,读取的图片内容为None,我们以一.png为例,演示程序如下:
1 2 3 4 5 6 import  cv2"一.png" 1 )print (img, type (img))
输出结果为None <class 'NoneType'>。也就是说,opencv在读取带汉字的文件路径时会报错,解决办法如下:
1 2 3 4 5 6 7 import  cv2import  numpy as  np"一.png" 1 )print (img.shape, type (img))
输出结果为(100, 100, 3) <class 'numpy.ndarray'>。
总结 
本文通过将汉字转化为图片,获取图片的向量表示来表征汉字,在获取形近字方面有着不错的效果。
我们可以通过更复杂的图片相似度算法来增强获得更好的形近字能力。
也有不少研究者,通过四角码、音形码等算法来获取形近字,取得了不错的效果。本文想法朴素,容易用程序实现,且效果也较为不错。
后面将继续记录笔者在文本纠错方面的尝试,欢迎大家继续阅读~
2021年6月29日于上海浦东,此日上海暑气逼人~
欢迎关注我的公众号
NLP奇幻之旅 ,原创技术文章第一时间推送。
 
欢迎关注我的知识星球“自然语言处理奇幻之旅 ”,笔者正在努力构建自己的技术社区。