基于opencv答题卡识别判卷

我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万+粉丝,拥有2篇国家级人工智能发明专利。

社区特色:深度实战算法创新

获取全部完整项目数据集、代码、视频教程,请进入官网:zzgcz.com。竞赛/论文/毕设项目辅导答疑,v:zzgcz_com


1. 项目简介

本项目旨在开发一种自动化的试卷判分系统,通过图像处理技术对试卷中的多选题答案进行识别和评分。该项目采用了基于OpenCV的图像处理方法和深度学习模型,主要用于识别扫描图像中的试卷内容,提取考生的作答区域,并根据预设的正确答案进行自动评分。项目的核心技术包括边缘检测、轮廓识别、透视变换和Otsu阈值分割等。通过一系列图像处理操作,将输入的试卷图片转化为标准化的矩形结构,并根据候选区域的轮廓特征确定每道题目的答案。该项目的应用场景包括教育评估、考试系统自动化和作业批改等。最终实现了通过图像识别对多选题进行准确评分,极大提高了试卷批改的效率和准确性。
在这里插入图片描述

2.技术创新点摘要

本项目的主要创新点在于结合经典的图像处理技术与深度学习思想,实现了自动化试卷判分系统的准确答案识别和评分。项目中采用了一系列图像处理方法,包括边缘检测、透视变换、轮廓分析和Otsu阈值分割,这些技术相互配合,在无训练数据的情况下实现了对目标区域(试卷答案区)的精确定位和特征提取。此外,该系统通过对轮廓的几何特征进行分析和排序来定位每个答案的候选区域,并结合自定义规则(例如宽高比和面积等几何特征)过滤噪声区域,从而保证了答案提取的准确性和稳定性。

在答案识别部分,项目中采用了一个基于轮廓面积的局部特征提取方法,通过对每个选项区域的非零像素点数量进行统计,并使用最大值策略选择出考生最有可能的答案。这种方法的优势在于能够适应不同类型的扫描图像和字体大小变化,同时消除了因图像光照或模糊导致的噪声干扰。该项目还集成了自定义的答案映射表,通过与预设的答案键进行比对,实现了快速评分。

整体架构设计的亮点在于,通过图像预处理和深度学习思路的结合,实现了图像中复杂目标的精确识别和分类。在技术细节上,系统的创新体现在以下几个方面:1) 通过多种图像变换(如透视变换)将任意角度的试卷图像进行标准化处理,从而避免了输入图像角度不一致导致的定位误差;2) 通过Otsu阈值法实现了自适应的答案区分割策略,使得系统能在不同光照条件下保持较高的分割精度;3) 利用局部轮廓排序方法和面积分析准确定位每道题目答案,并结合深度学习框架中的卷积思想,通过逐像素计算非零值的分布特征,最终实现了高效的答案匹配与评分。该系统能够大幅提升传统考试批改工作的效率和准确度,是对传统试卷处理方式的有效改进。

3. 数据集与预处理

本项目主要处理的是扫描的试卷图像数据集,数据集的来源可以是扫描的纸质试卷或拍摄的电子试卷图像。这类数据集通常具有以下特点:图像分辨率和质量不一致、拍摄角度存在偏差、不同光照条件下可能出现局部阴影或模糊等问题。因此,在数据处理过程中,需要针对这些问题进行相应的图像预处理操作,以确保答案区域的提取和答案识别的准确性。

