CnOCR算法解析

源代码路径:

https://github.com/breezedeus/CnOCR

OCR文字识别技术简述

OCR英文全称是Optical Character Recognition,中文叫做光学字符识别。它是通过扫描等光学技术与计算机技术结合的方式将各种证件、票据、文件及其它印刷品的文字转化为图像信息,再利用文字识别技术将图像信息转化为可以使用的计算机输入技术。也就是说,ocr识别技术 直接从影像中提取各类数据,省去人工录入,节约成本。

目前许多开源OCR技术不断出现,如paddleOCR,百度OCR,阿里OCR等等,OCR技术在我们生活中的运用范围十分广泛:比如一个手机APP就能帮忙扫描名片、身份证,并识别出里面的信息;汽车进入停车场、收费站都不需要人工登记了,都是用车牌识别技术;我们看书时看到不懂的题,拿个手机一扫,APP就能在网上帮你找到这题的答案等。

CnOCR介绍

CnOCR是Python 3下的文字识别(Optical Character Recognition,简称OCR)工具包,支持简体中文、繁体中文(部分模型)、英文和数字的常见字符识别,支持竖排文字的识别。有适用于PyTorch版本与ONNX版本的模型。该开源算法自带了20+个训练好的识别模型,适用于不同应用场景。

基本原理说明——为了识别一张图片中的文字,通常包含两个步骤:

  1. 文本检测:检测出图片中文字所在的位置;
  2. 文字识别:识别包含文字的图片局部,预测具体的文字。

文本检测算法CnStd

检测的代码部分比较简单,对输入的图像数据做一些简单的处理后输入模型

传入参数解析

支持对单个图片或者多个图片(列表)的检测

可接受参数为图片文件路径,或PIL格式,numpy格式的图像数据对应格式——RGB 3通道 shape:(height, width, 3)取值:[0, 255]

img_list: Union[
            str,
            Path,
            Image.Image,
            np.ndarray,
            List[Union[str, Path, Image.Image, np.ndarray]],
        ],

前处理简述:

对批量传入的图像数据按照定义的参数batch进行打包,后对每个batch的图像数据以PIL格式进行读取,转化为PIL格式的RGB图像输入到模型中进行检测。

def read_img(img_fp) -> Image.Image:
    img = Image.open(img_fp)
    img = ImageOps.exif_transpose(img).convert('RGB')  # 识别旋转后的图片
    return img

输出结果

返回一个字典或字典的列表,包含一张图片的检测结果:

* 'rotated_angle': float, 整张图片旋转的角度。
* 'detected_texts': list, 每个元素存储了检测出的一个框的信息,使用词典记录,包括以下几个值:
'box':检测出的文字对应的矩形框;np.ndarray, shape: (4, 2),对应 box 4个点的坐标值 (x, y) ;
'score':得分;float 类型;分数越高表示越可靠;
'cropped_img':对应'box'中的图片patch(RGB格式),会把倾斜的图片旋转为水平。
np.ndarray 类型,shape: (height, width, 3), 取值范围:[0, 255];

示例:

>>>out
{'rotated_angle': 0.0,
 'detected_texts': [{'box': array([[        199,         183],
          [        469,         183],
          [        469,         237],
          [        199,         237]], dtype=float32),
   'score': 0.8020596971160255,
   'cropped_img': array([[[253, 236, 229],
           [253, 243, 234],
           [252, 242, 233],
           ...,
           [232, 222, 213],
           [234, 224, 215],
           [234, 224, 215]],

           ...,

           [[255, 200, 184],
           [255, 221, 206],
           [255, 232, 219],
           ...,
           [255, 237, 232],
           [255, 235, 230],
           [255, 236, 237]]], dtype=uint8)}]}    

后处理部分:

对检测到的文本区域图像进行角度分类,并更新每个文本区域对应的图像

for out in outs:
    crop_img_list = [info['cropped_img'] for info in out['detected_texts']]
    try:
        crop_img_list, angle_list = self.angle_clf(crop_img_list)
        for info, crop_img in zip(out['detected_texts'], crop_img_list):
            info['cropped_img'] = crop_img
    except Exception as e:
        logger.info(traceback.format_exc())
        logger.info(e)

遍历检测到的文本信息的输出列表中的每一个元素并提取['cropped_img']字段,即对应的图像数据。后调用self.angle_clf()方法对crop_img_list中的文本区域图像进行角度分类,该方法返回分类后的文本区域图像列表crop_img_list和对应的角度列表angle_list

接下来,使用zip()函数将out['detected_texts']crop_img_list进行打包,然后通过for循环遍历打包后的元素,将crop_img赋值给对应的文本信息字典info'cropped_img'字段,从而更新了每个文本区域对应的图像。

文字识别算法CnOcr

可接受的参数同样为Path, torch.Tensor, np.ndarray

代码将输入的图像列表转化为numpy格式的图像数据——shape(height, width, 1), dtype uint8, 取值:[0, 255] 后转换图像数据维度:[H, W, C]->[C, H, W]并转换为torch类型数据

img = img.transpose((2, 0, 1))
img = torch.from_numpy(img)

对图像数据列表按宽度从小到大排列以提升效率

# sorted_idx_list返回的是一个排序后的索引列表
sorted_idx_list = sorted(range(len(img_list)), key=lambda i: img_list[i].shape[2])
sorted_img_list = [img_list[i] for i in sorted_idx_list]

按照batch_size大小对图像进行批量处理,先通过pad_img_seq完成对图像序列进行填充,这一步骤的目的是使得序列中的所有图像具有相同的宽度,输入图像列表中每个张量的形状为[C, H, W],其中W是可变的宽度。函数使用指定的填充值padding_value对图像序列进行填充。

首先,代码将图像列表中的每个图像张量的维度顺序进行转置,变为[W, C, H]的形式。然后,使用pad_sequence函数对转置后的图像列表进行填充,使得所有图像具有相同的宽度。填充的值为padding_value。填充后的结果形状为[B, W_max, C, H],其中B是图像序列的长度,W_max是图像序列中最大的宽度。最后,代码再次对填充后的结果进行维度转置,变为[B, C, H, W_max]的形式,并将结果返回。

def pad_img_seq(img_list: List[torch.Tensor], padding_value=0) -> torch.Tensor:
    img_list = [img.permute((2, 0, 1)) for img in img_list]  # [W, C, H]
    imgs = pad_sequence(
        img_list, batch_first=True, padding_value=padding_value
    )  # [B, W_max, C, H]
    return imgs.permute((0, 2, 3, 1))  # [B, C, H, W_max]

输入模型即可得出文本识别输出结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值