一、实验目的
1、提取答题卡的信息
2、能够有效辨识答题卡的信息
二、实验内容
1、实验步骤
①配置python在实现图像处理下的运行环境,配置opencv-python,opencv-contrib-python,numpy库,这些库可以保证对于图像二值化的基本实现,在这些库的基础上,为了方便图像更加直观的可视化,又添加了matplotlib,wheel,pipllow库来实现数据的可视化。
②查阅资料,了解python编程语言下的opencv方法使用方式以及代码编写方法.
③根据实验要求,读取图像,生成灰度图,迭代阈值算法,计算阈值,图像二值化,显示处理结果
④找到连通域 v计算连通域的面积、中心、外接矩形 利用连通域提取答题框部分ROI
⑤hough直线提取,矩形框顶点定位

2、关键代码的设计、实现与执行
【报告要体现出设计思路】
【报告简要给出关键代码,注意,关键代码,关键代码,关键代码,禁止贴上代码原文或截屏】
【关键代码要具有可读性,可附上简单的说明或者程序流程图】
【可附上实验过程数据的截图,同时请注明截图内容】
【可以给出不同的实现版本,对比分析】
(1)图像二值化
首先将获得的图像进行灰度处理,可使用公式Gray=R0.299+G0.587+B*0.114,python+opencv库中可以直接调用cv2.cvtColor(image,cv2.COLOR_BGRA2GRAY)使图片转换为灰度图效果如下

原图 灰度图
转换为灰度图后有三种方式可以将其二值化:
①手动赋予全局阈值

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

Cv2.threshold中第一个参数为目标灰度图,第二个为手动设置的阈值,第三个为最大值,最后一个为阈值类型,阈值常用类型有如下几种:

• cv2.THRESH_BINARY(黑白二值)
• cv2.THRESH_BINARY_INV(黑白二值反转)
• cv2.THRESH_TRUNC (得到的图像为多像素值)

手动设置全局阈值得到的效果图如上。
②迭代阈值分割算法
迭代阈值算法的流程图如下

用代码描述则是首先读入图片并转化为矩阵,然后求出矩阵的大小,根据得到的矩阵求出初始阈值

zmin = np.min(im)
zmax = np.max(im)
t0 = int((zmin+zmax)/2)

使用迭代法计算最佳阈值

while abs(t0-t1)>0:
#遍历每一个像素点for i in range(0,l-1):for j in range(0,w-1):
#判断是否大于t0,分别存入两个数组res1和res2if im[i,j]<t0:res1=res1+im[i,j]s1=s1+1elif im[i,j]>t0:res2=res2+im[i,j]s2=s2+1avg1=res1/s1avg2=res2/s2res1 = 0res2 = 0s1 = 0s2 = 0t1 = t0     #旧阈值储存在t1中t0=int((avg1+avg2)/2)   #计算新阈值

经迭代阈值算法分析后得到的最佳阈值直方图

原始图片与迭代阈值分析算法分析后的二值化图片

③自适应阈值分割
自适应阈值分割可以通过滤波器处理后二值化图片,也可以通过去除阴影,图像拉伸后二值化处理
滤波器处理可以在python+opencv下的
dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)方法下进行
这个方法代表自适应阈值二值化
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
thresh_type: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C.其中第一个代表均值像素计算
type:二值化操作的类型,与固定阈值函数相同,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV.
Block Size: 图片中分块的大小
C :阈值计算方法中的常数项
效果图如下

第二种方法可以采用去除光照后灰度拉伸在采用迭代阈值分割算法进行二值化处理
去除光照可采用首先计算每个修改的像素块的大小然后使用高斯滤波进行处理
效果图如下

(2)连通域获取
首先求得图片内的最大连通域
Python+opencv下获取二值图连通域可使用skimage的measure.label

参数介绍:

label 是返回的已经将input中连通域标注为1,2,3。。num的标签数组

num 连通域个数

input_array 输入数组

neighbors 连通域计算样式

from skimage import measure
label, num = measure.label(input_array, neighbors=8, background=0, return_num=True)

