目录
1 项目介绍
2 代码分析
2.1 导入库
2.2 设置参数
2.3 设置正确答案
2.4 定义找到四个角点的函数
2.5 定义变换函数
2.6 定义 sort_contours()
2.7 定义展示函数 cv_show()
2.8 图像滤波
2.9 边缘检测
2.10 整体轮廓检测
2.11 处理轮廓
2.12 透视变换
2.13 二值处理
2.14 寻找轮廓并画出来
2.15 提取答题卡上的答案
2.16 对比正确答案
2.17 计算其余信息
3 新了解的方法
1 项目介绍
现在我有一张写好答案的答题卡并且我有一组答案
为我们把正确的结果标出来,然后得出正确率
2 代码分析
2.1 导入库
2.2 设置参数
2.3 设置正确答案
第0行的答案的B,第1行的答案是E,第2行的答案是A,第3行的答案是D,第4行的答案是B
2.4 定义找到四个角点的函数
- 我觉得这个并不是很科学,我在该专栏的 11.提取图像内容区域 做过更改,我们可以使用我改过的函数
2.5 定义变换函数
在该专栏的 11.提取图像内容区域 有讲过,就不赘述了
2.6 定义 sort_contours()
这个是排序用的 在该专栏的 11.银行卡号识别 有讲过
2.7 定义展示函数 cv_show()
2.8 图像滤波
读取图片后复制一张,然后将原图转为灰度图,之后对其进行布尔滤波,然后展示出来
2.9 边缘检测
2.10 整体轮廓检测
2.11 处理轮廓
首先我们定义一个docCnt,这个变量用来存放我们轮廓的内容,之后如果我们检测到了轮廓就进入分支,进入分支后将轮廓按面积大小排序,之后遍历排序好的每一个轮廓对其进行轮廓近似(将每一个轮廓搞成多边形,大概是这样的),如果我近似后的结果多余四边形就将该轮廓近似后的结果赋值给docCnt()
我们下面看一下近似前与近似后的轮廓
- 近似前
- 近似后
可以看出来是差不多的,我们后面的遍历与近似是为了让代码也能更好的匹配别的图像
我们看一下docCnt的内容
2.12 透视变换
刚刚我们得到的docCnt就是内容区域的轮廓,现在我们使用docCnt提取图像内容(进行透视变换),首先我么们把docCnt降一维变成(4,2),然后执行four_point_transform()提取图像内容
2.13 二值处理
处理之后复制一张处理过的图片
2.14 寻找轮廓并画出来
由于图像是二值化的图像所以我们看不出来是红色,我们现在把轮廓在image上画验证一下
- 这个只是验证灰度图上画轮廓不显示红色,在刚刚灰度图中画的轮廓不是上图红色的样子
2.15 提取答题卡上的答案
- 如果答题卡涂成一个圆,我们也可以用霍夫变换来检测圆,但如果涂的不像是一个圆就没有办法检测出来了,下面这个图右边可以检测出来,左边这个检测不出来
首先我们创建一个空的列表用于存储 答题卡上答案 的轮廓
遍历图中的所有轮廓,对轮廓进行矩形近似,之后算出矩形的宽高比ar,之后进入判定,如果宽>=20,高>=20,宽高比在0.9-1.1之间,我们将轮廓加入questionCnts,这样我们就能筛选出来所有圈的轮廓了
之后使用上面定义的sort_contours对轮廓进行从上到下排序
我们现在看一下questionCnts,很长我就只截取头和尾了
然后定义correct用于记录正确的个数
下面涉及到了np.arange()这个方法,我们举个例子
import numpy as np
a = np.arange(3)
print(a)
print(type(a))
a = np.arange(1,5)
print(a)
print(type(a))
a = np.arange(1,5,2)
print(a)
print(type(a))
上面是三种加入参数的方式
- 直接写一个整形进去,这样就会生成一个内容为从0到n-1的numpy.ndarray
- 写两个整形进去,这样会生成内容为从a到b的numpy.ndarray
- 写三个整形进去,这样会生成内容为从a到b,步长为c的numpy.ndarray
回到我们的代码,我们此时做了一个循环
q是我们np.arange的结果从0到25,步长为5,q的取值范围为[0,5),i是enumerate给的序号,一共25个,所以i的取值范围为[0,25)
进入循环后,把每5个圆形轮廓归为一堆,并以默认的方法排序(从左到右)这样我们就得出了一行的圆形轮廓,然后将bubble置为none
然后我们再上面的循环中进入一个小循环,这个循环是遍历我们同一行的轮廓,我们先用enumerate()对同一行的轮廓进行标号
之后我们创建全0(黑)掩膜,大小与图像内容大小图片相同,之后在mask上把轮廓画出来,第一个-1是全部都画出来(由于是遍历的,所以只有一个),第二个-1是填充,把轮廓内的值都置为255(白色),然后展示出来
一共展示25次,我们展示一下前几次的什么样子的
然后我们使用mask对图自身做与运算,这样可以把选中的答案筛选出来,涂过的会比没涂过的非0值更多,之后我们使用检测出非零值个数,如果多就覆盖掉,少就下一轮,这样我们就选出来了一行中涂过的答案轮廓
2.16 对比正确答案
之后我们小循环就结束了,然后定义一个红颜色,之后把正确答案赋值给k
- ANSWER_KEY 我们之前定义过,是内容为正确答案的字典
如果判断正确,我们将颜色改为绿色,然后correct(正确数量)+1
然后把该轮廓画出来
2.17 计算其余信息
score是答题卡的得分,对一个20分,然后终端显示出来,之后在图上画出来,然后展示原图与最终的结果进行对比
由于我们搞的是灰度图,所以颜色就显示不出来了
如果我们要把颜色搞出来我们应该把图像的颜色通道变为3条,首先在大循环前复制,然后转换
然后在img上画
在img上写
展示img
3 新了解的方法
np.arange() 生成内容为顺序整形的numpy.ndarray