美文网首页每周一赞
整张答题卡识别原理(将选项按照题目分组1)

整张答题卡识别原理(将选项按照题目分组1)

作者: 大龙10 | 来源:发表于2023-11-13 13:12 被阅读0次

    书名:计算机视觉40例从入门到深度学习:OpenCV-Python
    作者:李立宗
    出版社:电子工业出版社
    出版时间:2022-07-01
    ISBN:9787121436857


    第9章 答题卡识别

    9.2 整张答题卡识别原理

    9.2.4 将选项按照题目分组

    1、无序变有序

    • 在默认情况下,所有轮廓是无序排列的,因此无法直接使用序号将其划分到不同的题目上。
      若将所有选项轮廓按照从上到下的顺序排列,则可以获得如图9-13所示的排序规律。
      由于第1道题目的四个选项一定在第2道题目的四个选项的上方,所以第1道题目的四个选项的序号一定是{0、1、2、3}这四个值,但是具体哪个选项对应哪个值还不确定。
      同理,第2道题目的四个选项一定在第3道题目的上方,所以第2道题目的四个选项的序号一定是{4、5、6、7}这四个值。
      以此类推,。排序结果示意图如图9-13所示。


      图9-13 排序结果示意图

    2、初步排序

    【例9.8】确定选项的大致序号,确保每一道题选项的序号在下一道题选项的序号的前面。

    import cv2
    
    thresh =  cv2.imread("d:\\OpenCVpic\\thresh.bmp",-1)  
    # cv2.imshow("thresh", thresh)
    
    cnts, hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    print("共找到各种轮廓",len(cnts), "个")
    
    # =======构造载体=======
    # thresh:在该图像内显示选项无序时的序号
    # thresh 是灰度图像,将其转换至色彩空间是为了能够显示彩色序号
    threshColor=cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR)
    # result:在该图像内显示选项序号调整后的序号
    result=threshColor.copy()
    
    
    #===========用于存储筛选出的选项====
    options =[]
    font = cv2.FONT_HERSHEY_SIMPLEX
    for (i,ci) in enumerate(cnts):
        
        #获取轮廓的矩形包围框
        x,y, w, h = cv2.boundingRect(ci)
        #计算纵横比
        ar = w / float(h)
        # 将满足长度、宽度大于 24 像素且纵横比介于[0.7,1.3]的轮廓加入 options 
        if w >= 24 and h>= 24 and ar >= 0.7 and ar <= 1.4:
            options.append(ci)
            #绘制序号
            cv2.putText(threshColor,str(i), (x-1,y-5),font,0.5,(0,0,255),2)
    
    cv2.imshow("thresh", threshColor)
    # 需要注意的是,此时得到了很多选项的轮廓,但是它们在 options 中是无规则存放的
    print("共找到选项",len(options), "个")
    
    # =====将找到的所有选项轮廓绘制出来==
    color = (0,0,255) # 红色
    cv2.drawContours(threshColor, options,-1, color, 2)
    # cv2.imshow("threshColor",threshColor)
    
    # ==将轮廓按照从上到下的顺序排列===
    boundingBoxes = [cv2.boundingRect(c) for c in options]
    (options, boundingBoxes) = zip(*sorted(zip(options,boundingBoxes),key=lambda b:b[1][1],reverse=False))
    
    
    # ====按照序号,显示排序后的轮廓===========
    for (i,ci) in enumerate(options):
         x,y, w, h = cv2.boundingRect(ci)
         cv2.putText(result,str(i), (x-1,y-5),font,0.5,(0,0,255),2)
    
    cv2.imshow("result", result)
    
    cv2.waitKey()
    cv2.destroyAllWindows()
    
    
    
    运行结果

    3、结果分析

    • 简而言之,排序后将轮廓按照位置关系从上到下排列,该操作能够把每道题的4个选项放在邻近的位置上,并且保证每道题的4个选项的序号都在下道题的前面。
    • 按照此操作,采用for语句,在步长为4的情况下,遍历所有选项,每次提取的4个选项正好是同一个题目的4个选项。
    • 具体来说,一共有5道题,每道题都有A、B、C、D四个选项,答题卡内共计有20个选项。每次提取4个选项:
      • 第1次提取索引为0、1、2、3的轮廓,这些轮廓恰好是第1道题的4个选项。
      • 第2次提取索引为4、5、6、7的轮廓,这些轮廓恰好是第2道题的4个选项。
      • 第3次提取索引为8、9、10、11的轮廓,这些轮廓恰好是第3道题的4个选项。
      • 第4次提取索引为12、13、14、15的轮廓,这些轮廓恰好是第4道题的4个选项。
      • 第5次提取索引为16、17、18、19的轮廓,这些轮廓恰好是第5道题的4个选项。
    • 按照上述提取过程,可以把答题卡内每道题目的4个选项限定在特定的位置范围内。

    相关文章

      网友评论

        本文标题:整张答题卡识别原理(将选项按照题目分组1)

        本文链接:https://www.haomeiwen.com/subject/sawcwdtx.html