OCRAutoScore
OCR自动化阅卷项目
Install / Use
/learn @vkgo/OCRAutoScoreREADME
OCRAutoScore
此仓库为大创集成仓库的README介绍资料。仓库用于将各模块按照流程图一个个完成,并留下输入输出相关接口、文档。README用于说明此项目的原理、实现方式、复现方法等。
GitHub仓库地址:https://github.com/vkgo/OCRAutoScore
1 总流程图

2 模块开发规范
示例,如scoreblocks/fillblankmodel.py文件一样,写一个类,实际操作中,我们实例化这个类,然后在这个类的init中加载各使用到的模型(后面就不用每次调用都要加载了),然后使用类中各个成员函数来实现功能。而py文件中的if __name__ == "__main__":可以用来测试用。类、函数的注释中英文都行。
import paddleocr
import numpy as np
from PIL import Image
import torch
from transformers import CLIPProcessor, CLIPModel
debug = False
class model:
def __init__(self, language:str="en"):
"""
:parameter language: the language of the text, `ch`, `en`, `french`, `german`, `korean`, `japan`, type: str
"""
self.ocr = paddleocr.PaddleOCR(use_angle_cls=True, lang=language)
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.clip_model = CLIPModel.from_pretrained("openai/clip-vit-large-patch14").to(self.device)
self.clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14", device=self.device)
def recognize_text(self, _img:Image):
"""
Predict the text from image
:parameter img: image, type: np.ndarray
:return: result, type: tuple{location: list, text: str}
"""
img = np.array(_img)
result = self.ocr.ocr(img)
if debug:
print(result)
if len(result[0]) == 0:
return None
else:
location = result[0][0][0]
text = result[0][0][1][0]
return (location, text)
def judge_with_clip(self, _answer:str, _predict:str, _img:Image):
"""
Use clip to judge which one is more similar to the Image
:parameter answer: the answer text, type: str
:parameter predict: the predict text, type: str
:parameter img: image, type: np.ndarray
:return: result, the index of the more similar text, type: int
"""
image = _img
inputs = self.clip_processor(text=[f"A picture with the text \"{_answer}\"", f"A picture with the text \"{_predict}\"",
"A picture with the other text"], images=image, return_tensors="pt", padding=True)
inputs.to(self.device)
outputs = self.clip_model(**inputs)
logits_per_image = outputs.logits_per_image # this is the image-text similarity score
probs = logits_per_image.softmax(dim=1) # we can take the softmax to get the label probabilities
if debug:
print(probs)
index = torch.argmax(probs, dim=1)
return index
if __name__ == "__main__":
"""
用于测试函数
"""
debug = True
import paddle
print(paddle.device.is_compiled_with_cuda())
model = model()
while True:
img_path = input("请输入图片路径: ")
answer = input("请输入正确答案: ")
img = Image.open(img_path)
predict = model.recognize_text(img)[1]
print("预测结果: ", predict)
if (predict != answer):
print("正确结果:", answer)
index = model.judge_with_clip(answer, predict, img)
print("判断结果: ", (answer, predict, "error")[index])
3 文件目录说明
OCRAutoScore
+----scoreblocks # 填空题、选择题、作文的批改模型文件夹
| CharacterRecognition
| | +----SpinalVGG.pth # SpinalVGG模型
| | +----WaveMix.pth # WaveMix模型
| | +----example # 测试图片
| fillblank_testdata # 填空题测试图片
| MSPLM # AES模型
| +----essayscoremodel.py # 作文评分模型
| +----fillblankmodel.py # 填空题批改模型
| +----singleCharacterRecognition.py # 单字母识别模型
+----score_web # 前端网页文件夹
| | components # 前端组件
| | pages # 页面
| | routes # 路由
+----score_server # 后端文件夹
| | index
| +----models.py # 数据库模型
| +----urls.py # 接口文件
| +----views.py # 视图处理函数
+----CAN # 共识识别 CAN模型的部分依赖
+----README.assets # README的图片文件夹
+----README.md # 仓库说明文件
+----.gitignore # git忽略的文件夹、文件
4 作答区域分割-大题分割
在大题分割部分,我们使用了YOLOv8模型,通过使用老师提供的数据集进行训练,最终呈现了十分完美的效果。
4.1 YOLOv8
<img src="README.assets/62b5ed8625d6c4a157f1ee7a1c10c4e9.png" alt="YOLOv8来啦 | 详细解读YOLOv8的改进模块!YOLOv5官方出品YOLOv8,必卷! - 智源社区" style="zoom: 67%;" />YOLOv8是一个包括了图像分类、Anchor-Free物体检测和实例分割的高效算法,检测部分设计参考了目前大量优异的最新的YOLO改进算法,实现了新的SOTA。YOLOv8抛弃了前几代模型的Anchor-Base,是一种基于图像全局信息进行预测的目标检测系统。
与前代相比,YOLOv8有以下不同:
-
提供了全新的SOTA模型,包括具有P5 640和P6 1280分辨率的目标检测网络以及基于YOLACT的实例分割模型。与YOLOv5类似,还提供了不同大小的N/S/M/L/X比例模型,根据缩放系数来满足不同场景需求。
-
骨干网络和Neck部分可能参考了YOLOv7 ELAN的设计思路。在YOLOv5中,C3结构被替换为具有更丰富梯度流动性的C2f结构。对于不同比例模型进行了不同通道数量调整,并经过精心微调而非盲目应用一组参数到所有模型上,大大提高了模型性能。然而,在这个C2f模块中存在一些操作(如Split)并不像之前那样适合特定硬件部署。
-
与YOLOv5相比,在Head部分进行了重大改变,采用主流解耦头结构将分类和检测头分离,并从Anchor-Based转向Anchor-Free。
-
在损失计算策略方面,采用TaskAlignedAssigner正样本分配策略以及引入Distribution Focal Loss。
-
在训练过程中进行数据增强时,引入自YOLOX关闭Mosaic增强操作后10个epoch可以有效提高准确性。
YOLOv8作为一种实时目标检测算法,可能被应用于多种场景,包括但不限于:
- 无人驾驶汽车:实时检测道路上的行人、车辆、交通信号等目标,为自动驾驶系统提供关键信息。
- 视频监控:实时检测和跟踪安全系统中的异常行为,如闯入、偷窃等。
- 工业自动化:用于产品质量检测、机器人导航等领域。
- 无人机航拍:实时目标检测和跟踪,为无人机提供导航和避障能力。
此处,我们将其应用于大题分割,也就是,在我们提供的整张试卷中,找到对应的大题(如:客观题、填空题、主观题等)。
4.2 单独执行大题分割
大题分割源码在segmentation/Layout4Card,也可以通过URL进入我们仓库中大题分割的目录查看、复制、运行,需要更多的支持,可以查看文档。
infer.py是一个推理代码的示范,在这之中:
- CLS_ID_NAME_MAP是一个字典,里面有我们支持的识别类别和它对应的index。
- model是载入模型,此处可以使用我们训练好的模型不需要改动。
- folder是将要测试的图片的目录,可以换为测试图片。
- 运行后,由于
model.predict(source=imgs, save=True, imgsz=640)中的save=True,文件将被村粗在segmentation/Layout4Card/run目录之下。
CLS_ID_NAME_MAP = {
0: 'student_id',
1: 'subjective_problem',
2: 'fillin_problem',
3: 'objective_problem'
}
model = YOLO(model='./runs/detect/train3/weights/best.pt')
folder = './testdata'
file_names = os.listdir(folder)
random.shuffle(file_names)
imgs = []
for file_name in file_names[:10]:
img_path = os.path.join(folder, file_name)
img = cv2.imread(img_path)
imgs += [img]
results = model.predict(source=imgs, save=True, imgsz=640)
4.3 样例
cd .\segmentation\Layout4Card\
python .\infer.py

