-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocument_processor.py
More file actions
112 lines (95 loc) · 5.2 KB
/
Copy pathdocument_processor.py
File metadata and controls
112 lines (95 loc) · 5.2 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
# document_processor.py
import os
import re
import pytesseract
from pdf2image import convert_from_path
from langdetect import detect, LangDetectException
# --- НОВЫЕ ИМПОРТЫ ДЛЯ ОБРАБОТКИ ИЗОБРАЖЕНИЙ ---
import numpy as np
import cv2 # OpenCV
# --- СЛОВАРНЫЙ ФИЛЬТР (без изменений) ---
def load_dictionary(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as f:
return set(word.strip().lower() for word in f)
except FileNotFoundError:
print(f"Файл словаря не найден: {file_path}. Фильтр качества PDF будет отключен.")
return None
def is_text_coherent(text, dictionary, min_coherence_percent):
if not dictionary or not text:
return True
words = re.findall(r'\b[а-яА-Яa-zA-Z]{3,}\b', text.lower())
if not words:
return False
recognized_words = sum(1 for word in words if word in dictionary)
coherence_percent = (recognized_words / len(words)) * 100
return coherence_percent >= min_coherence_percent
# --- НОВЫЙ КОНВЕЙЕР ПРЕДВАРИТЕЛЬНОЙ ОБРАБОТКИ ---
def preprocess_image_for_ocr(image):
"""
Применяет серию фильтров OpenCV для очистки изображения перед OCR.
"""
# 1. Конвертируем изображение из формата PIL (от pdf2image) в формат OpenCV
open_cv_image = np.array(image)
# 2. Конвертируем в оттенки серого
gray = cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2GRAY)
# 3. Применяем бинаризацию (превращаем в Ч/Б).
# THRESH_OTSU автоматически подбирает оптимальный порог.
# Это ключевой шаг для удаления шума, печатей и т.д.
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# Инвертируем изображение обратно, чтобы текст был черным на белом фоне
thresh = 255 - thresh
return thresh
# --- ФИНАЛЬНАЯ ПОСТ-ОБРАБОТКА ТЕКСТА ---
def post_process_ocr_text(text):
"""
Удаляет типичный "мусор" после OCR.
"""
if not text:
return ""
# Удаляем строки, состоящие в основном из не-буквенно-цифровых символов (линии, разделители)
lines = text.split('\n')
cleaned_lines = []
for line in lines:
# Считаем количество "полезных" символов
meaningful_chars = re.findall(r'[а-яА-Яa-zA-Z0-9]', line)
# Считаем общее количество символов (кроме пробелов)
total_chars = len(line.replace(" ", ""))
if total_chars > 5 and len(meaningful_chars) / total_chars < 0.5:
# Если в строке более 5 символов и менее 50% из них - это буквы/цифры,
# скорее всего, это мусорная линия. Пропускаем ее.
continue
cleaned_lines.append(line)
return "\n".join(cleaned_lines)
# --- ОСНОВНАЯ ФУНКЦИЯ (обновленная) ---
def process_pdf_document(file_path, dictionary, min_coherence_percent, tesseract_cmd=None):
"""
Распознает текст из PDF, используя продвинутую предобработку изображений.
"""
if tesseract_cmd:
pytesseract.pytesseract.tesseract_cmd = tesseract_cmd
try:
# Увеличиваем DPI для лучшего качества
images = convert_from_path(file_path, dpi=300)
except Exception as e:
print(f"Не удалось конвертировать PDF: {file_path}, ошибка: {e}")
return None
full_text = ''
for i, image in enumerate(images):
try:
# 1. ПРИМЕНЯЕМ ПРЕДВАРИТЕЛЬНУЮ ОБРАБОТКУ
processed_image = preprocess_image_for_ocr(image)
# 2. Распознаем текст с обработанного изображения
custom_config = r'--oem 3 --psm 3' # PSM 3 - лучший автоматический режим
text = pytesseract.image_to_string(processed_image, lang='rus+eng', config=custom_config)
full_text += text + '\n\n'
except Exception as e:
print(f"Ошибка при OCR страницы {i+1} файла {file_path}: {e}")
continue
# 3. ПРИМЕНЯЕМ ФИНАЛЬНУЮ ОЧИСТКУ ТЕКСТА
post_processed_text = post_process_ocr_text(full_text)
# 4. ПРОВЕРЯЕМ ОСМЫСЛЕННОСТЬ ТЕКСТА
if not is_text_coherent(post_processed_text, dictionary, min_coherence_percent):
print(f"PDF отфильтрован как 'шумный' после всех обработок: {os.path.basename(file_path)}")
return None
return post_processed_text