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 50<y<350:
            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识别答题卡的资料请关注我们其它相关文章!

(0)

相关推荐

  • 从0到1使用python开发一个半自动答题小程序的实现

    前言 最近每天都有玩微信读书上面的每日一答的答题游戏,完全答对12题后,可以瓜分无限阅读卡.但是从小就不太爱看书的我,很难连续答对12道题,由此,产生了写一个半自动答题小程序的想法.我们先看一张效果图吧(ps 这里主要是我电脑有点卡,点击左边地选项有延迟) 项目GIthub地址:微信读书答题python小程序 觉得对你有帮助的请点个⭐来支持一下吧. 演示图: 做前准备 mumu模拟器 因为手边没有安卓手机,所以只能在模拟器上进行模拟,如果手上有安卓手机地,可以适当地修改一下程序.需要安装微信和微

  • python实现百万答题自动百度搜索答案

    用python搭建百万答题.自动百度搜索答案. 使用平台 windows7 python3.6 MIX2手机 代码原理 手机屏幕内容同步到pc端 对问题截图 对截图文字分析 用浏览器自动搜索文本 使用教程 1.使用Airdroid 将手机屏幕显示在电脑屏幕上.也可使用360手机助手实现.不涉及任何代码.实现效果如图: 2.在提问出现时,运行python程序,将问题部分截图. 这里要用到两个函数: get_point()  #采集要截图的坐标,以及图片的高度宽度 window_capture() 

  • 答题辅助python代码实现

    本文实例为大家分享了答题辅助python具体代码,供大家参考,具体内容如下 from screenshot import pull_screenshot import time, urllib.request try: import Image except ImportError: from PIL import Image, ImageDraw import pytesseract # 屏幕顶端到问题的距离/屏幕高度,随分辨率变化(默认1920*1080) top_off_c = 0.15

  • python实现用户答题功能

    python实战,用户答题分享给大家. 主要包含内容,文件的读取,更改,保存.不同文件夹引入模块.输入,输出操作.随机获取数据操作 随机生成算数表达式,用户输入答案,正确记录分数,错误返回0,并把用户分数记录到文本文件中,如用户名不存在着新建用户 myPythonFunction.py包含三个函数 #coding=utf-8 from random import randint from os import remove,rename #function 输入用户名字,获得用户得分,返回得分或者

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

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

  • python OpenCV实现答题卡识别判卷

    本文实例为大家分享了python OpenCV实现答题卡识别判卷的具体代码,供大家参考,具体内容如下 完整代码: #导入工具包 import numpy as np import argparse import imutils import cv2 # 设置参数 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", default="./images/test_03.png"

  • 基于Opencv图像识别实现答题卡识别示例详解

    目录 1. 项目分析 2.项目实验 3.项目结果 总结 在观看唐宇迪老师图像处理的课程中,其中有一个答题卡识别的小项目,在此结合自己理解做一个简单的总结. 1. 项目分析 首先在拿到项目时候,分析项目目的是什么,要达到什么样的目标,有哪些需要注意的事项,同时构思实验的大体流程. 图1. 答题卡测试图像 比如在答题卡识别的项目中,针对测试图片如图1 ,首先应当实现的功能是: 能够捕获答题卡中的每个填涂选项. 将获取的填涂选项与正确选项做对比计算其答题正确率. 2.项目实验 在对测试图像进行形态学操

  • opencv实现答题卡识别

    本文实例为大家分享了opencv实现答题卡识别的具体代码,供大家参考,具体内容如下 """ 识别答题卡 """   import cv2 import numpy as np   def showImg(img_name, img): cv2.imshow(img_name, img) cv2.waitKey() cv2.destroyAllWindows()   def get_max_rect(sorted_cnts): for cnt in

  • Python+Opencv答题卡识别用例详解

    使用Python3和Opencv识别一张标准的答题卡.大致的过程如下: 1.读取图片 2.利用霍夫圆检测,检测出四个角的黑圆位置,从确定四个角的位置 3.利用透视变换和四个角的位置,矫正图片(直接用的网上的图片,没有拍照,所以这一步没有实现) 4.裁剪四个边框,获取边框上小黑格的位置 5.根据小黑格的位置确定每个涂卡区域的位置 6.将答题卡腐蚀和膨胀,遍历所有的格子的区域,计算每个区域内像素值为0的个数,若数量达到某个值,那么就确认这个格子是被黑笔涂过,并记录该位置的题目选项. 具体的实现 一.

  • Python chardet库识别编码原理解析

    这篇文章主要介绍了python chardet库识别编码原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 chardet库是python的字符编码检测器,能够检测出各种编码的类型,例如: import chardet import urllib.request testdata = urllib.request.urlopen('http://m2.cn.bing.com/').read() print(chardet.detect(te

  • python利用opencv如何实现答题卡自动判卷

    目录 1.设定答题卡模板 2.读取答题卡图像并对图像进行灰度化处理 3.高斯模糊图像去噪点 4.使用大津法二值分割图像 5.使用开运算去噪点 6.使用canny边缘检测算法 7.筛选答题区域轮廓,透视变换矫正目标区域 使用摄像头实时判卷部分 总结 1.设定答题卡模板 该图像为答题卡的答题区域,黑色边框是为了能够在各种环境中轻易的检测,左部分和上部分的黑色矩形,是为能够定位到答题选项的坐标而设置,同时题目数量为20×3共60道选择题,在进行批改试卷之前,需要手动输入该次考试的正确答案作为模板来对识

  • 使用 OpenCV-Python 识别答题卡判卷功能

    任务 识别用相机拍下来的答题卡,并判断最终得分(假设正确答案是B, E, A, D, B) 主要步骤 轮廓识别--答题卡边缘识别 透视变换--提取答题卡主体 轮廓识别--识别出所有圆形选项,剔除无关轮廓 检测每一行选择的是哪一项,并将结果储存起来,记录正确的个数 计算最终得分并在图中标注 分步实现 轮廓识别--答题卡边缘识别 输入图像 import cv2 as cv import numpy as np # 正确答案 right_key = {0: 1, 1: 4, 2: 0, 3: 3, 4

  • python 通过手机号识别出对应的微信性别(实例代码)

    python 通过手机号识别出对应的微信性别,具体代码如下所述: def getGender(self,tel): self.d(resourceId="com.tencent.mm:id/kh").clear_text() self.d(resourceId="com.tencent.mm:id/kh").set_text(tel) self.d(resourceId="com.tencent.mm:id/mf").click() time.s

  • Python OpenCV实现识别信用卡号教程详解

    目录 通过与 OpenCV 模板匹配的 OCR 信用卡 OCR 结果 总结 今天的博文分为三个部分. 在第一部分中,我们将讨论 OCR-A 字体,这是一种专为辅助光学字符识别算法而创建的字体. 然后我们将设计一种计算机视觉和图像处理算法,它可以: 本地化信用卡上的四组四位数字. 提取这四个分组中的每一个,然后单独分割 16 个数字中的每一个. 使用模板匹配和 OCR-A 字体识别 16 个信用卡数字中的每一个. 最后,我们将看一些将信用卡 OCR 算法应用于实际图像的示例. 通过与 OpenCV

随机推荐