| import gradio as gr |
| from PIL import Image, ImageStat |
| import numpy as np |
| import io |
| import math |
|
|
| print("🚀 Glow AI - Skin Analysis Tool Starting...") |
| print("Using pure image processing (no ML models)") |
|
|
| def analyze_skin_detailed(image): |
| """Advanced skin analysis using image processing techniques""" |
| |
| if image is None: |
| return "❌ Please upload an image first.", None |
| |
| try: |
| |
| if isinstance(image, np.ndarray): |
| pil_image = Image.fromarray(image) |
| else: |
| pil_image = image |
| |
| |
| original = pil_image.copy() |
| |
| |
| pil_image = pil_image.resize((400, 400)) |
| |
| |
| if pil_image.mode != 'RGB': |
| pil_image = pil_image.convert('RGB') |
| |
| |
| width, height = pil_image.size |
| |
| |
| if width < 100 or height < 100: |
| return "⚠️ Image too small. Please upload a clearer photo.", original |
| |
| |
| img_array = np.array(pil_image) |
| r_avg = np.mean(img_array[:,:,0]) |
| g_avg = np.mean(img_array[:,:,1]) |
| b_avg = np.mean(img_array[:,:,2]) |
| |
| |
| brightness = (r_avg + g_avg + b_avg) / 3 |
| |
| |
| gray = np.dot(img_array[...,:3], [0.2989, 0.5870, 0.1140]) |
| |
| |
| |
| if r_avg > g_avg and r_avg > b_avg: |
| dominant = "🔴 Red/Warm tones" |
| if r_avg - g_avg > 30: |
| condition_name = "Redness / Inflammation" |
| condition_confidence = min(85, (r_avg - g_avg) / 3) |
| condition_advice = "Use gentle, soothing products. Avoid harsh ingredients. Consider consulting a dermatologist." |
| else: |
| condition_name = "Warm Skin Undertones" |
| condition_confidence = 65 |
| condition_advice = "Your skin shows warm undertones. Look for products with golden or peachy tones." |
| elif g_avg > r_avg and g_avg > b_avg: |
| dominant = "🟢 Greenish tones" |
| condition_name = "Potential Skin Sensitivity" |
| condition_confidence = 55 |
| condition_advice = "This coloring may indicate certain conditions. Please consult a dermatologist." |
| else: |
| dominant = "⚪ Neutral/Cool tones" |
| condition_name = "Neutral Skin Undertones" |
| condition_confidence = 75 |
| condition_advice = "Your skin shows cool undertones. Look for products with pink or blue undertones." |
| |
| |
| r_std = np.std(img_array[:,:,0]) |
| g_std = np.std(img_array[:,:,1]) |
| b_std = np.std(img_array[:,:,2]) |
| texture_score = (r_std + g_std + b_std) / 3 |
| |
| if texture_score > 60: |
| texture_result = "⚠️ Noticeable texture variation" |
| texture_confidence = 70 |
| elif texture_score > 40: |
| texture_result = "📊 Moderate texture" |
| texture_confidence = 60 |
| else: |
| texture_result = "✅ Smooth texture" |
| texture_confidence = 80 |
| |
| |
| if brightness < 80: |
| lighting_result = "❌ Too Dark" |
| lighting_confidence = 85 |
| lighting_advice = "Please use better lighting for more accurate analysis" |
| elif brightness > 200: |
| lighting_result = "❌ Too Bright / Overexposed" |
| lighting_confidence = 85 |
| lighting_advice = "Please reduce lighting for more accurate analysis" |
| else: |
| lighting_result = "✅ Good" |
| lighting_confidence = 90 |
| lighting_advice = "Lighting conditions are optimal" |
| |
| |
| highlights = np.sum(gray > 200) |
| highlight_percent = (highlights / (width * height)) * 100 |
| |
| if highlight_percent > 15: |
| oiliness_name = "High Oiliness" |
| oiliness_confidence = min(85, highlight_percent * 2) |
| oiliness_advice = "Use oil-free, non-comedogenic products. Cleanse twice daily. Consider salicylic acid." |
| elif highlight_percent > 5: |
| oiliness_name = "Moderate Oiliness" |
| oiliness_confidence = 60 |
| oiliness_advice = "Maintain balanced cleansing. Use lightweight, oil-free moisturizers." |
| else: |
| oiliness_name = "Normal Oil Levels" |
| oiliness_confidence = 75 |
| oiliness_advice = "Your oil production appears balanced. Continue with your current routine." |
| |
| |
| darkness_threshold = brightness * 0.6 |
| dark_pixels = np.sum(gray < darkness_threshold) |
| dark_percent = (dark_pixels / (width * height)) * 100 |
| |
| if dark_percent > 20: |
| pigmentation_name = "Hyperpigmentation / Dark Spots" |
| pigmentation_confidence = min(80, dark_percent * 1.5) |
| pigmentation_advice = "Use Vitamin C serum daily. Always wear SPF 50+. Consider niacinamide for brightening." |
| elif dark_percent > 8: |
| pigmentation_name = "Uneven Pigmentation" |
| pigmentation_confidence = 55 |
| pigmentation_advice = "Consider incorporating brightening ingredients like Vitamin C or alpha arbutin." |
| else: |
| pigmentation_name = "Even Pigmentation" |
| pigmentation_confidence = 85 |
| pigmentation_advice = "Your skin tone appears even. Continue with sun protection to maintain it." |
| |
| |
| output = f""" |
| <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 650px; margin: 0 auto;"> |
| <div style="background: linear-gradient(135deg, #ec4899 0%, #f43f5e 100%); padding: 25px; border-radius: 20px; color: white; text-align: center; margin-bottom: 25px;"> |
| <h2 style="margin: 0; font-size: 28px;">✨ Glow AI Analysis Report</h2> |
| <p style="margin: 8px 0 0; opacity: 0.9;">Image Processing Analysis</p> |
| </div> |
| |
| <div style="background: #f0fdf4; padding: 20px; border-radius: 15px; margin-bottom: 20px; border-left: 4px solid #22c55e;"> |
| <h3 style="margin: 0 0 12px; color: #166534;">📊 Image Quality</h3> |
| <p><strong>💡 Lighting:</strong> {lighting_result} <span style="color: #666;">(Confidence: {lighting_confidence:.0f}%)</span></p> |
| <p><strong>🎨 Dominant Color:</strong> {dominant}</p> |
| <p><strong>✨ Texture:</strong> {texture_result} <span style="color: #666;">(Confidence: {texture_confidence:.0f}%)</span></p> |
| <p><strong>☀️ Brightness:</strong> {brightness:.0f}/255</p> |
| <p style="font-size: 14px; color: #666; margin-top: 12px; background: #f9fafb; padding: 10px; border-radius: 8px;"> |
| 💡 {lighting_advice} |
| </p> |
| </div> |
| |
| <div style="background: white; border: 1px solid #e5e7eb; border-radius: 15px; padding: 20px; margin-bottom: 20px;"> |
| <h3 style="margin: 0 0 15px; color: #1f2937;">🔍 Analysis Results</h3> |
| |
| <div style="margin-bottom: 15px; padding: 15px; background: #fef2f2; border-radius: 12px; border-left: 3px solid #ef4444;"> |
| <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> |
| <strong style="font-size: 16px;">🩸 {condition_name}</strong> |
| <span style="background: #fee2e2; color: #dc2626; padding: 2px 10px; border-radius: 20px; font-size: 12px; font-weight: bold;"> |
| {condition_confidence:.0f}% |
| </span> |
| </div> |
| <p style="margin: 0; font-size: 14px; color: #4b5563;">💡 {condition_advice}</p> |
| </div> |
| |
| <div style="margin-bottom: 15px; padding: 15px; background: #fefce8; border-radius: 12px; border-left: 3px solid #eab308;"> |
| <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> |
| <strong style="font-size: 16px;">💧 {oiliness_name}</strong> |
| <span style="background: #fef3c7; color: #d97706; padding: 2px 10px; border-radius: 20px; font-size: 12px; font-weight: bold;"> |
| {oiliness_confidence:.0f}% |
| </span> |
| </div> |
| <p style="margin: 0; font-size: 14px; color: #4b5563;">💡 {oiliness_advice}</p> |
| </div> |
| |
| <div style="padding: 15px; background: #f3e8ff; border-radius: 12px; border-left: 3px solid #9333ea;"> |
| <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> |
| <strong style="font-size: 16px;">🎨 {pigmentation_name}</strong> |
| <span style="background: #ede9fe; color: #7c3aed; padding: 2px 10px; border-radius: 20px; font-size: 12px; font-weight: bold;"> |
| {pigmentation_confidence:.0f}% |
| </span> |
| </div> |
| <p style="margin: 0; font-size: 14px; color: #4b5563;">💡 {pigmentation_advice}</p> |
| </div> |
| </div> |
| |
| <div style="background: #eff6ff; padding: 20px; border-radius: 15px; margin-bottom: 20px;"> |
| <h3 style="margin: 0 0 12px; color: #1e40af;">💡 Daily Skincare Routine</h3> |
| <ul style="margin: 0; padding-left: 20px;"> |
| <li>🧼 Cleanse gently morning and night</li> |
| <li>☀️ Apply SPF 30+ every single day</li> |
| <li>💧 Use moisturizer suitable for your skin type</li> |
| <li>🥗 Eat antioxidant-rich foods</li> |
| <li>😴 Get 7-9 hours of quality sleep</li> |
| <li>💊 Consider consulting a dermatologist for personalized advice</li> |
| </ul> |
| </div> |
| |
| <div style="background: #fef2f2; padding: 20px; border-radius: 15px; border: 1px solid #fecaca;"> |
| <h3 style="margin: 0 0 10px; color: #991b1b;">⚕️ Medical Disclaimer</h3> |
| <p style="margin: 0; font-size: 14px;"> |
| <strong>This analysis is for INFORMATIONAL purposes only and is NOT a medical diagnosis.</strong><br><br> |
| 🚫 This tool cannot detect skin cancer, serious conditions, or replace professional medical advice.<br><br> |
| ✅ <strong>Please consult a dermatologist if you have:</strong> |
| </p> |
| <ul style="margin: 10px 0 0; padding-left: 20px;"> |
| <li>Moles changing in size, shape, or color</li> |
| <li>Sores that won't heal</li> |
| <li>Persistent itching, bleeding, or pain</li> |
| <li>Any sudden or concerning skin changes</li> |
| </ul> |
| </div> |
| </div> |
| """ |
| |
| return output, original |
| |
| except Exception as e: |
| return f"❌ Error analyzing image: {str(e)}", image |
|
|
| def clear_all(): |
| """Clear all inputs and outputs""" |
| return None, None, None |
|
|
| |
| with gr.Blocks(title="Glow AI - Skin Analysis", theme=gr.themes.Soft()) as demo: |
| gr.Markdown(""" |
| # ✨ Glow AI - Skin Analysis |
| ### Upload a clear, well-lit photo of your skin |
| """) |
| |
| gr.Markdown("✅ **Active:** Real-time image processing analysis") |
| |
| with gr.Row(): |
| with gr.Column(): |
| image_input = gr.Image(type="pil", label="📸 Upload Photo", height=350) |
| |
| with gr.Row(): |
| analyze_btn = gr.Button("🔬 Analyze", variant="primary", size="lg") |
| clear_btn = gr.Button("🗑️ Clear", variant="secondary") |
| |
| gr.Markdown(""" |
| ### 📋 Tips: |
| - Use natural lighting |
| - Take a clear, focused photo |
| - Remove makeup if possible |
| """) |
| |
| with gr.Column(): |
| output_text = gr.HTML("### 📊 Click 'Analyze' to start") |
| output_image = gr.Image(label="📷 Your Image", height=250) |
| |
| analyze_btn.click( |
| fn=analyze_skin_detailed, |
| inputs=[image_input], |
| outputs=[output_text, output_image] |
| ) |
| |
| clear_btn.click( |
| fn=clear_all, |
| inputs=[], |
| outputs=[image_input, output_text, output_image] |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch(server_name="0.0.0.0", server_port=7860) |