基于opencv的答题卡识别

文章目录

  • 一、背景需求
  • 二、处理步骤
    • 图片预处理
    • 检测到答题卡轮廓
    • 透视变换
    • 找每个圆圈的轮廓
    • 轮廓排序
    • 判断是否答题正确

一、背景需求

传统的手动评分方法耗时且容易出错,自动化评分可以可以显著提高评分过程的速度和准确性、减少人工成本。
答题卡图片处理效果如下:

在这里插入图片描述

在这里插入图片描述

二、处理步骤

图片预处理

# 读图片
img = cv2.imread('./images/test_01.png')
cv_show('img', img)
# 变成黑白图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 去掉一些噪点
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
cv_show('blurred', blurred)# 边缘检测
edged = cv2.Canny(blurred, 75, 200)
cv_show('edged', edged)

检测到答题卡轮廓

# 检测轮廓
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
# 画轮廓会修改被画轮廓的图. 
contours_img = img.copy()
cv2.drawContours(contours_img, cnts, -1, (0, 0, 255), 3)
cv_show('contous_img', contours_img)
# 确保我们拿到的轮廓是答题卡的轮廓.
if len(cnts) > 0:# 根据轮廓面积对轮廓进行排序.cnts = sorted(cnts, key=cv2.contourArea, reverse=True)# 遍历每一个轮廓for c in cnts:# 计算周长perimeter = cv2.arcLength(c, True)# 得到近似的轮廓approx = cv2.approxPolyDP(c, 0.02 * perimeter, True)# 近似完了之后, 应该只剩下4个角的坐标.
#         print(c)
#         print(approx)if len(approx) == 4:# 保存approxdocCnt = approx# 找到答题卡近似轮廓, 直接推荐.break

在这里插入图片描述

透视变换

# 把透视变换功能封装成一个函数
def four_point_transform(image, pts):# 对输入的4个坐标排序rect = order_points(pts)(tl, tr, br, bl) = rect# 空间中两点的距离widthA = np.sqrt((br[0] - bl[0]) ** 2 + (br[1] - bl[1]) ** 2)widthB = np.sqrt((tr[0] - tl[0]) ** 2 + (tr[1] - tl[1]) ** 2)max_width = max(int(widthA), int(widthB))heightA = np.sqrt((tr[0] - br[0]) ** 2 + (tr[1] - br[1]) ** 2)heightB = np.sqrt((tl[0] - bl[0]) ** 2 + (tl[1] - bl[1]) ** 2)max_height = max(int(heightA), int(heightB))# 构造变换之后的对应坐标位置.dst = np.array([[0, 0],[max_width - 1, 0],[max_width - 1, max_height - 1],[0, max_height - 1]], dtype='float32')# 计算变换矩阵M = cv2.getPerspectiveTransform(rect, dst)# 透视变换warped = cv2.warpPerspective(image, M, (max_width, max_height))return warped

透视变化后二值化:

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

在这里插入图片描述


此时图片预处理好后如果需要 OCR 文本识别可借助 tesseract 工具识别文字

import pytesseract
from PIL import Image
# pytesseract要求的image不是opencv读进来的image, 而是pillow这个包, 即PIL,按照 pip install pillow
text = pytesseract.image_to_string(Image.open('./scan.jpg'))
print(text)

找每个圆圈的轮廓

# 找到每一个圆圈的轮廓
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
thresh_contours = thresh.copy()
cv2.drawContours(thresh_contours, cnts, -1, 255, 3)
cv_show('thresh_contours', thresh_contours)
plt.imshow(thresh_contours, cmap='gray')# 遍历所有的轮廓, 找到特定宽高和特定比例的轮廓, 即圆圈的轮廓.
question_cnts = []
for c in cnts:# 找到轮廓的外接矩形(x, y, w, h) = cv2.boundingRect(c)# 计算宽高比ar = w / float(h)# 根据实际情况制定标准.if w >= 20 and h >= 20 and 0.9 <= ar <= 1.1:question_cnts.append(c)

在这里插入图片描述

轮廓排序

对轮廓按照y轴排序

