【转载】项目实战—答题卡识别判卷(十四)

本次我们将进行另一个实战项目,从本质上来讲,其与之前的卡片的数字识别基本上原理是一样的。

本次我们将使用的实验图片:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现答题卡识别的7步

 Step #1: 检测到图片中的答题卡

 Step #2: 应用****变换来提取图中的答题卡(以自上向下的鸟瞰视图)

 Step #3: 从****变换后的答题卡中提取 the set of 气泡/圆点 (答案选项)

 Step #4: 将题目/气泡排序成行

 Step #5: 判断每行中被标记/涂的答案

 Step #6: 在我们的答案字典中查找正确的答案来判断答题是否正确

 Step #7: 为其它题目重复上述操作

算法实现

让我们新建一个Python文件,然后添加以下内容:

# 引入必要的库

view plaincopy to clipboardprint?
from imutils.perspective import four_point_transform  
from imutils import contours  
import numpy as np  
import argparse  
import imutils  
import cv2  
   
# 构建命令行参数解析并分析参数  
# 对应使用方式 python test_grader.py --image images/test_01.png  
ap = argparse.ArgumentParser()  
ap.add_argument("-i", "--image", required=True,  
    help="path to the input image")  
args = vars(ap.parse_args())  
   
# 构建答案字典,键为题目号,值为正确答案  
ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}  

补充:vars()接受一个对象返回它的内建字典:
当然我们需要有OpenCV和Numpy的包,一个便于基本图像处理操作的库。使用下面的命令来安装和升级该库:
pip install --upgrade imutils
补充:在Windows10_64位+ Python 3.7测试,对于OpenCV的安装有两种方法,推荐第一种方法。(由于是python3,使用的是OpenCV 4.2.0)
我们在命令行中只解析了一个参数,那就是要分析的图片的路径。然后定义了答案字典,在这里,题目对应的值是正确答案在行中的索引位置,跟python中列表的索引方式相同。

# 加载图片,将它转换为灰阶,轻度模糊,然后边缘检测。  
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)  

先来看滤波之后的图像:
在这里插入图片描述
我们先从磁盘中加载了图片文件,然后将它转换为灰阶,再进行模糊处理来消除高频噪声。最后,使用Canny边缘检测器来获取答题卡的边缘。结果如下 :
在这里插入图片描述
注意,答题卡长方形的四个顶点都要在图中出现,这是我们事先约定的答题卡的边缘。

获取轮廓非常重要,因为下一步我们将它作为应用****变换的标记(锚点),来获得一个答题卡的自上而下的鸟瞰视图。

而类似的情况,我们在之前的文档OCR扫描也用过,就是采用****变换进行图片的校正,它对于之后的图像处理十分的重要。

view plaincopy to clipboardprint?
# 从边缘图中寻找轮廓,然后初始化答题卡对应的轮廓  
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,  
    cv2.CHAIN_APPROX_SIMPLE)  
cnts = cnts[0] if imutils.is_cv2() else cnts[1]  
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  

首先我们通过cv2.findContours从边缘检测的结果更进一步得到轮廓值。然后我们对轮廓的区域大小进行排序,在这里我们假设答题卡就是我们图像的焦点,它会比图中其它对象大,所以从大到小对轮廓进行检测,符合长方形特征的就是我们的答题卡了。
此外,对于每个轮廓,我们进行了近似,这在本质上意味着我们简化了轮廓点的数量,使其成为一个“更基本的”几何形状。

现在,如果边缘轮廓在原始图像中画出来它将是这样的:
在这里插入图片描述
下次我们将进行****变换,继而进行下一步的处理。
查看文章汇总页https://blog.csdn.net/weixin_44237705/article/details/107864965
更多openvino技术信息可以入群交流~
申请备注:CSDN
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值