保存的图片如下::
<img src="README.assets/image-20230422110135175.png" alt="image-20230422110135175" style="zoom: 33%;" />5 作答区域分割-小题分割
5.1 工具
opencv-python 4.5.5.62
5.2 具体实现
(1) 图片预处理
将输入的填空题图片处理成二值图片

(2) 保留水平线
对二值图片进行腐蚀处理,保留图片中的水平线,其余不相关的笔迹

(3) 消除干扰的水平线
对所有水平线的位置进行排序,排序法则为垂直方向降序,水平方向升序。根据上图排序结果如下:

遍历所有定位,获取当前的水平线(在此水平线被视为宽度小于长度的矩形,每条边的存储形式为[x,y,w,h])的位置(x, y),并标记当前的y坐标,给定hmin与hmax,设置高度范围限制(y - hmax,y - hmin),记录处于该范围的定位,若遇见范围外的,更新y坐标和高度限制。 遍历结束后将标记的目标移除,剩下的即为检测目标。
最后再进行升序排序,进行遍历。得到检测的效果如下所示:

5.3 使用说明
cd segmentation/blankSegmentation
python blank_segmentation.py
根据提示输入识别的文件夹路径,确定Debug模式
在Debug模式下会在debug文件夹中输出扫描结果,如样例所示:

6 选择题模型
6.1 数据集
使用EMNIST数据集的letters部分,该部分只包含手写字母数据,适合作为选择题单字母模型数据集。
6.2 模型框架
6.2.1 SpinalNet模型

模型参考地址:https://github.com/dipuk0506/SpinalNet
该神经网络模拟的是人体的躯体感觉系统。该神经网络的特点主要有:神经丛结构(体现在中间层),全局影响与局部输出等。
神经网络模型流向:输入层->中间层->输出层
中间子层接收输入的方向有输入层和前一个中间子层的输入。
6.2.2 WaveMix模型

