В настоящее время я решаю задачу, в которой мне нужно извлечь алфавит или цифры из изображения. Я использовал OpenCV для извлечения текста из фона, порогового изображения, выравнивания изображения, используя строку под каждым символом в изображении, и подачи его в тессеракт, используя pytesseract
. Я использую по умолчанию tesseract eng
trainingdata, но результаты для персонажей очень плохие.
Это оригинальное изображение
После обрезки ROI и обработки изображения я получил это:
Из этого изображения я запустил 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()