[Day 4 of 17]opencv扫描文稿并应用于考试测试答题卡

这篇具有很好参考价值的文章主要介绍了[Day 4 of 17]opencv扫描文稿并应用于考试测试答题卡。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

https://pyimagesearch.com/2016/10/03/bubble-sheet-multiple-choice-scanner-and-test-grader-using-omr-python-and-opencv/?utm_source=Drip&utm_medium=Email&utm_campaign=CVandDLCrashCourse&utm_content=email4

Bubble sheet multiple choice scanner and test grader using OMR, Python, and OpenCV

数据集至关重要,允许训练一个模型来准确识别和评分,对自动化评估非常有用。Roboflow为计算机视觉每个流程提供工具,有先进的数据库。

Optical Mark Recognition (OMR)

光学标记识别,是自动分析人类标记的文档并解释其结果的过程。

“Bubble sheet tests”:考试中的每一道题都是多选题,你可以用2号铅笔标记与正确答案相对应的“气泡”

Implementing

使用Python和OpenCV构建一个计算机视觉系统,该系统可以读取气泡表测试并对其进行评分

  1. 在图像中检测考试
  2. 应用透视变换提取自上而下的鸟瞰图
  3. 从变换后的图像提取bubbles集合(可能的答案)
  4. sortthhe bubbles(按行排序)
  5. 确定每行的标记答案
  6. 在答案集中找正确答案,来确定选择的正确性
  7. 对所有exam重复

注意:请注意文档的边缘是如何清晰定义的,检查的所有四个顶点都显示在图像中。

# import the necessary packages
from imutils.perspective import four_point_transform
from imutils import contours
import numpy as np
import argparse
import imutils
import cv2

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
	help="path to the input image")
args = vars(ap.parse_args())

# define the answer key 
# which maps the question number to the correct answer
ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1} #提供了问题编号到正确气泡索引的整数映射
# 0:Question 1#, 1->B:correct answer; (ABCDE--01234)
# 1:Question 2#, 4->E

# 预处理输入图像

# load the image, convert it to grayscale, blur it
# slightly, then find edges
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.imshow("Exam", edged)
cv2.waitKey(0)