数据预处理流程:

  1. 图像读取与灰度化:首先将输入的彩色图像转换为灰度图,这一步骤能够有效降低计算复杂度,并消除颜色信息的干扰,使得后续的边缘检测更加稳定。
  2. 图像平滑与去噪:使用高斯模糊对图像进行平滑处理,减少图像中因噪声造成的误差。通过设置合适的滤波器大小,可以在保留主要轮廓特征的同时消除图像中的小噪声点。
  3. 边缘检测:采用Canny边缘检测算法提取图像中的明显边缘,便于后续轮廓的定位与提取。边缘检测能够帮助定位试卷区域以及答案区域的轮廓特征。
  4. 轮廓检测与排序:在检测到的边缘图中提取所有可能的轮廓,并通过轮廓面积和形状特征(如长宽比和位置)对答案区域进行排序和筛选。最终将包含候选答案的区域筛选出来,并按指定顺序排列,确保后续答案识别时不发生错位。
  5. 透视变换与图像矫正:为了消除图像拍摄角度和试卷摆放角度对答案定位的影响,使用透视变换将不规则的图像转换为标准的矩形图像。透视变换能够矫正图像中的倾斜角度,使试卷区域与参考答案的匹配更加精准。
  6. 二值化处理:使用Otsu自适应阈值分割法对矫正后的图像进行二值化处理,进一步提升答案区域的清晰度,确保在复杂光照条件下仍然能够分割出有效的答案区域。

4. 模型架构

1) 模型结构的逻辑

该项目的代码主要基于图像处理算法来完成答案识别与评分,而不是传统的深度学习模型。因此,并没有标准的神经网络层结构,但在图像处理的各个步骤中,包含了许多数学模型和算法逻辑。以下是主要的模型逻辑描述及其数学公式:

  • 图像灰度化 (Grayscale Conversion) : 使用OpenCV中的cv2.cvtColor函数将彩色图像转换为灰度图像。数学上,每个像素点的灰度值可以表示为:
  • G r a y = 0.299 × R + 0.587 × G + 0.114 × B Gray = 0.299 \times R + 0.587 \times G + 0.114 \times B Gray=0.299×R+0.587×G+0.114×B
  • 其中,R,G,B 分别表示红、绿、蓝通道的值。
  • 图像平滑与高斯模糊 (Gaussian Blurring) : 使用高斯模糊处理来降低噪声并平滑图像,采用 cv2.GaussianBlur。高斯模糊的数学表示为:
  • G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x, y) = \frac{1}{2\pi\sigma^2} e^{-\frac{x^2 + y^2}{2\sigma^2}} G(x,y)=2πσ21e2σ2x2+y2
  • 其中,σ 为高斯函数的标准差。
  • Canny边缘检测 (Canny Edge Detection) : 用于提取图像的边缘,通过计算图像的梯度变化来检测边缘。其数学表示为:
  • G = G x 2 + G y 2 G = \sqrt{G_x^2 + G_y^2} G=Gx2+Gy2
  • 其中,Gx 和 Gy 分别表示图像在 x 和 y 方向的梯度值。
  • 透视变换与矩阵映射 (Perspective Transform) : 使用四点透视变换将图像转换为标准矩形。映射矩阵 MMM 的计算公式为:
  • [ x ′ y ′ 1 ] = M × [ x y 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = M \times \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} xy1 =M× xy1
  • 其中,M 是基于输入坐标和输出坐标计算的3x3矩阵,[x,y,1] 为输入坐标,[x′,y′,1] 为输出坐标。
  • Otsu自适应阈值分割 (Otsu’s Binarization) : 使用Otsu方法计算最佳的全局阈值,以最小化类间方差。目标是找到一个阈值 ttt 使得图像的类内方差最小:
  • σ w 2 ( t ) = q 1 ( t ) σ 1 2 ( t ) + q 2 ( t ) σ 2 2 ( t ) \sigma^2_w(t) = q_1(t)\sigma^2_1(t) + q_2(t)\sigma^2_2(t) σw2(t)=q1(t)σ12(t)+q2(t)σ22(t)
  • 其中,q1 和 q2 是两类像素点的概率分布,σ12 和 σ22 是两类的方差。

2) 模型的整体训练流程

