传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统,其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术,自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述:

1. 导入必要的库

系统首先导入了numpyargparseimutilscv2等Python库。这些库提供了处理图像、解析命令行参数等功能。

# 导入工具包
import numpy as np
import argparse
import imutils
import cv2

2. 参数设置

使用argparse库来处理命令行输入参数,允许用户指定输入图像的路径。

# 设置参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", default="images/test_01.png",help="path to the input image")
args = vars(ap.parse_args())

3. 定义答案键

系统中定义了一个答案键(ANSWER_KEY),这是一个字典,用于存储每个问题的正确答案选项

# 正确答案
ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}

以下是针对每个主要步骤的对应代码片段,以及如何实现在上述答题卡识别系统中的功能:

4. 图像预处理

image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 75, 200)

实现细节

  • cv2.imread:加载图像。
  • cv2.cvtColor:将图像从BGR颜色空间转换为灰度。
  • cv2.GaussianBlur:应用高斯模糊,减少噪声。
  • cv2.Canny:执行Canny边缘检测。
    在这里插入图片描述

5. 轮廓检测

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
docCnt = Noneif len(cnts) > 0:cnts = sorted(cnts, key=cv2.contourArea, reverse=True)for c in cnts:peri = cv2.arcLength(c, True)approx = cv2.approxPolyDP(c, 0.02 * peri, True)if len(approx) == 4:docCnt = approxbreak

实现细节

  • cv2.findContours:查找边缘。
  • sorted:按轮廓面积大小排序。
  • cv2.approxPolyDP:轮廓近似,寻找角点。
    在这里插入图片描述

6. 透视变换

paper = four_point_transform(image, docCnt.reshape(4, 2))
warped = four_point_transform(gray, docCnt.reshape(4, 2))

实现细节

  • 使用自定义函数four_point_transform来执行透视变换,以得到答题卡的顶视图。
    在这里插入图片描述

7. 应用阈值

thresh = cv2.threshold(warped, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

实现细节

  • cv2.threshold:通过Otsu方法自动确定最优阈值并二值化图像。
    在这里插入图片描述

8. 轮廓再次检测

cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

实现细节

  • 再次检测二值化图像中的轮廓。
    在这里插入图片描述

9. 筛选与排序

questionCnts = []for c in cnts:(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h)if w >= 20 and h >= 20 and ar >= 0.9 and ar <= 1.1:questionCnts.append(c)questionCnts = contours.sort_contours(questionCnts, method="top-to-bottom")[0]

实现细节

  • 筛选形状近似于圆的轮廓,并按从上到下排序。
    在这里插入图片描述

10. 评分逻辑

correct = 0
for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):cnts = contours.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)mask = cv2.bitwise_and(thresh, thresh, mask=mask)total = cv2.countNonZero(mask)if bubbled is None or total > bubbled[0]:bubbled = (total, j)if bubbled[1] == ANSWER_KEY[q]:correct += 1

实现细节

  • 遍历每个问题的答题区域,通过填涂密度判断学生选择,通过计算填涂区域的像素密度来判断学生的的选项。然后将这个选择与答案键中的正确选项进行比较,统计出正确的答案数量。
    在这里插入图片描述

11. 结果展示

score = (correct / float(len(ANSWER_KEY))) * 100
print("总分: {:.2f}%".format(score))
cv2.imshow("Original", image)
cv2.imshow("Exam", paper)
cv2.waitKey(0)

实现细节

  • 计算出得分百分比,并输出。
  • cv2.imshow:展示原始图像和处理后的图像,以便检查标记的正确与错误的答案。

源码下载

源码下载:答题卡识别判卷系统

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

openlayers+vite+vue3实现规划某一特定行政区(二)

在前一期实现离线地图初始化的基础上&#xff0c;本文中主要阐述如何实现规划某一特定行政区&#xff0c;并展示其行政区的区县名称。 提示&#xff1a;因前文中阐述了如何实现离线地图的初始化&#xff0c;所以在此不再进行书写并详解初始化的过程和流程&#xff0c;如有不明…

MySQL简介和管理

目录 一、数据库基本概念 1.1、数据 1.2、表 1.3、数据库 1.4、数据库管理系统 1.5、数据库系统 二、数据库发展史 2.1、第一代数据库 2.2、第二代数据库 2.3、第三代数据库 三、数据库类型 3.1、关系型数据库 3.2、关系型数据库应用 3.3、非关系型数据库 3.4、…

【Python】数据分析分类图可视化

目录 条形图 箱形图 散点图 分簇散点图 小提琴 分簇小提琴 条形图 条形图是一种直观的图表形式&#xff0c;它通过不同长度的矩形条&#xff08;即“条形”&#xff09;来展示数值变量的中心趋势估计值&#xff0c;其中每个矩形的高度直接对应于该组数据的某个中心量度&…

若依微服务Admin控制台不显示ruoyi-file问题解决

本地启动完若依微服务,发现Admin控制台只显示了6个服务,其中ruoyi-file启动成功,但是没有在Admin控制台中显示处理,本章问题,给出这个问题的解决办法。 一、什么是服务监控 监视当前系统应用状态、内存、线程、堆栈、日志等等相关信息,主要目的在服务出现问题或者快要出…

JMeter 安装使用

JMeter 安装使用 a.安装 下载链接:Apache JMeter - Download Apache JMeter 环境变量 打开 cmd 输入 jmeter&#xff0c;即可启动 b.使用 http请求接口 300 个线程设置 1 s 的预热时间 右键 start

【STM32+HAL库】---- 基础定时器中断控制LED

