Сегментируйте и извлекайте текст из таблицы строк чередующихся цветов с помощью OpenCV - PullRequest
0 голосов
/ 05 августа 2020

У меня есть несколько таблиц с одинаковой структурой: чередующиеся строки очень светлого синего и одного немного более темного синего оттенка, и я хотел бы извлечь текст строка за строкой:

Исходное цветное изображение

Большинство строк имеют одинаковую высоту, но некоторые строки в 2 ~ 4 раза длиннее.

Мой метод направлен на извлечение y-координат (вертикальное направление) граничных линий, разделяющих соседние строки. Поскольку два синих цвета фона различаются по оттенку и значению в таблицах из-за печати или сканирования теней, я сначала конвертирую ROI в оттенки серого, затем выполняю выравнивание гистограммы, чтобы увеличить контраст между двумя оттенками синего, с последующим установлением порога и открытием *. 1008 *

roi_equalized: после применения выравнивания гистограммы к изображению в оттенках серого

Затем я применяю фильтр Собела, чтобы превратить границы в линии, прежде чем использовать Преобразование линии Хафа для извлечения y-координат этих линий. С некоторыми условиями для фильтрации множества строк, возвращаемых преобразованием линии Хафа, которые возникают из-за шума, я беру y-координаты оставшихся линий за границы.

Этот метод хорошо работает примерно на 60-70% времени. Проблема в том, что текст и пиксельный фон добавляют значительный шум к изображению пост-собел.

roi_sobel_8u_inv: после применения фильтров Собеля

Так что даже после фильтрации результатов преобразования линии Хафа я все равно иногда получаю неправильные координаты y. Мой вопрос: Есть ли способ удалить лишний шум между строками из roi_sobel_8u_inv? Я попытался удалить часть текста, сначала получив word_mask, а затем установив область word_mask к среднему пиксельному цвету фона построчно, но это очень дорого и не так эффективно. Был бы признателен за любой альтернативный метод, который действительно повышает точность :)

    # 1. histogram equalization
    roi_equalized = cv2.equalizeHist(roi_gray)

    # 2. thresholding + opening
    roi_thresh = cv2.threshold(roi_equalized, 200, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    roi_thresh = cv2.morphologyEx(roi_thresh, cv2.MORPH_OPEN, np.ones((2, 2)))

    # 3. sobel - roi_sobel_8u_inv has black background
    roi_sobel_64f = cv2.Sobel(roi_thresh, cv2.CV_64F, 0, 2, ksize=3)
    roi_sobel_64f = np.absolute(roi_sobel_64f)
    roi_sobel_8u_inv = np.uint8(roi_sobel_64f)

    # 4. Hough transform to find the lines' coordinates
    min_line_len = 180
    max_line_len = 320
    ys = [0]
    linesP = cv2.HoughLinesP(roi_sobel_8u_inv, 1, np.pi / 180, 50, None, min_line_len, 20)

    # sort the linesP from top to bottom by y1
    linesP = sorted(linesP, key=lambda x: x[0][1])

    if linesP is not None:
        for i in range(0, len(linesP)):
            x1, y1, x2, y2 = linesP[i][0]

            # If y2 and y1 are far apart, it means that this is probably not a horizontal line?
            if abs(y2 - y1) > 5:
                continue

            if abs(x2 - x1) > max_line_len:
                continue
            # If this y-coord is close enough to any of the existing y-coords in the list, don't add the y-coord to
            # list.

            diff = y1 - ys[-1]

            if 25 < diff < 35 or 50 < diff < 65 or 70 < diff < 95:
                ys.append(y1)

    ys = sorted(ys)
    ys.append(roi.shape[0] - 1)
...