虽然本项目没有传统的深度学习训练流程,但可以将其看作一个基于图像处理的“训练”过程,其中包含以下步骤:

  1. 数据准备:项目使用输入的扫描图像作为数据源,并且不需要进行复杂的数据预处理(如数据增强、归一化等),只需对输入的图像进行灰度化和边缘检测处理。
  2. 特征提取与处理:通过轮廓检测和透视变换,将试卷中每个多选题的答案区域定位并提取出来。特征提取过程中,主要使用几何特征(轮廓面积、宽高比、位置)来判断是否属于有效的候选区域。
  3. 答案匹配与评分:使用非零像素统计法对每个答案区域进行特征提取,并与预设的答案进行比对。在答案比对过程中,使用了如下判别逻辑:

s c o r e = 正确答案数 总题目数 × 100 score = \frac{\text{正确答案数}}{\text{总题目数}} \times 100 score=总题目数正确答案数×100

这里,正确答案数是通过与预设答案进行逐个比对得到的。

  1. 模型评估与指标:本项目的核心评估指标是“答案识别准确率”,通过下述公式计算:

准确率 = 正确识别的答案个数 所有识别的答案总数 \text{准确率} = \frac{\text{正确识别的答案个数}}{\text{所有识别的答案总数}} 准确率=所有识别的答案总数正确识别的答案个数

本项目的目标是将识别准确率提升到接近100%,确保每个扫描图像都能够被精准判分。

整体来看,本项目通过图像处理技术(而非传统深度学习模型)完成了试卷答案的识别、定位与评分,并且引入了透视变换、Otsu自适应阈值等多种处理策略来提升系统在不同环境下的鲁棒性与准确性。

5. 核心代码详细讲解

1. 读取输入图像并进行灰度化和边缘检测
# 读取输入图像并生成副本
image = cv2.imread(args["image"])
contours_img = image.copy()
# 将图像转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  • cv2.imread(args["image"]): 从指定路径读取输入图像文件,并以彩色图像格式加载。
  • contours_img = image.copy(): 创建一个图像副本,用于后续画出轮廓时使用,避免修改原始图像。
  • cv2.cvtColor(image, cv2.COLOR_BGR2GRAY): 将原始彩色图像转换为灰度图像,减少颜色信息的干扰,同时降低计算复杂度。
# 进行高斯模糊处理,减少噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
  • cv2.GaussianBlur(gray, (5, 5), 0): 应用5x5大小的高斯模糊滤波器来平滑图像,以去除小的噪声点,使得后续边缘检测更加稳定。参数 (5, 5) 表示高斯核的大小,0 表示根据内置算法自适应地计算标准差。
# 使用Canny边缘检测,提取图像的边缘
edged = cv2.Canny(blurred, 75, 200)
  • cv2.Canny(blurred, 75, 200): 使用Canny算法提取图像边缘。Canny算法采用了双阈值方法,75 是最小阈值,200 是最大阈值。这一步能够提取出图像中的显著边缘,便于轮廓的检测和定位。
2. 检测并排序轮廓
# 使用findContours函数检测图像中所有的轮廓
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
# 在图像中绘制所有轮廓
cv2.drawContours(contours_img, cnts, -1, (0, 0, 255), 3)
  • cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE): 识别二值化图像中的轮廓。参数 cv2.RETR_EXTERNAL 仅检测外部轮廓,cv2.CHAIN_APPROX_SIMPLE 使用点近似算法来减少存储每个轮廓点的数量。
  • cv2.drawContours(contours_img, cnts, -1, (0, 0, 255), 3): 在图像副本中绘制所有检测到的轮廓,-1 表示绘制所有轮廓,颜色为红色 (0, 0, 255),线条宽度为 3 像素。
3. 透视变换与图像矫正
# 执行透视变换以获取标准化的试卷区域
warped = four_point_transform(gray, docCnt.reshape(4, 2))
  • four_point_transform(gray, docCnt.reshape(4, 2)): 调用自定义函数 four_point_transform,通过将轮廓点映射到标准矩形坐标系中,矫正图像角度,消除图像拍摄角度不一致带来的误差。
