opencv+python机读卡识别(三)对选择题识别
博客专区 > Digimon 的博客 > 博客详情
opencv+python机读卡识别(三)对选择题识别
Digimon 发表于4个月前
opencv+python机读卡识别(三)对选择题识别
  • 发表于 4个月前
  • 阅读 625
  • 收藏 15
  • 点赞 1
  • 评论 0
摘要: 机读卡选择题识别

第一部分预处理: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))

至此完成选择题部分 选择题演示

标签: 机读卡识别
共有 人打赏支持
粉丝 31
博文 13
码字总数 12068
×
Digimon
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: