File size: 12,304 Bytes
5c6141b c67397a 5c6141b c67397a 11d72cb 5c6141b 11d72cb 5c6141b 11d72cb 5c6141b 11d72cb 5c6141b 0da07af 5c6141b 0da07af 5c6141b 0da07af 5c6141b 11d72cb 4835d52 11d72cb 4835d52 11d72cb b8cabae 11d72cb 789ec36 11d72cb b8cabae 11d72cb b8cabae 789ec36 88ce90f 789ec36 b8cabae 789ec36 d1daad9 789ec36 d1daad9 b8cabae d1daad9 b8cabae 789ec36 b8cabae 789ec36 b8cabae 789ec36 b8cabae 789ec36 d1daad9 789ec36 d1daad9 789ec36 b8cabae 11d72cb b8cabae 789ec36 11d72cb b8cabae 11d72cb b8cabae d1daad9 b8cabae 11d72cb b8cabae 11d72cb b8cabae 11d72cb b8cabae 11d72cb b8cabae 11d72cb b8cabae 11d72cb b8cabae 11d72cb |
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 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# Use TensorFlow backend for better compatibility with existing models
import os
os.environ["KERAS_BACKEND"] = "tensorflow"
import gradio as gr
import tensorflow as tf
from tensorflow import keras
import numpy as np
from PIL import Image
from tensorflow.keras.applications.efficientnet_v2 import preprocess_input
from huggingface_hub import hf_hub_download
# Class names for the 5 skin conditions
CLASS_NAMES = [
'Atopic Dermatitis',
'Eczema',
'Psoriasis',
'Seborrheic Keratoses',
'Tinea Ringworm Candidiasis'
]
# Class descriptions
CLASS_DESCRIPTIONS = {
'Atopic Dermatitis': 'A chronic inflammatory skin condition causing dry, itchy patches',
'Eczema': 'Inflammatory skin condition causing red, itchy, and inflamed patches',
'Psoriasis': 'Autoimmune condition causing thick, scaly patches on the skin',
'Seborrheic Keratoses': 'Common benign (non-cancerous) skin growths',
'Tinea Ringworm Candidiasis': 'Fungal skin infections causing circular, scaly patches'
}
class DermaAIModel:
def __init__(self):
self.model = None
self.load_model()
def load_model(self):
"""Load the DermaAI model from Hugging Face Hub using traditional approach"""
try:
print("π Loading DermaAI model from Hugging Face...")
# Get authentication token from environment variable only (secure)
hf_token = os.getenv("HF_TOKEN")
# Download model file using HuggingFace Hub
if hf_token:
print("π Using authentication token...")
model_path = hf_hub_download(
repo_id="Siraja704/DermaAI",
filename="DermaAI.keras",
token=hf_token,
cache_dir="./model_cache"
)
else:
print("π Trying without authentication...")
model_path = hf_hub_download(
repo_id="Siraja704/DermaAI",
filename="DermaAI.keras",
cache_dir="./model_cache"
)
# Load the model using TensorFlow/Keras
print(f"π Loading model from: {model_path}")
self.model = keras.models.load_model(model_path)
print("β
Model loaded successfully!")
except Exception as e:
error_msg = str(e)
print(f"β Error loading model: {e}")
if "401" in error_msg or "gated" in error_msg.lower() or "restricted" in error_msg.lower():
print("\nπ AUTHENTICATION ERROR:")
print("- The model repository is private/gated")
print("- Please add your HF_TOKEN to the Space secrets")
print("- Go to Space Settings > Repository secrets")
print("- Add: HF_TOKEN = your_huggingface_token")
print("- Make sure the token has access to Siraja704/DermaAI\n")
raise e
def predict(self, image):
"""Make prediction on the input image"""
if self.model is None:
return {"error": "Model not loaded"}
try:
# Preprocess image
if image is None:
return {"error": "No image provided"}
# Convert to RGB if necessary
if image.mode != 'RGB':
image = image.convert('RGB')
# Resize to model input size
image_resized = image.resize((224, 224))
# Convert to numpy array and preprocess
image_array = np.array(image_resized)
image_array = preprocess_input(image_array)
image_array = np.expand_dims(image_array, axis=0)
# Make prediction
predictions = self.model.predict(image_array, verbose=0)
# Get results
predicted_class_idx = np.argmax(predictions[0])
confidence = float(predictions[0][predicted_class_idx])
# Prepare results dictionary for Gradio
results = {}
for i, class_name in enumerate(CLASS_NAMES):
results[class_name] = float(predictions[0][i])
return results
except Exception as e:
print(f"β Error during prediction: {e}")
return {"error": f"Prediction failed: {str(e)}"}
# Initialize model
print("π Initializing DermaAI...")
derma_model = DermaAIModel()
def predict_skin_condition(image):
"""Wrapper function for Gradio interface"""
if image is None:
return {"error": "Please upload an image"}
return derma_model.predict(image)
def get_medical_advice(image):
"""Provide medical advice based on prediction"""
if image is None:
return "Please upload an image first."
results = derma_model.predict(image)
if "error" in results:
return results["error"]
# Find the top prediction
top_prediction = max(results, key=results.get)
confidence = results[top_prediction] * 100
# Generate advice based on confidence
advice = f"**Predicted Condition:** {top_prediction}\n\n"
advice += f"**Confidence:** {confidence:.1f}%\n\n"
advice += f"**Description:** {CLASS_DESCRIPTIONS.get(top_prediction, 'No description available')}\n\n"
if confidence < 30:
advice += "β οΈ **Low Confidence Warning:** The AI model has low confidence in this prediction. Please retake the image with better lighting and focus, or consult a healthcare professional."
elif confidence < 60:
advice += "π **Moderate Confidence:** This is a preliminary assessment. Consider consulting with a healthcare professional for accurate diagnosis."
else:
advice += "β
**High Confidence:** The model shows high confidence, but this is still a preliminary assessment."
advice += "\n\nπ₯ **Important Medical Disclaimer:** This AI tool is for educational purposes only and should not replace professional medical diagnosis. Always consult qualified healthcare professionals for proper medical evaluation and treatment."
return advice
# Custom CSS for better styling with dark/light mode support
custom_css = """
/* Simple blue theme that works in both light and dark modes */
.gradio-container {
font-family: 'Inter', 'Segoe UI', 'Roboto', sans-serif;
max-width: 1200px;
margin: 0 auto;
}
/* All text blue for universal visibility */
.gradio-container * {
color: #2196f3 !important;
}
/* Main heading - darker blue */
.main-title h1 {
color: #1565c0 !important;
font-size: 2.5rem !important;
font-weight: 700 !important;
text-align: center !important;
}
.main-title p {
color: #1976d2 !important;
font-size: 1.2rem !important;
text-align: center !important;
}
/* Section headings - medium blue */
.gradio-container h1,
.gradio-container h2,
.gradio-container h3,
.gradio-container h4,
.gradio-container h5,
.gradio-container h6,
.section-header {
color: #1976d2 !important;
font-weight: 600 !important;
}
.section-header {
font-size: 1.4rem !important;
margin-bottom: 15px !important;
}
/* Regular text - lighter blue */
.gradio-container p,
.gradio-container span,
.gradio-container div,
.gradio-container li,
.gradio-container label,
.gradio-container button {
color: #2196f3 !important;
}
/* Special components */
.gradio-container .gr-markdown,
.gradio-container .gr-markdown *,
.gradio-container .gr-label-text,
.gradio-container .gr-input-label {
color: #2196f3 !important;
}
/* Icons and SVG elements */
.gradio-container svg {
fill: #2196f3 !important;
stroke: #2196f3 !important;
}
/* Links */
.gradio-container a {
color: #1565c0 !important;
text-decoration: underline;
}
/* Simple styling without backgrounds */
.medical-disclaimer,
.info-box,
.about-section {
border-radius: 8px;
padding: 15px;
margin: 10px 0;
border: 1px solid #2196f3;
}
.conditions-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 15px;
margin-top: 15px;
}
.condition-item {
padding: 15px;
border-radius: 8px;
border: 1px solid #2196f3;
}
"""
# Create Gradio interface
with gr.Blocks(
css=custom_css,
title="DermaAI - Skin Disease Classification",
theme=gr.themes.Base().set(
button_primary_background_fill="*primary_500",
button_primary_background_fill_hover="*primary_600",
button_primary_text_color="white",
block_background_fill="*background_fill_primary",
body_background_fill="*background_fill_primary",
)
) as demo:
gr.HTML("""
<div class="main-title">
<h1>π₯ DermaAI - Skin Disease Classification</h1>
<p>AI-powered skin condition analysis using deep learning</p>
</div>
""")
gr.HTML("""
<div class="medical-disclaimer">
<h3>βοΈ Important Medical Disclaimer</h3>
<p><strong>This AI tool is for educational and research purposes only.</strong>
It should not be used as a substitute for professional medical diagnosis or treatment.
Always consult with qualified healthcare professionals for proper medical evaluation.</p>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
gr.HTML("<h3 class='section-header'>πΈ Upload Skin Image</h3>")
input_image = gr.Image(
type="pil",
label="Upload a clear image of the skin condition",
height=400
)
gr.HTML("""
<div class="info-box">
<h4>π Image Guidelines:</h4>
<ul>
<li>Use good lighting and focus</li>
<li>Ensure the affected area is clearly visible</li>
<li>Avoid blurry or dark images</li>
<li>JPG, PNG formats supported</li>
</ul>
</div>
""")
with gr.Column(scale=1):
gr.HTML("<h3 class='section-header'>π Analysis Results</h3>")
prediction_output = gr.Label(
label="Prediction Confidence Scores",
num_top_classes=5
)
medical_advice = gr.Markdown(
label="Medical Assessment",
value="Upload an image to see the analysis..."
)
gr.HTML("""
<div class="info-box">
<h3>π©Ί Supported Skin Conditions</h3>
<div class="conditions-grid">
<div class="condition-item"><strong>Atopic Dermatitis:</strong> Chronic inflammatory skin condition</div>
<div class="condition-item"><strong>Eczema:</strong> Red, itchy, inflamed skin patches</div>
<div class="condition-item"><strong>Psoriasis:</strong> Thick, scaly skin patches</div>
<div class="condition-item"><strong>Seborrheic Keratoses:</strong> Benign skin growths</div>
<div class="condition-item"><strong>Tinea Ringworm Candidiasis:</strong> Fungal skin infections</div>
</div>
</div>
""")
# Set up the interface interactions
input_image.change(
fn=predict_skin_condition,
inputs=input_image,
outputs=prediction_output
)
input_image.change(
fn=get_medical_advice,
inputs=input_image,
outputs=medical_advice
)
gr.HTML("""
<div class="about-section">
<h3>π About DermaAI</h3>
<p>DermaAI is built using EfficientNetV2 architecture and trained on dermatological images.
The model analyzes skin images and provides confidence scores for 5 different skin conditions.</p>
<p><strong>Model:</strong> <a href="https://huggingface.co/Siraja704/DermaAI" target="_blank">Siraja704/DermaAI</a></p>
<p><strong>Framework:</strong> TensorFlow/Keras | <strong>Architecture:</strong> EfficientNetV2</p>
</div>
""")
# Launch the interface
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
) |