示例#1
0
def process_the_template(template_ref):
    # 读取图片
    template_ref_image =cv2.imread(template_ref)
    #  转化为灰度图片
    template_ref_gray= cv2.cvtColor(template_ref_image,cv2.COLOR_BGR2GRAY)
    # 二值图像
    ret,ref = cv2.threshold(template_ref_gray, 10, 255, cv2.THRESH_BINARY_INV)
    # cv_show('ref', ref)

    # 计算轮廓
    # cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
    # 返回的list中每个元素都是图像中的一个轮廓

    #获得维度的轮廓
    ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(template_ref_image, refCnts, -1, (0, 0, 255), 3)
    # cv_show('ref_with_refCnts',template_ref_image)

    #一共有10个外轮廓
    print("Contours Mount of the ref is ",np.array(refCnts).shape[0])
    # 对轮廓进行排序,从左到右,从上到下
    refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]

    ref_dict={}

    # 遍历每一个轮廓,0,1,2,3,4,5,6,7,8,9,进行resize,提取ROI
    for (i, c) in enumerate(refCnts):
        # 计算外接矩形并且resize成合适大小
        (x, y, w, h) = cv2.boundingRect(c)
        roi = ref[y:y + h, x:x + w]
        roi = cv2.resize(roi, (57, 88))
        # 每一个数字对应每一个模板
        ref_dict[i] = roi

    return  ref_dict
示例#2
0
文件: own_test.py 项目: jummyht/AI
def read_process_template(template_path):
    # 读取一个模板图像
    img = cv2.imread(template_path)
    # 灰度图
    ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 二值图像 一般的(BINARY)效果是:
    # 将一个灰色的图片,变成要么是白色要么就是黑色。
    # (大于规定thresh值就是设置的最大值(常为255,也就是白色))
    ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
    # cv_show('',ref)
    # 计算轮廓
    # cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),
    # cv2.RETR_EXTERNAL只会返回最外边的的轮廓,所有的子轮廓都会被忽略掉。,
    # cv2.CHAIN_APPROX_SIMPLE会压缩轮廓,将轮廓上冗余点去掉,比如说四边形就会只储存四个角点。
    _, refCnts, _ = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,
                                     cv2.CHAIN_APPROX_SIMPLE)
    # 画出所有的边框
    cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
    # cv_show('',img)
    refCnts = myutils.sort_contours(refCnts,
                                    method="left-to-right")[0]  # 排序,从左到右,从上到下

    digits = {}
    # 遍历每一个轮廓
    for (i, c) in enumerate(refCnts):
        # 计算外接矩形并且resize成合适大小
        (x, y, w, h) = cv2.boundingRect(c)
        roi = ref[y:y + h, x:x + w]
        roi = cv2.resize(roi, (template_high, template_wigth))
        # cv_show("",roi)
        # 每一个数字对应每一个模板
        digits[i] = roi
    return digits
示例#3
0
# 二值图像,因为做轮廓检测输入进去的一般都为一个二值图像
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('ref', ref)

# 计算轮廓
#cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓

ref_, refCnts, hierarchy = cv2.findContours(
    ref.copy(), cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)  #注意传进去的图像要进行一个.copy(),返回的参数refCnts是轮廓

cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)  #-1表示显示所有轮廓
cv_show('img', img)  #将轮廓画出来看一下
print(np.array(refCnts).shape)  #打印出来为10,表示10个轮廓
refCnts = myutils.sort_contours(refCnts,
                                method="left-to-right")[0]  #对轮廓进行排序,从左到右,从上到下
digits = {}

# 遍历每一个轮廓,i是数值,c是对应的轮廓
for (i, c) in enumerate(refCnts):
    # 计算外接矩形并且resize成合适大小
    (x, y, w, h) = cv2.boundingRect(c)
    roi = ref[y:y + h, x:x + w]
    roi = cv2.resize(roi, (57, 88))  #调整矩形框的大小

    # 每一个数字对应每一个模板
    digits[i] = roi

# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
示例#4
0
gray_tem = cv.cvtColor(template, cv.COLOR_BGR2GRAY)
ret, bi_tem = cv.threshold(gray_tem, 127, 255, cv.THRESH_BINARY)
# cv_show("res", bi_tem)  # 展示模板的二值图像
# 轮廓检测(outside)
bt = bi_tem.copy()
contours, hierarchy = cv.findContours(bt, cv.RETR_EXTERNAL,
                                      cv.CHAIN_APPROX_SIMPLE)
# draw contours
contours_res = cv.drawContours(template, contours, -1, (0, 255, 0),
                               3)  # 在二值图上得到, 需要画在原图上,
# cv_show("contours_res", contours_res)
print(np.array(contours).shape)

# 对轮廓进行了排序从左到右

contours = myutils.sort_contours(contours, method="left-to-right")[0]
digits = {}  # 存模板的数字
print(digits)

# 遍历轮廓, 外接矩形

for (i, c) in enumerate(contours):  # c 是每个轮廓的终点坐标 讲一个可遍历的数据对象组合成一个索引序列
    (x, y, w, h) = cv.boundingRect(c)  # 计算外接矩形, resize 成合适大小
    # 扣模板
    roi = gray_tem[y:y + h, x:x + w]  # 每个roi对应一个数字
    roi = cv.resize(roi, (57, 85))  # 模板拆分数字
    digits[i] = roi  # 每个数字对应一个模板

# image of detecting
# 初始化卷积核
rectKernel = cv.getStructuringElement(cv.MORPH_RECT, (9, 3))  #
示例#5
0
#灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('灰度图', ref)
#二值图
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('二值图', ref)
# 计算轮廓
# cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
# 返回的list中每个元素都是图像中的一个轮廓
#三个返回值:图像,轮廓,轮廓的层析结构
ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,
                                            cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
cv_show('画出模板轮廓', img)
print(np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts,
                                method='left-to-right')[0]  #排序,从左到右,从上到下
digits = {}

#遍历每一个轮廓
for (i, c) in enumerate(refCnts):
    # 计算外接矩形并且resize成合适大小
    (x, y, w, h) = cv2.boundingRect(c)
    roi = ref[y:y + h, x:x + w]
    roi = cv2.resize(roi, (57, 88))
    # 每一个数字对应每一个数字模板矩形
    digits[i] = roi

#****************************模板处理结束,开始输入数据处理
#print(digits)
#初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
# 【二、模板处理流程】: 轮廓检测, 外接矩形, 抠出模板, 让模板对应每个数值
# 1.计算轮廓
'''
cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),
	cv2.RETR_EXTERNAL只检测外轮廓,
	cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
	返回的list中每个元素都是图像中的一个轮廓
'''
refCnts = cv2.findContours(
    ref.copy(), cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)[0]  # copy是因为以后还要用到ref,用copy以保留
img = cv2.drawContours(img, refCnts, -1, (0, 255, 0),
                       2)  # 轮廓在二值图上得到, 画是画在原图上( 参数-1代表画所有的轮廓 )
cv_show('template_Contours', img)
print(np.array(refCnts, dtype=object).shape)  # 10个轮廓,所以是10
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]  # 排序
digits = {}
# 2.遍历每一个轮廓,外接矩形
for (i, c) in enumerate(refCnts):  # c是每个轮廓的终点坐标
    # 计算外接矩形并且resize成合适大小
    (x, y, w, h) = cv2.boundingRect(c)
    # 3.抠出模板
    roi = ref[y:y + h, x:x + w]  # 每个roi对应一个数字
    # print(roi.shape)
    roi = cv2.resize(roi, (57, 88))  # 太小,调大点

    # 4.每一个数字对应每一个模板
    digits[i] = roi
    # cv2.imshow('roi_'+str(i),roi)
    # cv2.waitKey(0)
    # print(digits)