获取最大连通域的方法如下

for i in range(1, num+1):if np.sum(labeled_img == i) > max_num:max_num = np.sum(labeled_img == i)max_label = i
mcr = (labeled_img == max_label)

遍历所得的每一个连通域,从1开始是为了防止计算最大连通域时将外边框计算入内,每次遍历得到一个更大的连通域就将 max_label转为此连通域对应的下标,最后将连通域内下标为max_label的连通域赋给mcr
然后可通过

minr, minc, maxr, maxc = regionprops(labeled_img)[max_label-1].bbox

得到最大连通域的高度宽度,其中max_label-1的原因在于数组从0开始因此需要减去一才是应得的值,再通过crop函数裁剪就能得到连通域所对应的区域

region = img.crop((minc,minr,maxc,maxr))

矩形则通过matplotlib.patches所带的Rectangle可得到矩形边框

rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,fill=False, edgecolor='red', linewidth=2)

效果图如下

(3)harris角点检测
Harris角点检测的原理:
角点向任何方向移动变化都很大,Chris_Harris 和 Mike_Stephens 早在 1988 年的文章《A Combined Corner and Edge Detector》中就已经提出了焦点检测的方法,被称为 Harris 角点检测。他把这个简单的想法转换成了数学形式。将窗口向各个方向移动(u,v)然后计算所有差异的总和。表达式如下:

窗口函数可以是正常的矩形窗口也可以是对每一个像素给予不同权重的高斯窗口
角点检测中要使 E (µ, ν) 的值最大。这就是说必须使方程右侧的第二项的取值最大。对上面的等式进行泰勒级数展开然后再通过几步数学换算,我们得到下面的等式:

其中

这里 Ix 和 Iy 是图像在 x 和 y 方向的导数。(可以使用函数 cv2.Sobel()计算得到)。
然后就是主要部分了。他们根据一个用来判定窗口内是否包含角点的等式进行打分。

其中

λ1 和 λ2 是矩阵 M 的特征值
所以根据这些特征中我们可以判断一个区域是否是角点,边界或者是平面。
当 λ1 和 λ2 都小时,|R| 也小,这个区域就是一个平坦区域。
当 λ1≫ λ2 或者 λ1≪ λ2,时 R 小于 0,这个区域是边缘
当 λ1 和 λ2 都很大,并且 λ1~λ2 中的时,R 也很大,(λ1 和 λ2 中的最 小值都大于阈值)说明这个区域是角点。
可用下图表示我们的结论

所以 Harris 角点检测的结果是一个由角点分数构成的灰度图像。选取适当的阈值对结果图像进行二值化我们就检测到了图像中的角点。
Harris角点检测函数
cv2.cornerHarris(src, blockSize, ksize, k, dst, borderType)
src:数据类型为float32的输入图像
blockSize:角点检测中要考虑的领域大小
ksize:Sobel求导中使用的窗口大小
k:Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06].
dst:目标图像
borderType:边界类型
gray = np.float32(gray)

输入图像必须是 float32,最后一个参数在 0.04 到 0.05 之间

dst = cv2.cornerHarris(gray, 2, 3, 0.04)
#进行膨胀操作
dst = cv2.dilate(dst, None)
#将满足条件的角点用红色标注出来
img[dst > 0.005 * dst.max()] = [255, 0, 0]

实验结果如下

将参数变为0.2时

