Rivalcoder commited on
Commit
d780beb
Β·
1 Parent(s): 71ff29e
Files changed (1) hide show
  1. app.py +25 -28
app.py CHANGED
@@ -1,32 +1,32 @@
 
 
 
 
1
  import os
2
  import io
3
- import warnings
4
  import easyocr
5
  import numpy as np
6
  from fastapi import FastAPI, UploadFile, File
7
  from fastapi.responses import JSONResponse
8
  from PIL import Image
9
  from pdf2image import convert_from_bytes
10
- from concurrent.futures import ProcessPoolExecutor
11
 
12
  # =========================
13
  # EasyOCR config
14
  # =========================
15
- warnings.filterwarnings("ignore", message=".*pin_memory.*")
16
-
17
  MODEL_DIR = "/app/.EasyOCR"
18
  USER_NET_DIR = os.path.join(MODEL_DIR, "user_network")
19
 
20
  os.makedirs(MODEL_DIR, exist_ok=True)
21
  os.makedirs(USER_NET_DIR, exist_ok=True)
22
 
23
- # βœ… preload reader (CPU only for Hugging Face)
24
  reader = easyocr.Reader(
25
  ['en', 'hi'],
26
  model_storage_directory=MODEL_DIR,
27
  user_network_directory=USER_NET_DIR,
28
- download_enabled=False,
29
- gpu=False
30
  )
31
 
32
  # =========================
@@ -34,18 +34,19 @@ reader = easyocr.Reader(
34
  # =========================
35
  app = FastAPI()
36
 
37
-
38
  @app.get("/")
39
  async def root():
40
  return {"message": "OCR API is running on Hugging Face πŸš€"}
41
 
42
 
43
- def run_ocr_on_image(image_bytes: bytes) -> str:
44
- """OCR worker: takes image bytes, runs OCR, returns text"""
45
- image = Image.open(io.BytesIO(image_bytes))
46
  image_np = np.array(image)
47
  results = reader.readtext(image_np)
48
- return " ".join([str(text) for _, text, _ in results]).strip()
 
 
 
49
 
50
 
51
  @app.post("/ocr")
@@ -54,29 +55,25 @@ async def ocr(file: UploadFile = File(...)):
54
  contents = await file.read()
55
 
56
  if file.filename.lower().endswith(".pdf"):
57
- # βœ… Convert PDF β†’ images (lower DPI for speed)
58
- pages = convert_from_bytes(contents, dpi=150)
59
-
60
- # Convert each page to raw bytes (so workers don’t share PIL objects)
61
- page_bytes = []
62
- for p in pages:
63
- buf = io.BytesIO()
64
- p.save(buf, format="PNG")
65
- page_bytes.append(buf.getvalue())
66
 
 
67
  text_results = []
68
- # βœ… Multiprocessing (parallel CPU workers)
69
- with ProcessPoolExecutor(max_workers=4) as executor: # adjust workers
70
- page_texts = list(executor.map(run_ocr_on_image, page_bytes))
71
-
72
- for i, text in enumerate(page_texts, start=1):
73
- text_results.append({"page": i, "text": text})
 
74
 
75
  return JSONResponse(content={"pdf_results": text_results})
76
 
77
  else:
78
  # βœ… Single image case
79
- text = run_ocr_on_image(contents)
 
80
  return JSONResponse(content={"text": text})
81
 
82
  except Exception as e:
 
1
+ import warnings
2
+ warnings.filterwarnings("ignore", message=".*pin_memory.*")
3
+
4
+
5
  import os
6
  import io
 
7
  import easyocr
8
  import numpy as np
9
  from fastapi import FastAPI, UploadFile, File
10
  from fastapi.responses import JSONResponse
11
  from PIL import Image
12
  from pdf2image import convert_from_bytes
13
+ from concurrent.futures import ThreadPoolExecutor
14
 
15
  # =========================
16
  # EasyOCR config
17
  # =========================
 
 
18
  MODEL_DIR = "/app/.EasyOCR"
19
  USER_NET_DIR = os.path.join(MODEL_DIR, "user_network")
20
 
21
  os.makedirs(MODEL_DIR, exist_ok=True)
22
  os.makedirs(USER_NET_DIR, exist_ok=True)
23
 
24
+ # βœ… preload reader
25
  reader = easyocr.Reader(
26
  ['en', 'hi'],
27
  model_storage_directory=MODEL_DIR,
28
  user_network_directory=USER_NET_DIR,
29
+ download_enabled=False
 
30
  )
31
 
32
  # =========================
 
34
  # =========================
35
  app = FastAPI()
36
 
 
37
  @app.get("/")
38
  async def root():
39
  return {"message": "OCR API is running on Hugging Face πŸš€"}
40
 
41
 
42
+ def run_ocr_on_image(image: Image.Image) -> str:
43
+ """Convert PIL β†’ numpy, run OCR, return plain text"""
 
44
  image_np = np.array(image)
45
  results = reader.readtext(image_np)
46
+
47
+ # βœ… only text, join all detections
48
+ extracted_text = " ".join([str(text) for _, text, _ in results])
49
+ return extracted_text.strip()
50
 
51
 
52
  @app.post("/ocr")
 
55
  contents = await file.read()
56
 
57
  if file.filename.lower().endswith(".pdf"):
58
+ # βœ… Convert PDF β†’ images
59
+ pages = convert_from_bytes(contents)
 
 
 
 
 
 
 
60
 
61
+ # βœ… Run OCR in parallel
62
  text_results = []
63
+ with ThreadPoolExecutor() as executor:
64
+ page_texts = list(executor.map(run_ocr_on_image, pages))
65
+ for i, text in enumerate(page_texts, start=1):
66
+ text_results.append({
67
+ "page": i,
68
+ "text": text
69
+ })
70
 
71
  return JSONResponse(content={"pdf_results": text_results})
72
 
73
  else:
74
  # βœ… Single image case
75
+ image = Image.open(io.BytesIO(contents))
76
+ text = run_ocr_on_image(image)
77
  return JSONResponse(content={"text": text})
78
 
79
  except Exception as e: