• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Python答题卡识别并给出分数的实现代码

      哈喽大家好,这里是滑稽研究所。看过我们图像处理系列的朋友,应该知道识别答题卡那期文章。其中利用opencv框架,完美的实现了答题卡填涂区域的识别。在后台有小伙伴想要我完善一下判断选项对错并打分的功能,本期我们就来实现一下。
      那么我们来复习一下往期的代码原理。我们需要对图片素材进行灰度化处理、透视变换、轮廓检测、腐蚀膨胀处理、区域分割、边框计算、区域计算。实际上我们是通过像素面积的过滤、填涂区域优化和获取选项坐标来完成答题卡的识别的。
    素材:

      那么在获取到答题卡的填涂区域之后就好办了。我们首先分隔答题卡,去除干扰项,然后把不同的区域打上标签。我们的答题卡是自上而下排序的。那么我们获取到的填涂项的x坐标即横坐标就派上了用场。选项A~E一定是占据了五个不同的区域。我们已经为不同区域打上了标签。剩下的就是交给我们的if判断语句了。这时我们已经为填涂项赋上了实际的意义。即从像素坐标转换成了具有实际意义的选项。
      那y坐标就没有用了吗?非也。经过上面的处理我们只是得到了填涂区域对应的选项。但是我们还没有进行排序。大家知道无序的选项是没有意义的。而刚刚我们说了该答题卡的题号顺序是自上而下的。因为我们遍历选项时,是同时得到x、y坐标的,因此我们可以保证得到的坐标是配对的。
      其中横纵坐标分别填入两个list中,然后使用zip方法合并list。这时我们再按照每个list的第二个元素也就是纵坐标进行由小到大的排序,就可以得到正确的顺序。
      这时我们才真正获取到了需要的数据。即考生填涂的选项顺序,我们再新建一个list放正确的答案,与考生的答案进行对比,经计算得出考生的正确率,并给出分数。
      好,思路清晰,上代码!

    import cv2
    import numpy as np
    
    path = './test_01.png'
    img = cv2.imread(path)
    
    imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    imgBlur = cv2.GaussianBlur(imgGray,(3,3),1)
    imgCanny = cv2.Canny(imgBlur,100,120)
    
    cv2.imshow("O", imgCanny)
    
    imgContour = img.copy()
    
    cnts = cv2.findContours(imgCanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    for cnt in cnts:
        area = cv2.contourArea(cnt)
        # 这个输出各个轮廓的面积
        #print(area)
    #
    if area >= 500:
        cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)
        peri = cv2.arcLength(cnt, True)
        # 找出轮廓的突变值
        approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
        # approx找到的是一个轮廓有几个突变值,有几个角就会有几个突变值
        # 返回的是一个list,输出他的长度,就可以知道到底有几个角
        #print(approx)
        a1,a2,a3,a4 = list(approx[0][0]),list(approx[1][0]),list(approx[2][0]),list(approx[3][0])
    
    #cv2.imshow("Canny Image",imgContour)
    
    mat1 = np.array([a1,a2,a3,a4],dtype=np.float32)
    
    #透视变换
    #计算矩形宽高
    width = 402#int(((a4[0]-a1[0])+(a3[0]-a2[0]))/2)
    height = 518#int(((a2[1]-a1[1])+(a3[1]-a4[1]))/2)
    
    #计算还原后的坐标
    new_a1 = [0,0]
    new_a2 = [0,height]
    new_a3 = [width,height]
    new_a4 = [width,0]
    
    mat2 = np.array([new_a1,new_a2,new_a3,new_a4],dtype=np.float32)
    #计算变换矩阵
    mat3 = cv2.getPerspectiveTransform(mat1,mat2)
    
    #进行透视变换
    res = cv2.warpPerspective(imgCanny,mat3,(width,height))
    res1 = cv2.warpPerspective(img,mat3,(width,height))
    
    imgxx = cv2.cvtColor(res1,cv2.COLOR_BGR2GRAY)
    binary = cv2.threshold(imgxx,0,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU )[1]
    #变换完成
    #cv2.imshow("Output",res1)
    
    cntss = cv2.findContours(res, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    for cnt1 in cntss:
        area1 = cv2.contourArea(cnt1)
        # 这个输出各个轮廓的面积
        #print(area)
    #
        if area1 >= 1500 and area1=1700:
            #把圆的轮廓画成黑色
            cv2.drawContours(binary, cnt1, -1, (0, 0, 0), 10)
    
            kernel = np.ones((5, 5), np.uint8)
            imgDialation = cv2.dilate(binary, kernel, iterations=1)
    
    cv2.imshow("Out", imgDialation)
    
    cntsss = cv2.findContours(imgDialation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    
    l1 = []
    l2 = []
    l3 = ['B','E','A','D','B']
    
    for cnt2 in cntsss:
        area2 = cv2.contourArea(cnt2)
                #print(area)
    
        if area2 = 1200 and 800=area2:
                    #cv2.drawContours(res1, cnt, -1, (0, 255, 0), 5)
                    #轮廓长
            peri = cv2.arcLength(cnt2, True)
                    # 找出轮廓的突变值
            approx1 = cv2.approxPolyDP(cnt2, 0.02 * peri, True)
    
            x, y, w, h = cv2.boundingRect(approx1)
                    #外接矩形
            #print(x+w//2,y+h//2)
    
            m = x+w//2
            n = y+h//2
            l1.append(m)
            l2.append(n)
            #拼接两个一维列表,使x,y坐标配对。
            mix1 = list(zip(l1,l2))
            #按列表第二个元素升序,即按y值由小到大排列。
            #这是我们得到的答案为正确顺序。
            mix1.sort(key=lambda x: x[1])
    
            if 400>x>80 and 50y350:
                cv2.rectangle(res1, (x, y), (x + w, y + h), (0, 0, 255), 2)
                #圆心
                # (图像,x.y位置,半径,颜色,轮廓粗细)
                cv2.circle(res1, (x+w//2,y+h//2), 1, (255, 0, 0), 5)
    
    l4 = []
    for i in mix1:
        if 75  i[0]  130:
            print("A")
            l4.append('A')
        elif 130  i[0]  185:
            print("B")
            l4.append('B')
        elif 185  i[0]  240:
            print("C")
            l4.append('C')
        elif 240  i[0]  295:
            print("D")
            l4.append('D')
        elif 295  i[0]  350:
            print("E")
            l4.append('E')
    
    print('正确答案:',l3)
    print('考生答案',l4)
    
    
    h = 0
    for i in range(0, len(l3)):
        if l3[i] == l4[i]:
            h=h+1
    print('得分:',str(h/5*100)+'分')
    
    cv2.imshow("cc Image",res1)
    
    cv2.imshow("dd Image",binary)
    
    cv2.waitKey(0)

    运行结果:


      以上为两个图片素材的运行结果,我们只放出其中一部分。剩余的素材大家自行实验。
      可以看到,程序成功的识别了考生填涂的答题卡,并给出了考生答案、正答案和考生最后的得分。
      综上功能实现,任务完成。大家学会了吗?

    以上就是Python识别答题卡并给出分数的详细内容,更多关于Python识别答题卡的资料请关注脚本之家其它相关文章!

    您可能感兴趣的文章:
    • python OpenCV实现答题卡识别判卷
    • python实现百万答题自动百度搜索答案
    • python实现用户答题功能
    • 答题辅助python代码实现
    • python3.5+tesseract+adb实现西瓜视频或头脑王者辅助答题
    • 从0到1使用python开发一个半自动答题小程序的实现
    • Python冲顶大会 快来答题!
    • python利用opencv如何实现答题卡自动判卷
    上一篇:Python 中的单分派泛函数你真的了解吗
    下一篇:python中的class_static的@classmethod的巧妙用法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Python答题卡识别并给出分数的实现代码 Python,答题,卡,识别,并,给出,