当前位置: 首页 > news >正文

传统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:展示原始图像和处理后的图像,以便检查标记的正确与错误的答案。

源码下载

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 机器学习项目——基于机器学习(RNN LSTM 高斯拟合 MLP)的锂离子电池剩余寿命预测方法研究(代码/论文)
  • python办公自动化:使用`Python-PPTX`的样式与格式
  • C++ ─── List的模拟实现
  • Datawhale X 李宏毅苹果书 AI夏令营-深度学习进阶task3:批量归一化
  • 接口请求400
  • C#面试题系列--动态更新
  • ES6中是如何实现模块化
  • 【聚星文社】AI一键生成工具素材包
  • 收藏夹里的“小网站”被误报违规不让上怎么办?如何将Chrome和Edge安装到 D 盘(含用户数据),重装系统也不会丢失收藏夹和密码?
  • 碳水化合物的摄入量笔记
  • 如何选择合适的合同比对工具以满足企业的不同需求?
  • 虚拟化技术 使用vSphere Client管理ESXi服务器系统
  • AI写作保姆级方法论第六节-AI的终极调教心法(问题+解决方案)
  • PP强酸强碱氮气柜和普通氮气柜的区别及共同点
  • 轻量级的git-server工具:docker部署gogs
  • JavaScript-如何实现克隆(clone)函数
  • 2017-09-12 前端日报
  • Computed property XXX was assigned to but it has no setter
  • crontab执行失败的多种原因
  • Cumulo 的 ClojureScript 模块已经成型
  • docker python 配置
  • Fundebug计费标准解释:事件数是如何定义的?
  • Invalidate和postInvalidate的区别
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Java程序员幽默爆笑锦集
  • js ES6 求数组的交集,并集,还有差集
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • PAT A1050
  • ReactNative开发常用的三方模块
  • Vue ES6 Jade Scss Webpack Gulp
  • 从重复到重用
  • 动态魔术使用DBMS_SQL
  • 二维平面内的碰撞检测【一】
  • 复杂数据处理
  • 规范化安全开发 KOA 手脚架
  • 机器学习中为什么要做归一化normalization
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 来,膜拜下android roadmap,强大的执行力
  • 前端相关框架总和
  • 深度学习在携程攻略社区的应用
  • 通过npm或yarn自动生成vue组件
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (21)起落架/可伸缩相机支架
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (C语言)二分查找 超详细
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (利用IDEA+Maven)定制属于自己的jar包
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (四)stm32之通信协议
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • .bat批处理(九):替换带有等号=的字符串的子串