OpenCV实例(三)答题卡识别

news2025/1/12 4:44:08

OpenCV实例(三)答题卡识别

  • 1.答题卡识别概述
  • 2.单道题目的识别
    • 2.1基本流程及原理
    • 2.2代码实例:

作者:Xiou

1.答题卡识别概述

随着信息化的发展,计算机阅卷已经成为一种常规操作。在大型考试中,客观题基本不再需要人工阅卷。

答题卡识别的基本实现原理如图所示,其主要包含以下步骤。
(1)进行反二值化阈值处理,将后续操作中要使用的选项处理为前景(白色),将答题卡上其他不需要进行后续处理的位置处理为背景(黑色)。
(2)将每个选项提取出来,并计算各选项的白色像素点个数。
(3)筛选出白色像素点个数最大的选项,将该选项作为考生作答选项。
(4)将考试作答选项与标准答案进行比较,给出评阅结果。

在这里插入图片描述

2.单道题目的识别

为了方便理解,先讨论单道题目的情况。

2.1基本流程及原理

在这里插入图片描述
下面对具体步骤进行详细介绍。
Step 1:导入库将需要使用的库导入。
Step 2:答案及选项初始化为了方便处理,将各个选项放入一个字典内保存,让不同的选项对应不同的索引。例如,“选项A”对应索引0,“选项B”对应索引1,以此类推。本题目的标准答案为“选项C”。
Step 3:读取原始图像将选项图像读取到系统内。
Step 4:图像预处理图像预处理主要包含色彩空间转换、高斯滤波、阈值变换三个步骤。
Step 5:获取轮廓及排序获取轮廓是图像处理的关键,借助轮廓能够确定每个选项的位置、选项是否被选中等。

Step 6:计算每个选项包含的白色像素点个数本步骤主要完成任务如下。
任务1:提取每一个选项。
任务2:计算每一个选项内的白色像素点个数。

Step 7:识别考生作答选项白色像素点个数最多的选项即考生作答选项。

8)Step 8:输出结果用不同颜色标注考生作答选项正确与否,并打印输出结果。

根据考生作答选项是否与标准答案一致设置要绘制的颜色,
具体如下:
● 考生作答选项与标准答案一致,将考生填涂选项的轮廓设置为绿色。
● 考生作答选项与标准答案不一致,将考生填涂选项的轮廓设置为红色。按照上述规则,在考生作答选项上绘制轮廓,并打印输出文字提示。

2.2代码实例:

# -*- coding: utf-8 -*-
# ==================导入库=======================
import numpy as np
import cv2
# ==================答案及选项初始化=======================
# 将选项放入字典内
ANSWER_KEY = {0: "A", 1: "B", 2: "C", 3: "D"}
# 标准答案
ANSWER = "C"
# ==================读取原始图像=======================
img = cv2.imread('xiaogang.jpg')
cv2.imshow("original",img)
# ==================图像预处理=======================
# 转换为灰度图像
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 高斯滤波
gaussian_bulr = cv2.GaussianBlur(gray, (5, 5), 0)  
# 阈值变换,将所有选项处理为前景(白色)
ret,thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
# cv2.imshow("thresh",thresh)
# cv2.imwrite("thresh.jpg",thresh)
# ==================获取轮廓及排序=======================
# 获取轮廓
cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 将轮廓按照从左到右排列,方便后续处理
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
                                    key=lambda b: b[1][0], reverse=False))
# ==================构建列表,用来存储每个选项非零值个数及序号===================
options=[]
# 自左向右,遍历每一个选项的轮廓
for (j, c) in enumerate(cnts):
    # 构造一个与原始图像大小一致的灰度图像,用来保存每一个选项用
    mask = np.zeros(gray.shape, dtype="uint8")
    # 获取单个选项
    # 这里通过循环,将每一个选项单独放入一个mask中
    cv2.drawContours(mask, [c], -1, 255, -1)
    # 获取thresh中mask指定部分,每次循环,mask对应ABCD的不同选项
    cv2.imshow("s1",mask)
    cv2.imwrite("s1.jpg",mask)
    cv2.imshow("thresh",thresh)
    cv2.imwrite("thresh.jpg",thresh)
    mask = cv2.bitwise_and(thresh, thresh, mask=mask)  
    cv2.imshow("s2",mask)
    cv2.imwrite("s2.jpg",mask)
    # cv2.imshow("mask"+str(j),mask)
    # cv2.imwrite("mask"+str(j)+".jpg",mask)
    # 计算每一个选项的非零值(白色像素点)
    # 涂为答案的选项,非零值较多;没有涂选的选项,非零值较少   
    total = cv2.countNonZero(mask)
    #将选项非零值个数、选项序号放入列表options内
    options.append((total,j))
    # print(options)  #在循环中打印存储的非零值(白色点个数)及序号
