File size: 4,521 Bytes
d83150d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import os
from PIL import Image
import pytesseract
from tqdm import tqdm
from pytesseract import Output
from transformers import VisionEncoderDecoderModel, TrOCRProcessor

def recognize_row(row_file):
    hf_model = VisionEncoderDecoderModel.from_pretrained("Serovvans/trocr-prereform-orthography")
    image = Image.open(row_file)
    processor = TrOCRProcessor.from_pretrained("microsoft/trocr-base-printed")
    pixel_values = processor(images=image, return_tensors="pt").pixel_values
    generated_ids = hf_model.generate(pixel_values)
    generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
    return generated_text

def recognize_page(image_path, output_dir="./", page_name=None):
    """
    Разбивает изображение страницы на строки, сортирует строки, распознаёт их и соединяет текст.

    Параметры:
        image_path (str): Путь к изображению страницы.
        output_dir (str): Путь к папке для сохранения строк.
        page_name (str): Имя страницы для сохранения строк (по умолчанию None).

    Возвращает:
        str: Итоговый распознанный текст страницы.
    """
    os.makedirs(output_dir, exist_ok=True)
    image = Image.open(image_path)
    data = pytesseract.image_to_data(image, config='--psm 3', output_type=Output.DICT)

    lines = []
    current_line = []
    previous_y = None
    y_threshold = 15  # Порог для объединения слов в одну строку

    # Обход всех блоков текста
    n_boxes = len(data['level'])
    for i in range(n_boxes):
        if data['level'][i] == 5 or data['level'][i] == 4:  # Уровень строки или слова
            x, y, w, h = data['left'][i], data['top'][i], data['width'][i], data['height'][i]
            text = data['text'][i].strip()

            if not text:
                continue

            # Проверяем, начинается ли новая строка
            if previous_y is None or abs(y - previous_y) > y_threshold:
                if current_line:
                    # Объединяем слова в строку и добавляем в список строк
                    min_x = min([word['x'] for word in current_line])
                    max_x = max([word['x'] + word['w'] for word in current_line])
                    avg_y = sum([word['y'] for word in current_line]) / len(current_line)
                    max_y = max([word['y'] + word['h'] for word in current_line])
                    lines.append((min_x, avg_y, max_x - min_x, max_y - avg_y, current_line))
                    current_line = []

            # Добавляем текущее слово в текущую строку
            current_line.append({'x': x, 'y': y, 'w': w, 'h': h, 'text': text})
            previous_y = y

    # Добавляем последнюю строку
    if current_line:
        min_x = min([word['x'] for word in current_line])
        max_x = max([word['x'] + word['w'] for word in current_line])
        avg_y = sum([word['y'] for word in current_line]) / len(current_line)
        max_y = max([word['y'] + word['h'] for word in current_line])
        lines.append((min_x, avg_y, max_x - min_x, max_y - avg_y, current_line))

    # Сортировка строк по координате Y
    lines.sort(key=lambda line: line[1])

    # Сохранение строк как изображений и распознавание текста
    recognized_text = []
    i = 0
    for line in tqdm(lines, desc="Processing page"):
        x, y, w, h, words = line
        min_x = x
        max_x = x + w
        min_y = max(0, y - 10)
        max_y = y + h

        # Обрезаем изображение по координатам строки
        row_image = image.crop((min_x, min_y, max_x, max_y))
        row_image_path = os.path.join(output_dir, f'{page_name}_row_{i}.png')
        row_image.save(row_image_path)

        # Распознаём текст строки
        row_text = recognize_row(row_image_path)
        
        os.remove(row_image_path)
        
        recognized_text.append(row_text)
        i += 1

    # Соединяем распознанный текст строк
    full_text = ' '.join(recognized_text)
    return full_text