File size: 6,063 Bytes
33cb218
990bf6f
 
 
 
 
 
 
61f613f
 
 
 
 
 
 
990bf6f
61f613f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8096272
826be80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8096272
61f613f
 
 
 
 
826be80
61f613f
 
 
 
826be80
61f613f
 
 
826be80
61f613f
 
 
 
 
826be80
990bf6f
61f613f
 
 
826be80
990bf6f
61f613f
 
826be80
8096272
61f613f
2152bda
8096272
 
 
61f613f
8096272
 
f88bd74
8096272
 
 
 
61f613f
 
8096272
826be80
8096272
826be80
c51946e
61f613f
c51946e
 
61f613f
8096272
 
 
61f613f
 
 
8096272
990bf6f
61f613f
990bf6f
 
61f613f
 
9775801
61f613f
8096272
990bf6f
61f613f
33cb218
 
61f613f
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
import gradio as gr
from transformers import CLIPProcessor, CLIPModel
from PIL import Image

# Load the model and processor
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

# Define the broad BMI classes for Model 1
bmi_classes_model1 = [
    "underweight (x < 18.5 BMI)", 
    "normal weight (18.5 < x < 25 BMI)", 
    "overweight (25 BMI < x < 30)",  
    "obesity (x > 30 BMI)"
]

# Define the finer BMI ranges for Model 2
bmi_ranges_model2 = {
    "underweight (x < 18.5 bmi)": [
        "BMI less than 16.0", 
        "BMI between 16.0 and 16.99",  
        "BMI between 17.0 and 18.49"
    ],
    "normal weight (18.5 < x < 25 bmi)": [
        "BMI between 18.5 and 20.4", 
        "BMI between 20.5 and 22.4",  
        "BMI between 22.5 and 24.9"
    ],
    "overweight (25 bmi < x < 30)": [
        "BMI between 25.0 and 26.9", 
        "BMI between 27.0 and 28.9",  
        "BMI between 29.0 and 29.9"
    ],
    "obesity (x > 30 bmi)": [
        "BMI between 30.0 and 34.9", 
        "BMI between 35.0 and 39.9",  
        "BMI 40.0 and above"
    ]
}
bmi_mapp = {
    "BMI less than 16.0":"BMI < 16.0",
        "BMI between 16.0 and 16.99":"16.0 ≤ BMI ≤ 16.99",
        "BMI between 17.0 and 18.49":"17.0 ≤ BMI ≤ 18.49",
    "BMI between 18.5 and 20.4":"18.5 ≤ BMI ≤ 20.4",
        "BMI between 20.5 and 22.4":"20.5 ≤ BMI ≤ 22.4",
        "BMI between 22.5 and 24.9":"22.5 ≤ BMI ≤ 24.9",
    "BMI between 25.0 and 26.9":"25.0 ≤ BMI ≤ 26.9",
        "BMI between 27.0 and 28.9":"27.0 ≤ BMI ≤ 28.9",
        "BMI between 29.0 and 29.9":"29.0 ≤ BMI ≤ 29.9",
    "BMI between 30.0 and 34.9": "30.0 ≤ BMI ≤ 34.9",
        "BMI between 35.0 and 39.9": "35.0 ≤ BMI ≤ 39.9",
        "BMI 40.0 and above":"BMI ≥ 40.0"
}

