Sanjayraju30 commited on
Commit
cc6391c
·
verified ·
1 Parent(s): bc09f12

Update weight_detector.py

Browse files
Files changed (1) hide show
  1. weight_detector.py +91 -43
weight_detector.py CHANGED
@@ -4,64 +4,93 @@ import easyocr
4
  import re
5
  from typing import Tuple, List, Optional
6
  from PIL import Image, ImageDraw
 
 
7
 
8
  class WeightDetector:
9
  def __init__(self):
10
- """Initialize the OCR reader with English language support"""
11
- self.reader = easyocr.Reader(['en'])
 
 
 
 
 
 
12
 
13
- def preprocess_image(self, image_path: str) -> np.ndarray:
14
- """Preprocess the image for better OCR results"""
15
- img = cv2.imread(image_path)
16
- if img is None:
17
- raise ValueError("Could not read image from path")
18
-
19
  # Convert to grayscale
20
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
21
 
22
- # Apply adaptive thresholding
23
- processed = cv2.adaptiveThreshold(
24
- gray, 255,
25
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
26
- cv2.THRESH_BINARY, 11, 2
27
- )
 
 
 
 
28
 
29
- return processed
30
 
31
  def extract_weight_value(self, text: str) -> Optional[float]:
32
- """Extract weight value from text using regex patterns"""
33
- # Common weight patterns: 12.34g, 56.78 kg, 90.12 lbs, etc.
 
 
 
34
  patterns = [
35
- r'(\d+\.\d+)\s*(g|kg|grams|kilograms|lb|lbs|pounds)',
36
- r'(\d+)\s*(g|kg|grams|kilograms|lb|lbs|pounds)',
37
- r'(\d+\.\d+)', # Just numbers with decimal
38
- r'(\d+)' # Just whole numbers
39
  ]
40
 
41
  for pattern in patterns:
42
- match = re.search(pattern, text, re.IGNORECASE)
43
  if match:
44
  try:
45
- return float(match.group(1))
 
 
 
 
46
  except ValueError:
47
  continue
48
  return None
49
 
50
- def detect_weight(self, image_path: str) -> Tuple[Optional[float], List[dict], Image.Image]:
51
- """Detect weight from an image and return value, metadata, and annotated image"""
52
  try:
53
- # Read and preprocess image
54
  img = Image.open(image_path).convert("RGB")
55
  img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
56
 
57
- # Perform OCR
58
- results = self.reader.readtext(img_cv)
 
 
 
 
 
 
 
 
 
 
59
 
60
- # Find the most likely weight value
61
  detected_weights = []
62
  for (bbox, text, prob) in results:
63
  weight = self.extract_weight_value(text)
64
- if weight is not None:
65
  detected_weights.append({
66
  'weight': weight,
67
  'text': text,
@@ -69,26 +98,45 @@ class WeightDetector:
69
  'bbox': bbox
70
  })
71
 
72
- # Sort by probability and get the highest
 
 
 
73
  if detected_weights:
74
- detected_weights.sort(key=lambda x: x['probability'], reverse=True)
 
 
 
 
 
 
 
 
 
75
  best_match = detected_weights[0]
76
 
77
- # Draw bounding boxes on image
78
- draw = ImageDraw.Draw(img)
79
  for item in detected_weights:
80
  bbox = item['bbox']
81
- # Convert bbox coordinates to tuple of tuples
82
  polygon = [(int(x), int(y)) for [x, y] in bbox]
83
- draw.polygon(polygon, outline="red", width=2)
84
- # Add text label
85
  label = f"{item['weight']}g (p={item['probability']:.2f})"
86
- draw.text((polygon[0][0], polygon[0][1] - 10), label, fill="red")
87
 
88
- return best_match['weight'], detected_weights, img
 
89
 
90
- return None, [], img
 
 
 
 
91
 
92
  except Exception as e:
93
- print(f"Error processing image: {e}")
94
- return None, [], Image.new("RGB", (100, 100), color="white")
 
 
 
 
 
4
  import re
5
  from typing import Tuple, List, Optional
6
  from PIL import Image, ImageDraw
7
+ import pytz
8
+ from datetime import datetime
9
 
10
  class WeightDetector:
11
  def __init__(self):
12
+ """Initialize with English and optimized settings"""
13
+ self.reader = easyocr.Reader(
14
+ ['en'],
15
+ gpu=True,
16
+ model_storage_directory='model',
17
+ download_enabled=True
18
+ )
19
+ self.ist = pytz.timezone('Asia/Kolkata')
20
 
