ugolefoo commited on
Commit
430a6c7
Β·
verified Β·
1 Parent(s): 2167acd

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -0
app.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import pytesseract
4
+ import requests
5
+ import pandas as pd
6
+ import gradio as gr
7
+ from io import BytesIO
8
+
9
+ # ──────────────────────────────────────────────────────────────
10
+ # 1. Utility: Detect rectangular contours (approximate book covers)
11
+ # ──────────────────────────────────────────────────────────────
12
+ def detect_book_regions(image: np.ndarray, min_area=10000, eps_coef=0.02):
13
+ """
14
+ Detect rectangular regions in an image that likely correspond to book covers.
15
+ Returns a list of bounding boxes: (x, y, w, h).
16
+ """
17
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
18
+ blurred = cv2.GaussianBlur(gray, (5, 5), 0)
19
+ edges = cv2.Canny(blurred, 50, 150)
20
+
21
+ # Dilate + erode to close gaps
22
+ kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
23
+ closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
24
+
25
+ contours, _ = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
26
+ boxes = []
27
+
28
+ for cnt in contours:
29
+ area = cv2.contourArea(cnt)
30
+ if area < min_area:
31
+ continue
32
+
33
+ peri = cv2.arcLength(cnt, True)
34
+ approx = cv2.approxPolyDP(cnt, eps_coef * peri, True)
35
+
36
+ # Keep only quadrilaterals
37
+ if len(approx) == 4:
38
+ x, y, w, h = cv2.boundingRect(approx)
39
+ ar = w / float(h)
40
+ # Filter by typical book-cover aspect ratios
41
+ if 0.4 < ar < 0.9 or 1.0 < ar < 1.6:
42
+ boxes.append((x, y, w, h))
43
+
44
+ # Sort left→right, top→bottom
45
+ boxes = sorted(boxes, key=lambda b: (b[1], b[0]))
46
+ return boxes
47
+
48
+ # ──────────────────────────────────────────────────────────────
49
+ # 2. OCR on a cropped region
50
+ # ──────────────────────────────────────────────────────────────
51
+ def ocr_on_region(image: np.ndarray, box: tuple):
52
+ """
53
+ Crop the image to the given box and run Tesseract OCR.
54
+ Return the raw OCR text.
55
+ """
56
+ x, y, w, h = box
57
+ cropped = image[y:y+h, x:x+w]
58
+ gray_crop = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY)
59
+ _, thresh_crop = cv2.threshold(gray_crop, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
60
+ custom_config = r'--oem 3 --psm 6'
61
+ text = pytesseract.image_to_string(thresh_crop, config=custom_config)
62
+ return text.strip()
63
+
64
+ # ──────────────────────────────────────────────────────────────
65
+ # 3. Query OpenLibrary API
66
+ # ──────────────────────────────────────────────────────────────
67
+ def query_openlibrary(title_text: str, author_text: str = None):
68
+ """
69
+ Search OpenLibrary by title (and optional author).
70
+ Return a dict with title, author_name, publisher, first_publish_year, or None.
71
+ """
72
+ base_url = "https://openlibrary.org/search.json"
73
+ params = {"title": title_text}
74
+ if author_text:
75
+ params["author"] = author_text
76
+
77
+ try:
78
+ resp = requests.get(base_url, params=params, timeout=5)