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()