(4)hough变换
Hough变换思想(参数空间变换):
在原始图像坐标系下的一个点对应了参数坐标系中的一条直线,同样参数坐标系的一条直线对应了原始坐标系下的一个点,然后,原始坐标系下呈现直线的所有点,它们的斜率和截距是相同的,所以它们在参数坐标系下对应于同一个点。这样在将原始坐标系下的各个点投影到参数坐标系下之后,看参数坐标系下有没有聚集点,这样的聚集点就对应了原始坐标系下的直线。
在实际应用中,y=kx+b形式的直线方程没有办法表示x=c形式的直线(这时候,直线的斜率为无穷大)。所以实际应用中,是采用参数方程p=xcos(theta)+y*sin(theta)。这样,图像平面上的一个点就对应到参数p—theta平面上的一条曲线上,其它的还是一样。
Hough变换思想(参数空间划分网格统计):
为了检测出直角坐标X-Y中由点所构成的直线,可以将极坐标a-p量化成许多小格。根据直角坐标中每个点的坐标(x,y),在a = 0-180°内以小格的步长计算各个p值,所得值落在某个小格内,便使该小格的累加记数器加1。当直角坐标中全部的点都变换后,对小格进行检验,计数值最大的小格,其(a,p)值对应于直角坐标中所求直线。
Python+opencv所用函数

HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)

image: 必须是二值图像,推荐使用canny边缘检测的结果图像;
rho: 线段以像素为单位的距离精度,double类型的,推荐用1.0
theta: 线段以弧度为单位的角度精度,推荐用numpy.pi/180
threshod: 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先用100试试
lines:这个参数的意义未知,发现不同的lines对结果没影响,但是不要忽略了它的存在
minLineLength:线段以像素为单位的最小长度,根据应用场景设置
maxLineGap:同一方向上两条线段判定为一条线段的最大允许间隔(断裂),超过了设定值,则把两条线段当成一条线段,值越大,允许线段上的断裂越大,越有可能检出潜在的直线段

lines = cv2.HoughLinesP(edges,1,np.pi/180,180,minLineLength=60,maxLineGap=10)
lines1 = lines[:,0,:]#提取为二维
for x1,y1,x2,y2 in lines1[:]:cv2.line(img,(x1,y1),(x2,y2),(255,0,0),2)

参数设置为180时得到的图像最合理

3、实验结果分析
【测试数据说明,实验结果的正确性分析,程序不足点分析等】
第一部分(图像二值化)
图像二值化部分,总共采用了三种方法对图像二值化进行处理,分为手动设置全局阈值,局部自适应阈值(均值滤波分割和去除阴影),在阴影影响较为严重时,去除阴影图像拉伸的方法更加适用,而在阴影影响很小的情况下,均值滤波分割对信息的还原度最高

分别为去除阴影后采用迭代阈值分割法和均值滤波分割
第二部分(连通域)
连通域可以识别计算出最大连通域及他所对应的矩形边框的坐标

第三部分(harris角点检测)
基本能检测出关键点,同时调整参数的话会使点的数量发生改变
第四部分(hough变换)
基本能测绘出所需要的线段

三、实验思考
Python+opencv为我们封装了大量与视觉检测有关的方法,熟练使用这些方法我们就可以用很少的代码量实现复杂的功能,但同时,我们在使用这些方法的时候也需要了解这些方法背后的原理和其他的一些实现方法,在面对需要更加复杂具体的功能时,我们需要自己的算法加入其中才能完成更加充实可靠的功能。
(还请各位尽量多加自己的东西。切勿照搬)

