File size: 5,721 Bytes
0507081
1a5f8fd
 
1d1e3da
 
 
1a5f8fd
 
 
87a883e
1d1e3da
225d986
1d1e3da
 
225d986
49bdc4d
7f7b647
 
 
49bdc4d
 
1a5f8fd
7f7b647
49bdc4d
225d986
49bdc4d
808ff7b
49bdc4d
7f7b647
 
808ff7b
 
 
49bdc4d
7f7b647
 
0b5db95
808ff7b
7f7b647
0b5db95
225d986
49bdc4d
 
 
87a883e
49bdc4d
7f7b647
1a5f8fd
225d986
1a5f8fd
49bdc4d
 
3caa343
49bdc4d
7f7b647
1a5f8fd
7f7b647
 
0b5db95
808ff7b
7f7b647
c0652ff
7f7b647
 
c0652ff
 
 
7f7b647
c0652ff
225d986
c0652ff
49bdc4d
 
225d986
7f7b647
49bdc4d
3caa343
49bdc4d
1ff656a
49bdc4d
c0652ff
3caa343
1a5f8fd
 
3caa343
1a5f8fd
225d986
0507081
7f7b647
0507081
1ff656a
3caa343
5699ebb
7f7b647
0507081
0b5db95
7f7b647
3caa343
5699ebb
7f7b647
1a5f8fd
49bdc4d
3caa343
5699ebb
7f7b647
3caa343
 
 
 
1325895
7f7b647
3caa343
06308c8
225d986
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
142
143
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 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'  # Adjust path if necessary
    pytesseract.get_tesseract_version()  # Test Tesseract installation
    logging.info("Tesseract is properly configured.")
except Exception as e:
    logging.error(f"Tesseract not found or misconfigured: {str(e)}")

# Improved Image Preprocessing function for OCR
def preprocess_image(img_cv):
    """Enhance the image to improve OCR performance."""
    try:
        # Convert to grayscale
        gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)

        # Increase contrast using histogram equalization
        contrast = cv2.equalizeHist(gray)

        # Apply Gaussian blur to reduce noise
        blurred = cv2.GaussianBlur(contrast, (5, 5), 0)

        # Apply adaptive thresholding to binarize the image
        thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)

        # Sharpening the image to bring out more details
        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 image using OCR
def extract_weight(img):
    """Extract weight using Tesseract OCR, focusing on digits and decimals."""
    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
        img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

        # Preprocess the image for better OCR results
        processed_img = preprocess_image(img_cv)

        # Configure Tesseract to detect only digits and decimals
        custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789.'

        # Use Tesseract OCR to extract text
        text = pytesseract.image_to_string(processed_img, config=custom_config)
        logging.info(f"OCR result: '{text}'")
        
        # Extract the weight (numbers and decimal)
        weight = ''.join(filter(lambda x: x in '0123456789.', text.strip()))
        
        if weight:
            try:
                weight_float = float(weight)
                if weight_float >= 0:
                    confidence = 95.0  # Assume high confidence if we detect a 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 uploaded image and display results
def process_image(img):
    """Process the uploaded image, extract weight, and return results."""
    if img is None:
        logging.error("No image uploaded")
        return "No image uploaded", None, gr.update(visible=False), gr.update(visible=False)
    
    # Get timestamp for IST (Indian Standard Time)
    ist_time = datetime.now(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y %I:%M:%S %p")
    
    # Call the function to extract weight and confidence
    weight, confidence, processed_img = extract_weight(img)
    
    # If OCR fails to detect weight
    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 the processed image to base64 format for displaying
    pil_image = Image.fromarray(processed_img)
    buffered = io.BytesIO()
    pil_image.save(buffered, format="PNG")
    img_base64 = base64.b64encode(buffered.getvalue()).decode()

    # Return the detected weight, timestamp, and base64 image for Gradio
    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()