学习笔记|文字识别之cnocr(一)

举报
darkpard 发表于 2021/08/03 21:58:49 2021/08/03
【摘要】 前几天分享了ddddocr热点复现|验证码识别,但发现这个包没有提供个性化训练接口,底层又是用C++写的,作为一名只懂python的伪算法工程师,止步应用不甘心,修改底层没能力,只好另请高明,于是找到了cnocr。1. cnocr预训练模型试用首先安装cnocr。!pip install cnocr开源贡献者提供了预训练模型,我们将对预训练模型的效果进行一些验证。from cnocr imp...

前几天分享了ddddocr热点复现|验证码识别,但发现这个包没有提供个性化训练接口,底层又是用C++写的,作为一名只懂python的伪算法工程师,止步应用不甘心,修改底层没能力,只好另请高明,于是找到了cnocr。

1. cnocr预训练模型试用

首先安装cnocr。

!pip install cnocr

开源贡献者提供了预训练模型,我们将对预训练模型的效果进行一些验证。

from cnocr import CnOcr
ocr = CnOcr()
res = ocr.ocr('images/t1.jpg')
p = plt.imread('images/t1.jpg')
plt.imshow(p)
print(res)

图片

res = ocr.ocr('images/t2.jpg')
p = plt.imread('images/t2.jpg')
plt.imshow(p)
print(res)

res = ocr.ocr('images/t3.jpg')
p = plt.imread('images/t3.jpg')
plt.imshow(p)
print(res)

res = ocr.ocr('images/t4.jpg')
p = plt.imread('images/t4.jpg')
plt.imshow(p)
print(res)

res = ocr.ocr('images/t5.jpg')
p = plt.imread('images/t5.jpg')
plt.imshow(p)
print(res)

res = ocr.ocr('images/t6.jpg')
p = plt.imread('images/t6.jpg')
plt.imshow(p)
print(res)

图片


res = ocr.ocr('images/t7.jpg')
p = plt.imread('images/t7.jpg')
plt.imshow(p)
print(res)

显然,cnocr对验证码的识别率远不如ddddocr(ddddocr试用见热点复现|验证码识别),那么对于标准的文字呢?

res = ocr.ocr('images/t12.jpg')
p = plt.imread('images/t12.jpg')
plt.imshow(p)
print(res)

res = ocr.ocr('images/t17.jpg')
p = plt.imread('images/t17.jpg')
plt.imshow(p)
print(res)

res = ocr.ocr('images/t20.jpg')
p = plt.imread('images/t20.jpg')
plt.imshow(p)
print(res)

可以看到,cnocr对标准文字的识别率还是可以的。那么它对于其他不同字体的支持率如何呢?我们随便准备了几个微软雅黑字体。

res = ocr.ocr('images/t23.jpg')
p = plt.imread('images/t23.jpg')
plt.imshow(p)
print(res)

发现效果并不是很好。

总的来说,cnocr自带预训练模型的准确率不及ddddocr,cnocr的运行效率也明显不如ddddocr,但cnocr提供了个性化训练的方法,并且cnocr完全是用python实现的,我们试图通过自定义训练来提高cnocr对微软雅黑字体的识别率。


2. 个性化训练尝试

2.1. 个性化训练必须clone cnocr项目。

!git clone https://gitee.com/cyahua/cnocr.git

2.2. 准备训练样本。

由于水平有限,不会有服务器上生成微软雅黑字体,我们在windows上准备训练需要的样本。

2.2.1. 在cnocr下新建文件夹datasets。

2.2.2. 在datasets文件夹下再新建文件夹dataset2_002。

2.2.3. 在dataset2_002文件夹下新建test.txt文件,将我们刚刚打的那行字分成两行,加上.jpg(如下图)。

2.2.4. 在dataset_002文件夹下新建train.txt文件,将我们刚刚那行字打乱后加上.jpg,写成三行(如下图)。

2.2.5. 将test.txt和train.txt里的文字转化为微软雅黑字体的图片,同时生成每个字在字表中的位置。

2.2.5.1. 从windows里找到微软雅黑字体,一般在C:\Windows\Fonts文件夹下,将msyh.ttc复制到datasets文件夹下面。

2.2.5.2. 在cnocr项目下的examples文件夹下找到label_cn.txt,将其复制到datasets下面。

