当前位置:   article > 正文

opencv +python采集识别填涂卡(答题卡)数据_答题卡数据集

答题卡数据集

在社科研究中的问卷调查,或者需要进行问卷答题的场景中,需要用纸质问卷采集答案,然后将问卷的答案输入电脑。这是一般的问卷采集答案的方法,如果问卷数量并不是很多能很快速的将问卷的结果输入到电脑中,但是如果有很多张相同的问卷的情况下,工作效率就会减慢(一张一张的录入)。采用电脑识别的方式能很快的将纸质答案转换为电脑可识别的数据。

采用python+opencv的方式,在识别每一张问卷唯一性上,可以在每一张问卷上张贴二维码,用以区别问卷的唯一。

思路:

1,将答题卡扫描,进行灰度转变、高斯模糊、cv2.Canny边缘转化等操作,把图片转换。

2,扫描答题卡,确定左边和上边的黑块基点,进而根据黑块的基础位置和大小推算确定每一个答题选项的位置。

3,确定每一个答题选项后,由于是每一行扫描,所以每4个确定的坐标分为一组,每组的顺序就是题目答案的顺序。

4,对分组的一组中的4个区域计算cv2.countNonZero像素值,像素值越小的就表示涂得最多,进而确定填涂的选项。空选项的情况,将4个选项的像素值进行比较最大值减去最小值的差值若小于某一个值,则认为此选项没有填涂。

代码如下:

  1. import cv2
  2. import numpy as np
  3. from imutils.perspective import four_point_transform
  4. from pyzbar import pyzbar
  5. img000 = cv2.imread('\\example01\\33334.jpg')
  6. #答题卡左边的黑块数量、答题卡题目总量
  7. leftji = 16
  8. allji = 32
  9. res=cv2.resize(img000,(1043,int(img000.shape[0]*1043/img000.shape[1])),interpolation=cv2.INTER_CUBIC)
  10. img = res
  11. openw = 0
  12. openh = 0
  13. #转化成灰度图片
  14. gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  15. gaussian_bulr = cv2.GaussianBlur(gray, (5, 5), 0) # 高斯模糊
  16. edged=cv2.Canny(gaussian_bulr,75,1) # 边缘检测,灰度值小于2参这个值的会被丢弃,大于3参这个值会被当成边缘,在中间的部分,自动检测
  17. toushi = ''
  18. toushiq = ''
  19. # 寻找轮廓
  20. cts, hierarchy = cv2.findContours( edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  21. list=sorted(cts,key=cv2.contourArea,reverse=True)
  22. jidian = []
  23. for c in list:
  24. peri=0.01*cv2.arcLength(c,True)
  25. approx=cv2.approxPolyDP(c,peri,True)
  26. # 打印定点个数
  27. # print("顶点个数:",len(approx))
  28. if peri >= 10 and len(approx) == 4:
  29. ox_sheet = four_point_transform(img, approx.reshape(4, 2))
  30. tx_sheet = four_point_transform(gray, approx.reshape(4, 2))
  31. toushiq = four_point_transform(edged, approx.reshape(4, 2))
  32. toushi = ox_sheet
  33. ret, thresh2 = cv2.threshold(tx_sheet, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
  34. # cv2.imshow("ostu", thresh2)
  35. r_cnt, r_hierarchy = cv2.findContours(thresh2.copy(), 1, 2)
  36. for ii in r_cnt:
  37. peris = 0.01 * cv2.arcLength(ii, True)
  38. approxa = cv2.approxPolyDP(ii, peris, True)
  39. x, y, w, h = cv2.boundingRect(approxa)
  40. if w >= 40 and (x < 100 or y < 100) and len(approxa) == 4 and peris < 10:
  41. cv2.rectangle(ox_sheet, (x, y), (x + w, y + h), (0, 0, 255), 2)
  42. jidian.append([x, y])
  43. openw = w
  44. openh = h
  45. data = np.array(jidian)
  46. idex=np.lexsort([data[:,1], data[:,0]])
  47. sorted_data = data[idex, :]
  48. hang = sorted_data[0:leftji]
  49. lie = sorted_data[leftji:allji]
  50. aswgroup = []
  51. for b in hang:
  52. for n in lie:
  53. cv2.rectangle(toushi, (n[0], b[1]), (n[0] + openw, b[1] + openh), (0, 0, 255), 2)
  54. aswgroup.append([n[0], b[1]])
  55. def list_split(items, n):
  56. return [items[i:i+n] for i in range(0, len(items), n)]
  57. list2 = list_split(aswgroup, 4)
  58. totals = []
  59. for lll in list2:
  60. a = []
  61. b = []
  62. for ll in lll:
  63. cropImg = toushiq[ll[1]:ll[1] + openh, ll[0]:ll[0] + openw]
  64. total = cv2.countNonZero(cropImg)
  65. a.append([total,ll])
  66. b.append(total)
  67. if max(b)-min(b) < 120:
  68. bindex = 4
  69. else :
  70. bindex = b.index(min(b))
  71. totals.append([bindex,(max(b)-min(b)),a])
  72. i = 1
  73. w = ['A','B','C','D','NULL']
  74. for llwwww in totals:
  75. print(i,w[llwwww[0]],llwwww)
  76. i = i+1
  77. # 识别二维码
  78. barcodes = pyzbar.decode(img)
  79. for barcode in barcodes:
  80. barcodeData = barcode.data.decode("utf-8")
  81. print(barcodeData)
  82. cv2.imshow("hongse",toushi)
  83. cv2.waitKey(0)

运行结果的图片:

 

一行的输出释义:题号、答案4个坐标中最小像素值的位置、最大像素值减最小像素值的差值、4个坐标的值。有多少个题目就输出多少行。其中随后一个输出值是答题卡二维码识别的值。

答题卡原图:

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号