def four_point_transform(image, pts):# 按顺序排列输入的4个顶点坐标rect = order_points(pts)(tl, tr, br, bl) = rect...# 计算透视变换矩阵,并对图像进行变换M = cv2.getPerspectiveTransform(rect, dst)warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))return warped
  • order_points(pts): 先对输入的四个顶点进行排序,确保四个角点分别对应左上、右上、右下和左下。
  • cv2.getPerspectiveTransform(rect, dst): 计算透视变换矩阵 M,根据输入顶点和目标顶点位置进行图像变换。
  • cv2.warpPerspective(image, M, (maxWidth, maxHeight)): 执行透视变换,将原图像变换为矩形的标准形态。
4. 二值化处理和答案识别
# 对矫正后的图像进行二值化处理,区分背景与前景
thresh = cv2.threshold(warped, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
  • cv2.threshold(warped, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU): 使用Otsu阈值法进行二值化处理,将图像分为前景(白色)和背景(黑色)。cv2.THRESH_BINARY_INV 表示使用二值反转(即前景为白色时显示为黑色)。
# 检测并筛选出可能的答案圆圈轮廓
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
  • 再次使用 cv2.findContours 检测二值化图像中的圆圈轮廓,并按比例和大小特征进行筛选,确定为有效的候选答案区域。
5. 选项识别与答案评分
# 对每个题目的候选区域进行特征提取,并进行答案比对for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):# 按从左到右顺序对候选区域进行排序cnts = sort_contours(questionCnts[i:i + 5])[0]bubbled = Nonefor (j, c) in enumerate(cnts):# 创建掩码图像,仅保留当前轮廓mask = np.zeros(thresh.shape, dtype="uint8")cv2.drawContours(mask, [c], -1, 255, -1)# 计算掩码区域的非零像素数量total = cv2.countNonZero(mask)if bubbled is None or total > bubbled[0]:bubbled = (total, j)
  • mask = np.zeros(thresh.shape, dtype="uint8"): 创建一个与原图同大小的全黑掩码图像。
  • cv2.drawContours(mask, [c], -1, 255, -1): 在掩码图像上填充当前轮廓区域,使其为白色(前景)。
  • cv2.countNonZero(mask): 统计当前掩码图像中非零像素点的数量,判断考生在该选项处是否涂黑。

6. 模型优缺点评价

该项目的模型优势在于基于图像处理的非深度学习方法,通过经典的边缘检测、轮廓分析、透视变换和Otsu阈值等图像处理技术,在无训练数据的情况下实现了高效的答案区域提取和答案判别。该方法的优点主要体现在以下几个方面:1) 计算效率高:与深度学习模型相比,不需要大量计算资源即可完成多选题答案识别。2) 鲁棒性好:在不同图像分辨率、拍摄角度和光照条件下,经过预处理后的图像仍然能够稳定识别答案区域。3) 实现简单:不需要复杂的模型训练流程和大规模数据集,易于部署和维护。

然而,该模型也存在一定局限性:1) 无法处理复杂背景或噪声严重的图像:依赖于图像的清晰边缘和稳定的轮廓特征,当图像质量较差时(如模糊、强光反射、角度偏差过大),识别效果可能不理想。2) 缺乏通用性:仅能处理预定义格式的标准化试卷,对于其他类型的文档(如含有文本、表格等)适用性较差。3) 灵活性不足:无法动态适应答案区域位置变化(如多选题的题目数量和选项数量不同)。

改进方向:1) 引入深度学习模型:可以考虑使用深度学习的目标检测模型(如YOLO或Faster R-CNN)来替代传统的轮廓检测,从而提高复杂背景下的答案区域定位能力。2) 加入数据增强:在图像预处理时使用数据增强策略(如随机旋转、裁剪、噪声注入等),提高模型在不同拍摄条件下的鲁棒性。3) 优化透视变换算法:加入更复杂的几何校正方法,以适应更多种类的拍摄角度和变形情况,进一步提升模型的稳定性与识别精度。

↓↓↓更多热门推荐:
钢板表面缺陷检测基于HRNET模型
基于opencv的人脸闭眼识别疲劳监测

全部项目数据集、代码、教程进入官网zzgcz.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/446326.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Qt】窗口预览(1)—— 菜单栏

窗口预览(1) 1. QMainWindow2. QMenuBar——菜单栏2.1 创建菜单栏/将菜单栏添加到widget中2.2 addMenu——在菜单栏中添加菜单2.3 在菜单中添加选项2.4 添加快捷键2.5 支持嵌套添加菜单2.6 添加信号2.7 添加分割线 1. QMainWindow Qt窗口是通过QMainWin…

基于SSM框架学籍管理系统的设计与实现

我 | 在这里 ⭐ 全栈开发攻城狮、全网10W粉丝、2022博客之星后端领域Top1、专家博主。 🎓擅长 指导毕设 | 论文指导 | 系统开发 | 毕业答辩 | 系统讲解等。已指导60位同学顺利毕业 ✈️个人公众号:乡下小哥编程。回复 Java全套视频教程 或 前端全套视频教…

微信小程序和抖音小程序的分享和广告接入代码

开发完成小程序或者小游戏之后,我们为什么要接入分享和广告视频功能,主要原因有以下几个方面。 微信小程序和抖音小程序接入分享和广告功能主要基于以下几个原因: 用户获取与增长:分享功能可以帮助用户将小程序内容传播给更多人&…

# 在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 分析

在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 分析 一、问题描述: 在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 如下图: 二、报错分析&…

【HarmonyOS NEXT】实现页面水印功能

关键词:鸿蒙、水印、Watermark、页面、触摸问题 注:本期文章同样适用 OpenHarmony 的开发 在app开发过程中时常会出现敏感信息页面,为保护信息安全和及时的数据追踪,通常会采用给页面加水印的形式,那么本期文章会介绍…

ARC学习(4)基本编程模型认识(四)----寄存器以及异常数据读取

笔者来聊一下ARC寄存器的获取 在介绍了ARC编程模型的知识点之后,来看一些具体的编程操作,比如如何获取寄存器,如何编写汇编语言实现特定功能? 1、获取寄存器 可以使用内联汇编来实现寄存器的获取,具体格式如下: _Asm:汇编宏标识符,指示内联汇编代码_Save_all_regs:…

轻量服务器和云服务器ecs哪个好用一些?

轻量服务器和云服务器ecs哪个好用一些?轻量服务器与云服务器ECS在多方面存在显著差异,对于需要高性能计算和大规模数据处理的用户来说,ECS可能是更好的选择;而对于预算有限且需求较为简单的用户来说,轻量服务器可能更为…

Node.js入门——fs、path模块、URL端口号、模块化导入导出、包、npm软件包管理器

Node.js入门 1.介绍 定义:跨平台的JS运行环境,使开发者可以搭建服务器端的JS应用程序作用:使用Node.Js编写服务器端代码Node.js是基于Chrome V8引擎进行封装,Node中没有BOM和DOM 2.fs模块-读写文件 定义:封装了与…

分布式事务管理-Seata从入门到精通

一、基本概念 什么是数据库事务? 1、一个操作数据库数据的执行单元 2、到围从开始到结束的多个操作组成 3、事务内的多个操作要么都成功,要么都失败 什么是分布式事务? 1.分布式场景下,完成某一个业务功能可能需要横跨多个服务&#xff0…

jmeter入门:脚本录制

1.设置代理。 网络连接-》代理-》手动设置代理. ip: 127.0.0.1, port:8888 2. add thread group 3. add HTTP(s) test script recorder, target controller chooses Test plan-> thread Group 4. click start. then open the browser …

