File size: 5,605 Bytes
0507081
1a5f8fd
 
1d1e3da
 
 
1a5f8fd
 
 
87a883e
1d1e3da
71f6c9d
1d1e3da
 
71f6c9d
49bdc4d
71f6c9d
 
1ff656a
49bdc4d
 
1a5f8fd
71f6c9d
49bdc4d
71f6c9d
49bdc4d
71f6c9d
49bdc4d
1ff656a
71f6c9d
0b5db95
49bdc4d
1ff656a
71f6c9d
49bdc4d
1ff656a
71f6c9d
0b5db95
1ff656a
71f6c9d
0b5db95
49bdc4d
 
 
87a883e
49bdc4d
71f6c9d
1a5f8fd
71f6c9d
1a5f8fd
49bdc4d
 
3caa343
49bdc4d
71f6c9d
1a5f8fd
1ff656a
71f6c9d
0b5db95
49bdc4d
71f6c9d
c0652ff
49bdc4d
71f6c9d
c0652ff
 
 
71f6c9d
c0652ff
 
49bdc4d
 
1ff656a
71f6c9d
49bdc4d
3caa343
49bdc4d
1ff656a
49bdc4d
c0652ff
3caa343
1a5f8fd
 
3caa343
1a5f8fd
71f6c9d
0507081
71f6c9d
0507081
1ff656a
3caa343
5699ebb
71f6c9d
0507081
0b5db95
1ff656a
3caa343
5699ebb
71f6c9d
1a5f8fd
49bdc4d
3caa343
5699ebb
71f6c9d
3caa343
 
 
 
 
 
06308c8
71f6c9d
0507081
 
1d1e3da
06308c8
0507081
58fea44
0507081
06308c8
0507081
 
743d772
06308c8
0507081
1d1e3da
 
 
87a883e
1d1e3da
 
 
 
1ff656a
1d1e3da
87a883e
1d1e3da
06308c8
1a5f8fd
496e98a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import gradio as gr
import cv2
import pytesseract
from PIL import Image
import io
import base64
from datetime import datetime
import pytz
import numpy as np
import logging

# Set up logging for better debugging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Ensure Tesseract is correctly set up
try:
    pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract'  # Make sure to set the correct path
    pytesseract.get_tesseract_version()  # Confirm Tesseract is installed
    logging.info("Tesseract is configured properly.")
except Exception as e:
    logging.error(f"Tesseract not found or misconfigured: {str(e)}")

# Image Preprocessing to enhance OCR accuracy
def preprocess_image(img_cv):
    """Preprocess the image for better OCR accuracy."""
    try:
        # Convert to grayscale
        gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
        
        # Enhance contrast with CLAHE
        clahe = cv2.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))
        contrast = clahe.apply(gray)
        
        # Apply Gaussian blur to reduce noise
        blurred = cv2.GaussianBlur(contrast, (5, 5), 0)
        
        # Apply adaptive thresholding
        thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
        
        # Sharpen the image to emphasize edges
        sharpened = cv2.filter2D(thresh, -1, np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]))
        return sharpened
    except Exception as e:
        logging.error(f"Image preprocessing failed: {str(e)}")
        return img_cv

# Function to extract weight using Tesseract OCR
def extract_weight(img):
    """Extract weight using Tesseract OCR, focused on digits and decimals."""
    try:
        if img is None:
            logging.error("No image provided for OCR")
            return "Not detected", 0.0, None
        
        # Convert PIL image to OpenCV format
        img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        
        # Preprocess the image
        processed_img = preprocess_image(img_cv)
        
        # Tesseract configuration to focus on digits and decimal points
        custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789.'
        
        # Run OCR
        text = pytesseract.image_to_string(processed_img, config=custom_config)
        logging.info(f"OCR result: '{text}'")
        
        # Extract the valid weight (numbers and decimal points)
        weight = ''.join(filter(lambda x: x in '0123456789.', text.strip()))
        if weight:
            try:
                weight_float = float(weight)
                if weight_float >= 0:  # Ensure it's a valid weight
                    confidence = 95.0  # High confidence for valid weight
                    logging.info(f"Weight detected: {weight} (Confidence: {confidence:.2f}%)")
                    return weight, confidence, processed_img
            except ValueError:
                logging.warning(f"Invalid weight format: {weight}")
        
        logging.error("OCR failed to detect a valid weight")
        return "Not detected", 0.0, None
    except Exception as e:
        logging.error(f"OCR processing failed: {str(e)}")
        return "Not detected", 0.0, None

# Main function to process the image and display results
def process_image(img):
    """Process the uploaded image and show results."""
    if img is None:
        logging.error("No image uploaded")
        return "No image uploaded", None, gr.update(visible=False), gr.update(visible=False)
    
    # Get the current timestamp in IST format
    ist_time = datetime.now(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y %I:%M:%S %p")
    
    # Extract weight and confidence
    weight, confidence, processed_img = extract_weight(img)
    
    # If weight detection fails, show the error message
    if weight == "Not detected" or confidence < 95.0:
        logging.warning(f"Weight detection failed: {weight} (Confidence: {confidence:.2f}%)")
        return f"{weight} (Confidence: {confidence:.2f}%)", ist_time, gr.update(visible=True), gr.update(visible=False)
    
    # Convert processed image to base64 for Gradio to display
    pil_image = Image.fromarray(processed_img)
    buffered = io.BytesIO()
    pil_image.save(buffered, format="PNG")
    img_base64 = base64.b64encode(buffered.getvalue()).decode()
    
    return f"{weight} kg (Confidence: {confidence:.2f}%)", ist_time, img_base64, gr.update(visible=True)

# Gradio Interface setup for Hugging Face
with gr.Blocks(title="โš–๏ธ Auto Weight Logger") as demo:
    gr.Markdown("## โš–๏ธ Auto Weight Logger")
    gr.Markdown("๐Ÿ“ท Upload or capture an image of a digital weight scale (max 5MB).")

    with gr.Row():
        image_input = gr.Image(type="pil", label="Upload / Capture Image", sources=["upload", "webcam"])
        output_weight = gr.Textbox(label="โš–๏ธ Detected Weight (in kg)")

    with gr.Row():
        timestamp = gr.Textbox(label="๐Ÿ•’ Captured At (IST)")
        snapshot = gr.Image(label="๐Ÿ“ธ Snapshot Image", type="pil")

    submit = gr.Button("๐Ÿ” Detect Weight")
    submit.click(
        fn=process_image,
        inputs=image_input,
        outputs=[output_weight, timestamp, snapshot]
    )

    gr.Markdown("""
    ### Instructions
    - Upload a clear, well-lit image of a digital weight scale display (preferably a seven-segment font).
    - Ensure the image is < 5MB (automatically resized if larger).
    - Review the detected weight and try again if it's incorrect.
    """)

if __name__ == "__main__":
    demo.launch()