Spaces:
Runtime error
Runtime error
import gradio as gr | |
from PIL import Image, ImageEnhance, ImageOps | |
import cv2 | |
import numpy as np | |
from datetime import datetime | |
import pytz | |
import re | |
import easyocr | |
import pytesseract | |
import logging | |
# Set up logging | |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') | |
# Initialize OCR engines | |
try: | |
reader = easyocr.Reader(['en']) | |
logging.info("EasyOCR initialized successfully") | |
except Exception as e: | |
logging.error(f"Failed to initialize EasyOCR: {str(e)}") | |
reader = None | |
try: | |
# Verify Tesseract is installed | |
pytesseract.pytesseract.tesseract_cmd = r'/usr/bin/tesseract' # Adjust path if needed | |
logging.info("Tesseract initialized successfully") | |
except Exception as e: | |
logging.error(f"Failed to initialize Tesseract: {str(e)}") | |
pytesseract = None | |
# Image enhancement functions | |
def enhance_image(image): | |
try: | |
image = image.convert("L") | |
image = ImageEnhance.Contrast(image).enhance(3.0) | |
image = ImageEnhance.Sharpness(image).enhance(2.0) | |
image = image.resize((image.width * 3, image.height * 3), Image.Resampling.LANCZOS) | |
image = image.convert("RGB") | |
return image | |
except Exception as e: | |
logging.error(f"Error in enhance_image: {str(e)}") | |
return image | |
def apply_clahe(image): | |
try: | |
gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY) | |
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8)) | |
cl1 = clahe.apply(gray) | |
return Image.fromarray(cv2.cvtColor(cl1, cv2.COLOR_GRAY2RGB)) | |
except Exception as e: | |
logging.error(f"Error in apply_clahe: {str(e)}") | |
return image | |
def preprocess_7segment(img): | |
try: | |
np_img = np.array(img.convert("L")) | |
blurred = cv2.GaussianBlur(np_img, (3, 3), 0) | |
thresh = cv2.adaptiveThreshold( | |
blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, | |
cv2.THRESH_BINARY_INV, 15, 3 | |
) | |
kernel = np.ones((2, 2), np.uint8) | |
thresh = cv2.dilate(thresh, kernel, iterations=1) | |
scaled = cv2.resize(thresh, None, fx=3.0, fy=3.0, interpolation=cv2.INTER_LINEAR) | |
return Image.fromarray(cv2.cvtColor(scaled, cv2.COLOR_GRAY2RGB)) | |
except Exception as e: | |
logging.error(f"Error in preprocess_7segment: {str(e)}") | |
return img | |
def denoise_image(image): | |
try: | |
np_img = np.array(image) | |
denoised = cv2.fastNlMeansDenoisingColored(np_img, h=10, hColor=10, templateWindowSize=7, searchWindowSize=21) | |
return Image.fromarray(denoised) | |
except Exception as e: | |
logging.error(f"Error in denoise_image: {str(e)}") | |
return image | |
def recognize_7segment(image): | |
try: | |
gray = np.array(image.convert("L")) | |
_, binary = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) | |
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
contours = sorted(contours, key=lambda x: cv2.boundingRect(x)[0]) | |
digits = [] | |
for contour in contours: | |
x, y, w, h = cv2.boundingRect(contour) | |
if w < 10 or h < 10: | |
continue | |
roi = binary[y:y+h, x:x+w] | |
segment_count = np.sum(roi == 255) / (w * h) | |
if segment_count > 0.5: | |
digits.append("8") | |
elif segment_count > 0.3: | |
digits.append("7") | |
else: | |
digits.append("1") | |
text = "".join(digits) | |
if len(contours) > len(digits): | |
text = text[:2] + "." + text[2:] | |
return text | |
except Exception as e: | |
logging.error(f"Error in recognize_7segment: {str(e)}") | |
return "" | |
def detect_weight(image): | |
try: | |
if image is None: | |
logging.error("No image provided") | |
return "Error: No image provided", None | |
best_confidence = 0.0 | |
best_text = "" | |
weight = None | |
# Apply preprocessing variants | |
variants = [ | |
enhance_image(image), | |
apply_clahe(image), | |
preprocess_7segment(image), | |
denoise_image(image) | |
] | |
# EasyOCR processing | |
if reader: | |
for variant in variants: | |
try: | |
img_np = np.array(variant) | |
result = reader.readtext(img_np) | |
for detection in result: | |
text = detection[1] | |
confidence = detection[2] | |
logging.info(f"Detected Text (EasyOCR): {text}, Confidence: {confidence}") | |
match = re.search(r"(\d{1,4}(?:\.\d{1,2})?)", text) | |
if match and confidence > best_confidence: | |
weight = match.group(1) | |
best_confidence = confidence | |
best_text = text | |
except Exception as e: | |
logging.error(f"Error in EasyOCR processing: {str(e)}") | |
# Tesseract fallback if EasyOCR fails or is unavailable | |
if not weight and pytesseract: | |
for variant in variants: | |
try: | |
img_np = np.array(variant) | |
text = pytesseract.image_to_string(img_np, config='--psm 6 digits') | |
logging.info(f"Detected Text (Tesseract): {text}") | |
match = re.search(r"(\d{1,4}(?:\.\d{1,2})?)", text) | |
if match: | |
weight = match.group(1) | |
best_text = text | |
except Exception as e: | |
logging.error(f"Error in Tesseract processing: {str(e)}") | |
# Manual 7-segment recognition fallback | |
if not weight: | |
logging.info("OCR failed, trying manual 7-segment recognition...") | |
variant = preprocess_7segment(image) | |
manual_text = recognize_7segment(variant) | |
logging.info(f"Manual 7-segment recognition result: {manual_text}") | |
match = re.search(r"(\d{1,4}(?:\.\d{1,2})?)", manual_text) | |
if match: | |
weight = match.group(1) | |
best_text = manual_text | |
weight = weight if weight else "Not detected" | |
ist = pytz.timezone('Asia/Kolkata') | |
current_time = datetime.now(ist).strftime("%Y-%m-%d %H:%M:%S") | |
return f"Weight: {weight} kg\nCaptured At: {current_time} (IST)", image | |
except Exception as e: | |
logging.error(f"Error in detect_weight: {str(e)}") | |
return f"Error: {str(e)}", image | |
# Gradio UI | |
interface = gr.Interface( | |
fn=detect_weight, | |
inputs=gr.Image(type="pil", label="Upload or Capture Image"), | |
outputs=[gr.Textbox(label="Weight Info"), gr.Image(label="Snapshot")], | |
title="⚖️ Auto Weight Detector (EasyOCR + Tesseract + 7-Segment Fallback)", | |
description="OCR pipeline using EasyOCR and Tesseract with 7-segment display optimization." | |
) | |
if __name__ == "__main__": | |
interface.launch(server_port=8080) |