2.2.5.3. 在datasets文件夹下新建data_generator.py文件,代码如下:

import os
import pygame

pygame.init()
font = pygame.font.Font('msyh.ttc', 64)

def writing(txt, pth):
    r_txt = font.render(txt, True, (0, 0, 0), (255, 255, 255))
    pygame.image.save(r_txt, os.path.join(pth, txt+'.jpg'))

def indexing(txt):
    res = []
    for i in range(len(txt)):
        try:
            res.append(standards.index(txt[i]+'\n')+1)
        except:
            new_chrs.append(txt[i])
            res.append(len(standards)+len(new_chrs)+1)
    return res

if __name__ == '__main__':
    pth = 'self_dataset_002'

    f_tr = open(os.path.join(pth, 'train.txt'), encoding='utf-8-sig')
    f_ts = open(os.path.join(pth, 'test.txt'), encoding='utf-8-sig')
    f_st = open('label_cn.txt', 'r', encoding='utf-8-sig')

    f_tr2 = open(os.path.join(pth, 'train2.txt'), 'w', encoding='utf-8-sig')
    f_ts2 = open(os.path.join(pth, 'test2.txt'), 'w', encoding='utf-8-sig')

    train_items = f_tr.readlines()
    test_items = f_ts.readlines()
    standards = f_st.readlines()
    new_chrs = []

    f_tr.close()
    f_ts.close()
    f_st.close()

    for i in range(len(train_items)):
        txt = train_items[i].split(".")[0]
        idxes = indexing(txt)
        img = writing(txt, pth)

        cnt = "train_%06d.jpg" % i
        os.rename(os.path.join(pth, txt + '.jpg'), os.path.join(pth, cnt))
        for idx in idxes:
            cnt = cnt + " {}".format(idx)
        f_tr2.write(cnt + '\n')

    for i in range(len(test_items)):
        txt = test_items[i].split(".")[0]
        idxes = indexing(txt)
        img = writing(txt, pth)

        cnt = "test_%06d.jpg" % i
        os.rename(os.path.join(pth, txt + '.jpg'), os.path.join(pth, cnt))
        for idx in idxes:
            cnt = cnt + " {}".format(idx)
        f_ts2.write(cnt + '\n')

    fh = open('label_cn.txt', 'a', encoding='utf-8-sig')
    for nw in new_chrs:
        fh.write(nw + '\n')
    fh.close()

上面的样本准备过程参考了萧班的博客,代码基本来自于该博客,局部有所调整。由于代码比较长,此处不再具体解释,在此感谢萧班CNOCR重训练_WinerChopin的博客-CSDN博客_cnocr训练。

2.2.5.4. 运行以上代码。在运行以上代码后可以将test.txt和train.txt下的XXX.jpg分别生成微软雅黑字体的文字图片(见下图)

同时生成test2.txt和train2.txt,生成每个字在字表中的位置(见下图)。


2.2.6. 生成.lst文件。在项目下运行如下代码

python scripts/im2rec.py --list --num-label 20 --chunks 1 --train-idx-fp ./datasets/dataset_002/train2.txt --test-idx-fp ./datasets/dataset_002/test2.txt --prefix ./datasets/dataset_002/d002

生成d002_test.lst和d002_train.lst(见下图)


2.2.7. 生成.rec文件。在项目下运行如下代码

python scripts/im2rec.py --pack-label --color 1 --num-thread 1 --prefix ./datasets/dataset_002/d002 --root ./datasets/dataset_002

生成d002_test.rec和d002_train.rec(见下图)

至此,样本准备完成。

2.3. 个性化训练

运行以下代码

python scripts/cnocr_train.py --gpu 0 --emb_model_type "densenet-lite" --seq_model_type "fc" --optimizer adam --epoch 20 --lr 1e-4 --train_file ./datasets/dataset_002/d002_train --test_file ./datasets/dataset_002/d002_test

可以看到20次训练结果并不是很理想

实际识别结果也说明了同样的问题,20epoch训练的结果完全无效

问题是一模一样地再训练一次,得到的结果却并不一样:

图片

为什么会这样呢?我也还没来得及深入分析原因。如果同学们有知道原因的,或者有做OCR个性化训练更好的方法,欢迎留言。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200