# Define BMI ranges with boundaries and midpoints for adjusted BMI calculation
bmi_ranges = {
    "underweight (x < 18.5 bmi)": {
        "BMI < 16.0": (0, 16.0, 16.0),  # Upper boundary 16.0
        "16.0 ≤ BMI ≤ 16.99": (16.0, 16.99, 16.5),  # Midpoint 16.5
        "17.0 ≤ BMI ≤ 18.49": (17.0, 18.49, 17.75)  # Midpoint 17.75
    },
    "normal weight (18.5 < x < 25 bmi)": {
        "18.5 ≤ BMI ≤ 20.4": (18.5, 20.4, 19.45),  # Midpoint 19.45
        "20.5 ≤ BMI ≤ 22.4": (20.5, 22.4, 21.45),  # Midpoint 21.45
        "22.5 ≤ BMI ≤ 24.9": (22.5, 24.9, 23.7)    # Midpoint 23.7
    },
    "overweight (25 bmi < x < 30)": {
        "25.0 ≤ BMI ≤ 26.9": (25.0, 26.9, 25.95),  # Midpoint 25.95
        "27.0 ≤ BMI ≤ 28.9": (27.0, 28.9, 27.95),  # Midpoint 27.95
        "29.0 ≤ BMI ≤ 29.9": (29.0, 29.9, 29.45)   # Midpoint 29.45
    },
    "obesity (x > 30 bmi)": {
        "30.0 ≤ BMI ≤ 34.9": (30.0, 34.9, 32.5),   # Midpoint 32.5
        "35.0 ≤ BMI ≤ 39.9": (35.0, 39.9, 37.45),  # Midpoint 37.45
        "BMI ≥ 40.0": (40.0, 100, 40.0)            # Lower boundary 40.0
    }
}

def predict_bmi(image, height_in_inches):
    # Prepare inputs for Model 1
    inputs_model1 = processor(text=bmi_classes_model1, images=image, return_tensors="pt", padding=True)
    outputs_model1 = model(**inputs_model1)
    probs_model1 = outputs_model1.logits_per_image.softmax(dim=1)
    print(probs_model1,'probs_model1')
    
    # Get the broad category prediction from Model 1
    max_prob_index_model1 = probs_model1.argmax().item()
    predicted_bmi_class = bmi_classes_model1[max_prob_index_model1]
    print(predicted_bmi_class,'predicted_bmi_class')

    # Select class names for Model 2 based on Model 1's prediction
    model2_classes = bmi_ranges_model2[predicted_bmi_class.lower()]
    print(model2_classes,'model2_classes')
    
    # Prepare inputs for Model 2
    inputs_model2 = processor(text=model2_classes, images=image, return_tensors="pt", padding=True)
    outputs_model2 = model(**inputs_model2)
    probs_model2 = outputs_model2.logits_per_image.softmax(dim=1)
    print(probs_model2,'probs_model2')

    # Get the finer range prediction from Model 2
    max_prob_index_model2 = probs_model2.argmax().item()
    finer_bmi_range = model2_classes[max_prob_index_model2]
    print(finer_bmi_range,'finer_bmi_range')

    # Determine the BMI prediction based on the range
    bmi_prediction = get_adjusted_bmi(predicted_bmi_class, finer_bmi_range)
    print(bmi_prediction)
    
    # Calculate weight using user-provided height
    predicted_weight = calculate_weight(bmi_prediction, height_in_inches)

    # Create the JSON output
    result = {
        "weightCategory": f"{predicted_bmi_class} - {finer_bmi_range}",
        "bmiPrediction": f"{bmi_prediction:.2f}",
        "height": str(height_in_inches),
        "predictedWeight": f"{predicted_weight:.2f} lbs"
    }

    return result

def get_adjusted_bmi(weight_category, finer_range):
    """Return the appropriate BMI value for the given finer range within the weight category."""
    category_ranges = bmi_ranges.get(weight_category.lower())
    print(category_ranges,'category_ranges')
    for range_label, (low, high, mid) in category_ranges.items():
        print(range_label,'range_label')
        if range_label == bmi_mapp[finer_range]:
            return mid
        """elif "BMI <" in range_label or "BMI ≥" in range_label:
            return high if "BMI <" in range_label else low"""
    return None

def calculate_weight(bmi, height_in_inches):
    """Calculate the weight from BMI and height (in inches)."""
    height_in_meters = height_in_inches * 0.0254
    weight_kg = bmi * (height_in_meters ** 2)
    weight_lbs = weight_kg * 2.20462
    return weight_lbs

# Create Gradio interface with updated input components
interface = gr.Interface(
    fn=predict_bmi,
    inputs=[
        gr.Image(type="pil"),
        gr.Number(label="Height in inches")  # Allow user to enter height
    ],
    outputs="json",
    title="BMI Prediction",
    description="Upload an image and enter your height to predict BMI category and receive a detailed prediction."
)

interface.launch()