File size: 4,242 Bytes
975f9c6
 
 
 
5234a64
 
 
 
 
0bb13f0
5234a64
 
 
 
 
 
975f9c6
fcdea18
5234a64
 
 
fcdea18
5234a64
 
fcdea18
5234a64
 
 
fcdea18
5234a64
 
 
fcdea18
5234a64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fcdea18
975f9c6
 
 
5234a64
 
 
 
 
975f9c6
2154cf1
 
975f9c6
5234a64
8ccdb60
 
975f9c6
5234a64
0bb13f0
 
 
 
 
2154cf1
 
8ccdb60
2154cf1
5234a64
2154cf1
 
 
5234a64
 
0bb13f0
2154cf1
975f9c6
0bb13f0
5234a64
 
2154cf1
8ccdb60
975f9c6
8ccdb60
5234a64
385a153
975f9c6
2154cf1
975f9c6
 
 
5234a64
975f9c6
 
 
385a153
975f9c6
 
5234a64
 
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
import easyocr
import numpy as np
import cv2
import re
import logging

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

# Initialize EasyOCR
easyocr_reader = easyocr.Reader(['en'], gpu=False)

def estimate_blur(img):
    """Estimate image blur using Laplacian variance"""
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    return cv2.Laplacian(gray, cv2.CV_64F).var()

def enhance_image(img):
    try:
        # Convert to grayscale
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # Bilateral filter for noise reduction while preserving edges
        denoised = cv2.bilateralFilter(gray, d=9, sigmaColor=75, sigmaSpace=75)

        # CLAHE for contrast enhancement
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
        contrast = clahe.apply(denoised)

        # Adaptive thresholding for uneven lighting
        thresh = cv2.adaptiveThreshold(contrast, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                      cv2.THRESH_BINARY, 11, 2)

        # Morphological operations to enhance text
        kernel = np.ones((3, 3), np.uint8)
        morphed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)

        # Sharpen image
        sharpen_kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
        sharpened = cv2.filter2D(morphed, -1, sharpen_kernel)

        # Dynamic resizing
        h, w = sharpened.shape
        target_size = 800  # Target max dimension for OCR
        scale_factor = min(target_size / max(h, w), 2.0) if max(h, w) < 300 else min(target_size / max(h, w), 1.0)
        if scale_factor != 1.0:
            sharpened = cv2.resize(sharpened, None, fx=scale_factor, fy=scale_factor, 
                                 interpolation=cv2.INTER_CUBIC if scale_factor > 1 else cv2.INTER_AREA)

        return sharpened
    except Exception as e:
        logging.error(f"Image enhancement failed: {str(e)}")
        return img  # Return original image as fallback

def extract_weight_from_image(pil_img):
    try:
        img = np.array(pil_img)
        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

        # Estimate blur to adjust confidence threshold
        blur_score = estimate_blur(img)
        conf_threshold = 0.3 if blur_score < 100 else 0.5  # Lower threshold for blurry images

        # Preprocess image
        processed = enhance_image(img)

        # Initialize results
        best_weight = None
        best_conf = 0.0

        # EasyOCR detection
        results = easyocr_reader.readtext(processed, detail=1, paragraph=False)
        if not results:  # Fallback to original image if no results
            results = easyocr_reader.readtext(img, detail=1, paragraph=False)

        for (bbox, text, conf) in results:
            original_text = text
            text = text.lower().strip()

            # Fix common OCR errors
            text = text.replace(",", ".").replace(";", ".")
            text = text.replace("o", "0").replace("O", "0")
            text = text.replace("s", "5").replace("S", "5")
            text = text.replace("g", "9").replace("G", "6")
            text = text.replace("l", "1").replace("I", "1")
            text = text.replace("b", "8").replace("B", "8")
            text = text.replace("kgs", "").replace("kg", "").replace("k", "")
            text = re.sub(r"[^\d\.]", "", text)

            # Regex for weight (0.0 to 9999.999)
            if re.fullmatch(r"\d{1,4}(\.\d{0,3})?", text):
                if conf > best_conf and conf > conf_threshold:
                    best_weight = text
                    best_conf = conf

        if not best_weight:
            logging.info("No valid weight detected")
            return "Not detected", 0.0

        # Format output
        if "." in best_weight:
            int_part, dec_part = best_weight.split(".")
            int_part = int_part.lstrip("0") or "0"
            best_weight = f"{int_part}.{dec_part.rstrip('0')}"
        else:
            best_weight = best_weight.lstrip("0") or "0"

        return best_weight, round(best_conf * 100, 2)

    except Exception as e:
        logging.error(f"Weight extraction failed: {str(e)}")
        return "Not detected", 0.0