Spaces:
Sleeping
Sleeping
Download ocr.py from teuchi/dumm-image-translator: direct link, hf CLI and curl.
- Browser
- Download file 3.76 kB
-
https://huggingface.co/spaces/teuchi/dumm-image-translator/resolve/main/ocr.py
- Command line
-
hf download hf://spaces/teuchi/dumm-image-translator/ocr.py
-
curl -L -o ocr.py https://huggingface.co/spaces/teuchi/dumm-image-translator/resolve/main/ocr.py
3.76 kB
| import os | |
| import torch | |
| from PIL import Image | |
| from model import get_model | |
| from dataset import decode_prediction, get_val_transforms, ALPHABET | |
| from word_detector import split_into_words | |
| class OCR: | |
| def __init__( | |
| self, | |
| checkpoint_path: str = "best_model.pth", # По умолчанию смотрим в корень для Hugging Face | |
| device: str = None, | |
| ): | |
| self.device = device or ("cuda" if torch.cuda.is_available() else "cpu") | |
| # Если переданный путь не существует, но файл есть в корне — используем корень | |
| if not os.path.exists(checkpoint_path) and os.path.exists("best_model.pth"): | |
| checkpoint_path = "best_model.pth" | |
| elif not os.path.exists(checkpoint_path) and os.path.exists("../models/best_model.pth"): | |
| checkpoint_path = "../models/best_model.pth" | |
| num_classes = len(ALPHABET) + 1 | |
| self.model = get_model(num_classes=num_classes, device=self.device) | |
| print(f"[OCR] загружаем веса: {checkpoint_path}") | |
| checkpoint = torch.load(checkpoint_path, map_location=self.device) | |
| # Поддержка загрузки как чистого state_dict, так и сохраненного через чекпоинт словаря | |
| if "model_state_dict" in checkpoint: | |
| self.model.load_state_dict(checkpoint["model_state_dict"]) | |
| else: | |
| self.model.load_state_dict(checkpoint) | |
| self.model.eval() | |
| print(f"[OCR] точность модели при обучении: {checkpoint.get('accuracy', 'неизвестно') if isinstance(checkpoint, dict) else 'неизвестно'}") | |
| self.transform = get_val_transforms(img_height=32, img_width=128) | |
| def _recognize_single_word(self, image: Image.Image) -> str: | |
| image_tensor = self.transform(image.convert("RGB")).unsqueeze(0).to(self.device) | |
| logits = self.model(image_tensor) # [T, B, C] | |
| preds = logits.argmax(dim=2).permute(1, 0) # [B, T] | |
| text = decode_prediction(preds[0].tolist()) | |
| return text | |
| def recognize(self, image_path: str) -> str: | |
| image = Image.open(image_path) | |
| return self._recognize_single_word(image) | |
| def recognize_line(self, image_path: str, **detector_kwargs) -> str: | |
| image = Image.open(image_path) | |
| word_images = split_into_words(image, **detector_kwargs) | |
| if not word_images: | |
| return self._recognize_single_word(image) | |
| words = [self._recognize_single_word(w) for w in word_images] | |
| return " ".join(words) | |
| def recognize_batch(self, image_paths: list[str]) -> list[str]: | |
| images = [] | |
| for path in image_paths: | |
| image = Image.open(path).convert("RGB") | |
| images.append(self.transform(image)) | |
| batch = torch.stack(images).to(self.device) | |
| logits = self.model(batch) | |
| preds = logits.argmax(dim=2).permute(1, 0) | |
| results = [decode_prediction(seq.tolist()) for seq in preds] | |
| return results | |
| if __name__ == "__main__": | |
| # Для локальных тестов проверяет обе папки | |
| default_path = "best_model.pth" if os.path.exists("best_model.pth") else "../models/best_model.pth" | |
| ocr = OCR(checkpoint_path=default_path) | |
| test_image = "test_word.jpg" | |
| try: | |
| result = ocr.recognize_line(test_image) | |
| print(f"\nРаспознанный текст: '{result}'") | |
| except FileNotFoundError: | |
| print(f"\nКартинка '{test_image}' не найдена.") | |
| print("укажи нормальный путь.") |