File size: 3,125 Bytes
975f9c6
 
 
 
 
 
 
fcdea18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
975f9c6
 
 
 
fcdea18
975f9c6
 
 
 
 
fcdea18
 
 
 
 
 
975f9c6
fcdea18
975f9c6
8ccdb60
 
975f9c6
e75e9eb
8ccdb60
e75e9eb
8ccdb60
975f9c6
8ccdb60
975f9c6
 
 
 
 
8ccdb60
975f9c6
8ccdb60
 
 
 
975f9c6
8ccdb60
 
 
 
 
 
 
 
 
 
975f9c6
8ccdb60
385a153
975f9c6
 
 
 
 
 
 
 
385a153
975f9c6
 
385a153
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
import easyocr
import numpy as np
import cv2
import re

reader = easyocr.Reader(['en'], gpu=False)

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

    # Apply sharpening kernel
    kernel = np.array([[0, -1, 0], [-1, 5,-1], [0, -1, 0]])
    sharp = cv2.filter2D(gray, -1, kernel)

    # Contrast Limited Adaptive Histogram Equalization (CLAHE)
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    contrast = clahe.apply(sharp)

    # Denoising
    denoised = cv2.fastNlMeansDenoising(contrast, h=30)

    # Adaptive threshold for very dim images
    thresh = cv2.adaptiveThreshold(denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                   cv2.THRESH_BINARY, 11, 2)

    return thresh

def extract_weight_from_image(pil_img):
    try:
        img = np.array(pil_img)

        # Resize if too large or too small
        max_dim = 1000
        height, width = img.shape[:2]
        if max(height, width) > max_dim:
            scale = max_dim / max(height, width)
            img = cv2.resize(img, None, fx=scale, fy=scale, interpolation=cv2.INTER_AREA)
        elif max(height, width) < 400:
            scale = 2.5  # Upscale very small images
            img = cv2.resize(img, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)

        # Enhance image for OCR
        preprocessed = enhance_image(img)

        results = reader.readtext(preprocessed)

        best_weight = None
        best_conf = 0.0

        for item in results:
            if len(item) != 2 or not isinstance(item[1], tuple):
                continue
            text, conf = item[1]
            cleaned = text.lower().strip()

            cleaned = cleaned.replace(",", ".")
            cleaned = cleaned.replace("o", "0").replace("O", "0")
            cleaned = cleaned.replace("s", "5").replace("S", "5")
            cleaned = cleaned.replace("g", "9").replace("G", "6")
            cleaned = cleaned.replace("kg", "").replace("kgs", "")
            cleaned = re.sub(r"[^\d\.]", "", cleaned)

            if re.fullmatch(r"\d{2,4}(\.\d{1,3})?", cleaned):
                if conf > best_conf:
                    best_weight = cleaned
                    best_conf = conf

        if not best_weight:
            for item in results:
                if len(item) != 2 or not isinstance(item[1], tuple):
                    continue
                text, conf = item[1]
                fallback = re.sub(r"[^\d\.]", "", text)
                if fallback and fallback.replace(".", "").isdigit():
                    best_weight = fallback
                    best_conf = conf
                    break

        if not best_weight:
            return "Not detected", 0.0

        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}"
        else:
            best_weight = best_weight.lstrip("0") or "0"

        return best_weight, round(best_conf * 100, 2)

    except Exception as e:
        return f"Error: {str(e)}", 0.0