模型参考地址:https://github.com/pranavphoenix/WaveMix
WaveMix模型主要利用2D离散小波变换(DWT)对空间特征进行混合,无需展开图像与自我注意力机制,利用自身图像的2D结构来提高泛化能力。
6.3 模型实现
6.3.1 SpinalNet模型
输入层先将输入的数据传入卷积层提取特征,提取的特征分成几个部分,传入不同的中间层,最后将特征合并,经过线性层输入分类结果。
6.3.2 WaveMix模型
图像首先经过卷积层,再进入一系列WaveMix块(WaveMix块里主要做离散小波变换,再按序传到具有GELU的MLP层、转置卷积层与BatchNorm层),之后进入MLP Head,再通过全局平均池化层得到分类输出层。
6.4 模型训练
模型训练地址:https://github.com/YouHui1/Character_Recognition
python train.py -k number
number == 1 时选择SpinalNet模型,
number == 2 时选择WaveMix模型
训练前可在config.py里修改模型类型,训练轮数,学习率,batchsize等等。
训练完毕后,训练日志存储在log文件夹中,模型参数存储在param文件夹中
6.4 模型使用说明
将训练后的模型参数保存在某一路径中(本项目保存在CharacterRecognition文件夹中)
运行singleCharacterRecognition.py文件,根据提示输入识别单字母图片的文件夹路径,输出为字母识别结果
7 填空题模型-中英文识别
中英文识别部分,我们使用PaddlePaddleOCR+Clip来实现识别+评判的中英文填空题批改。
7.1 PaddlePaddleOCR
PaddlePaddleOCR是一个基于PaddlePaddle深度学习框架的免费、开源的OCR(Optical Character Recognition,光学字符识别)项目。它由百度开源并持续维护。PaddlePaddleOCR旨在提供一个易于使用、高性能、多语言支持的OCR解决方案。
该项目结合了最新的深度学习技术和实际应用需求,致力于为开发者提供一个简单易用、功能强大的OCR工具库。其支持的场景包括但不限于印刷体、手写体、场景文本的识别等。
7.1.1 选择PPOCR的原因
PaddlePaddleOCR在许多OCR竞赛中取得了优异的成绩,表现出了良好的泛化能力和性能。它被广泛应用于包括智能办公、金融、医疗、教育等多个领域。
PaddlePaddleOCR具有以下主要功能与特性:
- 多任务支持:PaddlePaddleOCR支持多种OCR任务,包括文本检测、方向分类、文本识别等,可灵活应对各种场景。
- 多语言支持:项目支持多种语言的识别,包括英文、中文、法文、德文、日文等,适用于国际化场景。
- 易于使用:PaddlePaddleOCR提供了丰富的API接口和预训练模型,开发者可以快速上手并实现自定义需求。
- 高性能:项目结合了最新的深度学习技术,包括卷积神经网络(CNN)和长短时记忆网络(LSTM),确保了较高的识别准确率和性能。
- 实时性:PaddlePaddleOCR在保证识别准确率的同时,关注实时性,可以满足实时场景下的OCR需求。
通过这些功能与特性,PaddlePaddleOCR为开发者提供了一个高效、易用、可扩展的OCR解决方案,是我们调研之后,对中文手写字体识别最好的一个开源项目。
7.1.2 PPOCR的基本结构
PaddlePaddleOCR的项目架构主要包括以下几个部分:
- 文本检测:文本检测模块负责在图像中定位文本区域。PaddlePaddleOCR提供了多种检测算法,如DB(Differentiable Binarization)、EAST(Efficient and Accurate Scene Text Detector)等,以满足不同场景下的检测需求。
- 方向分类:方向分类模块用于判断检测到的文本区域的方向,主要针对旋转文本进行处理。这有助于将文本区域校正到统一方向,为后续的文本识别做好准备。
- 文本识别:文本识别模块负责从校正后的文本区域中提取文本信息。PaddlePaddleOCR采用了CRNN(Convolutional Recurrent Neural Network)等先进算法进行文本识别,以实现高准确率的字符识别。
- 模型训练与优化:PaddlePaddleOCR提供了丰富的预训练模型和训练脚本,支持用户根据自己的数据集进行模型训练。此外,项目还提供了模型优化工具,帮助用户在保持准确率的同时,降低模型复杂度,提高推理速度。
- 推理部署:PaddlePaddleOCR支持多种部署方式,包括Python API、C++ API和服务端部署。项目提供了易用的部署工具和教程,使得OCR功能能够方便地集成到各种应用中。
- 工具与API:PaddlePaddleOCR提供了多种工具和API,帮助用户快速上手项目并实现自定义功能。例如,项目提供了可视化工具,方便用户对检测与识别结果进行分析。
这个架构确保了PaddlePaddleOCR可以适应不同场景的文本识别需求,同时易于开发者使用和定制。

7.1.3 预训练模型
PaddlePaddleOC
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.8kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