def cv_credit_card(img,image):
    FIRST_NUMBER = {  #字典
        "3":"American Express",
        "4":"Visa",
        "5":"MasterCart",
        "6":"Discover Card",
    }

    #cv_show('template',img)

    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转为灰度图
    #cv_show('gray',gray)

    binary = cv2.threshold(gray,10,255,cv2.THRESH_BINARY_INV)[1] #注意阈值二值化函数返回的参数有两个!!
    #cv_show('binary',binary)


    #计算轮廓
    #cv2.findContours()函数接受的参数为二值图。cv2.RETR_EXTERNAL只检测最外围的图像,cv2.CHAIN_APPROX_SIMPLE只保留中点坐标
    #返回的list中每个元素都是图像中的一个轮廓

    refCnts,hierarchy = cv2.findContours(binary.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)  

    cv2.drawContours(img,refCnts,-1,(0,0,255),3)  #画出轮廓
    #cv_show('img',img)

    #从左到右排序。0-9

    refCnts = myutils.sort_contours(refCnts,method="left-to-right")[0]
    digits= {}

    for (i,c) in enumerate(refCnts):
        #计算外接矩形
        (x,y,w,h) = cv2.boundingRect(c)
        #截取图像
        roi = binary[y:y+h,x:x+w]
        #重新设定大小
        roi = cv2.resize(roi,(57,88))
        #设定digits
        digits[i]=roi

    ###以上为模板的处理,以下为图片处理


    #初始化卷积核
    rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
    sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

    #cv_show('image',image)
    image = myutils.resize(image,width=300)
    image_gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) #转化为灰度图
    image_tophat = cv2.morphologyEx(image_gray,cv2.MORPH_TOPHAT,rectKernel)  #礼帽处理,突出更明亮的区域
    #cv_show('tophat',image_tophat)

    gradX = cv_sobel_x(image_tophat)  #水平方向梯度滤波处理
    #cv_show('gradX',gradX)

    gradX = cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel) #闭操作,让数字连在一起
    #cv_show('gradX_MORPH_CLOSE',gradX)

    image_threshold = cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]  #THRESH_OTSU自动寻找合适的阈值,适合双峰,需把阈值下限设为0
    #cv_show('image_threshold',image_threshold)

    image_threshold = cv2.morphologyEx(image_threshold,cv2.MORPH_CLOSE,sqKernel)



    threshCnts,hierarchy = cv2.findContours(image_threshold.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)  #计算最外层轮廓

    cnts = threshCnts
    cur_img = image.copy()
    cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)  #画出轮廓
    #cv_show('cur_img',cur_img)  

    locs=[]  #轮廓位置


    for (i,c) in enumerate(cnts):
        (x,y,w,h) = cv2.boundingRect(c)  #寻找矩形
        ar = w/float(h)  #求宽和高的比例

        if ar>2.5 and ar<4.0:  #把不符合的筛出去
            if(w>40 and w <55)and(h>10 and h <20):
                locs.append((x,y,w,h))   


    locs = sorted(locs,key=lambda x:x[0])  #排个序


    output = []

    for (i,(gX,gY,gW,gH)) in enumerate(locs):
        groupOutput = []
        group = image_gray[gY - 5:gY + gH + 5,gX-5:gX + gW + 5]

        group = cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]  #自适应二值化处理
        digitCnts,hierarchy = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)  #计算最外层轮廓
        digitCnts = contours.sort_contours(digitCnts,method = "left-to-right")[0]
        for c in digitCnts:
            (x,y,w,h) = cv2.boundingRect(c)
            roi = group[y:y+h,x:x+w]
            roi = cv2.resize(roi,(57,88))
            #cv_show('roi',roi)
            #print(roi)

            #匹配度
            scores=[]
            
            for (digit,digitROI) in digits.items(): #遍历求匹配度,在模板中计算每一个得分
                result = cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF)
                (_,score,_,_) = cv2.minMaxLoc(result)
                scores.append(score)
            #得到最合适的数字
            groupOutput.append(str(np.argmax(scores)))

        #画出来
        cv2.rectangle(image,(gX-5,gY-5),(gX+gW+5,gY+gH+5),(0,0,255),1)
        cv2.putText(image, "".join(groupOutput),(gX,gY-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)

        output.extend(groupOutput)

    return image,output
示例#8
0
# 灰度
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show(ref, 'ref')

# 二值化
ref = cv2.threshold(ref, 127, 255, cv2.THRESH_BINARY_INV)[1]
cv_show(ref, 'ref')

# 计算轮廓
ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,
                                            cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
cv_show(img, 'img')
# print(np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts)[0]
digits = {}

# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):
    # 计算外接矩形且resize成合适大小
    (x, y, w, h) = cv2.boundingRect(c)
    roi = ref[y:y + h, x:x + w]
    roi = cv2.resize(roi, (57, 88))

    # 每个数字对应一个模板
    digits[i] = roi

# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
示例#9
0
cv_show('ref', ref)
# 二值图像
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('ref', ref)

# 计算轮廓
# cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
# 返回的list中每个元素都是图像中的一个轮廓

ref_, ref_counts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,
                                               cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(img, ref_counts, -1, (0, 0, 255), 3)
cv_show('img', img)
print(np.array(ref_counts).shape)
ref_counts = myutils.sort_contours(ref_counts, method="left-to-right")[0]
# 排序, 从左到右, 从上到下
digits = {}

# 遍历每一个轮廓
for (i, c) in enumerate(ref_counts):
    # 计算外接矩形并且resize成合适大小
    (x, y, w, h) = cv2.boundingRect(c)
    roi = ref[y:y + h, x:x + w]
    roi = cv2.resize(roi, (57, 88))

    # 每一个数字对应每一个模板
    digits[i] = roi

# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
示例#10
0
def process_the_target_image(srcImage,ref_dict):

    # 初始化卷积核
    rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
    sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

    # 读取输入图像,预处理
    image = cv2.imread(srcImage)
    # cv_show('image', image)
    image = myutils.resize(image, width=300)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # cv_show('gray', gray)

    # 礼帽操作,突出更明亮的区域
    tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
    # cv_show('tophat', tophat)

    # 计算X方向的梯度,突出edage
    gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0,  # ksize=-1相当于用3*3的
                      ksize=-1)
    #对梯度进行归一化操作
    gradX = np.absolute(gradX)
    (minVal, maxVal) = (np.min(gradX), np.max(gradX))
    gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
    gradX = gradX.astype("uint8")

    print(np.array(gradX).shape)
    # cv_show('gradX', gradX)

    # 通过闭操作(先膨胀,再腐蚀)将数字连在一起
    gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
    # cv_show('gradX', gradX)
    # THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
    thresh = cv2.threshold(gradX, 0, 255,
                           cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    # cv_show('thresh', thresh)

    # 再来一个闭操作


    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)  # 再来一个闭操作
    # cv_show('thresh2', thresh)

    # 计算轮廓

    thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                                                      cv2.CHAIN_APPROX_SIMPLE)
    cnts = threshCnts
    cur_img = image.copy()
    cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
    # cv_show('img', cur_img)
    locs = []

    # 遍历轮廓
    for (i, c) in enumerate(cnts):
        # 计算外接矩形
        (x, y, w, h) = cv2.boundingRect(c)
        #计算长宽比
        ar = w / float(h)

        # 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
        #比较长宽比
        if ar > 2.5 and ar < 4.0:
            #比较w,h具体长度
            if (w > 40 and w < 55) and (h > 10 and h < 20):
                # 符合的留下来
                locs.append((x, y, w, h))
    print(len(locs))

    # 将符合的轮廓从左到右排序,空间顺序
    locs = sorted(locs, key=lambda x: x[0])

    #展示一下结果
    my_curImage = image.copy()
    for boudingbox in locs:
        cv2.rectangle(my_curImage,(boudingbox[0],boudingbox[1]),(boudingbox[0]+boudingbox[2],boudingbox[1]+boudingbox[3]),
                      (0,0,255),2)
    # cv_show("rect",my_curImage)


    '''提取每个boundingbox的图片信息'''
    output=[]
    # 遍历每一个轮廓中的数字
    for (i, (gX, gY, gW, gH)) in enumerate(locs):
        # initialize the list of group digits
        groupOutput = []

        # 根据坐标提取每一个组
        # 稍微扩充一下这个roi
        group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
        # cv_show('group', group)
        # 预处理,OTSU阈值化
        ret,group = cv2.threshold(group, 0, 255,
                              cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        # cv_show('group', group)
        # 计算每一组的轮廓
        group_, digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
                                                        cv2.CHAIN_APPROX_SIMPLE)
        #对轮廓进行空间排序
        digitCnts = myutils.sort_contours(digitCnts,
                                           method="left-to-right")[0]
        #显示这个轮廓
        # mygroup=group.copy()
        # cv2.drawContours(mygroup, digitCnts, -1, (0, 0, 255), 3)
        # cv_show("group_contours",mygroup)

        # 计算每一组中的每一个数值
        for c in digitCnts:
            # 找到当前数值的轮廓,resize成合适的的大小
            (x, y, w, h) = cv2.boundingRect(c)
            roi = group[y:y + h, x:x + w]
            roi = cv2.resize(roi, (57, 88))
            # cv_show('roi', roi)

            # 计算匹配得分
            scores = []

            # 在模板中计算每一个得分
            for (digit, digitROI) in ref_dict.items():
                # 模板匹配
                '''
                cv2.TM_CCOEFF (系数匹配法)
                cv2.TM_CCOEFF_NORMED(相关系数匹配法)
                cv2.TM_CCORR (相关匹配法)
                cv2.TM_CCORR_NORMED (归一化相关匹配法)
                cv2.TM_SQDIFF (平方差匹配法)
                cv2.TM_SQDIFF_NORMED (归一化平方差匹配法
                '''
                result = cv2.matchTemplate(roi, digitROI,
                                           cv2.TM_CCOEFF)

                #根据 匹配方法不同,选择最大还是最小
                (minval, maxval, minloc,maxloc) = cv2.minMaxLoc(result)
                scores.append(maxval)

            # 得到最合适的数字
            groupOutput.append(str(np.argmax(scores)))

            # 画出来
        cv2.rectangle(image, (gX - 5, gY - 5),
                          (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
        cv2.putText(image, "".join(groupOutput), (gX, gY - 15),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)

        # 得到结果
        output.extend(groupOutput)

    cv_show("img",image)
    return output
# read template
img = cv2.imread(args['template'])
cv_show(img)
# 灰階
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show(ref)
# 二值
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show(ref)
# 輪廓檢測
ref_cnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 只檢測外輪廓
cv2.drawContours(img, ref_cnts, -1, (0, 0, 255), 3)
cv_show(img)
print(np.array(ref_cnts).shape)
# 排序
ref_cnts = myutils.sort_contours(ref_cnts, method='left-to-right')[0]
digits = {}
# 遍歷輪廓
for (i, c) in enumerate(ref_cnts):
    (x, y, w, h) = cv2.boundingRect(c)
    roi = ref[y: y+h, x: x+w]
    roi = cv2.resize(roi, (57, 88))
    # 每個數字對應一個模板
    digits[i] = roi

# 對輸入圖像操作
# 初始化捲積核
rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sq_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 圖像輸入及預處理
image = cv2.imread(args['image'])
# (2.3) convert template to binary image
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)

# (2.4) compute external contours with function: cv2.findContours()
# (2.4) parameter 1: ref.copy(): binary image (black-white)
# (2.4) parameter 2: cv2.RETR_EXTERNAL: only check external contours
# (2.4) parameter 3: cv2.CHAIN_APPROX_SIMPLE: only save terminal coordinate
refCnts = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)   # return contour of each number in template image
refCnts = refCnts[1] if imutils.is_cv3() else refCnts[0]                             # check opencv version
# print('refCnts:',refCnts)
cv2.drawContours(img, refCnts, -1, (0,0,255), 3)                                     # -1: means it draws all contours
cv_show('img',img)
print('shape of refCnts:', np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]  				 # sort every contour by left-to-right order