AIGC毕设项目分享:基于RAG的数字人对话系统及其应用

本研究的主要目标是设计并实现一个基于检索增强生成(RAG)技术的数字人对话系统,旨在提升数字人系统在多轮对话中的上下文管理、情境感知能力以及动态内容生成效果。系统结合了深度学习中的最新大语言模型技术,通过引入RAG框架来增…

ubuntu下route命令详解

buntu下route命令详解 1、显示路由表 route -n2、临时路由设置,重启网卡失效#添加一条路由(发往192.168.62这个网段的全部要经过网关192.168.1.1)route add -net 192.168.62.0 netmask 255.255.255.0 gw 192.168.1.1#删除一条路由 删除的时候不用写网关route del …

华为海思:大小海思的双轮驱动战略分析

华为海思,作为华为旗下的半导体设计部门,近年来在芯片设计领域取得了显著成就,成为了中国乃至全球芯片设计的重要力量。实际上,华为海思并非单一实体,而是由两个主要分支构成:大海思和小海思。这两个分支虽然同属华为海思,但在定位、产品布局以及市场策略上有所不同,共…

【测试】BUG篇——BUG

bug的概念 定义:⼀个计算机bug指在计算机程序中存在的⼀个错误(error)、缺陷(flaw)、疏忽(mistake)或者故障(fault),这些bug使程序⽆法正确的运⾏。Bug产⽣于程序的源代码或者程序设计阶段的疏忽或者错误。 准确的来说: 当且仅当规格说明&am…

【大数据技术基础 | 实验二】Linux基础:常用基本命令和文件操作

文章目录 一、实验目的二、实验要求三、实验环境四、常用基本命令1、验证cd和pwd命令2、验证ls命令3、验证mkdir命令4、验证cp、mv和rm命令 五、Linux文件操作1、验证touch命令2、验证cat命令3、验证more命令 六、实验心得 一、实验目的 学会linux常用命令(cd,ls,pwd,mkdir,rm…

【Flutter】合并多个流Stream

1.说明 无意间发现了一个好用的库rxdart,它为 Dart 的 Stream 添加了额外的功能。 2.功能 (1)合并多个流Stream 借助Rx.combineLatest2()合并两个流stream1和stream2。 注意:如果dart文件中同时使用了getx,需要隐…

腾讯云视立方Electron 相关问题

安装相关 trtc-electron-sdk 是否兼容官方 Electron v12.0.1 版本? 兼容的,trtc-electron-sdk 没有特别依赖 elecron 自身的 SDK,所以没有相关的版本依赖。 Electron 下载慢甚至卡住不动? 当开始下载tmp-3320-1-SHASUMS256.txt-6.1.9文件…

【c语言——指针详解(4)】

文章目录 一、回调函数是什么?二、qsort的使⽤1、使⽤qsort函数排序整型数据2、使⽤qsort排序结构数据 三、qsort函数的模拟实现 作者主页 一、回调函数是什么? 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针(地址&#xf…

【进阶OpenCV】 (12)--人脸检测识别

文章目录 人脸识别一、获取分类器二、代码实现1. 图片预处理2. 加载人脸检测分类器3. 检测人脸4. 标注人脸 总结 人脸识别 要实现人脸识别首先要判断当前图像中是否出现了人脸,这就是人脸检测。只有检测到图像中出现了人脸,才能据此判断这个人到底是谁。…

模拟电子电路基础(常见半导体+multisim学习1)

目录 1.半导体的基础 1.1.半导体基础知识 1.1.1本征半导体 1.1.2杂质半导体 1.1.3PN结 1.2半导体二极管 1.2.1半导体二极管的几种常见结构 1.2.2二极管的伏安特性曲线 1.2.3二极管的主要参数 1.2.4二级管的等效电路 1.2.5稳压二极管 1.2.其他类型二极管 2.multisim的…