硬件开发板&#xff1a;STM32G0B1RET6 软件平台&#xff1a;cubemaxkeilVScode1 新建cubemax工程 1.1 配置系统时钟RCC 1.2 配置LED LED由PA5引脚控制&#xff0c;选择PA5引脚&#xff0c;选择GPIO_Output模式 1.3 定时时间的计算 T ( 预分频系数 1 ) ( 重装载值 1 ) 时…

数仓基础(九):各大公司实时数仓实践

文章目录 各大公司实时数仓实践 一、网易实时数仓实践 二、汽车之家实时数仓实践 三、顺丰实时数仓实践 四、​​​​​​​腾讯实时数仓实践 五、​​​​​​​​​​​​​​滴滴实时数仓实践 ​​​​​​​​​​​​​​各大公司实时数仓实践 一、网易实时数仓实践…

Opencv实现提取卡号(数字识别)

直接开始 实行方法 解析命令行参数&#xff1a;使用argparse库来解析命令行输入&#xff0c;确保用户提供了输入图像和模板图像的路径。 读取模板图像&#xff1a;使用cv2.imread()函数读取模板图像的路径&#xff0c;并显示原始图像。 图像预处理&#xff1a; 将图像转换为…

Promises - 从零开始(万字详解)

目录 前言 为何这样设计 回调函数 介绍Promises 使用Promises 创建自己的Promises Promise 链 传递数据 错误处理Promises async / await 结语 ❤️❤️❤️ 前言 在学习JavaScript的过程中往往会面临很多挑战&#xff0c;其中最让人头疼的要数Promises了。想真正理…

【CF补题数学裴蜀定理】 div969 C Dora and C++

Dora and C 分析&#xff1a; 对于两个数x,y 我们想要通过如下操作使得他们的差变得尽可能小 我们要如何操作&#xff1f; 这个操作也就是相当于 d e l ∣ y − x ∣ − k 1 ∗ x − k 2 ∗ y del|y-x|-k_1*x-k_2*y del∣y−x∣−k1​∗x−k2​∗y&#xff0c;让这个差值最小…

【网络安全】IDOR之敏感数据泄露

未经许可,不得转载。 文章目录 正文正文 在测试“添加到收藏夹”功能时,我拦截了发送到服务器的请求,请求体如下: {“uriTemplate”:“asset/{assetId}/favorite”,“version”:“v2”,“type”:“POST”,“req_service”:“pict”,“url”:“asset/VICTIMS_ASS…

Android Google Maps

Android 谷歌地图 前言正文一、设置Google Cloud 项目二、项目配置① 设置SDK② 配置API密钥③ 配置AndroidManifest.xml 三、添加地图四、定位当前① 请求定位权限② 我的位置控件③ 获取当前位置 五、配置地图① xml配置地图② 代码配置地图③ 地图点击事件④ 管理Marker 六、…

薛定谔的空气墙?一文带你了解其背后的技术原理

封面图 悟空来了都得撞墙&#xff1f; 目前&#xff0c;被称作“村里第一个大学生”的国产3A游戏《黑神话&#xff1a;悟空》发售已经有一段时间了&#xff0c;游戏采用虚幻引擎4技术&#xff0c;仿佛将传统与现代的界限模糊&#xff0c;玩家游玩时沉浸感极强。然而&#xff…

自然语言处理系列五十三》文本聚类算法》文本聚类介绍及相关算法

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列五十三文本聚类算法》文本聚类介绍及相关算法K…

四、基本电路设计笔记——4.1 DC-DC稳压电路

目录 4.1 DC-DC稳压电路 4.1.1 基于MT2492的DC-DC稳压电路 &#xff08;1&#xff09;芯片参数 &#xff08;2&#xff09;芯片引脚 &#xff08;3&#xff09;输出电压设置 4.1.2 基于MT2499A的DC-DC稳压电路 &#xff08;1&#xff09;芯片参数 &#xff08;2&#xf…

多模态生成发文量大涨!最新成果统一Transformer和Diffusion,含金量超高

最近多模态生成领域也在“神仙打架”&#xff0c;比如Meta的全新训练方法Transfusion&#xff0c;用单个模型就能同时生成文本和图像&#xff01; 还有之前华为、清华提出的个性化多模态内容生成技术PMG&#xff0c;生成的内容可“量身定制”&#xff0c;更能满足偏好。 这些…

深入解析Linux轻量级进程:线程的概念、原理、优缺点及其与进程的关系与区别

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f4da;Linux线程&#x1f4d5;什么是线程*可以使用多进程去并发的执行一个进程的代码&#xff0c;那为什么要由线程呢&#x…

搭子小程序开发,让社交更加有趣

如今&#xff0c;搭子成为了年轻人社交的新兴方式&#xff0c;它作为一种连接年轻人的社交纽带&#xff0c;深受大众的欢迎&#xff01;各式各样的旅游搭子、健身搭子、游戏搭子等&#xff0c;让年轻人享受到社交的魅力。 随着互联网的发展&#xff0c;寻找搭子也发展到了线上…

一个好用的Maven依赖冲突解决插件:Maven Helper

在项目开发&#xff0c;或项目Maven需要新增依赖、项目依赖组件升级时&#xff0c;经常会出现添加后&#xff0c;因为各个模块中有相同的依赖、不同的版本而导致依赖冲突&#xff0c;从而导致项目启动不起来&#xff0c;这种冲突非常恶心&#xff0c;因为是传递依赖所以会看不出…

Hackme靶场渗透攻略

步骤一&#xff0c;注册登录进去 步骤二&#xff0c;点击search 我们发现有很多书 步骤三&#xff0c;搜索一本书抓包发放到重放器 步骤四&#xff0c;数据改为1*&#xff0c;复制数据包到1.txt&#xff0c;然后打开sqlmap 步骤五&#xff0c;sqlmap查看当前数据库 python s…