机器学习进阶-案例实战-答题卡识别判

1.H = cv2.getPerspectiveTransform(rect, transform_axes) 获得投射变化后的H矩阵

参数说明:rect表示原始的位置左上,右上,右下,左下, transform_axes表示变换后四个角的位置

2.cv2.warpPerspective(gray, H, (width, height)) 根据H获得变化后的图像

参数说明: gray表示输入的灰度图像, H表示变化矩阵,(width, height)表示变换后的图像大小
3. cv2.approxPloyDP(contour, length*0.02, True) # 计算轮廓的近似值

参数说明:contour表示输入的轮廓值, length表示轮廓的大小, True表示是否闭合

4. cv2.threshold(wrap, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_AUTO) # 进行图像的二值化操作
参数说明: wrap表示输入图片,0表示最小值,255表示最大值,THRESH_BINARY_INV | cv2.THRESH_AUTO表示方法,即大于最小阈值的为0, 小于最小阈值的为255

5. cv2.draw_contours(image, [contour], -1, 255, -1) # 对轮廓进行画图

参数说明:image表示输入图片. [contour] 表示单个轮廓, -1表示轮廓的index, 255表示颜色,-1表示对轮廓进行填充

6. cv2.bitwise(image, image, mask=mask)  # 与判断,如果两个都大于1才为1,否则都为0

参数说明:image表示输入图片,image表示输出图片, mask=mask表示掩膜

7. cv2.countNoneZeros(mask) # 用于计算图像中不等于0的像素点

参数说明:mask表示经过图像与掩膜的与操作以后的图像

8.cv2.putText(image, text, org, font, font_scale, color, ticking) # 在图像上加上文字

参数说明:image表示输入图片,text表示文字,org表示文字位置,font表示字体的格式,font_scale表示字体的胖瘦,color表示颜色,ticking表示粗细

答题卡识别判卷, 需要做的就是将画圈圈的地方识别出来。

    

原始图像                             涂了铅笔的比没涂白色部分要多,使用掩膜进行逐个遍历

第一部分:对图片进行透视变化,使得图片中的答题卡可以凸显出来

第一步:读入图片

第二步:使用cv2.gray() 进行灰度值的变化
第三步:使用cv2.GuassianBlur() 进行高斯滤波操作

第四步:使用cv2.Canny找出图片的边缘信息,为了下一步找出轮廓值做准备

第五步:使用cv2.findCountor() 找出图片的轮廓值,使用key = cv2.ContourArea对轮廓值进行排序

第六步:对轮廓值进行遍历,使用cv2.approxPolyDP(c, 0.02*lenght, True) 获得轮廓的近似值,如果近似值的维度为4,即为最外层答题卡的四个角的维度,则跳出循环

第七步:构造函数,对求得的轮廓值,根据其位置信息,将其变成左上,右上,右下,左上的形式的rect

第八步:计算width,height,计算出变换后的四个角的位置(transform_axes)

第九步:使用H = cv2.getPerspectiveTransform(rect, transform_axes) rect为变化前的位置,transform_axes为变化后的位置,以x,y表示,获得变化矩阵H

第十步:使用cv2.warpPerspective(thresh, H, (width, height)) 获得最终的变化结果

第二步:根据正确答案和图卡的答案来判断正确率

第一步:根据上述获得的wrapped,进行二值化操作, 使用cv2.COLOR_BINARY_INV将图了颜色的地方变成白色

第二步:使用cv2.findContours进行轮廓检测

第三步:对获得的轮廓,使用外接矩形cv2.boundingRect的(x, y, w, h)对轮廓进行筛选,找出答案的轮廓
第四步:对轮廓进行从上到下的排序

第五步:分别对每一行进行遍历,np.arange(0, len(question_cnts, 5)), 遍历每一行的轮廓值,根据图像构造掩膜mask图像,使用cv2.draw_contours在掩膜上画出对应位置的白色轮廓, 使用cv2.bitwise_and 获得原始图像当前位置等于1的点,使用cv2.countNoneZero计算出不是零的点,我们发现涂了颜色的要比没涂颜色的要大

第六步:计算出颜色值最大的位置和Nonezeros的值,correct+= 1