# =================识别考生的选项========================
# 将所有选项按照非零值个数降序排序
options=sorted(options,key=lambda x: x[0],reverse=True)
# 获取包含最多白色像素点的选项索引(序号)
choice_num=options[0][1]
# 根据索引确定选项值:ABCD
choice= ANSWER_KEY.get(choice_num)
print("该生的选项:",choice)
# =================根据选项正确与否,用不同颜色标注考生选项==============
# 设定标注的颜色类型,绿对红错
if choice == ANSWER:
    color = (0, 255, 0)   #回答正确,用绿色表示
    msg="回答正确"
else:
    color = (0, 0, 255)   #回答错误,用红色表示
    msg="回答错误"
#  在选项位置上标注颜色(绿对红错)
cv2.drawContours(img, cnts[choice_num], -1, color, 2)
cv2.imshow("result",img)
# 打印识别结果
print(msg)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行上述程序,将根据考生作答情况打印出对应提示信息,同时会在答题卡上提示,具体情况如下:
● 当考生作答选项与标准答案一致时,在填涂的答案处绘制绿色边框。
● 当考生作答选项与标准答案不一致时,在填涂的答案处绘制红色边框。

输出结果:

在这里插入图片描述

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

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

相关文章

重整网站。。。。。。。。。

重整网站 写好回复的人 “ xxxxxxxx”通知栏,并且快速跳转到需要的页面。个人页面,记录自己发送的消息与回复的信息。以css 上传的图片防止被拉伸拉坏。 下拉的选择下拉的分页的好处。 评论功能的那一栏中的一个小的评论,如果手机端的话&a…

RabbitMQ 保证消息不丢失的几种手段

文章目录1.RabbitMQ消息丢失的三种情况2.RabbitMQ消息丢失解决方案2.1 针对生产者2.1.1 方案1 :开启RabbitMQ事务2.1.2 方案2:使用confirm机制2.2 Exchange路由到队列失败2.3 RabbitMq自身问题导致的消息丢失问题解决方案2.3.1 消息持久化2.3.2 设置集群…

无废话硬核分享:Linux 基础知识点总结很详细,全的很,吐血奉献

Linux 的学习对于一个程序员的重要性是不言而喻的。前端开发相比后端开发,接触 Linux 机会相对较少,因此往往容易忽视它。但是学好它却是程序员必备修养之一。 Linux 基础 操作系统 操作系统Operating System简称OS,是软件的一部分&#x…

【0基础学爬虫】爬虫基础之数据存储

大数据时代,各行各业对数据采集的需求日益增多,网络爬虫的运用也更为广泛,越来越多的人开始学习网络爬虫这项技术,K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章,为实现从易到难全方位覆盖,特设【0基础学…

物联网时代的网络安全

近年来,物联网 (IoT) 彻底改变了我们的生活和工作方式。从智能家居到自动驾驶汽车,物联网设备在我们的日常生活中变得越来越普遍。 根据 Statista 的一份报告,到 2025 年将有超过 750 亿个物联网 (IoT) 设备投入使用。 然而,这…

c++之STl容器-string

目录 容器的分类 string string的概念 string的初始化 string的遍历 string的一些基本操作 char*类型和string类型互转 字符串的连接 字符串的查找和替换 string的截断和删除 容器的分类 在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算…

SpringMVC03-文件上传、异常处理、拦截器

SpringMVC03 SpringMVC的文件上传 一 、文件上传的前端必要前提 form 表单的 entcype取值必须是:multipart/form-data。默认值:application/x-www-form-urlencoded,是表单请求正文的类型method 属性取值必须是 post提供一个文件选择域 二…

利用ChatGPT,一分钟制作思维导图

