Sanjayraju30 commited on
Commit
5234a64
·
verified ·
1 Parent(s): 13f40de

Update ocr_engine.py

Browse files
Files changed (1) hide show
  1. ocr_engine.py +84 -24
ocr_engine.py CHANGED
@@ -2,69 +2,129 @@ import easyocr
2
  import numpy as np
3
  import cv2
4
  import re
5
-
6
- reader = easyocr.Reader(['en'], gpu=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  def enhance_image(img):
9
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
 
10
 
11
- # CLAHE (adaptive histogram equalization for better contrast)
12
- clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
13
- contrast = clahe.apply(gray)
14
 
15
- # Sharpen image
16
- kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
17
- sharpened = cv2.filter2D(contrast, -1, kernel)
18
 
19
- # Resize if very small
20
- h, w = sharpened.shape
21
- if max(h, w) < 500:
22
- sharpened = cv2.resize(sharpened, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
23
 
24
- return sharpened
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  def extract_weight_from_image(pil_img):
27
  try:
28
  img = np.array(pil_img)
29
- img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) # convert from PIL to OpenCV BGR
 
 
 
 
30
 
31
  # Preprocess image
32
  processed = enhance_image(img)
33
 
34
- results = reader.readtext(processed)
35
-
36
  best_weight = None
37
  best_conf = 0.0
38
 
39
- for (bbox, text, conf) in results:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  original_text = text
41
  text = text.lower().strip()
42
 
43
  # Fix common OCR errors
44
- text = text.replace(",", ".")
45
  text = text.replace("o", "0").replace("O", "0")
46
  text = text.replace("s", "5").replace("S", "5")
47
  text = text.replace("g", "9").replace("G", "6")
48
- text = text.replace("kgs", "").replace("kg", "")
 
 
49
  text = re.sub(r"[^\d\.]", "", text)
50
 
51
- if re.fullmatch(r"\d{1,4}(\.\d{1,3})?", text):
52
- if conf > best_conf:
 
53
  best_weight = text
54
  best_conf = conf
55
 
56
  if not best_weight:
 
57
  return "Not detected", 0.0
58
 
59
  # Format output
60
  if "." in best_weight:
61
  int_part, dec_part = best_weight.split(".")
62
  int_part = int_part.lstrip("0") or "0"
63
- best_weight = f"{int_part}.{dec_part}"
64
  else:
65
  best_weight = best_weight.lstrip("0") or "0"
66
 
67
  return best_weight, round(best_conf * 100, 2)
68
 
69
  except Exception as e:
70
- return f"Error: {str(e)}", 0.0
 
 
2
  import numpy as np
3
  import cv2
4
  import re
5
+ import logging
6
+ from mmocr.utils.ocr import MMOCR
7
+
8
+ # Set up logging for debugging
9
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
10
+
11
+ # Initialize OCR engines
12
+ easyocr_reader = easyocr.Reader(['en'], gpu=False)
13
+ try:
14
+ mmocr_reader = MMOCR(det='DB_r18', recog='CRNN')
15
+ except:
16
+ mmocr_reader = None
17
+ logging.warning("MMOCR initialization failed, falling back to EasyOCR only")
18
+
19
+ def estimate_blur(img):
20
+ """Estimate image blur using Laplacian variance"""
21
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
22
+ return cv2.Laplacian(gray, cv2.CV_64F).var()
23
 
24
  def enhance_image(img):
25
+ try:
26
+ # Convert to grayscale
27
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
28
 
29
+ # Bilateral filter for noise reduction while preserving edges
30
+ denoised = cv2.bilateralFilter(gray, d=9, sigmaColor=75, sigmaSpace=75)
 
31
 
32
+ # CLAHE for contrast enhancement
33
+ clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
34
+ contrast = clahe.apply(denoised)
35
 
36
+ # Adaptive thresholding for uneven lighting
37
+ thresh = cv2.adaptiveThreshold(contrast, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
38
+ cv2.THRESH_BINARY, 11, 2)
 
39
 
40
+ # Morphological operations to enhance text
41
+ kernel = np.ones((3, 3), np.uint8)
42
+ morphed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)
43
+
44
+ # Sharpen image
45
+ sharpen_kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
46
+ sharpened = cv2.filter2D(morphed, -1, sharpen_kernel)
47
+
48
+ # Dynamic resizing
49
+ h, w = sharpened.shape
50
+ target_size = 800 # Target max dimension for OCR
51
+ scale_factor = min(target_size / max(h, w), 2.0) if max(h, w) < 300 else min(target_size / max(h, w), 1.0)
52
+ if scale_factor != 1.0:
53
+ sharpened = cv2.resize(sharpened, None, fx=scale_factor, fy=scale_factor,
54
+ interpolation=cv2.INTER_CUBIC if scale_factor > 1 else cv2.INTER_AREA)
55
+
56
+ return sharpened
57
+ except Exception as e:
58
+ logging.error(f"Image enhancement failed: {str(e)}")
59
+ return img # Return original image as fallback
60
 
