Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -8,68 +8,39 @@ from datetime import datetime
|
|
8 |
import pytz
|
9 |
import numpy as np
|
10 |
import logging
|
11 |
-
import os
|
12 |
|
13 |
# Set up logging
|
14 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
15 |
|
16 |
# Configure Tesseract path
|
17 |
try:
|
18 |
-
pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract' # Adjust
|
19 |
pytesseract.get_tesseract_version() # Test Tesseract availability
|
20 |
logging.info("Tesseract is available")
|
21 |
except Exception as e:
|
22 |
logging.error(f"Tesseract not found or misconfigured: {str(e)}")
|
23 |
|
|
|
24 |
def preprocess_image(img_cv):
|
25 |
"""Preprocess image for OCR: enhance contrast, reduce noise, and apply adaptive thresholding."""
|
26 |
try:
|
27 |
# Convert to grayscale
|
28 |
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
29 |
-
# Enhance contrast
|
30 |
-
clahe = cv2.createCLAHE(clipLimit=
|
31 |
contrast = clahe.apply(gray)
|
32 |
# Reduce noise with Gaussian blur
|
33 |
blurred = cv2.GaussianBlur(contrast, (5, 5), 0)
|
34 |
# Apply adaptive thresholding for better binary image representation
|
35 |
-
thresh = cv2.adaptiveThreshold(blurred, 255, cv2.
|
36 |
-
# Sharpen the image to
|
37 |
-
|
38 |
-
sharpened = cv2.filter2D(thresh, -1, kernel)
|
39 |
return sharpened
|
40 |
except Exception as e:
|
41 |
logging.error(f"Image preprocessing failed: {str(e)}")
|
42 |
return img_cv
|
43 |
|
44 |
-
|
45 |
-
"""Detect the region of interest (ROI) containing the weight display."""
|
46 |
-
try:
|
47 |
-
# Convert to grayscale for edge detection
|
48 |
-
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
49 |
-
# Apply edge detection
|
50 |
-
edges = cv2.Canny(gray, 50, 150)
|
51 |
-
# Find contours
|
52 |
-
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
53 |
-
if not contours:
|
54 |
-
logging.warning("No contours detected for ROI")
|
55 |
-
return img_cv # Return full image if no contours found
|
56 |
-
|
57 |
-
# Find the largest contour (assuming it’s the display)
|
58 |
-
largest_contour = max(contours, key=cv2.contourArea)
|
59 |
-
x, y, w, h = cv2.boundingRect(largest_contour)
|
60 |
-
# Add padding to the detected region to ensure weight is fully captured
|
61 |
-
padding = 10
|
62 |
-
x = max(0, x - padding)
|
63 |
-
y = max(0, y - padding)
|
64 |
-
w = min(img_cv.shape[1] - x, w + 2 * padding)
|
65 |
-
h = min(img_cv.shape[0] - y, h + 2 * padding)
|
66 |
-
roi = img_cv[y:y+h, x:x+w]
|
67 |
-
logging.info(f"ROI detected at ({x}, {y}, {w}, {h})")
|
68 |
-
return roi
|
69 |
-
except Exception as e:
|
70 |
-
logging.error(f"ROI detection failed: {str(e)}")
|
71 |
-
return img_cv
|
72 |
-
|
73 |
def extract_weight(img):
|
74 |
"""Extract weight from image using Tesseract OCR with improved configuration."""
|
75 |
try:
|
@@ -79,10 +50,8 @@ def extract_weight(img):
|
|
79 |
|
80 |
# Convert PIL image to OpenCV format
|
81 |
img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
|
82 |
-
#
|
83 |
-
|
84 |
-
# Preprocess the ROI
|
85 |
-
processed_img = preprocess_image(roi_img)
|
86 |
|
87 |
# OCR configuration for digit extraction
|
88 |
custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789.'
|
@@ -91,12 +60,12 @@ def extract_weight(img):
|
|
91 |
text = pytesseract.image_to_string(processed_img, config=custom_config)
|
92 |
logging.info(f"OCR result: '{text}'")
|
93 |
|
94 |
-
# Extract valid weight from OCR result
|
95 |
weight = ''.join(filter(lambda x: x in '0123456789.', text.strip()))
|
96 |
if weight:
|
97 |
try:
|
98 |
weight_float = float(weight)
|
99 |
-
if weight_float >= 0
|
100 |
confidence = 95.0 # Assume high confidence if we have a valid weight
|
101 |
logging.info(f"Weight detected: {weight} (Confidence: {confidence:.2f}%)")
|
102 |
return weight, confidence, processed_img
|
@@ -109,20 +78,24 @@ def extract_weight(img):
|
|
109 |
logging.error(f"OCR processing failed: {str(e)}")
|
110 |
return "Not detected", 0.0, None
|
111 |
|
|
|
112 |
def process_image(img):
|
113 |
"""Process uploaded or captured image and extract weight."""
|
114 |
if img is None:
|
115 |
logging.error("No image provided")
|
116 |
return "No image uploaded", None, gr.update(visible=False), gr.update(visible=False)
|
117 |
|
|
|
118 |
ist_time = datetime.now(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y %I:%M:%S %p")
|
|
|
|
|
119 |
weight, confidence, processed_img = extract_weight(img)
|
120 |
|
121 |
if weight == "Not detected" or confidence < 95.0:
|
122 |
logging.warning(f"Weight detection failed: {weight} (Confidence: {confidence:.2f}%)")
|
123 |
return f"{weight} (Confidence: {confidence:.2f}%)", ist_time, gr.update(visible=True), gr.update(visible=False)
|
124 |
|
125 |
-
# Convert processed image
|
126 |
pil_image = Image.fromarray(processed_img)
|
127 |
buffered = io.BytesIO()
|
128 |
pil_image.save(buffered, format="PNG")
|
|
|
8 |
import pytz
|
9 |
import numpy as np
|
10 |
import logging
|
|
|
11 |
|
12 |
# Set up logging
|
13 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
14 |
|
15 |
# Configure Tesseract path
|
16 |
try:
|
17 |
+
pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract' # Adjust path if needed
|
18 |
pytesseract.get_tesseract_version() # Test Tesseract availability
|
19 |
logging.info("Tesseract is available")
|
20 |
except Exception as e:
|
21 |
logging.error(f"Tesseract not found or misconfigured: {str(e)}")
|
22 |
|
23 |
+
# Preprocessing function
|
24 |
def preprocess_image(img_cv):
|
25 |
"""Preprocess image for OCR: enhance contrast, reduce noise, and apply adaptive thresholding."""
|
26 |
try:
|
27 |
# Convert to grayscale
|
28 |
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
29 |
+
# Enhance contrast using CLAHE (Contrast Limited Adaptive Histogram Equalization)
|
30 |
+
clahe = cv2.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))
|
31 |
contrast = clahe.apply(gray)
|
32 |
# Reduce noise with Gaussian blur
|
33 |
blurred = cv2.GaussianBlur(contrast, (5, 5), 0)
|
34 |
# Apply adaptive thresholding for better binary image representation
|
35 |
+
thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
|
36 |
+
# Sharpen the image to enhance details
|
37 |
+
sharpened = cv2.filter2D(thresh, -1, np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]))
|
|
|
38 |
return sharpened
|
39 |
except Exception as e:
|
40 |
logging.error(f"Image preprocessing failed: {str(e)}")
|
41 |
return img_cv
|
42 |
|
43 |
+
# Function to extract weight using OCR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
def extract_weight(img):
|
45 |
"""Extract weight from image using Tesseract OCR with improved configuration."""
|
46 |
try:
|
|
|
50 |
|
51 |
# Convert PIL image to OpenCV format
|
52 |
img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
|
53 |
+
# Preprocess the image
|
54 |
+
processed_img = preprocess_image(img_cv)
|
|
|
|
|
55 |
|
56 |
# OCR configuration for digit extraction
|
57 |
custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789.'
|
|
|
60 |
text = pytesseract.image_to_string(processed_img, config=custom_config)
|
61 |
logging.info(f"OCR result: '{text}'")
|
62 |
|
63 |
+
# Extract valid weight from OCR result (strip unwanted characters)
|
64 |
weight = ''.join(filter(lambda x: x in '0123456789.', text.strip()))
|
65 |
if weight:
|
66 |
try:
|
67 |
weight_float = float(weight)
|
68 |
+
if weight_float >= 0: # Only accept valid weights
|
69 |
confidence = 95.0 # Assume high confidence if we have a valid weight
|
70 |
logging.info(f"Weight detected: {weight} (Confidence: {confidence:.2f}%)")
|
71 |
return weight, confidence, processed_img
|
|
|
78 |
logging.error(f"OCR processing failed: {str(e)}")
|
79 |
return "Not detected", 0.0, None
|
80 |
|
81 |
+
# Main function to process image and display results
|
82 |
def process_image(img):
|
83 |
"""Process uploaded or captured image and extract weight."""
|
84 |
if img is None:
|
85 |
logging.error("No image provided")
|
86 |
return "No image uploaded", None, gr.update(visible=False), gr.update(visible=False)
|
87 |
|
88 |
+
# Get the current time in IST format
|
89 |
ist_time = datetime.now(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y %I:%M:%S %p")
|
90 |
+
|
91 |
+
# Extract weight and confidence from the image
|
92 |
weight, confidence, processed_img = extract_weight(img)
|
93 |
|
94 |
if weight == "Not detected" or confidence < 95.0:
|
95 |
logging.warning(f"Weight detection failed: {weight} (Confidence: {confidence:.2f}%)")
|
96 |
return f"{weight} (Confidence: {confidence:.2f}%)", ist_time, gr.update(visible=True), gr.update(visible=False)
|
97 |
|
98 |
+
# Convert processed image to base64 for display
|
99 |
pil_image = Image.fromarray(processed_img)
|
100 |
buffered = io.BytesIO()
|
101 |
pil_image.save(buffered, format="PNG")
|