传统CV算法——基于opencv的答题卡识别判卷系统
创作时间:
作者:
@小白创作中心
传统CV算法——基于opencv的答题卡识别判卷系统
引用
CSDN
1.
https://blog.csdn.net/weixin_42917352/article/details/137894913
本文介绍了一个基于OpenCV的答题卡识别系统,该系统能够自动读取并评分答题卡上的选择题答案。通过图像处理和计算机视觉技术,系统实现了从读取图像到输出成绩的自动化流程。文章详细介绍了系统的各个步骤和实现细节,包括图像预处理、轮廓检测、透视变换、阈值处理、轮廓筛选、评分逻辑等,非常适合对计算机视觉和图像处理感兴趣的读者学习参考。
基于OpenCV的答题卡识别系统,其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术,自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述:
1. 导入必要的库
系统首先导入了numpy、argparse、imutils和cv2等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 = None
if 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 = approx
break
实现细节:
- 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 = None
for (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:展示原始图像和处理后的图像,以便检查标记的正确与错误的答案。
源码下载
源码下载:答题卡识别判卷系统
热门推荐
天安门+故宫+慕田峪长城:北京最美一日游
丁香茶治胃寒:一杯缓解冷痛呕吐
从网格到解构:建筑设计的空间构成方法全解析
佛教英语术语与万条短语:中英双语学习宝典
一文掌握英语方向介词:8个核心词用法全解
丁香茶、桂花茶、姜枣茶:冬季胃寒的三款养生茶
冬季暖胃茶饮指南:生姜、红枣、普洱的功效与饮用建议
表语还是定语?英语学习者必懂的语法要点
5分钟打造吸睛自媒体简介,让你的账号脱颖而出
Nature研究:特定益生菌将癌症治疗有效率提升至79%
厨房台面保养大全:五种材质清洁护理要点
石英石更适合现代厨房,大理石需定期保养
耐用易洁还环保,不锈钢台面成厨房装修新宠
2024哈尔滨冰雪大世界:41届冰雪节必打卡胜地
从倾听、关怀到尊重:赢得女人心的三个关键
厄瓜多尔大白虾:从选购到烹饪的年夜饭指南
实用理性:古人如何玩转“实际”?
许昌454年城墙砖见证城市变迁,曾为解放战争立功
职场人排气多?专家详解四大类实用解决方案
排气多是消化不良?6种方法改善儿童功能性消化不良
萝卜富含芥子油膳食纤维,科学证实改善排气效果佳
管理焦虑,改善肠道:告别排气困扰的实用指南
科学应对豆类排气:原因解析与实用解决方案
东北旅游必打卡的八大景点和贴心攻略
探秘河套平原:历史博弈的焦点与塞外江南的奇迹
银发族游戏成瘾调查:25%老年人自认过度投入,60%有充值行为
侧边推剪不连接,这款短发为何成为时尚新宠?
从自我认同到存在主义:心理咨询师详解无意义感成因与对策
心理学不是伪科学:澄清三大误解
六国青年科学家齐聚西双版纳,共探热带亚洲生物多样性未来