У меня есть несколько таблиц с одинаковой структурой: чередующиеся строки очень светлого синего и одного немного более темного синего оттенка, и я хотел бы извлечь текст строка за строкой:
Исходное цветное изображение
Большинство строк имеют одинаковую высоту, но некоторые строки в 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)