File size: 3,131 Bytes
e58b1c2
975f9c6
 
 
e58b1c2
ef265f2
5234a64
25aa654
9ac49a2
5234a64
570a997
ef265f2
25aa654
ef265f2
 
 
 
 
25aa654
 
ef265f2
 
25aa654
ef265f2
 
 
 
25aa654
ef265f2
 
 
 
 
 
 
 
 
 
 
25aa654
ef265f2
 
25aa654
ef265f2
 
25aa654
ef265f2
 
 
 
 
 
25aa654
 
 
 
 
 
 
ef265f2
25aa654
ef265f2
 
25aa654
 
 
 
 
 
 
ef265f2
 
 
 
 
 
 
25aa654
 
301eb4d
25aa654
 
 
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
import pytesseract
import numpy as np
import cv2
import re
from PIL import Image
import logging

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

def preprocess_image(img):
    """Preprocess image for robust OCR."""
    try:
        # Convert to OpenCV format
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
        
        # Convert to grayscale
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        
        # Estimate brightness for adaptive processing
        brightness = np.mean(gray)
        
        # Apply CLAHE for contrast enhancement
        clahe_clip = 4.0 if brightness < 100 else 2.0
        clahe = cv2.createCLAHE(clipLimit=clahe_clip, tileGridSize=(8, 8))
        enhanced = clahe.apply(gray)
        
        # Apply adaptive thresholding
        block_size = max(11, min(31, int(img.shape[0] / 20) * 2 + 1))
        thresh = cv2.adaptiveThreshold(
            enhanced, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, block_size, 2
        )
        
        # Noise reduction
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
        thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
        
        return thresh
    except Exception as e:
        logging.error(f"Preprocessing failed: {str(e)}")
        return img

def extract_weight_from_image(pil_img):
    """Extract weight from any digital scale image."""
    try:
        # Convert PIL image to OpenCV
        img = np.array(pil_img)
        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
        
        # Preprocess image
        thresh = preprocess_image(img)
        
        # Try multiple Tesseract configurations
        configs = [
            r'--oem 3 --psm 7 -c tessedit_char_whitelist=0123456789.',  # Single line
            r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789.'   # Block of text
        ]
        for config in configs:
            text = pytesseract.image_to_string(thresh, config=config)
            logging.info(f"Tesseract raw output (config {config}): {text}")
            
            # Clean and validate text
            text = re.sub(r"[^\d\.]", "", text)
            if text.count('.') > 1:
                text = text.replace('.', '', text.count('.') - 1)
            text = text.strip('.')
            if text and re.fullmatch(r"^\d*\.?\d*$", text):
                text = text.lstrip('0') or '0'
                confidence = 95.0 if len(text.replace('.', '')) >= 3 else 90.0
                try:
                    weight = float(text)
                    if 0.001 <= weight <= 5000:
                        logging.info(f"Detected weight: {text} kg, Confidence: {confidence:.2f}%")
                        return text, confidence
                except ValueError:
                    logging.warning(f"Invalid weight format: {text}")
        
        logging.info("No valid weight detected.")
        return "Not detected", 0.0
    except Exception as e:
        logging.error(f"Weight extraction failed: {str(e)}")
        return "Not detected", 0.0