Spaces:
Runtime error
Runtime error
| from fastapi import FastAPI, File, UploadFile | |
| from fastapi.responses import JSONResponse | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from PIL import Image | |
| import io | |
| import torch | |
| from transformers import AutoImageProcessor, AutoBackbone | |
| import pytesseract # OCR | |
| app = FastAPI() | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| processor = AutoImageProcessor.from_pretrained("czczup/textnet-base") | |
| model = AutoBackbone.from_pretrained("czczup/textnet-base") | |
| model.eval() | |
| async def detect_text(file: UploadFile = File(...)): | |
| try: | |
| # Lire image | |
| image_bytes = await file.read() | |
| image = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
| # Entrée TextNet | |
| inputs = processor(image, return_tensors="pt") | |
| with torch.no_grad(): | |
| outputs = model(**inputs) | |
| # Feature map et heatmap | |
| fm = outputs.feature_maps[-1][0] # dernière layer | |
| heatmap = fm.mean(dim=0).numpy() | |
| H, W = heatmap.shape | |
| threshold = heatmap.max() * 0.2 | |
| # Points chauds | |
| points = [(x, y) for y in range(H) for x in range(W) if heatmap[y, x] > threshold] | |
| if not points: | |
| return JSONResponse([]) | |
| # Regrouper par lignes simples | |
| lines = {} | |
| for x, y in points: | |
| key = int(y / 10) | |
| lines.setdefault(key, []).append((x, y)) | |
| # Générer boxes et extraire texte OCR | |
| scale_x = image.width / W | |
| scale_y = image.height / H | |
| boxes = [] | |
| for line in lines.values(): | |
| xs = [p[0] for p in line] | |
| ys = [p[1] for p in line] | |
| min_x, max_x = min(xs), max(xs) | |
| min_y, max_y = min(ys), max(ys) | |
| if (max_x - min_x) < 5 or (max_y - min_y) < 2: | |
| continue | |
| # Crop pour OCR | |
| crop = image.crop(( | |
| int(min_x * scale_x), | |
| int(min_y * scale_y), | |
| int(max_x * scale_x), | |
| int(max_y * scale_y) | |
| )) | |
| text = pytesseract.image_to_string(crop, lang='eng').strip() | |
| if len(text) < 2: | |
| continue | |
| if len(boxes) == 0: | |
| boxes.append({ | |
| "x": 10, | |
| "y": 10, | |
| "w": 100, | |
| "h": 50, | |
| "text": "Aucun texte détecté" | |
| }) | |
| boxes.append({ | |
| "x": int(min_x * scale_x), | |
| "y": int(min_y * scale_y), | |
| "w": int((max_x - min_x) * scale_x), | |
| "h": int((max_y - min_y) * scale_y), | |
| "text": text or "texte non reconnu" | |
| }) | |
| print("BOXES:", boxes) | |
| return JSONResponse({ | |
| "image_width": image.width, | |
| "image_height": image.height, | |
| "boxes": boxes | |
| }) | |
| except Exception as e: | |
| return JSONResponse({"success": False, "error": str(e)}, status_code=500) |