File size: 5,878 Bytes
0507081
1a5f8fd
 
1d1e3da
 
 
1a5f8fd
 
 
87a883e
1d1e3da
1ff656a
1d1e3da
 
9df4fc9
49bdc4d
1ff656a
 
 
49bdc4d
 
1a5f8fd
1ff656a
49bdc4d
1ff656a
49bdc4d
1ff656a
49bdc4d
1ff656a
 
0b5db95
49bdc4d
1ff656a
 
49bdc4d
1ff656a
 
0b5db95
1ff656a
 
0b5db95
49bdc4d
 
 
87a883e
49bdc4d
9df4fc9
1a5f8fd
1ff656a
1a5f8fd
49bdc4d
 
3caa343
49bdc4d
1ff656a
1a5f8fd
1ff656a
 
0b5db95
49bdc4d
1ff656a
c0652ff
49bdc4d
9df4fc9
c0652ff
 
 
1ff656a
c0652ff
 
49bdc4d
 
1ff656a
 
49bdc4d
3caa343
49bdc4d
1ff656a
49bdc4d
c0652ff
3caa343
1a5f8fd
 
3caa343
1a5f8fd
1ff656a
0507081
1ff656a
0507081
1ff656a
3caa343
5699ebb
0b5db95
0507081
0b5db95
1ff656a
3caa343
5699ebb
1ff656a
1a5f8fd
49bdc4d
3caa343
5699ebb
1ff656a
3caa343
 
 
 
 
 
06308c8
1ff656a
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 debugging and better visibility
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Configure Tesseract path (ensure it's correctly set to your Tesseract installation)
try:
    pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract'  # Change path if necessary
    pytesseract.get_tesseract_version()  # Confirm Tesseract is properly set
    logging.info("Tesseract is configured properly.")
except Exception as e:
    logging.error(f"Tesseract not found or misconfigured: {str(e)}")

# Image Preprocessing to clean up the image for better OCR
def preprocess_image(img_cv):
    """Preprocess the image to enhance clarity for OCR."""
    try:
        # Convert image to grayscale for easier processing
        gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
        
        # Enhance the image contrast using CLAHE (Contrast Limited Adaptive Histogram Equalization)
        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 for better image clarity
        thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
        
        # Sharpen the image to emphasize digits
        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 from the image using Tesseract OCR
def extract_weight(img):
    """Extract weight using Tesseract OCR, focusing on numeric digits."""
    try:
        if img is None:
            logging.error("No image provided for OCR")
            return "Not detected", 0.0, None
        
        # Convert the PIL image to OpenCV format for processing
        img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        
        # Preprocess the image for better OCR results
        processed_img = preprocess_image(img_cv)
        
        # Tesseract configuration focusing on digits and decimals
        custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789.'
        
        # Run OCR on the processed image
        text = pytesseract.image_to_string(processed_img, config=custom_config)
        logging.info(f"OCR result: '{text}'")
        
        # Extract only the numeric part (weight)
        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  # Set 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 uploaded image and display results
def process_image(img):
    """Process the uploaded image, extract weight, and display 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 time 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 failed, display an appropriate 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 format for displaying in Gradio
    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
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()