File size: 3,645 Bytes
af3df0b a18dfe6 af3df0b a18dfe6 af3df0b a18dfe6 af3df0b a18dfe6 af3df0b a18dfe6 af3df0b a18dfe6 | 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 | import torch
from PIL import Image
import gradio as gr
from open_clip import create_model_from_pretrained, get_tokenizer
MODEL_NAME = "microsoft/BiomedCLIP-PubMedBERT_256-vit_base_patch16_224"
print("Loading BiomedCLIP...")
model, preprocess = create_model_from_pretrained(f"hf-hub:{MODEL_NAME}")
tokenizer = get_tokenizer(f"hf-hub:{MODEL_NAME}")
model.eval()
print("Model Loaded")
BASE_PROMPTS = {
"Eczema": "a dermatology clinical image showing eczema with dry itchy inflamed patches",
"Psoriasis": "a dermatology image of psoriasis with thick scaly plaques",
"Fungal Infection (Tinea)": "a fungal skin infection with circular expanding ring like rash",
"Acne": "a dermatology image showing acne with pimples and inflammation",
"Dermatitis": "a dermatitis rash with redness irritation and inflammation",
"Urticaria (Hives)": "raised itchy welts on skin like urticaria or hives",
"Benign Mole": "a harmless benign mole on the skin",
"Melanoma Suspicion": "a suspicious melanoma skin lesion with asymmetry border irregularity dark color",
"Healthy Skin": "a healthy normal skin image with no lesions"
}
CONFIDENCE_THRESHOLD = 0.42 # tune if needed
def build_prompts(symptoms):
prompts = []
for label, base in BASE_PROMPTS.items():
if symptoms and symptoms.strip() != "":
enriched_prompt = f"{base}. Patient symptoms: {symptoms}"
else:
enriched_prompt = base
prompts.append((label, enriched_prompt))
return prompts
def predict(image, symptoms):
if image is None:
return "Please upload an image.", None
image = preprocess(image).unsqueeze(0)
prompts = build_prompts(symptoms)
labels = [p[0] for p in prompts]
text_list = [p[1] for p in prompts]
with torch.no_grad():
image_features = model.encode_image(image)
text_tokens = tokenizer(text_list)
text_features = model.encode_text(text_tokens)
image_features /= image_features.norm(dim=-1, keepdim=True)
text_features /= text_features.norm(dim=-1, keepdim=True)
similarity = (100.0 * image_features @ text_features.T).softmax(dim=-1)
probs = similarity.squeeze().tolist()
label_scores = list(zip(labels, probs))
label_scores.sort(key=lambda x: x[1], reverse=True)
best_label, best_prob = label_scores[0]
explanation = ""
if best_prob < CONFIDENCE_THRESHOLD:
explanation = (
"⚠️ The model is uncertain about this case. "
"Consider consulting a dermatologist, especially if symptoms are worsening, painful, rapidly spreading, "
"bleeding, or changing in shape/color."
)
best_label = "Uncertain — Needs Clinical Evaluation"
top3 = {label: round(score, 3) for label, score in label_scores[:3]}
return (
f"Prediction: {best_label} (confidence: {round(best_prob,3)})\n\n"
f"{explanation}\n\n"
"🔒 Disclaimer: This is a research tool and NOT a medical diagnosis.",
top3
)
ui = gr.Interface(
fn=predict,
inputs=[
gr.Image(type="pil", label="Upload Skin Image"),
gr.Textbox(label="Describe Symptoms (optional)", placeholder="e.g., itchy red rash for 2 weeks, burning sensation, spreading, no bleeding")
],
outputs=[
gr.Textbox(label="Result"),
gr.Label(num_top_classes=3, label="Top Predictions")
],
title="BiomedCLIP Dermatology Assistant",
description="Upload a skin image and optionally describe symptoms. Uses zero-shot BiomedCLIP for prediction. Research use only — not medical advice."
)
ui.launch()
|