Spaces:
Sleeping
Sleeping
File size: 8,540 Bytes
0507081 1a5f8fd 1d1e3da 1a5f8fd 1d1e3da 1a5f8fd 1d1e3da 1a5f8fd 30ff189 1a5f8fd 1d1e3da 1a5f8fd 1d1e3da 5699ebb 1d1e3da a481416 30ff189 1a5f8fd 30ff189 1a5f8fd 30ff189 1a5f8fd 30ff189 1a5f8fd 0507081 1a5f8fd 0507081 30ff189 1d1e3da 5699ebb 0507081 1d1e3da 1a5f8fd 30ff189 1a5f8fd 5699ebb 1a5f8fd 30ff189 0c65757 5699ebb 1d1e3da 30ff189 0c65757 1d1e3da 1a5f8fd 1d1e3da 30ff189 1d1e3da 5699ebb 1d1e3da 5699ebb 1d1e3da 58fea44 1d1e3da 06308c8 1a5f8fd 0507081 1d1e3da 06308c8 0507081 58fea44 0507081 06308c8 0507081 06308c8 1d1e3da 0507081 1d1e3da 30ff189 1d1e3da 0c65757 30ff189 1d1e3da 06308c8 1a5f8fd |
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
import gradio as gr
import cv2
import pytesseract
from PIL import Image
import io
import base64
from datetime import datetime
import pytz
from simple_salesforce import Salesforce
import logging
import numpy as np
import os
# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Configure Tesseract path for Hugging Face
try:
pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract'
pytesseract.get_tesseract_version() # Test Tesseract availability
logging.info("Tesseract is available")
except Exception as e:
logging.error(f"Tesseract not found or misconfigured: {str(e)}")
# Salesforce configuration (use environment variables in production)
SF_USERNAME = os.getenv("SF_USERNAME", "your_salesforce_username")
SF_PASSWORD = os.getenv("SF_PASSWORD", "your_salesforce_password")
SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN", "your_salesforce_security_token")
SF_DOMAIN = os.getenv("SF_DOMAIN", "login") # or "test" for sandbox
def connect_to_salesforce():
"""Connect to Salesforce with error handling."""
try:
sf = Salesforce(username=SF_USERNAME, password=SF_PASSWORD, security_token=SF_SECURITY_TOKEN, domain=SF_DOMAIN)
logging.info("Connected to Salesforce successfully")
return sf
except Exception as e:
logging.error(f"Salesforce connection failed: {str(e)}")
return None
def resize_image(img, max_size_mb=5):
"""Resize image to ensure size < 5MB while preserving quality."""
try:
img_bytes = io.BytesIO()
img.save(img_bytes, format="PNG")
size_mb = len(img_bytes.getvalue()) / (1024 * 1024)
if size_mb <= max_size_mb:
return img, img_bytes.getvalue()
scale = 0.9
while size_mb > max_size_mb:
w, h = img.size
img = img.resize((int(w * scale), int(h * scale)), Image.Resampling.LANCZOS)
img_bytes = io.BytesIO()
img.save(img_bytes, format="PNG")
size_mb = len(img_bytes.getvalue()) / (1024 * 1024)
scale *= 0.9
logging.info(f"Resized image to {size_mb:.2f} MB")
return img, img_bytes.getvalue()
except Exception as e:
logging.error(f"Image resizing failed: {str(e)}")
return img, None
def preprocess_image(img_cv):
"""Preprocess image for OCR: convert to grayscale, reduce noise, adjust contrast, and apply adaptive thresholding."""
try:
# Convert to grayscale
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
# Reduce noise with Gaussian blur
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Adjust contrast
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
contrast = clahe.apply(blurred)
# Apply adaptive thresholding
thresh = cv2.adaptiveThreshold(contrast, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
return thresh
except Exception as e:
logging.error(f"Image preprocessing failed: {str(e)}")
return img_cv
def extract_weight(img):
"""Extract weight from image using Tesseract OCR with multiple PSM modes."""
try:
if img is None:
logging.error("No image provided for OCR")
return "Not detected", 0.0
# Convert PIL image to OpenCV format
img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
# Preprocess image
processed_img = preprocess_image(img_cv)
# Try multiple PSM modes for better detection
psm_modes = [
('--psm 7 digits', 'Single line, digits only'),
('--psm 6 digits', 'Single block, digits only'),
('--psm 10 digits', 'Single character, digits only')
]
for config, desc in psm_modes:
text = pyt validatingesseract.image_to_string(processed_img, config=config)
logging.info(f"OCR attempt with {desc}: Raw text = '{text}'")
weight = ''.join(filter(lambda x: x in '0123456789.', text.strip()))
try:
weight_float = float(weight)
if weight_float > 0:
confidence = 95.0 # Simplified confidence for valid numbers
logging.info(f"Weight detected: {weight} (Confidence: {confidence:.2f}%)")
return weight, confidence
except ValueError:
logging.warning(f"Invalid number format: {weight}")
continue
logging.error("All OCR attempts failed to detect a valid weight")
return "Not detected", 0.0
except Exception as e:
logging.error(f"OCR processing failed: {str(e)}")
return "Not detected", 0.0
def process_image(img):
"""Process uploaded or captured image and extract weight."""
if img is None:
logging.error("No image provided")
return "No image uploaded", None, None, None, gr.update(visible=False), gr.update(visible=False)
ist_time = datetime.now(pytz.timezone("Asia/Kolkata")).strftime("%d-%m-%Y %I:%M:%S %p")
img, img_bytes = resize_image(img)
if img_bytes is None:
logging.error("Image resizing failed")
return "Image processing failed", ist_time, img, None, gr.update(visible=False), gr.update(visible=False)
weight, confidence = extract_weight(img)
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, img, None, gr.update(visible=True), gr.update(visible=False)
img_buffer = io.BytesIO(img_bytes)
img_base64 = base64.b64encode(img_buffer.getvalue()).decode()
logging.info(f"Weight detected successfully: {weight} kg")
return f"{weight} kg (Confidence: {confidence:.2f}%)", ist_time, img, img_base64, gr.update(visible=True), gr.update(visible=True)
def save_to_salesforce(weight_text, img_base64):
"""Save weight and image to Salesforce Weight_Log__c object."""
try:
sf = connect_to_salesforce()
if sf is None:
logging.error("Salesforce connection failed")
return "Failed to connect to Salesforce"
weight = float(weight_text.split(" ")[0])
ist_time = datetime.now(pytz.timezone("Asia/Kolkata")).strftime("%Y-%m-%d %H:%M:%S")
record = {
"Name": f"Weight_Log_{ist_time}",
"Captured_Weight__c": weight,
"Captured_At__c": ist_time,
"Snapshot_Image__c": img_base64,
"Status__c": "Confirmed"
}
result = sf.Weight_Log__c.create(record)
logging.info(f"Salesforce record created: {result}")
return "Successfully saved to Salesforce"
except Exception as e:
logging.error(f"Salesforce save failed: {str(e)}")
return f"Failed to save to Salesforce: {str(e)}"
# Gradio Interface
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")
with gr.Row():
confirm_button = gr.Button("โ
Confirm and Save to Salesforce", visible=False)
status = gr.Textbox(label="Save Status", visible=False)
submit = gr.Button("๐ Detect Weight")
submit.click(
fn=process_image,
inputs=image_input,
outputs=[output_weight, timestamp, snapshot, gr.State(), confirm_button, status]
)
confirm_button.click(
fn=save_to_salesforce,
inputs=[output_weight, gr.State()],
outputs=status
)
gr.Markdown("""
### Instructions
- Upload a clear, well-lit image of a digital weight scale display (7-segment font preferred).
- Ensure the image is < 5MB (automatically resized if larger).
- Review the detected weight and click 'Confirm and Save to Salesforce' to log the data.
- Works on desktop and mobile browsers.
- If weight detection fails, check the image for glare or low contrast and try again.
""")
if __name__ == "__main__":
demo.launch() |