视觉检测设计与实践答题卡检测实验报告相关推荐

  1. 计算机辅助教学导学设计研究,《计算机辅助教学》实验报告

    <计算机辅助教学>实验报告 一.实验目的与要求 1.利用多媒体教室进行一节课的专业教学,教学对象为中学生,教学内容自选,学习内容适合采用多媒体教学手段. 2.以Authorware或Fla ...

  2. 南邮软件设计matlab,通信软件设计基础,南邮,实验报告(共10篇).doc

    通信软件设计基础,南邮,实验报告(共10篇) 通信软件设计基础,南邮,实验报告(共10篇) 南邮matlab软件设计实验报告 通信与信息工程学院 2014 /2015 学年 第2学期 软件设计 实验报 ...

  3. 基于 RICS-V 架构的单周期 38 条指令处理器设计(含源码及实验报告)

    一.概述   之前有专门的写过两篇博文来介绍基于 RICS-V 架构的单周期九条指令处理器设计,并提供了相关的代码结构介绍,之后我又对其进行了拓展,且修补了之前源码中存在的一些小问题,并将指令集从九条 ...

  4. 校园卡管理系统实验报告c语言,基于C++的校园一卡通管理系统

    一.需求分析 随着学校管理现代化方向意识的不断增强,基于卡片应用的计算机管理系统已日益普及,学生持有传统的多种卡片和不同证件已司空见惯.然而,随着各种卡证的管理功能不断发展,由于传统卡功能的局限,常常 ...

  5. 计算机网络基础实验简答题,计算机网络基础实验报告.doc

    计算机网络基础实验报告 计算机科学与技术系 实 验 报 告专业名称课程名称计算机网络基础项目名称局域网组网实验班 级学 号姓 名同组人员实验日期实验目的与要求: (一).实验目的: 通过组建局域网,了 ...

  6. 基于MATLAB的答题卡识别软件设计

    基于 MATLAB 的答题卡识别软件设计 课题意义 随着教育技术的飞速发展,考试普遍使用答题卡来记录答案,采用计算机自动识别答案卡信息,计算考生的成绩,可以减少阅卷人的工作量.本文利用 Matlab ...

  7. 毕业设计之 ---基于机器视觉的答题卡识别

    简介 今天我们来介绍一个与机器视觉相关的毕业设计 基于机器视觉的答题卡识别系统 多说一句, 现在越来越多的学校以及导师选题偏向于算法类, 这几年往往做web系统的同学很难通过答辩, 仔细一想这也在情理 ...

  8. 终于不用手撸了,解放你的双手,教你用数学建模的方式对答题卡进行有效识别

    前言 声明:后期原力计划活动期间的数学建模类文章都会转入MATLAB深入理解高级教程(附源码)专栏.对于理工科类及马上要毕业设计的小伙伴应该会有很大帮助,有需要的小伙伴赶紧订阅吧.包括AI系列博文,博 ...

  9. python CV 趣味项目 答题卡识别

    英文原文来自 Bubble sheet multiple choice scanner and test grader using OMR, Python and OpenCV 说到答题卡,满满的都是 ...

最新文章

  1. 面试题整理 1:将一个字符串转换为整数
  2. java高性能阻塞队列,Linux c/c   后台开发组建之:高性能阻塞队列
  3. 【Flink】Flink ES6写入报错 IncompatibleClassChangeError: Implementing class
  4. SpringCloud分布式开发五大神兽
  5. python玩转android_怎样用python玩安卓版跳一跳
  6. 营销任何产品都只解决2个功能
  7. 快速掌握 JavaScript 库必备的 5 大技巧!
  8. linux环境下VSCode的C++环境搭建
  9. Java验证导入excel格式
  10. 《矛盾论》与《实践论》
  11. 用Matlab实现人脸 68 landmarks详细教程
  12. Python小姿势 - # Python网络爬虫之如何通过selenium模拟浏览器登录微博
  13. 年底不要慌,这个EXCEL模板帮你打赢Q4收官战
  14. MySQL——超详细数据库触发器教程
  15. 【神经网络】神经网络中的矩阵的理解
  16. 树莓派控制57步进电机
  17. 前端必看的8个HTML+CSS技巧
  18. 第一章——操作系统概论
  19. C++:斐波那契数列(迭代和递归)
  20. 学嵌入式培训课程好不好?嵌入式培训课程哪家好?

热门文章

  1. 苹果M1芯片MacBook/iMac/Mac mini降级或者重装系统教程
  2. 沐风:小程序推广高手速成秘笈
  3. 学习java随堂练习-20220617
  4. 【转】 机器学习入门——浅谈神经网络
  5. 你知道如何判定一个大整数为素数吗?——米勒拉宾素数判定算法
  6. 【原创】北京智能云分院招商项目之五:智能
  7. Win10 系统下安装 vim
  8. 2023山西大学计算机考研信息汇总
  9. php word转化为html,php如何把word转换为html(这里使用COM)
  10. 客房管理android源码,c++ 客房管理系统完整源码(含数据库)