Spaces:
Sleeping
Sleeping
Download backend/app/api/detect_text.py from junyoung137/image-tool: direct link, hf CLI and curl.
- Browser
- Download file 1.99 kB
-
https://huggingface.co/spaces/junyoung137/image-tool/resolve/main/backend/app/api/detect_text.py
- Command line
-
hf download hf://spaces/junyoung137/image-tool/backend/app/api/detect_text.py
-
curl -L -o detect_text.py https://huggingface.co/spaces/junyoung137/image-tool/resolve/main/backend/app/api/detect_text.py
1.99 kB
| """ | |
| detect_text.py — POST /detect-text | |
| Runs PaddleOCR on the original image stored by /upload and returns a list | |
| of axis-aligned bounding boxes in original-image pixel coordinates. | |
| Why axis-aligned boxes, not raw quads? | |
| --------------------------------------- | |
| PaddleOCR returns rotated quadrilaterals (4 corner points per region). | |
| Converting to the minimum enclosing axis-aligned rect (min/max of the 4 x | |
| and y values) allows mask_service.build_masks() to rasterize them with zero | |
| changes — it already accepts {"x", "y", "width", "height"} dicts. The | |
| slight extra background at rotated-text corners is absorbed by the dilation | |
| and feathering steps, so the composite seam is invisible. | |
| Zero detections is not an error | |
| --------------------------------- | |
| If OCR finds no text, {"boxes": []} is returned with HTTP 200. The frontend | |
| displays a "nothing detected" hint; the user can still paint manually. | |
| """ | |
| from fastapi import APIRouter, HTTPException | |
| from pydantic import BaseModel | |
| from app.jobs_store import get_job | |
| from app.services.ocr_service import detect_text_regions | |
| router = APIRouter() | |
| class DetectTextRequest(BaseModel): | |
| job_id: str | |
| def detect_text(body: DetectTextRequest) -> dict: | |
| """Run OCR on the uploaded image and return detected text bounding boxes. | |
| Response | |
| -------- | |
| {"boxes": [{"x": int, "y": int, "width": int, "height": int}, ...]} | |
| All coordinates are in original-image pixels — the same space the mask | |
| JSON contract uses — so the frontend can put them directly into the | |
| ``boxes`` array of buildMaskJson() without any scaling. | |
| Raises 404 if the job_id is not found. | |
| Returns {"boxes": []} with HTTP 200 if no text is detected. | |
| """ | |
| job = get_job(body.job_id) | |
| if job is None: | |
| raise HTTPException( | |
| status_code=404, | |
| detail=f"Job '{body.job_id}' not found.", | |
| ) | |
| boxes = detect_text_regions(job.steps[0].original_image) | |
| return {"boxes": boxes} | |