Spaces:
Runtime error
Runtime error
Damanger
commited on
Commit
·
f16d0cc
1
Parent(s):
5d99b0b
corrigiendo app
Browse files- app.py +35 -16
- requirements.txt +2 -0
app.py
CHANGED
|
@@ -3,11 +3,14 @@ from typing import Optional, List
|
|
| 3 |
import numpy as np, cv2, torch
|
| 4 |
from ultralytics import YOLO
|
| 5 |
import easyocr
|
|
|
|
|
|
|
| 6 |
|
| 7 |
from fastapi import FastAPI, HTTPException, File, UploadFile, Form
|
| 8 |
from fastapi.middleware.cors import CORSMiddleware
|
| 9 |
from pydantic import BaseModel, Field
|
| 10 |
|
|
|
|
| 11 |
TMP_DIR = "/tmp"
|
| 12 |
paths = [
|
| 13 |
f"{TMP_DIR}/Ultralytics",
|
|
@@ -119,25 +122,42 @@ def bgr_to_jpeg_base64(bgr):
|
|
| 119 |
return None
|
| 120 |
return base64.b64encode(buf.tobytes()).decode("ascii")
|
| 121 |
|
| 122 |
-
def
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
arr = np.frombuffer(data, np.uint8)
|
| 126 |
bgr = cv2.imdecode(arr, cv2.IMREAD_COLOR)
|
| 127 |
-
if bgr is None:
|
| 128 |
-
|
| 129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
s = b64_or_data_url
|
| 133 |
if s.startswith("data:"):
|
| 134 |
s = s.split(",", 1)[1]
|
| 135 |
raw = base64.b64decode(s)
|
| 136 |
-
|
| 137 |
-
bgr = cv2.imdecode(arr, cv2.IMREAD_COLOR)
|
| 138 |
-
if bgr is None:
|
| 139 |
-
raise ValueError("No pude decodificar la imagen desde base64.")
|
| 140 |
-
return bgr
|
| 141 |
|
| 142 |
# --- FastAPI ---
|
| 143 |
app = FastAPI(title="Plates API (HF Space)")
|
|
@@ -192,6 +212,7 @@ def detect(req: DetectRequest):
|
|
| 192 |
try:
|
| 193 |
if not req.image_url and not req.image_b64:
|
| 194 |
raise HTTPException(400, "Proporciona 'image_url' o 'image_b64'.")
|
|
|
|
| 195 |
bgr = load_image_from_url(req.image_url) if req.image_url else load_image_from_b64(req.image_b64)
|
| 196 |
vis, dets, (w, h), dt_ms = run_on_image_bgr(
|
| 197 |
bgr, conf=req.conf, iou=req.iou, with_ocr=req.ocr, annotate=req.return_image
|
|
@@ -219,10 +240,9 @@ async def detect_upload(
|
|
| 219 |
if not data:
|
| 220 |
raise HTTPException(400, "Archivo vacío.")
|
| 221 |
|
| 222 |
-
|
| 223 |
-
bgr = cv2.imdecode(arr, cv2.IMREAD_COLOR)
|
| 224 |
if bgr is None:
|
| 225 |
-
#
|
| 226 |
raise HTTPException(415, f"Formato no soportado: {image.content_type or image.filename}")
|
| 227 |
|
| 228 |
vis, dets, (w, h), dt_ms = run_on_image_bgr(
|
|
@@ -236,7 +256,6 @@ async def detect_upload(
|
|
| 236 |
except HTTPException:
|
| 237 |
raise
|
| 238 |
except Exception as e:
|
| 239 |
-
# esto hará que tu front vea el mensaje real en data.detail
|
| 240 |
raise HTTPException(500, f"Error procesando la imagen: {e}")
|
| 241 |
|
| 242 |
@app.on_event("startup")
|
|
|
|
| 3 |
import numpy as np, cv2, torch
|
| 4 |
from ultralytics import YOLO
|
| 5 |
import easyocr
|
| 6 |
+
from PIL import Image
|
| 7 |
+
import pillow_heif
|
| 8 |
|
| 9 |
from fastapi import FastAPI, HTTPException, File, UploadFile, Form
|
| 10 |
from fastapi.middleware.cors import CORSMiddleware
|
| 11 |
from pydantic import BaseModel, Field
|
| 12 |
|
| 13 |
+
|
| 14 |
TMP_DIR = "/tmp"
|
| 15 |
paths = [
|
| 16 |
f"{TMP_DIR}/Ultralytics",
|
|
|
|
| 122 |
return None
|
| 123 |
return base64.b64encode(buf.tobytes()).decode("ascii")
|
| 124 |
|
| 125 |
+
def pil_to_bgr(pil_img: Image.Image) -> np.ndarray:
|
| 126 |
+
if pil_img.mode not in ("RGB", "RGBA"):
|
| 127 |
+
pil_img = pil_img.convert("RGB")
|
| 128 |
+
arr = np.array(pil_img)
|
| 129 |
+
if arr.ndim == 2:
|
| 130 |
+
arr = np.stack([arr]*3, axis=-1)
|
| 131 |
+
if arr.shape[2] == 4:
|
| 132 |
+
arr = arr[:, :, :3]
|
| 133 |
+
return cv2.cvtColor(arr, cv2.COLOR_RGB2BGR)
|
| 134 |
+
|
| 135 |
+
def decode_bytes_to_bgr(data: bytes, content_type: str = "") -> np.ndarray:
|
| 136 |
+
# 1) OpenCV rápido
|
| 137 |
arr = np.frombuffer(data, np.uint8)
|
| 138 |
bgr = cv2.imdecode(arr, cv2.IMREAD_COLOR)
|
| 139 |
+
if bgr is not None:
|
| 140 |
+
return bgr
|
| 141 |
+
# 2) Fallback PIL (con HEIC soportado por pillow-heif)
|
| 142 |
+
try:
|
| 143 |
+
with Image.open(io.BytesIO(data)) as im:
|
| 144 |
+
return pil_to_bgr(im)
|
| 145 |
+
except Exception as e:
|
| 146 |
+
raise ValueError(f"No pude decodificar la imagen ({content_type}): {e}")
|
| 147 |
|
| 148 |
+
def load_image_from_url(url: str) -> np.ndarray:
|
| 149 |
+
ssl._create_default_https_context = ssl._create_unverified_context
|
| 150 |
+
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
| 151 |
+
with urllib.request.urlopen(req, timeout=20) as r:
|
| 152 |
+
data = r.read()
|
| 153 |
+
return decode_bytes_to_bgr(data, content_type=r.headers.get("Content-Type",""))
|
| 154 |
+
|
| 155 |
+
def load_image_from_b64(b64_or_data_url: str) -> np.ndarray:
|
| 156 |
s = b64_or_data_url
|
| 157 |
if s.startswith("data:"):
|
| 158 |
s = s.split(",", 1)[1]
|
| 159 |
raw = base64.b64decode(s)
|
| 160 |
+
return decode_bytes_to_bgr(raw, content_type="base64")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
# --- FastAPI ---
|
| 163 |
app = FastAPI(title="Plates API (HF Space)")
|
|
|
|
| 212 |
try:
|
| 213 |
if not req.image_url and not req.image_b64:
|
| 214 |
raise HTTPException(400, "Proporciona 'image_url' o 'image_b64'.")
|
| 215 |
+
|
| 216 |
bgr = load_image_from_url(req.image_url) if req.image_url else load_image_from_b64(req.image_b64)
|
| 217 |
vis, dets, (w, h), dt_ms = run_on_image_bgr(
|
| 218 |
bgr, conf=req.conf, iou=req.iou, with_ocr=req.ocr, annotate=req.return_image
|
|
|
|
| 240 |
if not data:
|
| 241 |
raise HTTPException(400, "Archivo vacío.")
|
| 242 |
|
| 243 |
+
bgr = decode_bytes_to_bgr(data, content_type=image.content_type or image.filename)
|
|
|
|
| 244 |
if bgr is None:
|
| 245 |
+
# si llega aquí es que ni cv2 ni PIL pudieron
|
| 246 |
raise HTTPException(415, f"Formato no soportado: {image.content_type or image.filename}")
|
| 247 |
|
| 248 |
vis, dets, (w, h), dt_ms = run_on_image_bgr(
|
|
|
|
| 256 |
except HTTPException:
|
| 257 |
raise
|
| 258 |
except Exception as e:
|
|
|
|
| 259 |
raise HTTPException(500, f"Error procesando la imagen: {e}")
|
| 260 |
|
| 261 |
@app.on_event("startup")
|
requirements.txt
CHANGED
|
@@ -8,3 +8,5 @@ easyocr
|
|
| 8 |
opencv-python==4.10.0.84
|
| 9 |
huggingface_hub
|
| 10 |
torch
|
|
|
|
|
|
|
|
|
| 8 |
opencv-python==4.10.0.84
|
| 9 |
huggingface_hub
|
| 10 |
torch
|
| 11 |
+
pillow
|
| 12 |
+
pillow-heif
|