andevs commited on
Commit
ce0faff
·
verified ·
1 Parent(s): 8e5388a

Create models/skin_analysis_model.py

Browse files
Files changed (1) hide show
  1. models/skin_analysis_model.py +183 -0
models/skin_analysis_model.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torchvision.transforms as transforms
3
+ from PIL import Image
4
+ import mediapipe as mp
5
+ import numpy as np
6
+ import json
7
+ import os
8
+
9
+ class SkinAnalysisModel:
10
+ def __init__(self):
11
+ self.mp_face_detection = mp.solutions.face_detection
12
+ self.mp_face_mesh = mp.solutions.face_mesh
13
+ self.model = self._load_model()
14
+ self.transform = self._get_transforms()
15
+ self.conditions_map = self._load_conditions_map()
16
+
17
+ def _load_model(self):
18
+ """Load pre-trained model for skin analysis"""
19
+ # In production, load your trained model
20
+ # For now, using a placeholder
21
+ return torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True)
22
+
23
+ def _get_transforms(self):
24
+ """Get image transforms"""
25
+ return transforms.Compose([
26
+ transforms.Resize(256),
27
+ transforms.CenterCrop(224),
28
+ transforms.ToTensor(),
29
+ transforms.Normalize(mean=[0.485, 0.456, 0.406],
30
+ std=[0.229, 0.224, 0.225]),
31
+ ])
32
+
33
+ def _load_conditions_map(self):
34
+ """Load skin conditions mapping"""
35
+ return {
36
+ 0: {'id': 'blackheads', 'name': 'Blackheads', 'severity': 'mild'},
37
+ 1: {'id': 'whiteheads', 'name': 'Whiteheads', 'severity': 'mild'},
38
+ 2: {'id': 'papules', 'name': 'Papules', 'severity': 'moderate'},
39
+ 3: {'id': 'pustules', 'name': 'Pustules', 'severity': 'moderate'},
40
+ 4: {'id': 'cystic_acne', 'name': 'Cystic Acne', 'severity': 'severe'},
41
+ 5: {'id': 'nodules', 'name': 'Nodules', 'severity': 'severe'},
42
+ 6: {'id': 'acne_scars', 'name': 'Acne Scars', 'severity': 'mild'},
43
+ 7: {'id': 'hyperpigmentation', 'name': 'Hyperpigmentation', 'severity': 'moderate'},
44
+ 8: {'id': 'hypopigmentation', 'name': 'Hypopigmentation', 'severity': 'moderate'},
45
+ 9: {'id': 'oily_skin', 'name': 'Oily Skin', 'severity': 'mild'},
46
+ 10: {'id': 'dry_skin', 'name': 'Dry Skin', 'severity': 'mild'},
47
+ 11: {'id': 'combination_skin', 'name': 'Combination Skin', 'severity': 'mild'},
48
+ 12: {'id': 'sensitive_skin', 'name': 'Sensitive Skin', 'severity': 'moderate'},
49
+ 13: {'id': 'rosacea', 'name': 'Rosacea', 'severity': 'severe'},
50
+ 14: {'id': 'eczema', 'name': 'Eczema', 'severity': 'severe'},
51
+ 15: {'id': 'seborrheic_dermatitis', 'name': 'Seborrheic Dermatitis', 'severity': 'moderate'},
52
+ 16: {'id': 'milia', 'name': 'Milia', 'severity': 'mild'},
53
+ 17: {'id': 'keratosis_pilaris', 'name': 'Keratosis Pilaris', 'severity': 'mild'},
54
+ 18: {'id': 'folliculitis', 'name': 'Folliculitis', 'severity': 'moderate'},
55
+ 19: {'id': 'sunburn_uv_damage', 'name': 'Sunburn/UV Damage', 'severity': 'moderate'},
56
+ 20: {'id': 'fine_lines', 'name': 'Fine Lines', 'severity': 'mild'},
57
+ 21: {'id': 'uneven_texture', 'name': 'Uneven Texture', 'severity': 'mild'},
58
+ 22: {'id': 'enlarged_pores', 'name': 'Enlarged Pores', 'severity': 'mild'},
59
+ }
60
+
61
+ def analyze_skin(self, image_bytes: bytes) -> dict:
62
+ """
63
+ Analyze skin from image
64
+ Returns detected conditions with positions and severity
65
+ """
66
+ try:
67
+ # Load image
68
+ image = Image.open(image_bytes)
69
+ image_np = np.array(image)
70
+
71
+ # Detect face and get landmarks
72
+ with self.mp_face_detection.FaceDetection(
73
+ model_selection=1,
74
+ min_detection_confidence=0.5
75
+ ) as face_detection:
76
+
77
+ results = face_detection.process(image_np)
78
+
79
+ if not results.detections:
80
+ return {"error": "No face detected", "conditions": []}
81
+
82
+ # Get face bounding box
83
+ detection = results.detections[0]
84
+ bbox = detection.location_data.relative_bounding_box
85
+
86
+ # Extract face region
87
+ h, w, _ = image_np.shape
88
+ x = int(bbox.xmin * w)
89
+ y = int(bbox.ymin * h)
90
+ width = int(bbox.width * w)
91
+ height = int(bbox.height * h)
92
+
93
+ face_region = image_np[y:y+height, x:x+width]
94
+
95
+ # Run AI analysis on face region
96
+ conditions = self._detect_conditions(face_region)
97
+
98
+ # Generate pin positions based on detected conditions
99
+ pins = self._generate_pin_positions(conditions, bbox)
100
+
101
+ return {
102
+ "conditions": conditions,
103
+ "pins": pins,
104
+ "face_bbox": {
105
+ "x": float(bbox.xmin),
106
+ "y": float(bbox.ymin),
107
+ "width": float(bbox.width),
108
+ "height": float(bbox.height)
109
+ },
110
+ "dermatologist_warning": any(
111
+ c['severity'] in ['severe', 'moderate']
112
+ for c in conditions
113
+ )
114
+ }
115
+
116
+ except Exception as e:
117
+ return {"error": str(e), "conditions": []}
118
+
119
+ def _detect_conditions(self, face_region):
120
+ """Detect skin conditions from face region"""
121
+ # Convert to tensor
122
+ face_pil = Image.fromarray(face_region)
123
+ input_tensor = self.transform(face_pil).unsqueeze(0)
124
+
125
+ # Run inference (placeholder - in production, use actual model)
126
+ with torch.no_grad():
127
+ outputs = self.model(input_tensor)
128
+ probabilities = torch.nn.functional.softmax(outputs[0], dim=0)
129
+
130
+ # Get top conditions
131
+ top_probs, top_indices = torch.topk(probabilities, 5)
132
+
133
+ conditions = []
134
+ for idx, prob in zip(top_indices, top_probs):
135
+ condition_info = self.conditions_map.get(idx.item(), {
136
+ 'id': 'unknown',
137
+ 'name': 'Unknown',
138
+ 'severity': 'mild'
139
+ })
140
+
141
+ # Adjust severity based on confidence
142
+ severity = condition_info['severity']
143
+ if prob.item() > 0.8:
144
+ severity = 'severe'
145
+ elif prob.item() > 0.5:
146
+ severity = 'moderate'
147
+
148
+ conditions.append({
149
+ 'condition': condition_info['id'],
150
+ 'name': condition_info['name'],
151
+ 'severity': severity,
152
+ 'confidence': round(prob.item() * 100, 2)
153
+ })
154
+
155
+ return conditions
156
+
157
+ def _generate_pin_positions(self, conditions, face_bbox):
158
+ """Generate pin positions for detected conditions"""
159
+ # In production, use actual detection coordinates
160
+ # For now, distribute pins around face zones
161
+ zones = [
162
+ {'name': 'forehead', 'x': 0.5, 'y': 0.2},
163
+ {'name': 'left_cheek', 'x': 0.3, 'y': 0.5},
164
+ {'name': 'right_cheek', 'x': 0.7, 'y': 0.5},
165
+ {'name': 'chin', 'x': 0.5, 'y': 0.8},
166
+ {'name': 'nose', 'x': 0.5, 'y': 0.4},
167
+ ]
168
+
169
+ pins = []
170
+ for i, condition in enumerate(conditions):
171
+ zone = zones[i % len(zones)]
172
+ pins.append({
173
+ 'condition': condition['condition'],
174
+ 'position': {
175
+ 'x': zone['x'],
176
+ 'y': zone['y']
177
+ },
178
+ 'severity': condition['severity'],
179
+ 'confidence': condition['confidence'],
180
+ 'is_ai_detected': True
181
+ })
182
+
183
+ return pins