一、PP-OCR历史简要回顾
先请出PP-OCR官网,理解上有出入的,以官网为准。
1.1 PP-OCR系列历史
- PP-OCRv1(2020):首创3.5M超轻量模型,奠定两阶段架构基础(检测+方向分类+识别)
- PP-OCRv2(2021):引入知识蒸馏和增强数据策略,检测精度提升5%
- PP-OCRv3(2022):采用SVTR识别架构,中文识别准确率突破80%
- PP-OCRv4(2023):融合Transformer与CNN的混合架构,实现多维度性能突破
1.2 PP-OCRv4核心技术升级
检测模块四大创新:
- LCNetV3:通过可学习仿射变换模块增强特征提取能力,Hmean提升0.84%
- PFHead:并行多尺度特征融合结构,使小文本检测召回率提升3.2%
- DSR策略:动态调整收缩比例(0.4→0.6),提升弯曲文本适应能力
- CML蒸馏:KL散度损失优化师生网络交互,模型泛化性提升
二、PP-OCRv4的技术强项
2.1 极致的轻量化设计
- 移动端模型仅17M(检测4.7M+分类1.4M+识别10M)
- 量化后模型体积缩减60%,CPU推理速度达76ms/帧
2.2 多场景高精度表现
场景类型 | v3准确率 | v4准确率 | 提升幅度 |
---|---|---|---|
中文印刷体 | 71.5% | 75.8% | +4.3% |
英文手写体 | 64.0% | 70.1% | +6.1% |
阿拉伯语系 | 72.9% | 75.5% | +2.6% |
(数据来源:PaddleOCR官方技术报告) |
2.3 多语言支持能力
- 新增缅甸语、希伯来语等小语种支持,总支持语言达83种
- 混合语种识别准确率超75%(如中英混排场景)
2.4 动态适应能力
- 多尺度训练策略:随机选择32/48/64三种高度进行训练
- 自适应图像处理:最大边限制960px时,长宽比>3的文本识别准确率提升12%
三、实践指南:从入门到进屋
3.1 环境搭建
# 创建虚拟环境
conda create -n paddleocr python=3.9
conda activate paddleocr
# 安装依赖
pip install paddlepaddle paddleocr opencv-python
# 命令行快速识别
paddleocr --image_dir ./imgs/11.jpg --use_angle_cls true
亲测,即使不用镜像下载安装速度也可以的。
3.2 简单中文图片识别
import torch
from paddleocr import PaddleOCR
# 初始化识别器(自动下载预训练模型)
ocr = PaddleOCR(use_angle_cls=True, lang='ch') # 自动处理旋转文本
# 执行OCR识别
img_path = 'pic002.png' # 测试图片路径
result = ocr.ocr(img_path, cls=True)
# 解析并打印结果
for line in result[0]: # result[0]表示第一张图片的识别结果
coordinates = line[0] # 文字框坐标(四点坐标)
text = line[1][0] # 识别文本
confidence = line[1][1] # 置信度(0~1)
print(f"位置:{coordinates}")
print(f"内容:{text} | 可信度:{confidence:.2%}")
print("-" * 40)
同样的一张图片,PP-OCRv4的识别效果最好,结果如下:
[2025/03/30 13:20:33] ppocr DEBUG: dt_boxes num : 3, elapsed : 0.20115971565246582
[2025/03/30 13:20:33] ppocr DEBUG: cls num : 3, elapsed : 0.06674575805664062
[2025/03/30 13:20:33] ppocr DEBUG: rec_res num : 3, elapsed : 0.2163543701171875
位置:[[1.0, 8.0], [107.0, 8.0], [107.0, 30.0], [1.0, 30.0]]
内容:五、中文识别 | 可信度:99.95%
----------------------------------------
位置:[[2.0, 56.0], [141.0, 56.0], [141.0, 78.0], [2.0, 78.0]]
内容:六、高级应用场景 | 可信度:99.67%
----------------------------------------
位置:[[6.0, 76.0], [173.0, 78.0], [173.0, 101.0], [6.0, 98.0]]
内容:5.1结构化数据提取 | 可信度:99.81%
关于一个报错
OSError: [WinError 127] 找不到指定的程序。 Error loading “D:\xxxx.venv\Lib\site-packages\torch\lib\shm.dll” or one of its dependencies.
最开始遇到这个问题真是莫名其妙,找到资料也都怀疑是我安装的库有问题,索性把torch和paddleocr都重装了。继续按照官方的快速入门文档编写运行,依然报错。
就尝试一步步调试,先在python控制台中确认torch安装是否成功,import后,再次运行paddleocr,结果可以。
就尝试把import torch加上,一试果然成功。罢了罢了!
3.3 车牌识别
import torch
from paddleocr import PaddleOCR
import cv2
import re
class PlateRecognizer:
def __init__(self):
self.ocr = PaddleOCR(
use_angle_cls=True,
lang="ch",
det_db_thresh=0.5,
rec_image_shape="3, 48, 320",
show_log=False # 关闭调试日志
)
self.plate_pattern = re.compile(
r'^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}'
r'[A-Z]{1}'
r'([A-Z0-9]{5}|[A-Z0-9]{4}[A-Z0-9学警港澳]{1})$' # 扩展新能源车牌格式
)
self.province_short = ['京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑', '湘',
'皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘', '晋',
'蒙', '陕', '吉', '闽', '贵', '粤', '青', '藏', '川', '宁', '琼']
def preprocess(self, img):
# 灰度化 + CLAHE增强
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
return clahe.apply(gray)
def recognize_plate(self, img_path):
try:
raw_img = cv2.imread(img_path)
if raw_img is None:
raise ValueError("无法读取图像文件")
processed_img = self.preprocess(raw_img)
# 调试:预处理图像
cv2.imshow("debug_preprocess", processed_img)
cv2.waitKey(0)
# 执行OCR识别
result = self.ocr.ocr(processed_img)
print(f'resuilt:{result}')
if not result or not result[0]:
return "未识别到有效字符"
# 合并结果并筛选高置信度
texts = []
for line in result[0]:
if line[1][1] > 0.6: # 置信度阈值
texts.append(line[1][0].upper())
combined = ''.join(texts)
print(f'combined:{combined}')
# 后处理修正
final_text = self.postprocess2(combined)
return final_text if final_text else "无法识别有效车牌"
except Exception as e:
return f"处理异常: {str(e)}"
def postprocess2(self, text):
# 替换易混淆字符
replace_rules = {
'O': '0', 'I': '1',
'-': '',
'·': '', ' ': '', '_': ''
}
corrected = ''.join([replace_rules.get(c, c) for c in text.upper()])
print(f'corrected={corrected}')
province_chars = ''.join(self.province_short)
valid_pattern = fr'[^{province_chars}A-Z0-9学警港澳使领]'
# 过滤所有非字母数字字符
corrected = re.sub(valid_pattern, '', corrected.upper())
print(f'corrected={corrected}')
# 长度校验(新能源车牌可能8位)
if 7 <= len(corrected) <= 8:
# 调整正则表达式
patterns = [
r'^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领])'
r'([A-Z])'
r'([0-9A-Z]{5})$', # 普通车牌
r'^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领])'
r'([A-Z])'
r'([0-9A-Z]{5}[0-9A-Z学警港澳])$' # 新能源/特殊车牌
]
for pattern in patterns:
match = re.match(pattern, corrected)
if match and match.group(1) in self.province_short:
return match.group()
return None
# 使用示例
if __name__ == "__main__":
recognizer = PlateRecognizer()
print(recognizer.recognize_plate("pic006.png"))
上述实现,在图像预处理上没有做太多。请读者自行研究,这是一门大学问。
在车牌识别的结果上,强于很多库和模型了。
resuilt:[[[[[38.0, 48.0], [926.0, 41.0], [927.0, 240.0], [39.0, 247.0]], ('粤C-F12345', 0.9607976078987122)]]]
combined:粤C-F12345
粤CF12345
resuilt:[[[[[58.0, 57.0], [966.0, 57.0], [966.0, 287.0], [58.0, 287.0]], ('粤C·D12345', 0.9694777727127075)]]]
combined:粤C·D12345
粤CD12345
近期小结
连续调研了三个OCR库(模型或方案),给出下面一个简单的对比。
测试集 | EasyOCR | PaddleOCR | Tesseract |
---|---|---|---|
CTW3000 | 89.7% | 91.2% | 72.5% |
ICDAR2015 | 85.3% | 87.9% | 68.4% |
自建票据 | 93.1% | 90.5% | 65.2% |