OCR(optical character recognition)是将图片进行扫描,提取其中的文字的技术。如今,不少业务领域都用到了OCR技术。比如某些快递软件支持识别包含地址信息的图片,解析出用户地址。,
,在用户发布游戏商品时,我们希望用户将参数填得越全越好,这样有助于搜索、个性化推荐、统计数据。但是,以王者荣耀为例,目前王者荣耀有400+皮肤,将所有拥有的皮肤填写一遍非常麻烦,所以我们希望通过用户上传图片或商品封面,提取其中的参数信息,填入商品信息中,以达到补全参数、减少用户操作的目的。,
,目前腾讯、百度、58等公司都提供了OCR识别API,转转也有自研的OCR能力,对一张用户上传的图片进行OCR识别可以得到一个文本集合。,
,结合OCR识别结果我们可以发现一些问题,由此产生了两个要解决的问题,
,通过观察用户上传的图片我们可以发现:,如何将皮肤区域和背景区域分离呢?通过观察我们能看到:,所以是否能尝试使用色彩数来区分皮肤区域和背景区域呢?,对用户上传图片的色彩数量进行统计,得到以下趋势:,
,上图为从横向开始遍历,使用Set对纵向所有像素的颜色进行去重,得到的颜色数量变化趋势。可以看出,五个较为明显的凸起即对应了图上的5列皮肤。,
,上图为从纵向开始遍历,使用Set对横向所有像素的颜色进行去重,得到的颜色数量变化趋势。可以看出,两个较为明显的凸起即对应了图上的2行皮肤。,因此,如果某个点附近颜色数量发生剧烈变化就可以认为这是一个边界点,相邻两个边界点相连可以组成线段,横向的线段和纵向的线段相连可以组成矩形。按照这个思路对图片进行划分后效果如下。,
,这样就初步实现了将皮肤区域和背景区域分离,对于已拥有的皮肤和未拥有的皮肤,他们的颜色数量都很丰富,继续用颜色数量区分的效果不是很理想,那如何进行区分呢?,所以,我们可以在划分矩形后,首先对矩形的长宽比进行初次过滤,然后提取矩形中像素的颜色,计算亮度和饱和度大于阈值的像素占比,保留占比高的矩形,在对阈值进行一些调优后,最终保留结果如下。,
,这样,在进行OCR识别时,就不会把未拥有的皮肤也识别出来了。,要将“李信一念神度”匹配为“李信一念神魔”这个参数,基本思路是计算两个文本的重复度,如果高于一个阈值即可认定是相同的文本,目前文本相似度计算有两种大致方向:,提取两个文本的特征向量,计算向量空间两个向量夹角的余弦相似度。,将字符串进行分割,统计子串是否相同。,为了方便我们采用了第二种方法,在串匹配算法中我们选择了Rabin-Karp算法,其具体思路是使用滑动窗口得出文本的哈希集合,对两个哈希集合进行比对,计算出相似度。,
,例如:我们使用窗口大小为2,每次滑动1对“李信一念神魔”和“李信一念神度”进行分割,可以得到:,[ "李信" , "信一" , "一念" , "念神" , "神魔" ],[ "李信" , "信一" , "一念" , "念神" , "神度" ],而对窗口中元素计算哈希的操作我们可以交给String类的hashCode()方法,所以两个文本计算相似度方法大致如下:,在上述过程中,向HashSet中增加元素,以及使用contains方法判断HashSet中是否包含元素时,都是基于String类自带的hashCode()方法进行的:,由于我们的文本量比较小,对于这种哈希计算方式,是完全满足我们的需求的。,而Rabin-Karp算法认为,在文本量非常大的情况下,先分割窗口然后每次对窗口中的元素单独计算哈希效率是低下的,可以通过改良计算方式,使下一个窗口的哈希与,产生关联,加快运算速度,所以给出了一种更快分割窗口并且计算哈希的方式:,如果一个业务场景需要匹配的文本量非常大,可以尝试选用这种方式。,最终,我们的匹配流程大致如下,在系统启动时,会拉取我们的参数库,使用上面的方式对每个参数进行预处理,得到它们的哈希集合,存到本地,当一个OCR识别结果产生时,计算它的哈希集合,与本地进行匹配,如果发现相似度大于阈值,即认为匹配成功。,
,这样,我们就保证了一定的容错性。,当我们解决了:只识别拥有的皮肤、匹配时有一定容错,这两个问题后就可以线上部署了。,目前OCR只应用在王者荣耀、和平精英两款游戏,上线后每日可为我们的商品补充上千参数。后续会逐步扩展到其他游戏品类。,
,作者简介:,常睿,转转订单业务Java研发工程师。
© 版权声明
文章版权归作者所有,未经允许请勿转载。