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) |