'''

# 后续将使用轮廓作为标记,来对检查应用透视变换

# find contours in the edge map, then initialize
# the contour that corresponds to the document
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
	cv2.CHAIN_APPROX_SIMPLE)
# 找边缘图像 edged 的轮廓,cv2.RETR_LIST 表示检测所有轮廓,并将它们存储在列表中
cnts = imutils.grab_contours(cnts)
docCnt = None   # 文档轮廓初始化

# ensure that at least one contour was found
# 对每个轮廓,逼近轮廓形状并判断是否为一个矩形
if len(cnts) > 0:
	# sort the contours according to their size in descending order
	cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
	# loop over the sorted contours
	for c in cnts:
		# approximate the contour 近似轮廓
		peri = cv2.arcLength(c, True)   # 计算轮廓周长,True表示轮廓闭合
		approx = cv2.approxPolyDP(c, 0.02 * peri, True) # 对轮廓 c 进行多边形逼近
		# if our approximated contour has four points,
		# then we can assume we have found the paper
		if len(approx) == 4:    #找到四个顶点
			docCnt = approx     #保存
			break

# apply a four point perspective transform to both the
# original image and grayscale image to obtain a top-down
# birds eye view of the paper
paper = four_point_transform(image, docCnt.reshape(4, 2))
warped = four_point_transform(gray, docCnt.reshape(4, 2))
# 作用:倾斜试卷得到自上而下的视图

'''cv2.imshow("Exam", warped)
cv2.waitKey(0)
'''

# python test_grader.py --image bubble.png

# 文档打分:从二值化开始,即从图像的背景对前景进行阈值化/分割的过程

# apply Otsu's thresholding method to binarize the warped
# piece of paper
thresh = cv2.threshold(warped, 0, 255,
	cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
# 应用Otsu阈值法对翘曲的纸张进行二值化
# 得到二值化图像:图像的背景是黑色的,前景是白色的



# 这种二值化将允许我们再次应用轮廓提取技术来找到图中的每个气泡

# find contours in the thresholded image, then initialize
# the list of contours that correspond to questions
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
	cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
questionCnts = []
# loop over the contours
# 为了确定图像的哪些区域是气泡,我们首先在每个单独的轮廓上循环
for c in cnts:
	# compute the bounding box of the contour, then use the
	# bounding box to derive the aspect ratio
	(x, y, w, h) = cv2.boundingRect(c)      #计算边界框
	ar = w / float(h)                       #计算横纵比
	# in order to label the contour as a question, region
	# should be sufficiently wide, sufficiently tall, and
	# have an aspect ratio approximately equal to 1
	if w >= 20 and h >= 20 and ar >= 0.9 and ar <= 1.1: 
		#判断气泡区域的条件,足够宽和足够高,横纵比
		questionCnts.append(c)  # 更新questionCnts列表
# 此时能够圈出all bubbles


# grading-判断正误
# sort the question contours top-to-bottom, then initialize
# the total number of correct answers
questionCnts = contours.sort_contours(questionCnts,
	method="top-to-bottom")[0]
# 从上到下对问题轮廓进行排序,确保更接近试卷顶部的问题行将首先出现在排序列表中
correct = 0         # 初始化,记录正确答案的数量

# each question has 5 possible answers,
# to loop over the question in batches of 5
# 五个一组进行循环
for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):
	# 从左到右对当前轮廓集合进行排序,初始化冒泡答案的索引
	# sort the contours for the current question from left to right,
	# then initialize the index of the bubbled answer
	cnts = contours.sort_contours(questionCnts[i:i + 5])[0] #为了从左到右排序
	# 我们已经从上到下对轮廓进行了排序。
    # 我们知道每个问题的5个气泡将按顺序出现在列表中——但我们不知道这些气泡是否会从左到右排序。
    # contours.sort_contours排序轮廓调用,确保每行轮廓从左到右排序成行。
	bubbled = None

# 下一步是对给定某排bubbles, 确定填充了哪个
# 计算每个气泡区域中的非零像素(即前景像素)的数量
    # loop over the sorted contours
	for (j, c) in enumerate(cnts):
		# construct a mask that reveals only the current
		# "bubble" for the question
        # 构造一个掩码,只显示当前问题的“气泡”
		mask = np.zeros(thresh.shape, dtype="uint8")
		cv2.drawContours(mask, [c], -1, 255, -1)
		# apply the mask to the thresholded image, then
		# count the number of non-zero pixels in the
		# bubble area
        # 将mask应用于阈值图像,然后计算气泡区域中非零像素的数量
		mask = cv2.bitwise_and(thresh, thresh, mask=mask)
		total = cv2.countNonZero(mask)
		# if the current total has a larger number of total non-zero pixels,
		# then we are examining the currently bubbled-in answer
        # 如果当前的总数有更多的非零像素,那么我们正在检查当前冒泡的答案
        # 即:具有最大非零计数的气泡是测试者所选择标注的答案
		if bubbled is None or total > bubbled[0]:
			bubbled = (total, j)
			

# 在ANSWER_KEY中查找正确答案,更新任何相关的簿记器变量,并最终在我们的图像上绘制标记的气泡
    # initialize the contour color and the index of the
	# *correct* answer
	color = (0, 0, 255)
	k = ANSWER_KEY[q]
	# check to see if the bubbled answer is correct
	if k == bubbled[1]: #检查答案是否正确
		color = (0, 255, 0) #正确则绿色标出
		correct += 1
	# draw the outline of the correct answer on the test
	cv2.drawContours(paper, [cnts[k]], -1, color, 3)    
	# 画出正确答案的轮廓,红色标记答题错误的,会标出正确的答案位置

# 处理考试评分并在屏幕上显示结果
# grab the test taker
score = (correct / 5.0) * 100
print("[INFO] score: {:.2f}%".format(score))
cv2.putText(paper, "{:.2f}%".format(score), (10, 30),
	cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow("Original", image)
cv2.imshow("Exam", paper)
cv2.waitKey(0)

基于一个假设:考生在每个问题行中只涂满了一个气泡。我们只是通过计算一行中阈值像素的数量,然后按降序排序来确定一个特定的气泡是否被“填充”,这可能会导致两个问题:

  • 如果用户没有输入特定问题的答案,会发生什么?

  • 如果用户恶意地在同一行中将多个气泡标记为“正确”怎么办?

只需要插入一点逻辑:文章来源地址https://www.toymoban.com/news/detail-501936.html

  1. 如果考生选择不输入特定行的答案,那么我们可以在计算cv2.countNonZero设置最小阈值。如果这个值足够大,那么我们可以将气泡标记为“已填充”。相反,如果总数太小,那么我们可以跳过这个特定的气泡。如果在这一行的末尾没有足够大的阈值计数的气泡,我们可以将该问题标记为考生“跳过“。
  2. 应用阈值和计数步骤,这一次跟踪是否有多个气泡的总数超过了某个预定义的值。如果是这样,我们可以使问题无效,并将问题标记为不正确

到了这里,关于[Day 4 of 17]opencv扫描文稿并应用于考试测试答题卡的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 竞赛保研 机器视觉opencv答题卡识别系统

    🔥 优质竞赛项目系列,今天要分享的是 🚩 答题卡识别系统 - opencv python 图像识别 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:3分 🧿 更多资料, 项目分享: https://gitee.com/da

    2024年01月21日
    浏览(45)
  • 【实战精选】基于计算机视觉OpenCV的答题卡识别系统

    项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义: 随着科技的不断发展,计算机视觉技术在各个领域中的应用越来越广泛。其中,基于计算机视觉的答题卡识别系统在教育领域中具有重要的意义。传统的答题卡批阅方式需要大量的人力和时间,容易

    2024年04月25日
    浏览(45)
  • OpenCV从入门到精通实战(四)——答题卡识别判卷系统

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

    2024年04月22日
    浏览(34)
  • opencv-python基于计算机视觉的答题卡识别及判分系统ocr

    python  django  mysql 基于计算机视觉的答题卡识别及判分系统设计与实现 通过查阅资料和文献在充分掌握OpenCV图像处理开源框架,采用Python开发语言、实现简单答题卡识别系统,其基本功能包括:1,对答题卡进行图像处理;2,识别答题卡的选择题选项;3,将选择题所选答案与

    2024年02月20日
    浏览(61)
  • 详解【计算机类&面试真题】军队文职考试——第8期:OSI的七层模型 | 数据通信的三种方式 | 通信网络的检查方法,附Python进行网络连通性检查、带宽测试、端口扫描、链路质量测试、安全性扫描

      不知道命运是什么,才知道什么是命运。———史铁生     🎯作者主页: 追光者♂🔥          🌸个人简介:   💖[1] 计算机专业硕士研究生💖   🌟[2] 2022年度博客之星人工智能领域TOP4🌟   🏅[3] 阿里云社区特邀专家博主🏅   🏆[4] CSDN-人工智能领域优质创作者🏆

    2024年01月25日
    浏览(55)
  • OpenCvSharp (C# OpenCV) 实现扫描文本矫正应用与实现详解(附源码)

    导  读     本文主要介绍使用OpenCV对扫描文本矫正的应用实例及详细实现步骤。 背景介绍     在使用打印机或扫描仪扫描文档时,由于摆放位置差异难免造成扫描文档的倾斜。本文将使用OpenCV将倾斜的文档矫正水平并去除黑边。   实现步骤     本文只针对包含大部分文

    2024年02月16日
    浏览(56)
  • 17.应用负载压力测试

    早些点,下午题考,最近几年出现的少; 备考较为简单;历年真题相似度高; 主要议题: 注意这些测试细微的差别; 负载测试和压力测试的方法比较相似,但是目的不同; 1、负载测试:逐步增加系统的负载,以便 获取系统最大的负载情况 ;如服务器最大允许多少用户查

    2024年04月14日
    浏览(33)
  • iPhone手机如何删除照片应用程序的文稿与数据

    场景:iPhone使用多年( 穷没钱换新的 )照片视频一直没有删除,最近打开微信提示空间不足,删除100多G照片后,照片应用程序的 文稿与数据 仍然100G没有变化。 不想重置手机,处理方法如下,PC端安装第三方助手软件,数据线连接iPhone,打开 文件管理→文件系统 ,选中

    2024年02月07日
    浏览(41)
  • 全国工业和信息化应用人才考试-- 服务外包 软件测试复习整理

    201服务外包软件测试考试样卷(1)【附答案】 单项选择题(每题1分,共40题40分) 多项选择题(每题2分,共10题20分) 判断题(每题1分,共10题10分) 填空题(每题1分,共10题10分) 问答题(每题 5 分,共 4 题 20 分)(第四问为英译汉*2) 软件测试定义 软件测试(英语:Softwar

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包