Sanjayraju30 commited on
Commit
3165179
·
verified ·
1 Parent(s): 6f780aa

Rename weight_detector.py to ocr_engine.py

Browse files
Files changed (2) hide show
  1. ocr_engine.py +11 -0
  2. weight_detector.py +0 -155
ocr_engine.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import pytesseract
3
+ from PIL import Image
4
+ import numpy as np
5
+
6
+ def extract_weight(image: Image.Image) -> str:
7
+ img = np.array(image.convert("RGB"))
8
+ gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
9
+ text = pytesseract.image_to_string(gray, config="--psm 7 digits")
10
+ weight = ''.join(filter(lambda x: x in '0123456789.', text))
11
+ return weight if weight else "No valid weight detected"
weight_detector.py DELETED
@@ -1,155 +0,0 @@
1
- import cv2
2
- import numpy as np
3
- import easyocr
4
- import re
5
- from PIL import Image, ImageDraw
6
- import pytz
7
- from datetime import datetime
8
- from skimage import filters
9
-
10
- class WeightDetector:
11
- def __init__(self):
12
- """OCR optimized for 7-segment displays"""
13
- self.reader = easyocr.Reader(
14
- ['en'],
15
- gpu=True,
16
- model_storage_directory='model',
17
- download_enabled=True,
18
- recog_network='english_g2' # Better for digital displays
19
- )
20
- self.ist = pytz.timezone('Asia/Kolkata')
21
-
22
- def get_current_ist(self) -> str:
23
- """Get current IST time"""
24
- return datetime.now(self.ist).strftime('%Y-%m-%d %H:%M:%S IST')
25
-
26
- def is_blurry(self, image: np.ndarray, threshold=100) -> bool:
27
- """Check if image is blurry using Laplacian variance"""
28
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
29
- variance = cv2.Laplacian(gray, cv2.CV_64F).var()
30
- return variance < threshold
31
-
32
- def preprocess_7segment(self, image: np.ndarray) -> np.ndarray:
33
- """Optimized preprocessing for 7-segment displays"""
34
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
35
-
36
- # Adaptive thresholding for digital displays
37
- thresh = cv2.adaptiveThreshold(
38
- gray, 255,
39
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
40
- cv2.THRESH_BINARY_INV, 11, 2
41
- )
42
-
43
- # Remove small noise
44
- kernel = np.ones((2, 2), np.uint8)
45
- cleaned = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
46
-
47
- return cleaned
48
-
49
- def extract_weight(self, text: str) -> Optional[float]:
50
- """Extract weight value (handles decimals, units like g/kg)"""
51
- text = text.replace(" ", "").replace(",", ".")
52
-
53
- # Patterns for digital scales (e.g., "0.000g", "12.34 kg")
54
- patterns = [
55
- r'(\d+\.\d+)\s*[gGkK]', # 12.34g or 12.34kg
56
- r'(\d+)\s*[gGkK]', # 123g or 123kg
57
- r'(\d+\.\d+)', # Decimal only
58
- r'(\d+)' # Whole number
59
- ]
60
-
61
- for pattern in patterns:
62
- match = re.search(pattern, text)
63
- if match:
64
- try:
65
- value = float(match.group(1))
66
- if 'k' in text.lower(): # Convert kg to g
67
- return value * 1000
68
- return value
69
- except ValueError:
70
- continue
71
- return None
72
-
73
- def detect_weight(self, image_path: str) -> dict:
74
- """Detect weight from image with error checks"""
75
- try:
76
- img = Image.open(image_path).convert("RGB")
77
- img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
78
-
79
- # Check for blur
80
- if self.is_blurry(img_cv):
81
- return {
82
- "weight": None,
83
- "message": "⚠️ Image is blurry! Ensure clear focus.",
84
- "image": img,
85
- "time": self.get_current_ist()
86
- }
87
-
88
- # Preprocess for 7-segment digits
89
- processed = self.preprocess_7segment(img_cv)
90
-
91
- # OCR with 7-segment optimization
92
- results = self.reader.readtext(
93
- processed,
94
- allowlist='0123456789.gkGKlL',
95
- paragraph=False,
96
- text_threshold=0.7,
97
- width_ths=1.5
98
- )
99
-
100
- # Extract and validate weights
101
- detected_weights = []
102
- for (bbox, text, prob) in results:
103
- weight = self.extract_weight(text)
104
- if weight and prob > 0.5: # Minimum confidence
105
- detected_weights.append({
106
- "weight": weight,
107
- "text": text,
108
- "probability": prob,
109
- "bbox": bbox
110
- })
111
-
112
- # Select best match (highest confidence + largest area)
113
- if detected_weights:
114
- detected_weights.sort(
115
- key=lambda x: (x["probability"],
116
- (x["bbox"][2][0] - x["bbox"][0][0]) * # Width
117
- (x["bbox"][2][1] - x["bbox"][0][1])), # Height
118
- reverse=True
119
- )
120
- best_match = detected_weights[0]
121
-
122
- # Draw annotations
123
- draw = ImageDraw.Draw(img)
124
- for item in detected_weights:
125
- bbox = item["bbox"]
126
- polygon = [(int(x), int(y)) for [x, y] in bbox]
127
- color = "green" if item == best_match else "red"
128
- draw.polygon(polygon, outline=color, width=2)
129
- label = f"{item['weight']}g (Conf: {item['probability']:.2f})"
130
- draw.text((polygon[0][0], polygon[0][1] - 15), label, fill=color)
131
-
132
- # Add timestamp
133
- draw.text((10, 10), f"Time: {self.get_current_ist()}", fill="blue")
134
-
135
- return {
136
- "weight": best_match["weight"],
137
- "message": f"✅ Detected: {best_match['weight']}g (Conf: {best_match['probability']:.2f})",
138
- "image": img,
139
- "time": self.get_current_ist()
140
- }
141
-
142
- return {
143
- "weight": None,
144
- "message": "❌ No weight detected. Ensure clear 7-segment digits.",
145
- "image": img,
146
- "time": self.get_current_ist()
147
- }
148
-
149
- except Exception as e:
150
- return {
151
- "weight": None,
152
- "message": f"⚠️ Error: {str(e)}",
153
- "image": None,
154
- "time": self.get_current_ist()
155
- }