21
+ def get_current_ist(self) -> str:
22
+ """Get current time in Indian Standard Time"""
23
+ return datetime.now(self.ist).strftime('%Y-%m-%d %H:%M:%S %Z')
24
+
25
+ def preprocess_image(self, image: np.ndarray) -> np.ndarray:
26
+ """Enhanced image preprocessing for digital displays"""
27
  # Convert to grayscale
28
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
29
 
30
+ # Contrast enhancement
31
+ clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
32
+ contrast_enhanced = clahe.apply(gray)
33
+
34
+ # Thresholding for digital displays
35
+ _, thresh = cv2.threshold(contrast_enhanced, 0, 255,
36
+ cv2.THRESH_BINARY + cv2.THRESH_OTSU)
37
+
38
+ # Noise reduction
39
+ denoised = cv2.medianBlur(thresh, 3)
40
 
41
+ return denoised
42
 
43
  def extract_weight_value(self, text: str) -> Optional[float]:
44
+ """Improved weight extraction with better pattern matching"""
45
+ # Clean the text
46
+ text = text.replace(' ', '').replace(',', '.').lower()
47
+
48
+ # Patterns for digital scale displays
49
  patterns = [
50
+ r'(\d+\.\d+)[gkl]', # 12.34g or 12.34kg
51
+ r'(\d+)[gkl]', # 123g or 123kg
52
+ r'(\d+\.\d+)', # Just numbers with decimal
53
+ r'(\d+)' # Just whole numbers
54
  ]
55
 
56
  for pattern in patterns:
57
+ match = re.search(pattern, text)
58
  if match:
59
  try:
60
+ value = float(match.group(1))
61
+ # Assume grams if no unit specified
62
+ if 'k' in text:
63
+ return value * 1000 # Convert kg to g
64
+ return value
65
  except ValueError:
66
  continue
67
  return None
68
 
69
+ def detect_weight(self, image_path: str) -> Tuple[Optional[float], str, Image.Image]:
70
+ """Enhanced weight detection with better error handling"""
71
  try:
72
+ # Read image
73
  img = Image.open(image_path).convert("RGB")
74
  img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
75
 
76
+ # Preprocess
77
+ processed = self.preprocess_image(img_cv)
78
+
79
+ # OCR with configuration optimized for digital displays
80
+ results = self.reader.readtext(
81
+ processed,
82
+ paragraph=False,
83
+ detail=1,
84
+ allowlist='0123456789.gkGlL',
85
+ width_ths=2.0,
86
+ text_threshold=0.7
87
+ )
88
 
89
+ # Process all potential weight values
90
  detected_weights = []
91
  for (bbox, text, prob) in results:
92
  weight = self.extract_weight_value(text)
93
+ if weight is not None and prob > 0.4: # Minimum confidence
94
  detected_weights.append({
95
  'weight': weight,
96
  'text': text,
 
98
  'bbox': bbox
99
  })
100
 
101
+ # Prepare output
102
+ draw = ImageDraw.Draw(img)
103
+ current_time = self.get_current_ist()
104
+
105
  if detected_weights:
106
+ # Sort by probability and area (larger text is more likely the weight)
107
+ detected_weights.sort(
108
+ key=lambda x: (
109
+ x['probability'],
110
+ (x['bbox'][2][0] - x['bbox'][0][0]) * # Width
111
+ (x['bbox'][2][1] - x['bbox'][0][1]) # Height
112
+ ),
113
+ reverse=True
114
+ )
115
+
116
  best_match = detected_weights[0]
117
 
118
+ # Draw all detections
 
119
  for item in detected_weights:
120
  bbox = item['bbox']
 
121
  polygon = [(int(x), int(y)) for [x, y] in bbox]
122
+ color = "green" if item == best_match else "red"
123
+ draw.polygon(polygon, outline=color, width=2)
124
  label = f"{item['weight']}g (p={item['probability']:.2f})"
125
+ draw.text((polygon[0][0], polygon[0][1] - 15), label, fill=color)
126
 
127
+ # Add timestamp to image
128
+ draw.text((10, 10), f"Captured at: {current_time}", fill="blue")
129
 
130
+ return best_match['weight'], current_time, img
131
+
132
+ # No weight detected
133
+ draw.text((10, 10), f"Captured at: {current_time}", fill="blue")
134
+ return None, current_time, img
135
 
136
  except Exception as e:
137
+ current_time = self.get_current_ist()
138
+ error_img = Image.new("RGB", (300, 100), color="white")
139
+ draw = ImageDraw.Draw(error_img)
140
+ draw.text((10, 10), f"Error: {str(e)}", fill="red")
141
+ draw.text((10, 30), f"Time: {current_time}", fill="blue")
142
+ return None, current_time, error_img