使用方法
模型文件自动下载
首次使用 CnOCR 时,系统会自动下载 zip 格式的识别模型压缩文件,并存于 ~/.cnocr目录(Windows下默认路径为 C:\Users\<username>\AppData\Roaming\cnocr)。
下载后的zip文件代码会自动对其解压,然后把解压后的模型相关目录放于~/.cnocr/2.3目录中。
如果系统无法自动成功下载zip文件,则需要手动从 cnstd-cnocr-models 下载此zip文件并把它放于 ~/.cnocr/2.3目录。如果下载太慢,也可以从 百度云盘 下载, 提取码为 nocr。
检测模型的下载请参考 CnSTD 文档。
放置好 zip 文件后,后面的事代码就会自动执行了。
详细使用说明
初始化
类CnOcr 是识别主类,包含了三个函数针对不同场景进行文字识别。类CnOcr的初始化函数如下:
class CnOcr(object):
def __init__(
self,
rec_model_name: str = 'densenet_lite_136-gru',
*,
det_model_name: str = 'ch_PP-OCRv5_det',
cand_alphabet: Optional[Union[Collection, str]] = None,
context: str = 'cpu', # ['cpu', 'gpu', 'cuda']
rec_model_fp: Optional[str] = None,
rec_model_backend: str = 'onnx', # ['pytorch', 'onnx']
rec_vocab_fp: Union[str, Path] = VOCAB_FP,
rec_more_configs: Optional[Dict[str, Any]] = None,
rec_root: Union[str, Path] = data_dir(),
det_model_fp: Optional[str] = None,
det_model_backend: str = 'onnx', # ['pytorch', 'onnx']
det_more_configs: Optional[Dict[str, Any]] = None,
det_root: Union[str, Path] = det_data_dir(),
**kwargs,
)
其中的几个参数含义如下:
-
rec_model_name: 识别模型名称。默认为densenet_lite_136-gru。更多可选模型见 可直接使用的模型 。 -
det_model_name: 检测模型名称。默认为ch_PP-OCRv5_det。更多可选模型见 可直接使用的模型 。 -
cand_alphabet: 待识别字符所在的候选集合。默认为None,表示不限定识别字符范围。取值可以是字符串,如"0123456789",或者字符列表,如["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]。cand_alphabet也可以初始化后通过类函数CnOcr.set_cand_alphabet(cand_alphabet)进行设置。这样同一个实例也可以指定不同的cand_alphabet进行识别。
-
context:预测使用的机器资源,可取值为字符串cpu、gpu、cuda:0等。默认为cpu。此参数仅在model_backend=='pytorch'时有效。 -
rec_model_fp: 如果不使用系统自带的识别模型,可以通过此参数直接指定所使用的模型文件(.ckpt或.onnx文件)。 -
rec_model_backend:'pytorch', or 'onnx'。表明识别时是使用PyTorch版本模型,还是使用ONNX版本模型。 同样的模型,ONNX 版本的预测速度一般是 PyTorch 版本的 2倍左右。 默认为 'onnx'。 -
rec_vocab_fp:识别字符集合的文件路径,即label_cn.txt文件路径。若训练的自有模型更改了字符集,看通过此参数传入新的字符集文件路径。 -
rec_more_configs:dict,识别模型初始化时传入的其他参数。具体可参考 Recognizer 和 PPRecognizer 中的__init__接口。 -
rec_root: 识别模型文件所在的根目录。- Linux/Mac下默认值为
~/.cnocr,表示模型文件所处文件夹类似~/.cnocr/2.3/densenet_lite_136-gru。 - Windows下默认值为
C:\Users\<username>\AppData\Roaming\cnocr。
- Linux/Mac下默认值为
-
det_model_fp: 如果不使用系统自带的检测模型,可以通过此参数直接指定所使用的模型文件(.ckpt或.onnx文件)。 -
det_model_backend:'pytorch', or 'onnx'。表明检测时是使用PyTorch版本模型,还是使用ONNX版本模型。 同样的模型,ONNX 版本的预测速度一般是 PyTorch 版本的 2倍左右。 默认为 'onnx'。 -
det_more_configs:dict,识别模型初始化时传入的其他参数。具体可参考 CnSTD 文档,或者相关的源代码 CnSTD/CnStd 。 -
det_root: 检测模型文件所在的根目录。- Linux/Mac下默认值为
~/.cnstd,表示模型文件所处文件夹类似~/.cnstd/1.2/db_resnet18。 - Windows下默认值为
C:/Users/<username>/AppData/Roaming/cnstd。
- Linux/Mac下默认值为
每个参数都有默认取值,所以可以不传入任何参数值进行初始化:ocr = CnOcr()。
类CnOcr主要包含三个主要函数,下面分别说明。
1. 函数CnOcr.ocr(img_fp)
函数CnOcr.ocr()可以对任意包含文字的图片进行文字检测和识别,其中文字检测功能通过调用场景文字检测工具 CnSTD 完成。
def ocr(
self,
img_fp: Union[str, Path, Image.Image, torch.Tensor, np.ndarray],
rec_batch_size=1,
return_cropped_image=False,
**det_kwargs,
) -> List[Dict[str, Any]]:
函数说明:
-
输入参数
img_fp: 对应一张图片,- 可以是需要识别的图片文件路径;
- 或者由
Image.open()导入的Image.Image类型; - 或者是已经从图片文件中读入的数组,类型可以为
torch.Tensor或np.ndarray,取值应该是[0,255]的整数,维数应该是[height, width](灰度图片)或者[height, width, channel],channel可以等于1(灰度图片)或者3(RGB格式的彩色图片)。
-
输入参数
rec_batch_size:文字识别时可以批量进行,此值表示每次批量识别多少个文本框中的文字,默认值为1; - 输入参数
return_cropped_image:返回结果中是否返回检测出的文本框图片数据; **det_kwargs:可以为文本检测模型传入参数值,主要包含以下值:resized_shape:intortuple,tuple含义为(height, width),int则表示高宽都为此值; 检测前,先把原始图片resize到接近此大小(只是接近,未必相等)。默认为(768, 768)。 注:这个取值对检测结果的影响较大,可以针对自己的应用多尝试几组值,再选出最优值。 例如(512, 768),(768, 768),(768, 1024)等。preserve_aspect_ratio: 对原始图片resize时是否保持高宽比不变。默认为True。min_box_size: 如果检测出的文本框高度或者宽度低于此值,此文本框会被过滤掉。默认为8,也即高或者宽低于8的文本框会被过滤去掉。box_score_thresh: 过滤掉得分低于此值的文本框。默认为0.3。batch_size: 待处理图片很多时,需要分批处理,每批图片的数量由此参数指定。默认为20。
- 返回值:
List[Dict],其中的每个元素存储了对一行文字的识别结果,包含以下key:text(str): 识别出的文本score(float): 识别结果的得分(置信度),取值范围为[0, 1];得分越高表示越可信position(np.ndarrayorNone): 检测出的文字对应的矩形框;np.ndarray, shape:(4, 2),对应 box 4个点的坐标值(x, y); 注:此值只有使用检测模型时才会存在,未使用检测模型(det_model_name=='naive_det')时无此值cropped_img(np.ndarray): 当return_cropped_image==True时才会有此值。 对应position中被检测出的图片(RGB格式),会把倾斜的图片旋转为水平。np.ndarray类型,shape:(height, width, 3), 取值范围:[0, 255];- 示例:
[{'position': array([[ 31., 28.], [511., 28.], [511., 55.], [ 31., 55.]], dtype=float32), 'score': 0.8812797665596008, 'text': '第一行'}, {'position': array([[ 30., 71.], [541., 71.], [541., 97.], [ 30., 97.]], dtype=float32), 'score': 0.859879732131958, 'text': '第二行'}, {'position': array([[ 28., 110.], [541., 111.], [541., 141.], [ 28., 140.]], dtype=float32), 'score': 0.7850906848907471, 'text': '第三行'} ]
2. 函数CnOcr.ocr_for_single_line(img_fp)
如果明确知道要预测的图片中只包含了单行文字,可以使用函数CnOcr.ocr_for_single_line(img_fp)进行识别。和 CnOcr.ocr()相比,CnOcr.ocr_for_single_line()结果可靠性更强,因为它不需要做额外的分行处理。
def ocr_for_single_line(
self, img_fp: Union[str, Path, torch.Tensor, np.ndarray]
) -> Dict[str, Any]:
函数说明:
- 输入参数
img_fp: 对应一张图片,- 可以是需要识别的图片文件路径(如下例);
- 或者是已经从图片文件中读入的数组,类型可以为
torch.Tensor或np.ndarray,取值应该是[0,255]的整数,维数应该是[height, width](灰度图片)或者[height, width, channel],channel可以等于1(灰度图片)或者3(RGB格式的彩色图片)。
- 返回值:为一个
dict,对应一行文字的识别结果,包含以下key:text(str): 识别出的文本score(float): 识别结果的得分(置信度),取值范围为[0, 1];得分越高表示越可信- 示例:
{'score': 0.8812797665596008, 'text': '当前行'}
调用示例:
from cnocr import CnOcr
ocr = CnOcr()
res = ocr.ocr_for_single_line('examples/rand_cn1.png')
print("Predicted Chars:", res)
或:
from cnocr import CnOcr, read_img
ocr = CnOcr()
img_fp = 'examples/rand_cn1.png'
img = read_img(img_fp)
res = ocr.ocr_for_single_line(img)
print("Predicted Chars:", res)
3. 函数CnOcr.ocr_for_single_lines(img_list, batch_size=1)
函数CnOcr.ocr_for_single_lines(img_list)可以对多个单行文字图片进行批量预测。函数CnOcr.ocr(img_fp)和CnOcr.ocr_for_single_line(img_fp)内部其实都是调用的函数CnOcr.ocr_for_single_lines(img_list)。
def ocr_for_single_lines(
self,
img_list: List[Union[str, Path, torch.Tensor, np.ndarray]],
batch_size: int = 1,
) -> List[Dict[str, Any]]:
函数说明:
- 输入参数
img_list: 为一个图片list;其中每个元素- 可以是需要识别的图片文件路径(如下例);
- 或者是已经从图片文件中读入的数组,类型可以为
torch.Tensor或np.ndarray,取值应该是[0,255]的整数,维数应该是[height, width](灰度图片)或者[height, width, channel],channel可以等于1(灰度图片)或者3(RGB格式的彩色图片)。
- 输入参数
batch_size: 待处理图片很多时,需要分批处理,每批图片的数量由此参数指定。默认为1。 - 返回值:
List[Dict],其中的每个元素存储了对一行文字的识别结果,包含以下key:text(str): 识别出的文本score(float): 识别结果的得分(置信度),取值范围为[0, 1];得分越高表示越可信- 示例:
[{'score': 0.8812797665596008, 'text': '第一行'}, {'score': 0.859879732131958, 'text': '第二行'}, {'score': 0.7850906848907471, 'text': '第三行'} ]
调用示例:
import numpy as np
from cnocr import CnOcr, read_img, line_split
ocr = CnOcr()
img_fp = 'examples/multi-line_cn1.png'
img = read_img(img_fp)
line_imgs = line_split(np.squeeze(img, -1), blank=True)
line_img_list = [line_img for line_img, _ in line_imgs]
res = ocr.ocr_for_single_lines(line_img_list)
print("Predicted Chars:", res)
更详细的使用方法,可参考 tests/test_cnocr.py 中提供的测试用例。
各种场景的调用示例
常见的图片识别
所有参数都使用默认值即可。如果发现效果不够好,多调整下各个参数看效果,最终往往能获得比较理想的精度。
from cnocr import CnOcr
img_fp = './docs/examples/huochepiao.jpeg'
ocr = CnOcr() # 所有参数都使用默认值
out = ocr.ocr(img_fp)
print(out)
识别结果:

排版简单的印刷体截图图片识别
针对 排版简单的印刷体文字图片,如截图图片,扫描件图片等,可使用 det_model_name='naive_det',相当于不使用文本检测模型,而使用简单的规则进行分行。
使用 det_model_name='naive_det' 的最大优势是速度快,劣势是对图片比较挑剔。如何判断是否该使用此检测模型呢?最简单的方式就是拿应用图片试试效果,效果好就用,不好就不用。
from cnocr import CnOcr
img_fp = './docs/examples/multi-line_cn1.png'
ocr = CnOcr(det_model_name='naive_det')
out = ocr.ocr(img_fp)
print(out)
识别结果:
| 图片 | OCR结果 |
|---|---|
![]() |
网络支付并无本质的区别,因为 每一个手机号码和邮件地址背后 都会对应着一个账户--这个账 户可以是信用卡账户、借记卡账 户,也包括邮局汇款、手机代 收、电话代收、预付费卡和点卡 等多种形式。 |
竖排文字识别
采用来自 PaddleOCR(之后简称 ppocr)的中文识别模型 rec_model_name='ch_PP-OCRv3' 进行识别。
from cnocr import CnOcr
img_fp = './docs/examples/shupai.png'
ocr = CnOcr(rec_model_name='ch_PP-OCRv3')
out = ocr.ocr(img_fp)
print(out)
识别结果:

英文识别
虽然中文检测和识别模型也能识别英文,但专为英文文字训练的检测器和识别器往往精度更高。如果是纯英文的应用场景,建议使用来自 ppocr 的英文检测模型 det_model_name='en_PP-OCRv3_det', 和英文识别模型 rec_model_name='en_PP-OCRv3' 。
from cnocr import CnOcr
img_fp = './docs/examples/en_book1.jpeg'
ocr = CnOcr(det_model_name='en_PP-OCRv3_det', rec_model_name='en_PP-OCRv3')
out = ocr.ocr(img_fp)
print(out)
识别结果:

繁体中文识别
采用来自ppocr的繁体识别模型 rec_model_name='chinese_cht_PP-OCRv3' 进行识别。
from cnocr import CnOcr
img_fp = './docs/examples/fanti.jpg'
ocr = CnOcr(rec_model_name='chinese_cht_PP-OCRv3') # 识别模型使用繁体识别模型
out = ocr.ocr(img_fp)
print(out)
使用此模型时请注意以下问题:
-
识别精度一般,不是很好;
-
除了繁体字,对标点、英文、数字的识别都不好;
-
此模型不支持竖排文字的识别。
识别结果:

单行文字的图片识别
如果明确知道待识别的图片是单行文字图片(如下图),可以使用类函数 CnOcr.ocr_for_single_line() 进行识别。这样就省掉了文字检测的时间,速度会快一倍以上。

调用代码如下:
from cnocr import CnOcr
img_fp = './docs/examples/helloworld.jpg'
ocr = CnOcr()
out = ocr.ocr_for_single_line(img_fp)
print(out)
更多应用示例
-
核酸疫苗截图识别
-
身份证识别
-
饭店小票识别
