第一部分预处理:https://my.oschina.net/u/3268732/blog/1236298
第二部分图像切割:https://my.oschina.net/u/3268732/blog/1236344
第四部分数字识别:https://my.oschina.net/u/3268732/blog/1239954
1.对选择题图像部分预处理 经过四点变换后的图像需要经过重新转换标准长宽,以便对选择题部分标定题号及答案。这里的图像定义为2400*2800 。选择题部分最大的特点是需要将黑块突出,以及过滤掉没填涂的选项,以便确认。预处理方法选择均值滤波及二进制二值化的方法。
# 对灰度图应用二值化算法
thresh=cv2.adaptiveThreshold(warped,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,53,2)
#重塑可能用到的图像
thresh = cv2.resize(thresh, (width1, height1), cv2.INTER_LANCZOS4)
paper = cv2.resize(paper, (width1, height1), cv2.INTER_LANCZOS4)
warped = cv2.resize(warped, (width1, height1), cv2.INTER_LANCZOS4)
#均值滤波
ChQImg = cv2.blur(thresh, (23, 23))
#二进制二值化
ChQImg = cv2.threshold(ChQImg, 100, 225, cv2.THRESH_BINARY)[1]
'''
threshold参数说明
第一个参数 src 指原图像,原图像应该是灰度图。
第二个参数 x 指用来对像素值进行分类的阈值。
第三个参数 y 指当像素值高于(有时是小于)阈值时应该被赋予的新的像素值
第四个参数 Methods 指,不同的不同的阈值方法,这些方法包括:
•cv2.THRESH_BINARY
•cv2.THRESH_BINARY_INV
•cv2.THRESH_TRUNC
•cv2.THRESH_TOZERO
•cv2.THRESH_TOZERO_INV
'''
2.寻找结果中黑块坐标 这里寻找坐标的目的是为了确定黑块所代表的题号及选项,用轮廓中心来进行描述
# 在二值图像中查找轮廓
cnts = cv2.findContours(ChQImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
for c in cnts:
# 计算轮廓的边界框,然后利用边界框数据计算宽高比
(x, y, w, h) = cv2.boundingRect(c)
if (w > 60 & h > 20)and y>900 and y<2000:
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
#绘制中心及其轮廓
cv2.drawContours(paper, c, -1, (0, 0, 255), 5, lineType=0)
cv2.circle(paper, (cX, cY), 7, (255, 255, 255), -1)
#保存题目坐标信息
Answer.append((cX, cY))
3.计算选择题题号及答案 比较绕,主要还是根据取余和倍数关系
def judgey0(y):
if (y / 5 < 1):
return y + 1
elif y / 5 < 2 and y/5>=1:
return y % 5 + 20 + 1
else:
return y % 5 + 40 + 1
def judgex0(x):
if(x%5==1):
return 'A'
elif(x%5==2):
return 'B'
elif(x%5==3):
return 'C'
elif(x%5==4):
return 'D'
def judge0(x,y):
if x/5<1 :
#print(judgey0(y))
return (judgey0(y),judgex0(x))
elif x/5<2 and x/5>=1:
#print(judgey0(y)+5)
return (judgey0(y)+5,judgex0(x))
elif x/5<3 and x/5>=2:
# print(judgey0(y)+10)
return (judgey0(y)+10,judgex0(x))
else:
#print(judgey0(y)+15)
return (judgey0(y)+15,judgex0(x))
输出运算结果:
IDAnswer=[]
for i in Answer:
for j in range(0,len(xt1)-1):
if i[0]>xt1[j] and i[0]<xt1[j+1]:
for k in range(0,len(yt1)-1):
if i[1]>yt1[k] and i[1]<yt1[k+1]:
judge0(j,k)
IDAnswer.append(judge0(j,k))
#对答案部分重新排序,以最好的方式输出
IDAnswer.sort()
print(IDAnswer)
print(len(IDAnswer))
至此完成选择题部分