# (2.5) traverse template contours list and save it in a dictionary
digits = {}
# traverse contour of each number in template image
for (i, c) in enumerate(refCnts):
	# compute external rectangle and resize it
	(x, y, w, h) = cv2.boundingRect(c)
	roi = ref[y:y+h, x:x+w]
	roi = cv2.resize(roi, (57,88))
	# map each contour with number (0---0, 1---1, ......) with a dictionary
	digits[i] = roi


# PART III: operations for test image
# (3.1) initialize convolutional kernel
示例#13
0
def process_the_image(image):
    # 首先是预处理,包括灰度图片,高斯滤波和Canny边缘提取
    contours_img = image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    # cv_show('blurred', blurred)
    edged = cv2.Canny(blurred, 75, 200)
    # cv_show('edged', edged)

    # 轮廓检测,检测外轮廓
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)[1]
    #轮廓画图
    cv2.drawContours(contours_img, cnts, -1, (0, 0, 255), 3)
    # cv_show('contours_img', contours_img)

    docCnt = None

    # 外轮廓不一定是一个矩形,根据轮廓面积排序
    # 确保检测到了最外围的四大点作为矩形,
    if len(cnts) > 0:
        # 根据轮廓大小进行排序
        cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

        # 遍历每一个轮廓
        for c in cnts:
            # 多边形近似
            peri = cv2.arcLength(c, True)
            approx = cv2.approxPolyDP(c, 0.02 * peri, True)

            # 准备做透视变换,确保是一个矩形
            if len(approx) == 4:
                docCnt = approx
                break
    # print(docCnt.shape)  # shape is (4,1,2)
    '''docCnt 进行坐标变换'''
    warped = Four_points_transform(gray, docCnt)
    # cv_show('warped', warped)

    warped_copy = warped.copy()
    '''  提取圆形的轮廓   '''

    # 对变换后的图像进行Ostu阈值处理

    ret, thresh = cv2.threshold(warped, 0, 255,
                                cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
    # cv_show('thresh', thresh)
    # 二值的轮廓
    thresh_Contours = thresh.copy()

    # 进行轮廓检查
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)[1]
    cv2.drawContours(thresh_Contours, cnts, -1, (0, 255, 0), 3)
    # cv_show('thresh_Contours', thresh_Contours)

    questionCnts = []

    # 遍历,得到自己想要的轮廓信息信息,放在quesetionCnts中
    for c in cnts:
        # 计算比例和大小
        (x, y, w, h) = cv2.boundingRect(c)
        ar = w / float(h)

        # 根据实际情况指定标准,提取比较大的轮廓,长宽比在0.9到1.1
        if w >= 20 and h >= 20 and ar >= 0.9 and ar <= 1.1:
            questionCnts.append(c)

    # 显示自己要提取的部分轮廓
    cv2.drawContours(warped_copy, questionCnts, -1, (0, 255, 0), 3)
    # cv_show('circles', warped_copy)
    print(len(questionCnts))

    # 将提取出来的轮廓按照空间顺序进行排序
    # 按照从上到下进行排序
    questionCnts = sort_contours(questionCnts, method="top-to-bottom")[0]
    correct = 0

    # 每排有5个选项,q代表第几行,i=0,i=5,i=10,i=15,i=20
    for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):
        # 排序,默认从左向右排序
        cnts = sort_contours(questionCnts[i:i + 5])[0]
        # 学生选择的那个的非零的值应该是最大的
        student_seleted = None

        # 遍历每一个结果
        for (j, c) in enumerate(cnts):
            # 使用mask来判断结果
            mask = np.zeros(thresh.shape, dtype="uint8")
            cv2.drawContours(mask, [c], -1, 255, -1)  # 最后一个-1表示填充
            # cv_show('mask', mask)
            # 通过计算非零点数量来算是否选择这个答案,被涂抹的那个零点个数一定是最多的
            mask = cv2.bitwise_and(thresh, thresh, mask=mask)
            # 统计此时的非零点的个数
            total = cv2.countNonZero(mask)
            # 通过阈值判断
            if student_seleted is None or total > student_seleted[0]:
                # 记录此时最大的total,并且此时的位置 j 代表学生选的那个选项
                student_seleted = (total, j)

        # 正确的答案
        color = (0, 0, 255)
        correct_answer = ANSWER_KEY[q]
        if student_seleted[1] == correct_answer:
            color = (0, 255, 0)
            correct = correct + 1

        # 把真正的答案画出来绘图
        cv2.drawContours(warped, [cnts[correct_answer]], -1, color, 3)

    #计算机最后的得分
    score = (correct / 5.0) * 100
    print("[INFO] score: {:.2f}%".format(score))
    cv2.putText(warped, "{:.2f}%".format(score), (10, 30),
                cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
    cv2.imshow("Original", image)
    cv2.imshow("Exam", warped)
    cv2.waitKey(0)