61
  def extract_weight_from_image(pil_img):
62
  try:
63
  img = np.array(pil_img)
64
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
65
+
66
+ # Estimate blur to adjust confidence threshold
67
+ blur_score = estimate_blur(img)
68
+ conf_threshold = 0.3 if blur_score < 100 else 0.5 # Lower threshold for blurry images
69
 
70
  # Preprocess image
71
  processed = enhance_image(img)
72
 
73
+ # Initialize results
 
74
  best_weight = None
75
  best_conf = 0.0
76
 
77
+ # EasyOCR detection
78
+ easyocr_results = easyocr_reader.readtext(processed, detail=1, paragraph=False)
79
+ if not easyocr_results: # Fallback to original image if no results
80
+ easyocr_results = easyocr_reader.readtext(img, detail=1, paragraph=False)
81
+
82
+ # MMOCR detection (if available)
83
+ mmocr_results = []
84
+ if mmocr_reader:
85
+ try:
86
+ mmocr_result = mmocr_reader.readtext(processed)
87
+ mmocr_results = [(bbox, text, score) for bbox, text, score in mmocr_result]
88
+ except:
89
+ logging.warning("MMOCR processing failed, using EasyOCR results only")
90
+
91
+ # Combine results
92
+ all_results = easyocr_results + mmocr_results
93
+
94
+ for (bbox, text, conf) in all_results:
95
  original_text = text
96
  text = text.lower().strip()
97
 
98
  # Fix common OCR errors
99
+ text = text.replace(",", ".").replace(";", ".")
100
  text = text.replace("o", "0").replace("O", "0")
101
  text = text.replace("s", "5").replace("S", "5")
102
  text = text.replace("g", "9").replace("G", "6")
103
+ text = text.replace("l", "1").replace("I", "1")
104
+ text = text.replace("b", "8").replace("B", "8")
105
+ text = text.replace("kgs", "").replace("kg", "").replace("k9", "").replace("k", "")
106
  text = re.sub(r"[^\d\.]", "", text)
107
 
108
+ # Stricter regex for weight (0.0 to 9999.999)
109
+ if re.fullmatch(r"\d{1,4}(\.\d{0,3})?", text):
110
+ if conf > best_conf and conf > conf_threshold:
111
  best_weight = text
112
  best_conf = conf
113
 
114
  if not best_weight:
115
+ logging.info("No valid weight detected")
116
  return "Not detected", 0.0
117
 
118
  # Format output
119
  if "." in best_weight:
120
  int_part, dec_part = best_weight.split(".")
121
  int_part = int_part.lstrip("0") or "0"
122
+ best_weight = f"{int_part}.{dec_part.rstrip('0')}"
123
  else:
124
  best_weight = best_weight.lstrip("0") or "0"
125
 
126
  return best_weight, round(best_conf * 100, 2)
127
 
128
  except Exception as e:
129
+ logging.error(f"Weight extraction failed: {str(e)}")
130
+ return "Not detected", 0.0