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)