Ejemplo n.º 1
0
def get_image_box(gray):
    bw = imu.preprocess_bw_inv(gray)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (49, 13))
    bw2 = cv2.dilate(bw, kernel, iterations=3)
    image, contours, hierarchy = cv2.findContours(bw2, cv2.RETR_TREE,
                                                  cv2.CHAIN_APPROX_SIMPLE)
    boxes = []
    # cv2.imwrite('temp.png', bw2)
    cv2.namedWindow("bw2", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("bw2", bw2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    for i, cnt in enumerate(contours):
        area = cv2.contourArea(cnt)
        rect = cv2.minAreaRect(cnt)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        height = abs(box[0][1] - box[2][1])
        width = abs(box[0][0] - box[2][0])
        boxList = box.tolist()
        origin = min(boxList)
        # print(box)

        if (height > 150):
            boxes.append(
                (origin[0], origin[1], origin[0] + width, origin[1] + height))
    # exit(0)
    return boxes
Ejemplo n.º 2
0
def get_vertical_white_edge_dis(img):
    """Get vertical white edge distance of character image.

    Args:
        img: Character image.

    Returns:
        An interger distance.
    """
    bw = imu.preprocess_bw_inv(img)
    weight, profile = imu.horizontal_proj(bw)
    horCoorY1 = 0
    if weight[0] == 0:
        i = 0
        while weight[i] == 0 and i < len(weight):
            i += 1
        horCoorY1 = i

    horCoorY2 = len(weight) - 1
    if weight[-1] == 0:
        j = len(weight) - 1
        while weight[j] == 0 and j > 0:
            j -= 1
        horCoorY2 = j

    return horCoorY1, len(weight) - horCoorY2
Ejemplo n.º 3
0
 def text(self, options={}):
     imgInv = imu.preprocess_bw_inv(self.image_gray)
     cv2.imwrite('imgInv.jpg', imgInv)
     connected_components = get_cc('imgInv.jpg')
     os.remove('imgInv.jpg')
     connected_components = [
         length2coor(cc) for cc in connected_components
         if 5 < cc[2] < 60 and 3 < cc[3] < 60
     ]
     # word_boxes = generate_words(connected_components, 50)
     connected_components = generate_chars(connected_components)
     word_boxes = generate_lines(connected_components, 50)
     for word_box in word_boxes:
         word_result = self.text_word(word_box)
         keys = list(word_result.keys())
         keys.sort(key=lambda item: item[0])
         for key in keys:
             result = word_result[key]
             if options.get("probability") == "true":
                 print(f'({result["char"]}, {result["confidence"]})',
                       end=' ')
             else:
                 print(f'{result["char"]}', end=' ')
             # if result["char"]=="二":
             #     cv2.imwrite(f"二{now}.png", self.image_gray[key[1]:key[3], key[0]:key[2]])
         print()
Ejemplo n.º 4
0
def divide_ver(img):
    """Divide paper by blank detection in vertical direction.

    Args:
        img: Image to be divided.

    Returns:
        A list of horizontal coordinates.
    """
    verCoorX1 = []
    verCoorX2 = []
    temp = []
    temp1 = []
    temp2 = []
    result = []
    bw = imu.preprocess_bw_inv(img)
    weight, profile = imu.vertical_proj(bw)
    # print('weight = {}'.format(weight[:100]))
    for i in range(0, len(weight)):
        if weight[i] > 0:
            if i == len(weight) - 1 or weight[i + 1] == 0:
                verCoorX2.append(i)
            if i == 0 or weight[i - 1] == 0:
                verCoorX1.append(i)

    # print(verCoorX1)
    # print(verCoorX2)
    temp = list(zip(verCoorX1, verCoorX2))
    # print(temp)

    for r in temp:
        if r[1] - r[0] > 5:
            temp1.append(r)

    first = 1 if temp1[0][0] < 100 else 0
    start = temp1[first][0]
    end = temp1[first][1]
    for r in range(first, len(temp1)):
        if r == len(temp1) - 1:
            end = temp1[r][1]
            temp2.append((start, end))
        elif temp1[r + 1][0] - temp1[r][1] < 45:
            continue
        else:
            end = temp1[r][1]
            temp2.append((start, end))
            start = temp1[r + 1][0]

    for i in temp2:
        if i[1] - i[0] > 800:
            result.append(i)

    if len(result) > 2:
        result = result[0:2]
    # print(result)
    # print(temp)
    return result
Ejemplo n.º 5
0
def find_char(img, coor):
    """Divide line by blank detection in horizontal direction from left to right.

    Args:
        img: Image to be divided.
        coor: A list of line coordinates.

    Returns:
        A list of first 2 or 3 characters coordinates of each lines.
    """
    result = []
    for i, c in enumerate(coor):
        verCoorX1 = []
        verCoorX2 = []
        line = []
        imgLine = img[c[1]:c[3], c[0]:c[2]]
        bw = imu.preprocess_bw_inv(imgLine, smooth=False)
        # cv2.imwrite('./res/lines/'+str(i)+'.png', bw)
        weight, profile = imu.vertical_proj(bw)
        if weight[0] > 1:
            verCoorX1.append(0)

        for i in range(1, len(weight) - 1):
            if weight[i] > 1:
                if weight[i + 1] <= 1:
                    verCoorX2.append(i)
                if weight[i - 1] <= 1:
                    verCoorX1.append(i)

        if weight[-1] > 1:
            verCoorX2.append(len(weight) - 1)

        # print(verCoorX1)
        # print(verCoorX2)
        ver = list(zip(verCoorX1, verCoorX2))
        n = 3
        for v in ver:
            if n == 0:
                break
            elif v[1] - v[0] < 3:
                continue
            else:
                line.append((v[0] + c[0], c[1], v[1] + c[0], c[3]))
                n -= 1
        result.append(line)
    return result
Ejemplo n.º 6
0
def divide_hor(img, coor):
    """Divide paper by blank detection in horizontal direction.

    Args:
        img: Image to be divided.

    Returns:
        A list of vertical coordinates.
    """
    h, w = img.shape[0:2]
    result = []
    for c in coor:
        horCoorY1 = []
        horCoorY2 = []
        imgPart = img[0:h, c[0]:c[1]]
        bw = imu.preprocess_bw_inv(imgPart)
        weight, profile = imu.horizontal_proj(bw)
        if weight[0] > 0:
            horCoorY1.append(0)

        for i in range(1, len(weight) - 1):
            if weight[i] > 0:
                if weight[i + 1] == 0:
                    horCoorY2.append(i)
                if weight[i - 1] == 0:
                    horCoorY1.append(i)

        if weight[-1] > 0:
            horCoorY2.append(len(weight) - 1)

        # print(verCoorX1)
        # print(verCoorX2)
        line = list(zip(horCoorY1, horCoorY2))
        for l in line:
            if l[1] - l[0] > 10:
                result.append((c[0], l[0], c[1], l[1]))

    return result
Ejemplo n.º 7
0
def augment(gray, shift_low=-10):

    angle = (2 * np.random.random() - 1) * 5.0
    # print(angle)
    rotated = rotate_image(gray, angle)

    # imu.imshow_(rotated)

    rotated = imu.strip_white_boder(rotated)
    # imu.imshow_(rotated)

    shift = np.random.randint(low=shift_low, high=50)
    gray = rotated
    if shift >= 0:
        gray = cv2.add(gray, shift)
    else:
        bw = imu.preprocess_bw_inv(gray)
        gray[bw > 0] = gray[bw > 0] + shift

    # print(shift)
    # if shift>0:
    #     gray = cv2.add(gray, shift)
    # else:
    #     gray = cv2.subtract(gray, shift)
    # imu.imshow_(gray)

    h, w = gray.shape
    hcut = min(2, h // 5)
    wcut = min(2, w // 5)

    top = np.random.randint(hcut + 1)
    bottom = h - np.random.randint(hcut + 1)
    left = np.random.randint(wcut + 1)
    right = w - np.random.randint(wcut + 1)

    return gray[top:bottom, left:right]
Ejemplo n.º 8
0
def get_dilation(gray):
    bw = imu.preprocess_bw_inv(gray)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (49, 13))
    bw2 = cv2.dilate(bw, kernel, iterations=1)
    return bw2
Ejemplo n.º 9
0
def deal_one_page(srcPath,
                  desPath='',
                  stanPath='',
                  saveImage=True,
                  charsOnly=False,
                  rectification=False):
    """
    """
    global heightOfLine
    coor5 = []
    mistakes = 0
    bdResult = {}
    name = os.path.basename(srcPath)
    if not os.path.exists(srcPath):
        print("Image path not exists!")
        return None
    try:
        imgBgr = cv2.imread(srcPath)
        if rectification:
            imgBgr = rectify(imgBgr.copy())
        imgData = cv2.cvtColor(imgBgr, cv2.COLOR_BGR2GRAY)

        # imgData = cv2.imread(srcPath, cv2.IMREAD_GRAYSCALE)
        # imgBgr = cv2.cvtColor(imgData, cv2.COLOR_GRAY2BGR)
    except Exception as imageError:
        print(imageError, 'Could not read the image file, skip...')

    # cv2.namedWindow("imgData", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgData", imgData)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    # exit(0)

    imgEliVer = eli_ver(imgData.copy())  #
    # cv2.namedWindow("imgEliVer", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgEliVer", imgEliVer)

    coor1 = divide_ver(imgEliVer)  #
    # print('coor1: {}'.format(coor1))

    if heightOfLine == 0:  #
        coor2 = divide_hor(imgEliVer, coor1)
        heightOfLines = [c[3] - c[1] for c in coor2]
        heightOfLine = median(heightOfLines)

    imgInv = imu.preprocess_bw_inv(imgData.copy())
    cv2.imwrite('imgInv.jpg', imgInv)
    coorCC = get_no_intersect_boxes('imgInv.jpg')
    imgEliCC = eli_large_cc(coorCC, imgData.copy(), heightOfLine)
    os.remove('imgInv.jpg')
    # cv2.namedWindow("imgEliCC", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgEliCC", imgEliCC)

    imgEli = eli_ver(imgEliCC)  #1
    # cv2.namedWindow("imgEli", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgEli", imgEli)

    coor2 = divide_hor(imgEli, coor1)  #2
    # print('coor2: {}'.format(coor2))
    # img2 = mark_box(imgBgr, coor2, color=(0,255,0))
    # cv2.namedWindow("img2", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("img2", img2)

    coor3 = find_char(imgEli, coor2)  #3
    # print(np.array(coor3))
    # for l in coor3:
    #     img3 = mark_box(imgBgr, l, color=(0,255,0))
    # cv2.namedWindow("img3", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("img3", img3)

    if charsOnly:
        return coor3

    # print('SVM classifying...')
    coor4 = svm_classify(imgEli, coor3)  #4
    # print(*coor4, sep='\n')

    imgBw = imu.preprocess_bw(imgEli, boxSize=(4, 4), morph=False)  #re
    coor3Bw = find_char(imgBw, coor2)
    coor4Bw = svm_classify(imgBw, coor3Bw)
    coor5 = update_result(coor4, coor4Bw)

    try:
        # imgBd = preprocess_bw(imgEliCC)
        # print('BaiDu recognizing...')
        bdResult = bd_rec(imgEliCC,
                          client,
                          imgForm=srcPath[-4:],
                          api='general')
    # except ConnectionResetError as e:
    #     print('Connection reset by peer, repeat BaiDu recognizion...')
    #     bdResult = bd_rec(imgEliCC, client, api='accurate')
    except Exception as e:
        print(
            'Baidu recognition error, check your internet connection. exit...')
        exit(0)
    # print(bdResult)
    addResult = additional_questions(bdResult)
    # print(addResult)
    if addResult:
        coor5.append(([addResult], 2))
    # print(*coor4, sep='\n')

    if stanPath:
        stanResult = output_stan(coor5, os.path.basename(srcPath))
        mistakes = verification(stanResult, stanPath)

    # print(mistakes)

    # if saveImage:
    # for l in coor5:   #5
    #     # print(l)
    #     color = (255,255,0)
    #     if l[1] != 0:
    #         color = (255,0,0) if l[1] == 2 else (0,255,0)
    #     img5 = mark_box(imgBgr, l[0], color)
    # cv2.imwrite(desPath, img5)    #6

    # show_image(img5)
    # exit(0)
    # cv2.namedWindow("img5", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("img5", img5)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    # imgEliVer2 = detect_vertical_line2(imgData)
    # coor2 = divide_hor(imgEliVer2, coor1)
    sa = detect_self_assessment(bdResult)
    if sa:
        # imgEliSa = imgData.copy()
        imgData[sa:, coor1[1][0]:coor1[1][1] + 10] = 255
        # coor22 = divide_hor(imgEliSa, coor1)

    coor22 = divide_hor(imgData, coor1)
    region = integrate_lines(coor5, coor22, imgData.shape[1], imgData.shape[0])
    # print('region: {}'.format(region))
    # imgEliVerBgr = cv2.cvtColor(imgEliVer2, cv2.COLOR_GRAY2BGR)
    # imgRegion = mark_box(imgBgr, region, color=(0,255,0))
    # cv2.imwrite(desPath, imgRegion)

    # cv2.imwrite('imgInv.jpg', get_dilation(imgData.copy()))
    # coorCCDil = get_no_intersect_boxes('imgInv.jpg')
    # os.remove('imgInv.jpg')
    '''
    CCAndType = []
    wordBoxes = [w["location"] for w in bdResult["words_result"]]
    idxWords = index.Index()
    for j,b in enumerate(wordBoxes):
        idxWords.insert(j, (b["left"], b["top"], b["left"]+b["width"], b["top"]+b["height"]))

    idxRegion = index.Index()
    for j,r in enumerate(region):
        idxRegion.insert(j, r)

    idxCC = index.Index()
    for j,c in enumerate(coorCC):
        idxCC.insert(j, (c[0], c[1], c[0]+c[2], c[1]+c[3]))

    boxOfSpecialWord = get_match_location(bdResult, keyWordsConfig)
    hitsOfCC = []
    for j,s in enumerate(boxOfSpecialWord):
        b = (s[0], s[1], s[0]+s[2], s[1]+s[3])
        hitsOfRegion = list(idxRegion.intersection(b, objects=True))
        items = [item for item in hitsOfRegion if item.bbox[1] < s[1]+s[3]/2 < item.bbox[3]]
        for item in items:
            boxOfGraph = (item.bbox[0], b[3]+10, item.bbox[2]-item.bbox[0], item.bbox[3]-b[3]-20)
            boxOfGraph1 = (item.bbox[0], b[3]+10, item.bbox[2], item.bbox[3]-10)
            coorCC.append(boxOfGraph)
            hitsOfCC += list(idxCC.intersection(boxOfGraph1, objects=False))
    # print(hitsOfCC)
    coorCCCopy = coorCC.copy()
    coorCC = [coorCCCopy[i] for i in range(len(coorCCCopy)) if i not in hitsOfCC]

    boxRest = []
    for i,c in enumerate(coorCC.copy()):
        r = (c[0], c[1], c[0]+c[2], c[1]+c[3])
        hitsOfRegion = list(idxRegion.intersection(r))
        if len(hitsOfRegion) == 0:
            continue

        if c[2] > heightOfLine*3 or c[3] > heightOfLine*1.5:
            CCAndType.append((c, 1))
            # del(coorCC[i])
            continue
        elif c[2] < heightOfLine*0.5 and c[3] < heightOfLine*0.5:
            CCAndType.append((c, 0))
            continue
        
        hits = list(idxWords.intersection(r, objects=True))
        if hits:
            flag = False
            for item in hits:
                wordBox = (wordBoxes[item.id]["left"], wordBoxes[item.id]["top"], wordBoxes[item.id]["width"], wordBoxes[item.id]["height"])
                if is_within(c, wordBox):
                    CCAndType.append((c, 0))
                    flag = True
                    # del(coorCC[i])
                    continue
            if flag:
                continue
        boxRest.append(c)

    typesOfCC = tell_me_text_or_graph(imgBgr.copy(), imgData.copy(), boxRest)
    CCAndType += zip(boxRest, typesOfCC)
    resultFinal = get_items(region, imgData.copy(), bdResult, CCAndType, name)
    '''
    imgData1 = detect_vertical_line3(imgData.copy())
    resultFinal = get_items_v02(region, imgData1.copy(), coorCC, name)
    # coorRegion = []
    # coorGraph = []
    # coorText = []
    # resultFinalA = absolute_coor(resultFinal)
    # for x in resultFinalA["questions"]:
    #     coorRegion.append(dic2coor(x["location"]))
    #     coorGraph.extend([dic2coor(i["location"]) for i in x["content"] if i["type"]=="graph"])
    #     coorText.extend([dic2coor(i["location"]) for i in x["content"] if i["type"]=="text"])

    # imgRegion = mark_box(imgBgr, coorRegion, color=(0,255,0))
    # imgGraph = mark_box(imgRegion, coorGraph, color=(0,0,255))
    # imgText = mark_box(imgGraph, coorText, color=(255,255,0))

    if desPath:
        with open(desPath[:-4] + '.json', 'w') as f:
            json.dump(resultFinal, f)
        # if saveImage:
        #     cv2.imwrite(desPath, imgText)
    # cv2.namedWindow("imgData", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgData", imgData)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    #return coor5, mistakes
    return resultFinal
Ejemplo n.º 10
0
def deal_one_page(srcPath, desPath='', charsOnly=False, rectification=False):
    """Process a paper image.

    Args:
        srcPath: File path of image.
        desPath: Destination path.
        charsOnly: Whether only return chars coordinate result.
        rectification: Whether rectify image.

    Returns:
        Final result.
    """
    global heightOfLine
    coor5 = []
    mistakes = 0
    bdResult = {}
    ratio = 0

    name = os.path.basename(srcPath)
    if not os.path.exists(srcPath):
        print("Image path not exists!")
        return None
    try:
        imgBgr = cv2.imread(srcPath)
        if rectification:
            imgBgr = rectify(imgBgr.copy())
        imgData = cv2.cvtColor(imgBgr, cv2.COLOR_BGR2GRAY)

    except Exception as imageError:
        print(imageError, 'Could not read the image file, skip...')

    # 根据图像长宽判断是否为单栏
    ori_size = imgData.shape[0:2]
    single_column = True if ori_size[0] > ori_size[1] else False

    # 缩放到固定大小(双栏宽度为4000pixels, 单栏为2000pixels)
    if single_column and ori_size[1] != 2000:
        ratio = 2000 / ori_size[1]
    elif not single_column and ori_size[1] != 4000:
        ratio = 4000 / ori_size[1]

    if ratio:
        imgData = resize(imgData, x=ratio)
    new_size = imgData.shape[0:2]

    #原始图像去除竖线(长度大于100pixels,可能去除部分题目信息)
    imgEliVer = eli_ver(imgData.copy())  #
    # cv2.namedWindow("imgEliVer", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgEliVer", imgEliVer)

    #纵向划分试题区域
    coor1 = divide_ver(imgEliVer)
    # print('coor1: {}'.format(coor1))

    #计算行高(所有行高的中位数)
    if heightOfLine == 0:  #
        coor2 = divide_hor(imgEliVer, coor1)
        heightOfLines = [c[3] - c[1] for c in coor2]
        heightOfLine = median(heightOfLines)

    #获取原始图像联通区域以及消去较大的联通区域
    imgInv = imu.preprocess_bw_inv(imgData.copy())
    cv2.imwrite('imgInv.jpg', imgInv)
    coorCC = get_no_intersect_boxes('imgInv.jpg')
    imgEliCC = eli_large_cc(coorCC, imgData.copy(), heightOfLine)
    os.remove('imgInv.jpg')
    # cv2.namedWindow("imgEliCC", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgEliCC", imgEliCC)

    #去除较大联通区域的图像上去除竖线
    imgEli = eli_ver(imgEliCC)  #1
    # cv2.namedWindow("imgEli", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgEli", imgEli)

    #行划分
    coor2 = divide_hor(imgEli, coor1)  #2
    # print('coor2: {}'.format(coor2))
    # img2 = mark_box(imgBgr, coor2, color=(0,255,0))
    # cv2.namedWindow("img2", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("img2", img2)

    #获取每行前三个字符
    coor3 = find_char(imgEli, coor2)  #3
    # print(np.array(coor3))
    # for l in coor3:
    #     l = [length2coor(list(map(lambda x: x / ratio, coor2length(c)))) for c in l]
    #     img3 = mark_box(imgBgr, l, color=(0,255,0))
    # cv2.namedWindow("img3", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("img3", img3)
    # cv2.imwrite("img3.jpg", img3)

    if charsOnly:
        coor_chars = []
        #坐标换算
        for l in coor3:
            coor_chars.append([
                length2coor(list(map(lambda x: int(x / ratio),
                                     coor2length(c)))) for c in l
            ])
        return coor_chars

    #SVM分类字符图像
    # print('SVM classifying...')
    coor4 = svm_classify(imgEli, coor3)  #4
    # print(*coor4, sep='\n')

    #在二值图上重新获取字符以及SVM分类(补全部分漏检)
    imgBw = imu.preprocess_bw(imgEli, boxSize=(4, 4), morph=False)  #re
    coor3Bw = find_char(imgBw, coor2)
    coor4Bw = svm_classify(imgBw, coor3Bw)
    coor5 = update_result(coor4, coor4Bw)

    #百度识别
    try:
        # print('BaiDu recognizing...')
        bdResult = bd_rec(imgEliCC,
                          client,
                          imgForm=srcPath[-4:],
                          api='general')
    except Exception as e:
        print(
            'Baidu recognition error, check your internet connection. exit...')
        exit(0)
    # print(bdResult)

    #附加题处理
    addResult = additional_questions(bdResult)
    # print(addResult)
    if addResult:
        coor5.append(([addResult], 2))
    # print(*coor4, sep='\n')

    #自我评测处理
    sa = detect_self_assessment(bdResult)
    if sa:
        imgData[sa:, coor1[1][0]:coor1[1][1] + 10] = 255
    coor22 = divide_hor(imgData, coor1)
    # print(coor22)

    #生成题目区域
    region = integrate_lines(coor5, coor22, new_size)
    # print('region: {}'.format(region))

    #去除装订线及中间分割线(不会去除题目信息)
    imgData1 = detect_vertical_line3(imgData.copy())

    #导出最后结果
    resultFinal = get_items_v02(region, imgData1.copy(), coorCC, name)
    if desPath:
        with open(desPath[:-4] + '.json', 'w') as f:
            json.dump(resultFinal, f)

    # cv2.namedWindow("imgData", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("imgData", imgData)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    return resultFinal
Ejemplo n.º 11
0
def testpaper(file_path, save_path):
    """Process a paper image.

    Args:
        file_path: File path of image.
        save_path: Destination path.

    Returns:
        Final result.
    """
    name = os.path.basename(file_path)
    image = cv2.imread(file_path)
    if image is None:
        print('ImageError: Could not read the image file, exit...')
        return None

    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 根据图像长宽判断是否为单栏
    ori_size = image_gray.shape[0:2]
    single_column = True if ori_size[0] > ori_size[1] else False

    # 缩放到固定大小(双栏宽度为4000pixels, 单栏为2000pixels)
    if single_column and ori_size[1] != 2000:
        ratio = 2000 / ori_size[1]
    elif not single_column and ori_size[1] != 4000:
        ratio = 4000 / ori_size[1]
    else:
        ratio = 0

    if ratio:
        image_gray_scale = resize(image_gray, x=ratio)
    new_size = image_gray_scale.shape[0:2]

    img_bw_inv = imu.preprocess_bw_inv(image_gray_scale)
    img_bw = imu.preprocess_bw(image_gray_scale)
    img_bw2 = imu.preprocess_bw(image_gray_scale, boxSize=(5, 5))

    #原始图像去除竖线(长度大于100pixels,可能去除部分题目信息)
    imgEliVer = eli_ver(img_bw2)

    #纵向划分试题区域
    coor1 = divide_ver(imgEliVer)
    if not coor1:
        print('coor1: {}'.format(coor1))
        print("Can't divide vertically, skip...")
        return None

    #计算行高(所有行高的中位数)
    coor2 = divide_hor(imgEliVer, coor1)
    if coor2:
        heightOfLines = [c[3] - c[1] for c in coor2]
        heightOfLine = median(heightOfLines)
    else:
        print("Can't divide by line, skip...")
        return None

    #获取原始图像联通区域以及消去较大的联通区域
    imgInv = imu.preprocess_bw_inv(img_bw2.copy())
    cv2.imwrite('imgInv.jpg', imgInv)
    coorCC = get_no_intersect_boxes('imgInv.jpg')
    imgEliCC = eli_large_cc(coorCC, img_bw2.copy(), heightOfLine)
    os.remove('imgInv.jpg')

    #去除较大联通区域的图像上去除竖线
    imgEli = eli_ver(imgEliCC)

    #行划分
    coor2 = divide_hor(imgEli, coor1)

    #获取每行前三个字符
    coor3 = find_char(img_bw, coor2)

    #SVM分类字符图像
    coor4 = svm_classify(img_bw, coor3)

    #在二值图上重新获取字符以及SVM分类(补全部分漏检)
    imgBw = imu.preprocess_bw(imgEli, boxSize=(4, 4), morph=False)
    coor3Bw = find_char(imgBw, coor2)
    coor4Bw = svm_classify(imgBw, coor3Bw)
    coor5 = update_result(coor4, coor4Bw)

    # 百度文字识别API客户端
    client = bd_access()
    try:
        bdResult = bd_rec(imgEliCC, client, imgForm=name[-4:], api='general')
    except Exception as e:
        print(e, 'Baidu recognition error, exit...', sep='\n')
        return None

    # 附加题处理
    addResult = additional_questions(bdResult)
    if addResult:
        coor5.append(([addResult], 2))

    #自我评测处理
    sa = detect_self_assessment(bdResult)
    if sa:
        image_gray_scale[sa:, coor1[1][0]:coor1[1][1] + 10] = 255
    coor22 = divide_hor(image_gray_scale, coor1)

    # 生成题目区域
    region = integrate_lines(coor5, coor22, new_size)
    region = [
        length2coor(list(map(lambda x: int(x / ratio), coor2length(r))))
        for r in region
    ]

    #背景标记
    region_close = []
    for r in region:
        if r[2] <= r[0] or r[3] <= r[1]: continue
        border = imu.strip_white_boder2(image_gray[r[1]:r[3], r[0]:r[2]])
        r = num2int([
            border[0] + r[0], border[1] + r[1], border[2] + r[0],
            border[3] + r[1]
        ])
        region_close.append(r)
        background = np.zeros((r[3] - r[1], r[2] - r[0], 3), np.uint8)
        background[:] = (200, 170, 150)
        image[r[1]:r[3],
              r[0]:r[2]] = cv2.addWeighted(image[r[1]:r[3], r[0]:r[2]], 0.7,
                                           background, 0.3, 0)

    # image_process = np.concatenate([image_gray_scale, img_bw,
    #                 imgEliVer, imgEliCC, imgEli], axis=0)
    # cv2.imwrite("image_process.jpg", image_process)
    dic_result = {"positions": region_close}
    print(f'region: {region_close}')
    print('output to directory {}'.format(save_path))
    with open(save_path + '/' + name.replace('.jpg', '.json'), 'w') as f:
        json.dump(dic_result, f)
    cv2.imwrite(os.path.join(save_path, name), image)
    return region

    #去除装订线及中间分割线(不会去除题目信息)
    imgData1 = detect_vertical_line3(imgData.copy())

    #导出最后结果
    resultFinal = get_items_v02(region, imgData1.copy(), coorCC, name)
    if desPath:
        with open(desPath[:-4] + '.json', 'w') as f:
            json.dump(resultFinal, f)

    return resultFinal