OpenCV实现答题卡自动打分!

news2024/9/21 2:38:32

目录

1,主要原理以及函数介绍

全部代码,以

2 , 实现过程

3,结果展示


1,主要原理以及函数介绍

ap = argparse.ArgumentParser()

创建一个ArgumentParser对象,并将其赋值给变量ap。这个对象可以接受我们的脚本的命令行参数,从而实现根据命令行参数执行不同的操作。

ap.add_argument("-i", "--image", required=True,help="path to the input image")

添加一个命令行参数-i/--image,并指定它是必需的,用户必须提供一个图像路径作为输入。

args = vars(ap.parse_args())

解析命令行参数并将它们存储在args字典中

ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}

定义一个字典,其中包含每道题目的正确答案。键是问题的索引、值是正确答案的编号

def order_points(pts):

定义函数order_points,用于按照指定顺序找到四个坐标点

def four_point_transform(image, pts):

定义函数four_point_transform,用于执行透视变换。

透视变换是一种在图像处理领域中常用的变换方式,它可以将一个平面上的图像投影到一个新的视平面上。透视变换通常用于纠正图像中的透视畸变,例如将斜着拍摄的照片转换为正常的平面视图。在透视变换中,图像中的平行线可能会变成不平行线,而原本不平行的线可能会变成平行线。函数four_point_transform就是利用四个特定的点来确定透视变换矩阵,并对输入的图像进行透视变换。

def sort_contours(cnts, method="left-to-right"):

定义函数sort_contours,用于对轮廓进行排序

def cv_show(name,img):

定义函数cv_show,用于显示图像。

image = cv2.imread(args["image"]):

读取输入的图像,并将其存储在变量image中

contours_img = image.copy():

复制图像,用于在图像上绘制轮廓

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

查找图像中的轮廓,使用外部轮廓检查模式(RETR_EXTERNAL)只检测外部轮廓,使用简单的轮廓逼近算法(CHAIN_APPROX_SIMPLE)来减少点数。返回值是一个元组,其中第二个元素表示轮廓列表

cv2.drawContours(contours_img,cnts,-1,(0,0,255),3)

将找到的轮廓绘制在图像上,颜色为红色

docCnt = None

初始化docCnt变量,用于存储找到的四个坐标点

if len(cnts) > 0:

如果找到了轮廓,则执行以下操作

cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

对轮廓根据其面积大小进行排序,从大到小排列

peri = cv2.arcLength(c, True)     计算轮廓周长

approx = cv2.approxPolyDP(c, 0.02 * peri, True)

使用迭代逼近算法获取轮廓的近似形状。如果近似的轮廓拥有四个顶点,则将其作为找到的四个坐标点。

if len(approx) == 4:  如果找到了四个坐标点,则将它们保存到docCnt变量中,并跳出循环。

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

对图像进行透视变换,将找到的四个坐标点映射到新的矩阵中

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

对变换后的图像进行二值化处理,使用Otsu's自适应阈值处理算法来获取最优阈值。返回值是一个元组,其中第二个元素是处理后的图像。

hresh_Contours = thresh.copy()

复制处理后的图像,用于在上面绘制轮廓

cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]

查找处理后图像中的轮廓,并使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE参数。

cv2.drawContours(thresh_Contours,cnts,-1,(0,0,255),3)

将找到的轮廓绘制在二值化图像上

cv_show('thresh_Contours',thresh_Contours)

调用cv_show函数,显示绘制轮廓后的图像

questionCnts = []:初始化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列表中。

questionCnts = sort_contours(questionCnts,method="top-to-bottom")[0]:对questionCnts列表中的轮廓按照从上到下的顺序进行排序。

for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):对每一行问题进行处理。

cnts = sort_contours(questionCnts[i:i + 5])[0]:对每个问题中的五个选项进行排序。

bubbled = None:初始化变量bubbled,用于保存所选答案。