大家好,我是易安! 今天我来教你如何使用ChatGPT,一分钟制作出一份思维导图 大纲选题 想到一个课题,然后人工梳理出内容大纲,是个挺费精力的事情。但利用ChatGPT来做这件事. 5秒就可以搞定啦! 例如&#xf…

Python安全攻防之第二章Python语言基础

2.3 Python模块的安装与使用python模块的安装pip3 install 模块名称py -3 -m pip install 模块名称python模块的导入与使用(1)Import模块名称采用“Import模块名称”方式时,需要在对象前面加上模块名称作为前缀,具体形式为“模块名…

Nextcloud去掉URL中的index.php以及强制https(Win10子系统WSL)

一、Nextcloud去掉URL中的index.php 1、启用相关模块 cd /var/www/nextcloud #进入程序目录sudo chmod -R 777 .htaccess #设置.htaccess文件权限可读写sudo a2enmod envaudo a2enmod rewrite #启用rewrite模块2、修改nextcloud配置文件 vim /var/www/nextcloud/config/…

Redis数据备份与恢复

Redis数据备份与恢复 文章目录Redis数据备份与恢复1. Redis备份的方式2. RDB持久化2.1 什么是RDB?2.2 Fork操作2.3 save VS bgsave2.4 关于RDB备份的一些配置项2.5 RDB的备份与恢复2.6 RDB的自动触发2.7 RDB的优势与劣势3. AOF持久化3.1 什么是AOF?3.2 A…

hypothesis testing假设检验

假设检验是什么 比如一家巧克力工厂生产的巧克力每个1g,一个工人说,机器在维修之后生产的巧克力不是1g,为了验证工人说的是否正确,需进行假设检验。 随机挑选50个巧克力,计算平均重量。 H0:每个巧克力1g H…

Seatunnel-2.3.0源码解析

一、概述 SeaTunnel是一个简单易用的数据集成框架,在企业中,由于开发时间或开发部门不通用,往往有多个异构的、运行在不同的软硬件平台上的信息系统同时运行。数据集成是把不同来源、格式、特点性质的数据在逻辑上或物理上有机地集中&#x…

Spring学习笔记(二)【CGLIB浅拷贝BeanCopier的使用和详解】

CGLIB浅拷贝BeanCopier的使用和详解 一、bean拷贝工具 bean拷贝工具类比较 常用的bean拷贝工具类当中,主要有Apache提供的beanUtils、Spring提供的beanUtils、Cglib提供的beanCopier,性能上分析如下表所示(该表来自网上的数据) …

探索Apache Hudi核心概念 (3) - Compaction

Compaction是MOR表的一项核心机制,Hudi利用Compaction将MOR表产生的Log File合并到新的Base File中。本文我们会通过Notebook介绍并演示Compaction的运行机制,帮助您理解其工作原理和相关配置。 1. 运行 Notebook 本文使用的Notebook是:《A…

此战成硕,我成功上岸西南交通大学了~~~

友友们,好久不见,很长时间没有更一个正式点的文章了! 是因为我在去年年底忙着准备初试,今年年初在准备复试,直到3月底拟录取后,终于可以写下这篇上岸贴,和大家分享一下考研至上岸的一个过程 文章…

springboot+thymeleaf实现发Html邮件自由

2019年,我刚接触测试架构和测试开发类的工作时,经常会有自动化发邮件的功能,大都是从各个平台自动化统计一些数据出来,每周定时发一封邮件给领导交差,回过头来再看看我发的邮件,不美观,不专业。…

Android Jetpack:现代化Android开发的利器

Android Jetpack:现代化Android开发的利器 引言 随着移动应用的快速发展和用户体验的不断提升,现代化的Android应用开发变得愈发复杂和多样化。为了提高开发效率、简化代码、加速应用迭代,Google推出了Android Jetpack组件,成为现…

springboot零基础到项目实战

推荐教程: springboot零基础到项目实战 SpringBoot这门技术课程所包含的技术点其实并不是很多,但是围绕着SpringBoot的周边知识,也就是SpringBoot整合其他技术,这样的知识量很大,例如SpringBoot整合MyBatis等等。因此…

gitlab-ce升级方法

Centos7升级gitlab-ce: 1、记录当前版本 在升级前一定要做好备份,记录自己当前的gitlab-ce的版本: yum list | grep gitlab-ce 2、编辑/etc/gitlab/gitlab.rb文件: 1)将下面几行注释取消。 说明: 1&am…