哈喽大家好,这里是滑稽研究所。看过我们图像处理系列的朋友,应该知道识别答题卡那期文章。其中利用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,