Точность распознавания Тессеракта в односимвольных двоичных изображениях - PullRequest
0 голосов
/ 09 января 2019

В настоящее время я решаю задачу, в которой мне нужно извлечь алфавит или цифры из изображения. Я использовал OpenCV для извлечения текста из фона, порогового изображения, выравнивания изображения, используя строку под каждым символом в изображении, и подачи его в тессеракт, используя pytesseract. Я использую по умолчанию tesseract eng trainingdata, но результаты для персонажей очень плохие.

Это оригинальное изображение enter image description here

После обрезки ROI и обработки изображения я получил это: enter image description here

Из этого изображения я запустил cv2.HoughLinesP, чтобы найти линии и линии скопления, которые находятся на заданном расстоянии друг от друга. Из кластера линий я выбрал линию с наибольшим значением пикселя y в качестве базовой линии и выровнял заданную область интереса, используя угол изображения.

Вы можете увидеть результаты укоса и обрезки букв здесь

Однако, если вы внимательно посмотрите на цветное изображение и еще несколько изображений , вы увидите, что на некоторых буквах, особенно на «D», часть штрихов символа «смещается», как если бы это было срезано. Похоже, что эта функция часто приводит к сбою Tesseract. К какому методу я должен обратиться, чтобы исправить деформацию?

Код ниже - это то, что я использовал для предварительной обработки изображения:

def threshold_and_preprocess(input_image):
    """
    thresholds input image and performs preprocesing operations
    :param input_image: BGR image
    :return: Binary image with text as white
    """

    input_gray = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(input_gray, (3, 3), 0)
    sharpened = cv2.addWeighted(blur, 1.5, input_gray, -0.5, 0)
    denoised = cv2.fastNlMeansDenoising(sharpened, h=13, templateWindowSize=7, searchWindowSize=21)

    ret, thresh = cv2.threshold(denoised, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

    operated = thresh
    return operated

def find_baseline_and_deskew(input_img, line_group):
    """
    Given binary input_image and cluster data line_group, return list of tuples(img, point) where image is binary
    deskewed image with size of self.output_width and height, and point which is center point of reference line.
    :param input_img: Binary image where background is black, features are white
    :param line_group: this is a tuple of line coordinate cluster
    :return: list of tuples (img, point) where image is binary deskewed image where features are black,
    with width, height of self.output_width and self.output_height, point which is center point coordinate,
    relative to ROI region, of reference line.
    """
    return_list = []
    for group in self.cluster_line_groups:

        sorted_group = sorted(group, key=lambda x: max(x[0][1], x[0][3]), reverse=True)
        representation_line = sorted_group[0]
        r_c = representation_line[0]
        r_centroid = representation_line[1]
        # representation_line is the line selected to use as the baseline
        # r_c is the 4 coordinates of the start, end points of the line segment
        # r_centroid is just the x,y coordinates of the center of the line
        angle = math.atan2(r_c[3] - r_c[1], r_c[2] - r_c[0]) * 180.0 / math.pi


        t_img = cv2.bitwise_not(input_img).copy()
        rows, cols = t_img.shape
        root_mat = cv2.getRotationMatrix2D(representation_line[1], angle, 1)
        rotated = cv2.warpAffine(t_img, root_mat, (cols, rows), borderMode=cv2.BORDER_CONSTANT,
                                borderValue=(255, 255, 255))


        cropped_result = rotated[max(int(r_centroid[1] - self.output_height), 0):min(int(r_centroid[1] + 8), rotated.shape[0]),max(0, int(r_centroid[0] - self.output_width)):min(rotated.shape[1],int(r_centroid[0] + self.output_width))]



        return_list.append((cropped_result, r_centroid))

    return return_list

input_img = cv2.imread("input.png", cv2.IMREAD_COLOR)
processed = threshold_and_preprocess(input_img)
cv2.imshow("black", processed)
lines = calculate_lines(processed)
for img, coord in find_baseline_and_deskew(processed, lines):
    cv2.imshow(pytesseract.image_to_string(img,lang="eng", config="--psm 10"), img)

cv2.waitKey(0)
cv2.destroyAllWindows()
...