第七步:使用cv2.draw_contours在正确位置上进行画图操作

第八步:使用cv2.putText将正确率打印在图像上

代码:

# 第一部分代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 正确答案
ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}
def cv_show(name, image):
    cv2.imshow(name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def four_point_transform(image, dotCnt):
    # 第七步:按照轮廓近似的位置,将结果变成左上,右上,右下,左下的位置
    rect = sort_dotCnt(dotCnt)
    (tl, tr, br, bl) = rect
    # 第八步:计算轮廓的宽和长,构造出变化后四个角的位置
    widthA = np.sqrt(((tl[0]-tr[0])**2) + ((tl[1]-tr[1])**2))
    widthB = np.sqrt(((bl[0]-br[0])**2) + ((bl[1] - br[1])**2))
    widthMax = max(int(widthB), int(widthA))

    heightA = np.sqrt(((tl[0]-bl[0])**2) + ((tl[1]-bl[1])**2))
    heightB = np.sqrt(((tr[0]-br[0])**2) + ((tr[1] - br[1])**2))
    heightMax = max(int(heightA), int(heightB))
    # 四个角的位置信息
    transform_axis = np.array([
        [0, 0],
        [widthMax-1, 0],
        [widthMax-1, heightMax-1],
        [0, heightMax-1],
    ], dtype=‘float32‘)

    # 第九步:使用cv2.getPerspectiveTransform构造变化矩阵H
    H = cv2.getPerspectiveTransform(rect, transform_axis)
    # 第十步:使用cv2.warpPerspective()获得变化后的矩阵
    wrapped = cv2.warpPerspective(image, H, (widthMax, heightMax))

    cv_show(‘wrapped‘, wrapped)

    return wrapped

def sort_dotCnt(kps):

    rect = np.zeros((4, 2), dtype=‘float32‘)
    s = kps.sum(axis=1)
    # 找出左上和右下
    rect[0] = kps[np.argmin(s)]
    rect[2] = kps[np.argmax(s)]
    # 找出右上和左下
    diff = np.diff(kps, axis=1)
    rect[1] = kps[np.argmin(diff)]
    rect[3] = kps[np.argmax(diff)]

    return rect

def sorted_contours(cnt, model=‘left-to-right‘):

    if model == ‘top-to-bottom‘:
        cnt = sorted(cnt, key=lambda x:cv2.boundingRect(x)[1])

    elif model == ‘left-to-right‘:
        cnt = sorted(cnt, key=lambda x:cv2.boundingRect(x)[0])

    return cnt

# 第一部分:使用投射变化进行图像的转换, 将答题卡放在图片的正中央
# 第一步:读入图片
image = cv2.imread(‘images/test_01.png‘)
# 第二步:进行灰度化操作
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show(‘gray‘, gray)

# 第三步: 进行高斯变化
Guass = cv2.GaussianBlur(gray, (5, 5), 0)
# 第四步:使用cv2.Canny 找出图像的边缘部分
edges = cv2.Canny(Guass, 50, 200)
cv_show(‘edges‘, edges)
# 第五步:使用cv2.findCountours找出图像的轮廓, 并对轮廓进行排序
cnt = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
ret = cv2.drawContours(image.copy(), cnt, -1, (0, 0, 255), 2)
cv_show(‘ret‘, ret)

dotCnt = None

if len(cnt) > 0:

    cnt = sorted(cnt, key=cv2.contourArea, reverse=True)
    # 第六步: 遍历轮廓,获得cv2.approxPolyDP获得轮廓的近似值, 如果approx=4,即为填图卡的轮廓近似
    for c in cnt:

        length = cv2.arcLength(c, True)
        # 获得轮廓的近似值
        approx = cv2.approxPolyDP(c, 0.02*length, True)
        # 如果轮廓的维度是4,即由4个点组成,就是一个方框,那就是外面的方框
        if len(approx) == 4:

            dotCnt = approx
            break

wrapped = four_point_transform(gray, dotCnt.reshape(4, 2))
cv_show(‘wrapped‘, wrapped)

            

原始图片                            灰度变化后图片         边缘检测的图片                 检测到的轮廓图            最终透射变化结果

# 第二部分代码:

# 第二部分:对变化后的wrapped进行操作,构造mask根据有无填涂的特性,进行位置的计算

#第一步:对图像进行二值化操作
thresh = cv2.threshold(wrapped, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cv_show(‘thresh‘, thresh)

# 第二步:对图像进行轮廓检测
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

# 第三步:使用cv2.boudingRect将答案信息的轮廓进行筛选

questionCnts = []
for c in cnts:

    (x, y, w, h) = cv2.boundingRect(c)
    arc = w / float(h)

    # 根据实际情况找出合适的轮廓
    if w > 20 and h > 20 and arc >= 0.9 and arc<=1.1:
        questionCnts.append(c)

# 第四步:将轮廓进行从上到下的排序
questionCnts = sorted_contours(questionCnts, model=‘top-to-bottom‘)

# 第五步:对每一行的轮廓进行遍历,构造掩码,对每一行答案的轮廓进行遍历,使用cv2.countNoneZeros()计算出涂了颜色的答案,并计算最终的结果
correct = 0
for j, qC in enumerate(np.arange(0, len(questionCnts), 5)):

    questionCnt = questionCnts[qC:qC+5]
    # 进行排序
    questionCnt = sorted_contours(questionCnt)
    questionCnt = np.array(questionCnt)
    # 每个问题的答案
    bubbled = None
    for k, c in enumerate(questionCnt):
        # 根据轮廓值构造掩膜, 因为有涂答案的地方是白色的
        mask = np.zeros(thresh.shape, np.uint8)
        # 使用cv2.drawContours画出轮廓值
        cv2.drawContours(mask, [c], -1, 255, -1)
        cv_show(‘mask‘, mask)
        mask = cv2.bitwise_and(thresh, thresh, mask=mask)
        # 第六步:使用cv2.countNoneZero计算出白色最多的位置
        Nonezero = cv2.countNonZero(mask)
        if bubbled == None or Nonezero > bubbled[0]:
            bubbled = (Nonezero, k)

    question_answer = int(bubbled[1])
    answer_True = ANSWER_KEY[j]

    # 如果结果和正确结果相同,就+1
    if question_answer == answer_True:
        correct += 1
    # 第七步:对正确答案的轮廓进行画图操作
    cv2.drawContours(wrapped, [questionCnt[answer_True]], -1, 0, 2)

cv_show(‘wrapped‘, wrapped)

score = (correct / 5) * 100
# 第八步:使用cv2.putText将正确率打印在图上
cv2.putText(wrapped, ‘correct_score:%d‘ %score, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
            0.8, 0, 2)
cv2.imshow(‘orginal‘, image)
cv2.imshow(‘wrapped‘, wrapped)

cv2.waitKey(0)
cv2.destroyAllWindows()

               

Binary_Inv二值化的结果         draw_contours画出掩膜轮廓                      最终的结果图

原文地址:https://www.cnblogs.com/my-love-is-python/p/10439224.html

时间: 2024-08-24 20:38:08

机器学习进阶-案例实战-答题卡识别判的相关文章

机器学习进阶-项目实战-信用卡数字识别 1.cv2.findContour(找出轮廓) 2.cv2.boudingRect(轮廓外接矩阵位置) 3.cv2.threshold(图片二值化操作) 4.cv2.MORPH_TOPHAT(礼帽运算突出线条) 5.cv2.MORPH_CLOSE(闭运算图片内部膨胀) 6. cv2.resize(改变图像大小) 7.cv2.putText(在图片上放上文本)

7. cv2.putText(img, text, loc, text_font, font_scale, color, linestick) # 参数说明:img表示输入图片,text表示需要填写的文本str格式,loc表示文本在图中的位置,font_size可以使用cv2.FONT_HERSHEY_SIMPLEX, font_scale表示文本的规格,color表示文本颜色,linestick表示线条大小 信用卡数字识别: 信用卡      数字模板涉及到的内容:主要是采用模板匹配的思想 思

机器学习进阶-案例实战-图像全景拼接-书籍SIFT特征点连接

书籍的SIFT特征点连接: 第一步:使用sift.detectAndComputer找出关键点和sift特征向量 第二步:构建BFMatcher()蛮力匹配器,bf.match匹配sift特征向量,使用的是欧式距离 第三步:根据匹配结果matches.distance对matches按照距离进行排序 第四步:进行画图操作,使用cv2.drawMatches进行画图操作 import cv2 import numpy as np #读入图片 imgA = cv2.imread('box.png',

JMeter 深入进阶性能测试进阶案例实战

第1章 性能测试整体认知了解性能测试的目的,想做好性能测试都需要掌握哪些方面的技能(开发语言.操作系统.网络.工具等).性能测试.稳定性.压力.疲劳.容量预估.多并发逻辑.掌握如何开始性能测试,并且掌握在性能测试中每个部分的工作重点,了解软件架构.监控部署.脚本准备.场景设置及知道为什么需要做这些.掌握:事务.请求响应时间....1-1 性能测试行业分析1-2 性能测试技能树1-3 性能测试的目的及分类1-4 性能测试的工作流程1-5 常见系统应用分层架构1-6 性能测试指标定义1-7 性能测试

答题卡图像识别 需求分析、市场分析和技术实现

答题卡图像识别 需求分析.市场分析和技术实现 一.需求分析 一.以接口的方式开发此需求: 1:接收图片 以上传的方式把图片发送到接口. 2:识别图片 接口接收到图片后,进行图像识别. 3:返回数据 返回识别后的JSON格式数据. 二.答题卡图片识别的具体要求: 图片是通过手机.相机.扫描仪等设备拍照而来,其中手机.相机拍出的照片会出现像素低.图像不正.聚焦不清楚等问题: 1:图片只要是人眼能看清楚的即可完成识别: 2:800万像素以上的手机拍的照片能进行识别: 3:聚焦不清楚时也可以进行识别:

答题卡图像识别项目

答题卡图像识别 需求分析.市场分析和技术实现 一.需求分析 一.以接口的方式开发此需求: 1:接收图片 以上传的方式把图片发送到接口. 2:识别图片 接口接收到图片后,进行图像识别. 3:返回数据 返回识别后的JSON格式数据. 二.答题卡图片识别的具体要求: 图片是通过手机.相机.扫描仪等设备拍照而来,其中手机.相机拍出的照片会出现像素低.图像不正.聚焦不清楚等问题: 1:图片只要是人眼能看清楚的即可完成识别:  2:800万像素以上的手机拍的照片能进行识别:  3:聚焦不清楚时也可以进行识别

基于Python数据分析与机器学习案例实战教程

课程--基于Python数据分析与机器学习案例实战教程 分享网盘下载--https://pan.baidu.com/s/1jHSaRAY 密码: xk37 课程背景基于数据分析与机器学习领域,使用python作为课程的实战语言,随着大数据与人工智能领域日益火爆,数据分析和机器学习建模成了当下最热门的技术,课程旨在帮助同学们快速掌握python数据分析包以及经典机器学习算法并通过对真实数据集分析进行实战演示. 课程风格通俗易懂,基于真实数据集案例实战. 主体课程分成三个大模块 (1)python数

基于大数据技术推荐系统算法案例实战视频教程(项目实战)

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

Python数据挖掘与机器学习技术入门实战

摘要: 什么是数据挖掘?什么是机器学习?又如何进行Python数据预处理?本文将带领大家一同了解数据挖掘和机器学习技术,通过淘宝商品案例进行数据预处理实战,通过鸢尾花案例介绍各种分类算法. 课程主讲简介:韦玮,企业家,资深IT领域专家/讲师/作家,畅销书<精通Python网络爬虫>作者,阿里云社区技术专家. 以下内容根据主讲嘉宾视频分享以及PPT整理而成. 本次课程包含了五个知识点:1.数据挖掘与机器学习技术简介 2.Python数据预处理实战 3.常见分类算法介绍 4.对鸢尾花进行分类案例实

(升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课程会涵盖Scala编程详解.Spark核心编程.Spark SQL和Spark Streaming.Spark内核以及源码剖析.性能调优.企业级案例实战等部分.完全从零起步,让学员可以一站式精通Spark企业级大数据开发,提升自己的职场竞争力,实现更好的升职或者跳槽,或者从j2ee等传统软件开发工程