Python答题卡识别并给出分数的实现代码
Python答题卡识别并给出分数的实现代码
哈喽大家好,这里是滑稽研究所。看过我们图像处理系列的朋友,应该知道识别答题卡那期文章。其中利用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,a3,a4 = list(approx[0][0]),list(approx[1][0]),list(approx[2][0]),list(approx[3][0]) #cv2.imshow("Canny Image",imgContour) mat1 = np.array([a1,a2,a3,a4],dtype=np.float32) #透视变换 #计算矩形宽高 width = 402#int(((a4[0]-a1[0])+(a3[0]-a2[0]))/2) height = 518#int(((a2[1]-a1[1])+(a3[1]-a4[1]))/2) #计算还原后的坐标 new_a1 = [0,0] new_a2 = [0,height] new_a3 = [width,height] new_a4 = [width,0] mat2 = np.array([new_a1,new_a2,new_a3,new_a4],dtype=np.float32) #计算变换矩阵 mat3 = cv2.getPerspectiveTransform(mat1,mat2) #进行透视变换 res = cv2.warpPerspective(imgCanny,mat3,(width,height)) res1 = cv2.warpPerspective(img,mat3,(width,height)) imgxx = cv2.cvtColor(res1,cv2.COLOR_BGR2GRAY) binary = cv2.threshold(imgxx,0,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU )[1] #变换完成 #cv2.imshow("Output",res1) cntss = cv2.findContours(res, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] for cnt1 in cntss: area1 = cv2.contourArea(cnt1) # 这个输出各个轮廓的面积 #print(area) # if area1 >= 1500 and area1<=1700: #把圆的轮廓画成黑色 cv2.drawContours(binary, cnt1, -1, (0, 0, 0), 10) kernel = np.ones((5, 5), np.uint8) imgDialation = cv2.dilate(binary, kernel, iterations=1) cv2.imshow("Out", imgDialation) cntsss = cv2.findContours(imgDialation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] l1 = [] l2 = [] l3 = ['B','E','A','D','B'] for cnt2 in cntsss: area2 = cv2.contourArea(cnt2) #print(area) if area2 <= 1200 and 800<=area2: #cv2.drawContours(res1, cnt, -1, (0, 255, 0), 5) #轮廓长 peri = cv2.arcLength(cnt2, True) # 找出轮廓的突变值 approx1 = cv2.approxPolyDP(cnt2, 0.02 * peri, True) x, y, w, h = cv2.boundingRect(approx1) #外接矩形 #print(x+w//2,y+h//2) m = x+w//2 n = y+h//2 l1.append(m) l2.append(n) #拼接两个一维列表,使x,y坐标配对。 mix1 = list(zip(l1,l2)) #按列表第二个元素升序,即按y值由小到大排列。 #这是我们得到的答案为正确顺序。 mix1.sort(key=lambda x: x[1]) if 400>x>80 and 50<y<350: cv2.rectangle(res1, (x, y), (x + w, y + h), (0, 0, 255), 2) #圆心 # (图像,x.y位置,半径,颜色,轮廓粗细) cv2.circle(res1, (x+w//2,y+h//2), 1, (255, 0, 0), 5) l4 = [] for i in mix1: if 75 < i[0] < 130: print("A") l4.append('A') elif 130 < i[0] < 185: print("B") l4.append('B') elif 185 < i[0] < 240: print("C") l4.append('C') elif 240 < i[0] < 295: print("D") l4.append('D') elif 295 < i[0] < 350: print("E") l4.append('E') print('正确答案:',l3) print('考生答案',l4) h = 0 for i in range(0, len(l3)): if l3[i] == l4[i]: h=h+1 print('得分:',str(h/5*100)+'分') cv2.imshow("cc Image",res1) cv2.imshow("dd Image",binary) cv2.waitKey(0)
运行结果:
以上为两个图片素材的运行结果,我们只放出其中一部分。剩余的素材大家自行实验。
可以看到,程序成功的识别了考生填涂的答题卡,并给出了考生答案、正答案和考生最后的得分。
综上功能实现,任务完成。大家学会了吗?
以上就是Python识别答题卡并给出分数的详细内容,更多关于Python识别答题卡的资料请关注趣讯吧其它相关文章!
推荐阅读
-
华强北耳机和苹果耳机有啥区别(华强北苹果耳机跟正版有什么区别)
-
痛风食谱菜谱大全
痛风食谱菜谱大全男性到中年后,痛风食谱菜谱大全,最大的痛苦莫过于钱包鼓了,身子却垮了。现在都市人不健康的生活方式和过度劳累,让我们...
-
口里总是苦是什么原因(嘴里苦是什么原因)
大家好,今天来为大家解答嘴里苦是什么原因这个问题的一些问题点,包括口里总是苦是什么原因也一样很多人还不知道,因此呢,今天就来为大家...
-
全身美白产品排行榜10强(全身美白的产品)
全身美白的产品美白护肤是一项相对特殊的护肤方式,全身美白的产品,大家目前可以选购的美白功效护肤品,都是有特证认证的产品,也是官方认...
-
黄粱是小米吗(黄粱是小米还是水稻)
黄粱是小米。黄粱是一种粟米,粟米因为颗粒细小,又叫做小米,黄粱原产中国北方,是古代黄河流域重要的粮食作物之一,关于黄粱的典故有黄粱...
-
黑头黑脚的是什么动物(黑头黑脚代表什么动物)
黑头黑脚代表的动物是黑熊。黑熊全身的毛发都是黑色的,所以由此得来黑熊的称呼,黑熊的头部和脚部都是黑色的,所以黑头黑椒代表的动物是黑...
-
贵州选调生报考条件及时间2023年(贵州选调生报考条件及时间2023)
考研是场持久战,也是场信息战。每年临近暑假,就有很多院校发布公告,调整考研初试科目。这不,23考研人马上就又被“摆了一道”,又有几...
-
上海市公务员考报名时间2023时间(上海市公务员考报名时间2023)
2023年国考笔试考试延期举行,那2023年省考会延期吗?2023年省考对于已经发布招录考试简章地区,目前都已报名结束,进入笔试环...
-
银耳怎么吃降糖效果最好(银耳怎么吃)
银耳怎么吃说到银耳,银耳怎么吃,相信大家都不陌生了,经常拿来煲汤做糖水什么的!银耳口感脆爽,营养丰富,银耳富含维生素D,能防止钙的...
-
2023年纳音五行属什么命(2023年纳音)
2023年为农历【癸卯年】,属兔人为水兔之命。通过六十甲子纳音表查询可知,纳音为金箔金命,山林之兔。公元2023年,公历平年,共3...