# 轮廓排序功能封装成函数
def sort_contours(cnts, method='left-to-right'):reverse = False# 排序的时候, 取x轴数据, i=0, 取y轴数据i =1i = 0if method == 'right-to-left' or method == 'bottom-to-top':reverse = True# 按y轴坐标排序if method == 'top-to-bottom' or method == 'bottom-to-top':i = 1# 计算每个轮廓的外接矩形bounding_boxes = [cv2.boundingRect(c) for c in cnts](cnts, bounding_boxes) = zip(*sorted(zip(cnts, bounding_boxes), key=lambda b: b[1][i], reverse=reverse))return cnts, bounding_boxes
# 按照从上到下的顺序对question_cnts排序.
question_cnts = sort_contours(question_cnts, method='top-to-bottom')[0]

判断是否答题正确

进一步按照x轴排序,构造圆圈轮廓的掩膜得出答案,最后和正确答案比较评判答题卡分数。

# 正确答案
ANSWER_KEY = {0:1, 1:4, 2:0, 3:3, 4:1}
correct = 0
for (q, i) in enumerate(np.arange(0, 25, 5)):
#     print(q, i)# 每次取出5个轮廓, 再按照x轴坐标从小到大排序cnts = sort_contours(question_cnts[i: i + 5])[0]bubbled = None# 遍历每一个结果for (j, c) in enumerate(cnts):# 使用掩膜, 即maskmask = np.zeros(thresh.shape, dtype='uint8')cv2.drawContours(mask, [c], -1, 255, -1) 
#         cv_show('mask', mask)# 先做与运算mask = cv2.bitwise_and(thresh, thresh, mask=mask)
#         cv_show('mask', mask)# 计算非零个数, 选择的选项, 非零个数比较多, 没选中的选项非零个数少一些total = cv2.countNonZero(mask)if bubbled is None or total > bubbled[0]:bubbled = (total, j)color = (0, 0, 255)k = ANSWER_KEY[q]# 判断是否做题正确if k == bubbled[1]:correct += 1color = (0, 255, 0)# 绘图cv2.drawContours(warped, [cnts[k]], -1, color, 3)# 计算分数
print(correct)
score = (correct / 5.0) * 100
print(f'score: {score:.2f}%')
cv2.putText(warped, str(score) + '%', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv_show('result', warped)

在这里插入图片描述

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

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

相关文章

Unity Android接入SDK 遇到的问题

1. buildtools、platformtools、commandline tools 以及compiled sdk version、buildtools sdk version、target sdk version 的说明 Android targetSdkVersion了解一下 - 简书 2. 查看.class 和.jar文件 jd_gui 官网地址&#xff1a; 下载jd_gui 工具 &#xff0c;或者 idea 下…

【Django】anaconda环境变量配置及配置python虚拟环境

文章目录 配置环境变量配置python虚拟环境查看conda源并配置国内源在虚拟环境中安装django 配置环境变量 control sysdm.cpl,,3笔者anaconda安装目录为C:\ProgramData\anaconda3 那么需要加入path中的有如下三个 C:\ProgramData\anaconda3 C:\ProgramData\anaconda3\Scripts C:…

收银系统源码视频介绍

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

搭建本地私有知识问答系统:MaxKB + Ollama + Llama3 (wsl网络代理配置、MaxKB-API访问配置)

目录 搭建本地私有知识问答系统:MaxKB、Ollama 和 Llama3 实现指南引言MaxKB+Ollama+Llama 3 Start buildingMaxKB 简介:1.1、docker部署 MaxKB(方法一)1.1.1、启用wls或是开启Hyper使用 WSL 2 的优势1.1.2、安装docker1.1.3、docker部署 MaxKB (Max Knowledge Base)MaxKB …

聚观早报 | 微软邀测AI摘要功能;百川智能完成A轮融资

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 7月26日消息 微软邀测AI摘要功能 百川智能完成A轮融资 苹果地图网页版上线公测 郭明錤剧透iPhone 17 Slim 马斯…

DeviceNet转Profinet协议网关

怎么样才能把DeviceNet和Profinet网络连接起来呢?这几天有几个朋友问到了这个问题&#xff0c;作者在这里统一为大家详细说明一下。其实有一个设备可以很轻松地解决这个问题&#xff0c;名为JM-PN-DNTM&#xff0c;下面是详细介绍。 一&#xff0c;产品主要功能‌ 1、捷米特…

【BUG】已解决:The above exception was the direct cause of the following exception:

The above exception was the direct cause of the following exception: 目录 The above exception was the direct cause of the following exception: 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c…

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…

数据安全检查方兴未艾,天空卫士领跑检查工具市场

近日&#xff0c;数世咨询正式发布了《数据安全检查工具市场洞察报告》&#xff0c;其中&#xff0c;天空卫士的数据安全检查工具箱——数据安全扫描仪&#xff08;DSS)&#xff0c;以30.04%的市场份额位列第一。 图例&#xff1a;数据安全检查工具箱市场概况 此前&#xff0c…

Python字符串编解码,解决字符串乱码问题

目录 1、编码与解码基础 &#x1f4dd; 1.1 字符集与编码概念 1.2 Python中的str与bytes类型 2、使用str.encode()方法 &#x1f527; 2.1 encode()方法详解 2.2 实战&#xff1a;字符串转字节串 3、利用bytes.decode()方法 &#x1f527; 3.1 decode()方法解析 3.2 实…

数据恢复教程:如何从硬盘、SD存储卡、数码相机中恢复误删除数据。

您正在摆弄 Android 设备。突然&#xff0c;您意外删除了一张或多张图片。不用担心&#xff0c;您总能找到一款价格实惠的数据恢复应用。这款先进的软件可帮助 Android 用户从硬盘、安全数字 (SD) 或存储卡以及数码相机中恢复已删除的数据。 Android 上数据被删除的主要原因 在…

鸿蒙配置生产证书打包准备

1、生成P12文件 2、新增cer证书&#xff1a;https://developer.huawei.com/consumer/cn/service/josp/agc/index.html#/harmonyOSDevPlatform/9249519184596237889 3、证书名称&#xff1a;xxxx&#xff1b;证书类型&#xff1a;发布证书&#xff1b;证书请求文件&#x…

【MySQL篇】Percona XtraBackup标准化全库完整备份策略(第三篇,总共五篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

C++ 红黑树插入的实现

文章目录 前言一、红黑树有什么性质&#xff1f;二、插入的原理即步骤1.新增结点为红色2.寻找叔叔结点1.叔叔为红色2.叔叔不存在为nullptr3.叔叔存在且为黑 三、代码实现1.叔叔为红2.叔叔为空或者叔叔为黑 四、验证是否为红黑树1.代码实现2.测试1.测试代码2.测试结果 总结 前言…

系留无人机在技术上有哪些优势或创新点

系留无人机在技术上具有显著的优势和创新点&#xff0c;主要体现在以下几个方面&#xff1a; 1. 长航时飞行作业&#xff1a; - 系留无人机系统由地面通过市电、发电机或电池组供电&#xff0c;并通过系留线缆将电力传输至无人机&#xff0c;实现了不间断供电。 - 这种供电方式…

虚拟机复制后网络不可用,报错“network.service - LSB: Bring up/down networking”

查询IP地址&#xff0c;eth33 没有显示IP地址 尝试重启&#xff0c;有报错&#xff0c;并且有提示&#xff0c;按照提示执行下看看 解决办法 chkconfig NetworkManager offsystemctl disable NetworkManager.serviceservice NetworkManager stopservice network restart 之后检…

解析capl文件生成XML Test Module对应的xml工具

之前一直用的CAPL Test Module来写代码&#xff0c;所有的控制都是在MainTest()函数来实现的&#xff0c;但是有一次&#xff0c;代码都写完了&#xff0c;突然需要用xml的这种方式来实现&#xff0c;很突然&#xff0c;之前也没研究过&#xff0c;整理这个xml整的一身汗&#…

Python酷库之旅-第三方库Pandas(045)

目录 一、用法精讲 156、pandas.Series.count方法 156-1、语法 156-2、参数 156-3、功能 156-4、返回值 156-5、说明 156-6、用法 156-6-1、数据准备 156-6-2、代码示例 156-6-3、结果输出 157、pandas.Series.cov方法 157-1、语法 157-2、参数 157-3、功能 15…

Tensorflow中高维矩阵的乘法运算tf.matmul(tf.linalg.matmul)详悉

1.问题由来 在tensorflow框架下&#xff0c;经常会用到矩阵的乘法运算&#xff0c;特别是高&#xff08;多&#xff09;维的矩阵运算&#xff0c;在这些矩阵运算时&#xff0c;经常使用到其中的tf.matmul或tf.linalg.matmul等函数。但高维矩阵在内部怎么运算的&#xff1f;其内…

南大核心,25年内!

1、新质生产力与三农发展 2、水利建设助力乡村振兴 3、刑事诉讼法 4、民法 5、数字政府建设 6、数字资本与政治经济