• OpenCV图像处理——(实战)答题卡识别试卷


    总目录

    图像处理总目录←点击这里

    二十、答题卡识别试卷

    20.1、预处理

    灰度图

    输出灰度图+高斯滤波去噪

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    
    • 1
    • 2

    在这里插入图片描述

    边缘检测

    edged = cv2.Canny(blurred, 75, 200)
    
    • 1

    在这里插入图片描述

    20.2、轮廓检测

    找到原始图像中边框的四个矩形框的点

    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(contours_img, cnts, -1, (0, 0, 255), 3)
    
    • 1
    • 2

    在这里插入图片描述

    20.3、透视变换

    得到需要的图像范围

    def four_point_transform(image, pts):
        # 获取输入坐标点
        rect = order_points(pts)
        (tl, tr, br, bl) = rect
     
        # 计算输入的w和h值
        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))
        maxWidth = 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))
        maxHeight = max(int(heightA), int(heightB))
    
        # 变换后对应坐标位置
        dst = np.array([
            [0, 0],
            [maxWidth - 1, 0],
            [maxWidth - 1, maxHeight - 1],
            [0, maxHeight - 1]], dtype="float32")
    
        # 计算变换矩阵
        M = cv2.getPerspectiveTransform(rect, dst)
        warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    
        # 返回变换后结果
        return warped
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    20.4、阈值处理

    处理已经选择的题目

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

    在这里插入图片描述

    20.5、轮廓检测(小)

    每一个圆圈的轮廓检测

    (涂答题卡可能涂到外面)

    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(thresh_Contours, cnts, -1, (0, 0, 255), 3)
    
    • 1
    • 2

    在这里插入图片描述

    20.6、筛选,排序,选项

    筛选出符合条件的圆圈(通过宽高,宽高比例筛选)

    将符合条件的进行排序(默认乱序)

    • 先从上到下找到所有行排序
    • 在从左到右对每一行排序
    • 根据像素点对比找到答案
    
    # 遍历筛选
    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:
            questionCnts.append(c)
    
    # 排序
    def sort_contours(cnts, method="left-to-right"):
        # ...
        boundingBoxes = [cv2.boundingRect(c) for c in cnts]
        return cnts, boundingBoxes
    
    # 对所有行排序
    questionCnts = sort_contours(questionCnts, method="top-to-bottom")[0]
    
    # 循环,并找答案
    for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):
    	# 对每一行进行排序
    	cnts = sort_contours(questionCnts[i:i + 5])[0]
    	for (j, c) in enumerate(cnts):
    		mask = np.zeros(thresh.shape, dtype="uint8")
    		if bubbled is None or total > bubbled[0]:
        	# j为答案,total为像素点对比(选出最合适的)
        	bubbled = (total, j)
    		# ... 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    第一行跑完结果

    由 12345与操作得出最后结果

    在这里插入图片描述

    20.7、结果

    答案:BEADB

    第4题选错

    在这里插入图片描述

    答案:BEADB

    第1、2、4、5题选错
    在这里插入图片描述
    答案:BEADB

    第1、4 题选错

    在这里插入图片描述

    答案:BEADB

    第1、2、3、5题选错

    在这里插入图片描述

    答案:BEADB

    正确

    在这里插入图片描述

    原图

    # 正确答案 1 4 0 3 1  ------> B E A D B
    ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}
    
    • 1
    • 2

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    easyExcel导入
    fwknop服务端调试
    【附源码】计算机毕业设计JAVA仁爱公益网站
    MySQL进阶-----SQL提示与覆盖索引
    【Java】泛型的理解与使用,包装类
    vue2+elTree 实现右键菜单
    未来:spring响应式编程 Hands-On Reactive Programming in Spring 5(三),spring事件监听
    Ansys Speos | 新型计算方法:使用 GPU 提升计算速率
    Oracle ADG相关介绍
    智慧矿山&矿山安全生产:皮带撕裂识别AI算法不用激光,能迅速识别皮带纵撕!
  • 原文地址:https://blog.csdn.net/weixin_44635198/article/details/128013923