• OpenCV从入门到精通实战(四)——答题卡识别判卷系统


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

    1. 导入必要的库

    系统首先导入了numpyargparseimutilscv2等Python库。这些库提供了处理图像、解析命令行参数等功能。

    # 导入工具包
    import numpy as np
    import argparse
    import imutils
    import cv2
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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())
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. 定义答案键

    系统中定义了一个答案键(ANSWER_KEY),这是一个字典,用于存储每个问题的正确答案选项

    # 正确答案
    ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}
    
    • 1
    • 2

    以下是针对每个主要步骤的对应代码片段,以及如何实现在上述答题卡识别系统中的功能:

    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)
    
    • 1
    • 2
    • 3
    • 4

    实现细节

    • 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实现细节

    • cv2.findContours:查找边缘。
    • sorted:按轮廓面积大小排序。
    • cv2.approxPolyDP:轮廓近似,寻找角点。
      在这里插入图片描述

    6. 透视变换

    paper = four_point_transform(image, docCnt.reshape(4, 2))
    warped = four_point_transform(gray, docCnt.reshape(4, 2))
    
    • 1
    • 2

    实现细节

    • 使用自定义函数four_point_transform来执行透视变换,以得到答题卡的顶视图。
      在这里插入图片描述

    7. 应用阈值

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

    实现细节

    • cv2.threshold:通过Otsu方法自动确定最优阈值并二值化图像。
      在这里插入图片描述

    8. 轮廓再次检测

    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    
    • 1
    • 2

    实现细节

    • 再次检测二值化图像中的轮廓。
      在这里插入图片描述

    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]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    实现细节

    • 筛选形状近似于圆的轮廓,并按从上到下排序。
      在这里插入图片描述

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    实现细节

    • 遍历每个问题的答题区域,通过填涂密度判断学生选择,通过计算填涂区域的像素密度来判断学生的的选项。然后将这个选择与答案键中的正确选项进行比较,统计出正确的答案数量。
      在这里插入图片描述

    11. 结果展示

    score = (correct / float(len(ANSWER_KEY))) * 100
    print("总分: {:.2f}%".format(score))
    cv2.imshow("Original", image)
    cv2.imshow("Exam", paper)
    cv2.waitKey(0)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实现细节

    • 计算出得分百分比,并输出。
    • cv2.imshow:展示原始图像和处理后的图像,以便检查标记的正确与错误的答案。

    源码下载:答题卡识别判卷系统

  • 相关阅读:
    K8S部署mongodb-sharded-cluster(7.0.2)副本分片
    Digi重启XBee-Pro S2C生产,有些差别需要注意
    【用unity实现100个游戏之7】从零开始制作一个仿杀戮尖塔卡牌回合制游戏
    Docker镜像仓库
    消费升级下摩托车TBOX市场未来十年CAN数据应用发展趋势展望
    JAVA中自定义扩展Swagger的能力,自动生成参数取值含义说明
    今天我们来写个ArrayList
    6.pytest生成allure报告
    =(等号)在Excel中的3个实用技巧
    【Vue实战】使用elementui实现表格的增加、删除、跳转详情页功能
  • 原文地址:https://blog.csdn.net/weixin_42917352/article/details/137894913