for (j, c) in enumerate(cnts)::遍历每个选项。

mask = np.zeros(thresh.shape, dtype="uint8") :创建一个全黑图像,大小与thresh相同。

cv2.drawContours(mask, [c], -1, 255, -1):绘制选项的轮廓。

mask = cv2.bitwise_and(thresh, thresh, mask=mask):将二值化图像thresh与mask相乘,只保留交集部分。

total = cv2.countNonZero(mask):计算非零像素的数目,用于判断是否选择了这个选项。

if bubbled is None or total > bubbled[0]::如果之前没有选择过或者当前选择的像素数更多,则更新选择。

bubbled = (total, j):将当前选择的像素数以及选项索引保存到bubbled变量中。

color = (0, 0, 255):初始化颜色为红色。

k = ANSWER_KEY[q]:获取当前问题的正确答案。

if k == bubbled[1]::如果当前选项是正确的,则将颜色设置为绿色,并增加正确计数器。

color = (0, 255, 0)
correct += 1

cv2.drawContours(warped, [cnts[k]], -1, color, 3):将选项的轮廓绘制在变换后的图像上,颜色为正确或错误的颜色。

score = (correct / 5.0) * 100:计算得分。

print("[INFO] score: {:.2f}%".format(score)):输出得分。

cv2.putText(warped, "{:.2f}%".format(score), (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2):在变换后的图像上绘制得分。

cv2.imshow("Original", image):显示原始图像。

cv2.imshow("Exam", warped):显示处理结果。

cv2.waitKey(0):等待用户按下任意键。

全部代码,以

2 , 实现过程

  1. 导入所需的库和模块:首先导入numpy、argparse、imutils和cv2等库,用于进行科学计算、命令行参数解析、图像处理和机器视觉任务。

  2. 解析命令行参数:使用argparse库创建ArgumentParser对象,并添加一个命令行参数-i/--image,要求用户提供一个输入图像的路径。然后使用ap.parse_args()方法解析命令行参数,并将结果存储在args字典中。

  3. 定义正确答案字典:创建一个字典,其中包含每道题目的正确答案编号。

  4. 函数定义:定义了四个函数,分别用于找到四个坐标点、执行透视变换、对轮廓进行排序以及显示图像。

  5. 读取输入图像:使用cv2.imread()函数读取输入的图像,并将其存储在变量image中。

  6. 图像预处理:将图像转换为灰度图像,然后应用高斯模糊以平滑边缘并减少噪声。接下来使用Canny算法进行边缘检测,得到二值化的边缘图像。

  7. 查找轮廓:使用cv2.findContours()函数查找图像中的轮廓,并使用外部轮廓检查模式(RETR_EXTERNAL)只检测外部轮廓,使用简单的轮廓逼近算法(CHAIN_APPROX_SIMPLE)来减少点数。获取到的轮廓存储在cnts变量中。

  8. 找到答题卡区域:遍历轮廓,计算轮廓周长和近似形状,并通过一系列条件判断找到包含答题卡的轮廓。将找到的四个坐标点保存到docCnt变量中。

  9. 执行透视变换:使用four_point_transform()函数对图像进行透视变换,将找到的四个坐标点映射到新的矩阵中。

  10. 对变换后的图像进行二值化处理:使用Otsu's自适应阈值处理算法对图像进行二值化处理,得到二值化的图像。

  11. 查找轮廓:使用cv2.findContours()函数再次查找处理后图像中的轮廓,并使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE参数。

  12. 处理每个问题的选项:遍历每个问题所在的行,对该行中的五个选项进行处理。首先对选项进行排序,然后使用遍历的方式计算每个选项中非零像素的数量,根据数量确定是否选择了该选项,同时记录最多选择的选项和其索引。

  13. 计算得分:根据正确的选项数量和总题数计算得分,同时输出得分。

  14. 显示结果:在变换后的图像上绘制得分,并显示原始图像和处理结果。

  15. 等待用户按下任意键结束程序。

3,结果展示

高斯滤波后结果

边缘检测结果

图像轮廓检测结果:

透视变换结果:

二值化处理结果:

mask,只保留交集部分

遍历每一个结果,计算非零像素的数目,用于判断是否选择了这个选项

计算的得分并显示

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

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

相关文章

基于springboot实现教师人事档案管理系统项目【项目源码+论文说明】

基于springboot实现教师人事档案管理系统演示 摘要 教师人事档案管理系统理工作是一种繁琐的&#xff0c;务求准确迅速的信息检索工作。随着计算机信息技术的飞速发展&#xff0c;人类进入信息时代&#xff0c;社会的竞争越来越激烈&#xff0c;教师人事档案就越显示出其不可或…

JAVA开发者全家桶工具

一、前言 作为JAVA开发者&#xff0c;编码的时间其实只占平时工作的时间不到30%。作为项目管理和团队协作&#xff0c;平时处理的杂事其实很多&#xff0c;当然也是开发工作的一部分&#xff0c;比如写文档&#xff0c;任务管理&#xff0c;代码review、程序部署等等。这一节介…

墨西哥专线正清和双清包税有什么区别?

在国际贸易中&#xff0c;物流运输是一个至关重要的环节。对于从中国发往墨西哥的商品&#xff0c;物流公司通常会提供不同的运输方式和服务&#xff0c;如正清和双清包税等。那么&#xff0c;这两种方式有何不同呢? 首先&#xff0c;我们来看什么是“正清”和“双清”。 “正…

docker 登录本地仓库harbor问题

1、报错如下&#xff1a; 添加目标harbor 仓库的hosts vim /etc/hosts 2、报错如下&#xff1a; 添加修改/etc/docker/daemon.json文件中的 insecure-registries vim /etc/docker/daemon.json 然后 systemctl daemon-reload systemctl restart docker再次登录

【Hello Algorithm】暴力递归到动态规划(二)

暴力递归到动态规划&#xff08;二&#xff09; 背包问题递归版本动态规划 数字字符串改字母字符串递归版本动态规划 字符串贴纸递归版本动态规划 **特别需要注意的是 我们使用数组之前一定要进行初始化 不然很有可能会遇到一些意想不到的错误 比如说在Linux平台上 new出来的in…

易点易动让企业实现低值易耗品的智能化采购管理

对于企业而言&#xff0c;低值易耗品的采购和管理是一项重要的任务。然而&#xff0c;传统的采购管理方式往往繁琐且耗时&#xff0c;容易导致资源浪费和效率低下。为了解决这些问题&#xff0c;我们推出了易点易动采购管理系统&#xff0c;它以其高效、便捷和智能化的特点&…

怎样提取视频中的音频?分享一个一学就会的方法~

每次遇到视频中有好听的背景音乐都会想要保存下来&#xff0c;用于自己的视频创作。于是怎样单独提取视频中的音频部分就成了难题&#xff0c;今天教大家一个简单实用的视频提取音频办法&#xff0c;看完记得点赞收藏哦&#xff5e; 第一步&#xff1a;打开【音分轨】APP&#…

论文精读-Semi-Supervised Classification with Graph Convolutional Networks

Semi-Supervised Classification with Graph Convolutional Networks 目录 Semi-Supervised Classification with Graph Convolutional Networks一、摘要介绍二、图上的快速近似卷积2.1 谱图卷积 &#xff08;主要参考链接&#xff1a;[https://www.jianshu.com/p/35212baf6671…

100G SWDM4与100G BIDI SR光模块最新解决方案

随着数据中心和云计算网络的快速发展&#xff0c;高速度、高效率的数据传输需求不断增长。在这种背景下&#xff0c;100G SWDM4&#xff08;短波分复用技术&#xff09;和100G BIDI光模块作为两种先进的光模块技术&#xff0c;得到了广泛应用。下面我们来看看这两种光模块的应用…

基于Springboot实现垃圾分类网站管理系统项目【项目源码+论文说明】

基于Springboot实现垃圾分类网站管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述垃…

Fiddler抓包常用功能介绍

Fiddler中常用的功能如下&#xff1a; 停止抓包清空会话窗内容过滤请求解码设置断点 一. 停止抓包 二. 清空会话窗 方法一&#xff0c;工具栏工具&#xff1a; 方法二&#xff0c;命令行形式&#xff1a; 当然&#xff0c;命令行工具也还支持其他命令的输入&#xff0c;这里不…

CDN:加速型与高防型的不同

网络世界中的 CDN&#xff0c;也就是内容分发网络&#xff08;Content Delivery Network&#xff09;&#xff0c;是当今互联网体验的潜在改变者。它的作用原理可不止于让网页快一点&#xff0c;让我们深入了解一下。 CDN基本原理是通过在世界各地分布的节点服务器&#xff0c;…

视频剪辑达人秘籍:快进时光,精准调整多个视频的播放速度!

在创作视频的过程中&#xff0c;有时候我们可能需要将多个视频进行剪辑和调整&#xff0c;以展现所需的效果和节奏。而其中一个常见的需求就是快进视频&#xff0c;让观众更快地体验内容&#xff0c;提升观影体验。不用担心&#xff0c;我们将教你如何在众多视频中将视频播放速…

2023年【G2电站锅炉司炉】考试资料及G2电站锅炉司炉新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年G2电站锅炉司炉考试资料为正在备考G2电站锅炉司炉操作证的学员准备的理论考试专题&#xff0c;每个月更新的G2电站锅炉司炉新版试题祝您顺利通过G2电站锅炉司炉考试。 1、【多选题】《中华人民共和国特种设备安…

微信小程序点击事件bindtap传参

微信小程序点击事件bindtap传参 错误写法正确写法 微信小程序bindtap点击事件如何传参 错误写法 wxml页面 <view class"fix-add" bind:tap"goPage(/family_pages/form_electricity/form_electricity)"><van-icon name"add" /> <…

PMP证书烂大街?过来人理性分析

&#xff08;1&#xff09;究竟是不是智商税&#xff1f; “PMP证书是智商税&#xff0c;报名费这么贵&#xff0c;考了又没啥用” “又不像软考能评职称&#xff0c;地方补贴待遇好&#xff01;考了干嘛&#xff1f;” “考了就能年薪50W&#xff1f;就能当项目经理&#x…

【面试经典150 | 哈希表】有效的字母异位词

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;排序方法二&#xff1a;哈希数组 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于…

上海-华为全联接大会|竹云受邀参加华为云ROMAConnect行业生态联盟成立联合发布会

2023年9月22日&#xff0c;在上海举办的华为全联接大会上&#xff0c;竹云作为华为云全方位合作伙伴代表&#xff0c;受邀参加华为云ROMAConnect行业生态联盟成立联合发布会。华为云PaaS服务产品部副部长张甲磊以及联盟主要成员企业出席发布仪式&#xff0c;共同见证华为云ROMA…

项目结构目录说明--treer的使用

模块化项在模块比较多的时候&#xff0c;需要整理一份各模块的说明&#xff0c;怎么能够直观的和项目对比看比较清晰呢&#xff0c;有没有一种直观体现方式呢&#xff0c;有的&#xff0c;请看本篇文章足够。 效果图&#xff1a; 需要treer即可实现。 安装treer 在项目跟目录…

手机cpu架构查看及armeabi、armeabi-v7a、arm64-v8a及x86等说明

一、如何查看cpu加购 winR&#xff0c;输入cmd 填下指令如下 adb shell getprop ro.product.cpu.abi 二、架构描述 1.armeabiv-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它. 2.arm64-v8a: 第8代、64位ARM处理器&#xff0c;很少设备&a…