Spaces:
Sleeping
Sleeping
Commit
·
384c4a0
1
Parent(s):
2e94196
Add refined clothing analysis functionality: implement structured analysis endpoints, enhance API responses, and create detailed prompt documentation
Browse files- REFINED_PROMPT_README.md +143 -0
- fast.py +547 -6
REFINED_PROMPT_README.md
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Refined Clothing Analysis Prompt
|
2 |
+
|
3 |
+
This document describes the refined prompt for analyzing clothing in images, providing a structured and comprehensive approach to fashion analysis.
|
4 |
+
|
5 |
+
## Overview
|
6 |
+
|
7 |
+
The refined prompt has been integrated into the Fashion Analyzer API to provide structured clothing analysis that follows a consistent format. This ensures detailed, professional-quality fashion analysis suitable for various applications.
|
8 |
+
|
9 |
+
## API Endpoints
|
10 |
+
|
11 |
+
### 1. Structured Analysis Endpoint
|
12 |
+
- **URL**: `POST /analyze-structured`
|
13 |
+
- **Description**: Analyzes uploaded images using the refined structured format
|
14 |
+
- **Response**: Returns analysis in the exact format specified by the refined prompt
|
15 |
+
|
16 |
+
### 2. Refined Prompt Endpoint
|
17 |
+
- **URL**: `GET /refined-prompt`
|
18 |
+
- **Description**: Returns the complete refined prompt specification
|
19 |
+
- **Response**: Plain text containing the detailed prompt instructions
|
20 |
+
|
21 |
+
### 3. Traditional Analysis Endpoint
|
22 |
+
- **URL**: `POST /analyze-image`
|
23 |
+
- **Description**: Provides comprehensive fashion analysis with detailed insights
|
24 |
+
- **Response**: Returns traditional detailed fashion analysis
|
25 |
+
|
26 |
+
## Refined Prompt Structure
|
27 |
+
|
28 |
+
The refined prompt ensures analysis follows this exact structure:
|
29 |
+
|
30 |
+
### 1. UPPER GARMENT
|
31 |
+
- **Type**: Specific garment classification (shirt, blouse, sweater, dress, etc.)
|
32 |
+
- **Color**: Primary and secondary colors with color theory insights
|
33 |
+
- **Material**: Fabric type with intelligent inference
|
34 |
+
- **Features**: Distinguishing characteristics (patterns, buttons, sleeves, etc.)
|
35 |
+
|
36 |
+
### 2. LOWER GARMENT
|
37 |
+
- **Type**: Bottom wear classification (jeans, pants, skirt, etc.)
|
38 |
+
- **Color**: Color analysis with fashion context
|
39 |
+
- **Material**: Fabric identification or intelligent inference
|
40 |
+
- **Features**: Design elements (pockets, fit, length, etc.)
|
41 |
+
|
42 |
+
### 3. FOOTWEAR
|
43 |
+
- **Type**: Shoe classification (sneakers, heels, boots, etc.)
|
44 |
+
- **Color**: Color description and analysis
|
45 |
+
- **Material**: Material identification
|
46 |
+
- **Features**: Design details (laces, buckles, heel height, etc.)
|
47 |
+
|
48 |
+
### 4. OUTFIT SUMMARY
|
49 |
+
A comprehensive 3-5 sentence paragraph that:
|
50 |
+
- Describes overall aesthetic and style
|
51 |
+
- Explains how pieces complement each other
|
52 |
+
- Assesses occasion appropriateness and versatility
|
53 |
+
- Includes color harmony analysis
|
54 |
+
- Provides styling insights
|
55 |
+
|
56 |
+
## Key Features
|
57 |
+
|
58 |
+
### Intelligent Analysis
|
59 |
+
- Uses yainage90 fashion-specific AI models for object detection
|
60 |
+
- Provides intelligent inference when details aren't clearly visible
|
61 |
+
- Incorporates color theory and fashion expertise
|
62 |
+
- Considers fit, proportion, and styling principles
|
63 |
+
|
64 |
+
### Professional Terminology
|
65 |
+
- Uses appropriate fashion vocabulary
|
66 |
+
- Includes technical terms (silhouette, drape, texture)
|
67 |
+
- Provides industry-standard assessments
|
68 |
+
- Offers styling recommendations
|
69 |
+
|
70 |
+
### Comprehensive Coverage
|
71 |
+
- Analyzes all visible clothing elements
|
72 |
+
- Considers occasion appropriateness
|
73 |
+
- Assesses versatility and styling potential
|
74 |
+
- Provides color harmony insights
|
75 |
+
|
76 |
+
## Usage Examples
|
77 |
+
|
78 |
+
### Web Interface
|
79 |
+
1. Visit `http://localhost:7861`
|
80 |
+
2. Upload an image of clothing
|
81 |
+
3. Choose "Analyze Fashion (Structured)" for refined format
|
82 |
+
4. Choose "Analyze Fashion (Detailed)" for comprehensive analysis
|
83 |
+
|
84 |
+
### API Usage
|
85 |
+
```bash
|
86 |
+
# Structured analysis
|
87 |
+
curl -X POST "http://localhost:7861/analyze-structured" \
|
88 |
+
-H "accept: application/json" \
|
89 |
+
-H "Content-Type: multipart/form-data" \
|
90 |
+
-F "file=@your_image.jpg"
|
91 |
+
|
92 |
+
# Get refined prompt
|
93 |
+
curl -X GET "http://localhost:7861/refined-prompt"
|
94 |
+
```
|
95 |
+
|
96 |
+
## Technical Implementation
|
97 |
+
|
98 |
+
### AI Models Used
|
99 |
+
- **yainage90/fashion-object-detection**: Specialized fashion item detection
|
100 |
+
- **yainage90/fashion-image-feature-extractor**: Fashion feature extraction
|
101 |
+
- **Salesforce/blip-image-captioning-base**: Fallback image description
|
102 |
+
|
103 |
+
### Analysis Pipeline
|
104 |
+
1. Image preprocessing and validation
|
105 |
+
2. Fashion object detection using specialized models
|
106 |
+
3. Feature extraction and analysis
|
107 |
+
4. Intelligent inference for missing details
|
108 |
+
5. Structured output generation following refined prompt format
|
109 |
+
|
110 |
+
## Benefits
|
111 |
+
|
112 |
+
### Consistency
|
113 |
+
- Standardized output format across all analyses
|
114 |
+
- Predictable structure for integration with other systems
|
115 |
+
- Professional-quality descriptions
|
116 |
+
|
117 |
+
### Accuracy
|
118 |
+
- Specialized fashion AI models for better detection
|
119 |
+
- Intelligent inference based on garment types
|
120 |
+
- Color theory and fashion expertise integration
|
121 |
+
|
122 |
+
### Versatility
|
123 |
+
- Suitable for e-commerce applications
|
124 |
+
- Fashion blogging and content creation
|
125 |
+
- Personal styling recommendations
|
126 |
+
- Wardrobe analysis tools
|
127 |
+
|
128 |
+
## Future Enhancements
|
129 |
+
|
130 |
+
- Integration with fashion trend databases
|
131 |
+
- Seasonal styling recommendations
|
132 |
+
- Brand and style recognition
|
133 |
+
- Price point estimation
|
134 |
+
- Sustainability assessments
|
135 |
+
|
136 |
+
## Getting Started
|
137 |
+
|
138 |
+
1. Start the server: `python fast.py`
|
139 |
+
2. Open browser to `http://localhost:7861`
|
140 |
+
3. Upload an image and select analysis type
|
141 |
+
4. View the refined prompt at `/refined-prompt`
|
142 |
+
|
143 |
+
The refined prompt ensures consistent, professional fashion analysis suitable for various applications while maintaining the flexibility to provide detailed insights based on image content.
|
fast.py
CHANGED
@@ -122,6 +122,290 @@ class HuggingFaceFashionAnalyzer:
|
|
122 |
except Exception as e:
|
123 |
return f"Error analyzing image: {str(e)}"
|
124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
def detect_fashion_objects(self, image):
|
126 |
"""Detect fashion objects using yainage90 fashion detection model"""
|
127 |
if self.detection_model is None or self.detection_processor is None:
|
@@ -196,12 +480,18 @@ class HuggingFaceFashionAnalyzer:
|
|
196 |
detected_items = detection_results.get('detected_items', [])
|
197 |
detection_summary = self.summarize_detections(detected_items)
|
198 |
|
|
|
|
|
|
|
199 |
# Create comprehensive analysis
|
200 |
analysis_template = f"""🎽 ADVANCED FASHION ANALYSIS REPORT
|
201 |
|
202 |
🔍 AI-POWERED OBJECT DETECTION:
|
203 |
{detection_summary}
|
204 |
|
|
|
|
|
|
|
205 |
📋 DETAILED GARMENT ANALYSIS:
|
206 |
{self.create_detailed_garment_analysis(detected_items, basic_description)}
|
207 |
|
@@ -224,6 +514,140 @@ class HuggingFaceFashionAnalyzer:
|
|
224 |
|
225 |
return analysis_template
|
226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
def summarize_detections(self, detected_items):
|
228 |
"""Summarize detected fashion items"""
|
229 |
if not detected_items:
|
@@ -1131,7 +1555,10 @@ async def root():
|
|
1131 |
<div class="upload-area">
|
1132 |
<input type="file" id="imageInput" accept="image/*" style="margin: 10px;">
|
1133 |
<br>
|
1134 |
-
<button onclick="analyzeImage()" style="padding: 10px 20px; margin: 10px;">Analyze Fashion</button>
|
|
|
|
|
|
|
1135 |
</div>
|
1136 |
|
1137 |
<div id="result" class="result" style="display: none;">
|
@@ -1143,24 +1570,52 @@ async def root():
|
|
1143 |
async function analyzeImage() {
|
1144 |
const input = document.getElementById('imageInput');
|
1145 |
const file = input.files[0];
|
1146 |
-
|
1147 |
if (!file) {
|
1148 |
alert('Please select an image file');
|
1149 |
return;
|
1150 |
}
|
1151 |
-
|
1152 |
const formData = new FormData();
|
1153 |
formData.append('file', file);
|
1154 |
-
|
1155 |
document.getElementById('analysisText').textContent = 'Analyzing... Please wait...';
|
1156 |
document.getElementById('result').style.display = 'block';
|
1157 |
-
|
1158 |
try {
|
1159 |
const response = await fetch('/analyze-image', {
|
1160 |
method: 'POST',
|
1161 |
body: formData
|
1162 |
});
|
1163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1164 |
const result = await response.json();
|
1165 |
document.getElementById('analysisText').textContent = result.analysis;
|
1166 |
} catch (error) {
|
@@ -1187,6 +1642,92 @@ async def analyze_image(file: UploadFile = File(...)):
|
|
1187 |
except Exception as e:
|
1188 |
raise HTTPException(status_code=500, detail=f"Error analyzing image: {str(e)}")
|
1189 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1190 |
@app.get("/health")
|
1191 |
async def health_check():
|
1192 |
"""Health check endpoint"""
|
|
|
122 |
except Exception as e:
|
123 |
return f"Error analyzing image: {str(e)}"
|
124 |
|
125 |
+
def analyze_clothing_structured_format(self, image_bytes):
|
126 |
+
"""Analyze clothing using the refined structured format"""
|
127 |
+
try:
|
128 |
+
# Process image
|
129 |
+
image = self.process_image_from_bytes(image_bytes)
|
130 |
+
|
131 |
+
# Get fashion object detection results
|
132 |
+
detection_results = self.detect_fashion_objects(image)
|
133 |
+
|
134 |
+
# Get basic image description as fallback
|
135 |
+
basic_description = self.get_basic_description(image)
|
136 |
+
|
137 |
+
# Create structured analysis in the exact requested format
|
138 |
+
analysis = self.create_refined_structured_analysis(detection_results, basic_description)
|
139 |
+
|
140 |
+
return analysis
|
141 |
+
|
142 |
+
except Exception as e:
|
143 |
+
return f"Error analyzing image: {str(e)}"
|
144 |
+
|
145 |
+
def create_refined_structured_analysis(self, detection_results, basic_description):
|
146 |
+
"""Create analysis in the exact refined format requested"""
|
147 |
+
|
148 |
+
# Process detection results
|
149 |
+
detected_items = detection_results.get('detected_items', [])
|
150 |
+
|
151 |
+
# Categorize detected items
|
152 |
+
upper_items = []
|
153 |
+
lower_items = []
|
154 |
+
footwear_items = []
|
155 |
+
|
156 |
+
for item in detected_items:
|
157 |
+
category = item['category'].lower()
|
158 |
+
if category in ['top', 'shirt', 'blouse', 'outer', 'jacket', 'blazer', 'dress']:
|
159 |
+
upper_items.append(item)
|
160 |
+
elif category in ['bottom', 'pants', 'jeans', 'skirt']:
|
161 |
+
lower_items.append(item)
|
162 |
+
elif category in ['shoes']:
|
163 |
+
footwear_items.append(item)
|
164 |
+
|
165 |
+
analysis_parts = []
|
166 |
+
|
167 |
+
# UPPER GARMENT
|
168 |
+
analysis_parts.append("UPPER GARMENT:")
|
169 |
+
if upper_items or 'dress' in basic_description.lower() or any(word in basic_description.lower() for word in ['shirt', 'blouse', 'top', 'jacket']):
|
170 |
+
if upper_items:
|
171 |
+
primary_upper = upper_items[0]
|
172 |
+
garment_type = primary_upper['category'].title()
|
173 |
+
else:
|
174 |
+
garment_type = self.extract_garment_type(basic_description)
|
175 |
+
|
176 |
+
analysis_parts.append(f"Type: {garment_type}")
|
177 |
+
analysis_parts.append(f"Color: {self.extract_colors(basic_description)}")
|
178 |
+
analysis_parts.append(f"Material: {self.extract_material(basic_description)}")
|
179 |
+
analysis_parts.append(f"Features: {self.extract_comprehensive_features(basic_description, garment_type)}")
|
180 |
+
else:
|
181 |
+
analysis_parts.append("Type: Not clearly visible in image")
|
182 |
+
analysis_parts.append("Color: Unable to determine")
|
183 |
+
analysis_parts.append("Material: Unable to determine")
|
184 |
+
analysis_parts.append("Features: Unable to determine")
|
185 |
+
|
186 |
+
analysis_parts.append("")
|
187 |
+
|
188 |
+
# LOWER GARMENT
|
189 |
+
analysis_parts.append("LOWER GARMENT:")
|
190 |
+
if 'dress' in basic_description.lower() and not lower_items:
|
191 |
+
analysis_parts.append("[Not applicable - dress serves as complete outfit]")
|
192 |
+
elif lower_items or any(word in basic_description.lower() for word in ['pants', 'jeans', 'skirt', 'shorts']):
|
193 |
+
if lower_items:
|
194 |
+
primary_lower = lower_items[0]
|
195 |
+
garment_type = primary_lower['category'].title()
|
196 |
+
else:
|
197 |
+
# Infer from description
|
198 |
+
if 'jeans' in basic_description.lower():
|
199 |
+
garment_type = "Jeans"
|
200 |
+
elif 'pants' in basic_description.lower():
|
201 |
+
garment_type = "Pants"
|
202 |
+
elif 'skirt' in basic_description.lower():
|
203 |
+
garment_type = "Skirt"
|
204 |
+
else:
|
205 |
+
garment_type = "Lower garment"
|
206 |
+
|
207 |
+
analysis_parts.append(f"Type: {garment_type}")
|
208 |
+
analysis_parts.append(f"Color: {self.extract_colors(basic_description)}")
|
209 |
+
analysis_parts.append(f"Material: {self.extract_material(basic_description)}")
|
210 |
+
analysis_parts.append(f"Features: {self.extract_comprehensive_features(basic_description, garment_type)}")
|
211 |
+
else:
|
212 |
+
analysis_parts.append("Type: Not clearly visible in image")
|
213 |
+
analysis_parts.append("Color: Unable to determine")
|
214 |
+
analysis_parts.append("Material: Unable to determine")
|
215 |
+
analysis_parts.append("Features: Unable to determine")
|
216 |
+
|
217 |
+
analysis_parts.append("")
|
218 |
+
|
219 |
+
# FOOTWEAR
|
220 |
+
analysis_parts.append("FOOTWEAR:")
|
221 |
+
if footwear_items or any(word in basic_description.lower() for word in ['shoes', 'boots', 'sneakers', 'heels']):
|
222 |
+
if footwear_items:
|
223 |
+
primary_footwear = footwear_items[0]
|
224 |
+
footwear_type = primary_footwear['category'].title()
|
225 |
+
else:
|
226 |
+
# Infer from description
|
227 |
+
if 'sneakers' in basic_description.lower():
|
228 |
+
footwear_type = "Sneakers"
|
229 |
+
elif 'boots' in basic_description.lower():
|
230 |
+
footwear_type = "Boots"
|
231 |
+
elif 'heels' in basic_description.lower():
|
232 |
+
footwear_type = "Heels"
|
233 |
+
else:
|
234 |
+
footwear_type = "Shoes"
|
235 |
+
|
236 |
+
analysis_parts.append(f"Type: {footwear_type}")
|
237 |
+
analysis_parts.append(f"Color: {self.extract_colors(basic_description)}")
|
238 |
+
analysis_parts.append(f"Material: {self.extract_material(basic_description)}")
|
239 |
+
analysis_parts.append(f"Features: {self.extract_comprehensive_features(basic_description, footwear_type)}")
|
240 |
+
else:
|
241 |
+
analysis_parts.append("Type: Not clearly visible in image")
|
242 |
+
analysis_parts.append("Color: Unable to determine")
|
243 |
+
analysis_parts.append("Material: Unable to determine")
|
244 |
+
analysis_parts.append("Features: Unable to determine")
|
245 |
+
|
246 |
+
analysis_parts.append("")
|
247 |
+
|
248 |
+
# OUTFIT SUMMARY
|
249 |
+
analysis_parts.append("OUTFIT SUMMARY:")
|
250 |
+
outfit_summary = self.create_comprehensive_outfit_summary(detected_items, basic_description)
|
251 |
+
analysis_parts.append(outfit_summary)
|
252 |
+
|
253 |
+
return "\n".join(analysis_parts)
|
254 |
+
|
255 |
+
def extract_comprehensive_features(self, description, garment_type):
|
256 |
+
"""Extract comprehensive features based on garment type"""
|
257 |
+
desc_lower = description.lower()
|
258 |
+
garment_lower = garment_type.lower()
|
259 |
+
|
260 |
+
features = []
|
261 |
+
|
262 |
+
# Pattern and design features
|
263 |
+
pattern = self.extract_pattern(description)
|
264 |
+
if pattern and pattern != "Solid or minimal pattern":
|
265 |
+
features.append(pattern)
|
266 |
+
|
267 |
+
# Garment-specific features
|
268 |
+
if any(word in garment_lower for word in ['shirt', 'blouse', 'top']):
|
269 |
+
# Neckline
|
270 |
+
neckline = self.extract_neckline(description)
|
271 |
+
if neckline != "Neckline present but style not specified":
|
272 |
+
features.append(neckline)
|
273 |
+
|
274 |
+
# Sleeves
|
275 |
+
sleeves = self.extract_sleeves(description)
|
276 |
+
if sleeves != "Sleeve style not specified in description":
|
277 |
+
features.append(sleeves)
|
278 |
+
|
279 |
+
# Collar
|
280 |
+
if 'collar' in desc_lower:
|
281 |
+
features.append("Collared design")
|
282 |
+
|
283 |
+
# Buttons
|
284 |
+
if 'button' in desc_lower:
|
285 |
+
features.append("Button closure")
|
286 |
+
|
287 |
+
elif 'dress' in garment_lower:
|
288 |
+
# Length
|
289 |
+
if 'midi' in desc_lower:
|
290 |
+
features.append("Midi length")
|
291 |
+
elif 'maxi' in desc_lower:
|
292 |
+
features.append("Maxi length")
|
293 |
+
elif 'mini' in desc_lower:
|
294 |
+
features.append("Mini length")
|
295 |
+
|
296 |
+
# Sleeves
|
297 |
+
sleeves = self.extract_sleeves(description)
|
298 |
+
if sleeves != "Sleeve style not specified in description":
|
299 |
+
features.append(sleeves)
|
300 |
+
|
301 |
+
# Neckline
|
302 |
+
neckline = self.extract_neckline(description)
|
303 |
+
if neckline != "Neckline present but style not specified":
|
304 |
+
features.append(neckline)
|
305 |
+
|
306 |
+
# Fit
|
307 |
+
fit = self.extract_fit(description)
|
308 |
+
if fit != "Fit style not specified in description":
|
309 |
+
features.append(fit)
|
310 |
+
|
311 |
+
elif any(word in garment_lower for word in ['pants', 'jeans', 'skirt']):
|
312 |
+
# Fit
|
313 |
+
fit = self.extract_fit(description)
|
314 |
+
if fit != "Fit style not specified in description":
|
315 |
+
features.append(fit)
|
316 |
+
|
317 |
+
# Pockets
|
318 |
+
if 'pocket' in desc_lower:
|
319 |
+
features.append("Pockets")
|
320 |
+
|
321 |
+
# Belt
|
322 |
+
if 'belt' in desc_lower:
|
323 |
+
features.append("Belt")
|
324 |
+
|
325 |
+
# Length for skirts
|
326 |
+
if 'skirt' in garment_lower:
|
327 |
+
if 'mini' in desc_lower:
|
328 |
+
features.append("Mini length")
|
329 |
+
elif 'midi' in desc_lower:
|
330 |
+
features.append("Midi length")
|
331 |
+
elif 'maxi' in desc_lower:
|
332 |
+
features.append("Maxi length")
|
333 |
+
|
334 |
+
elif any(word in garment_lower for word in ['shoes', 'sneakers', 'boots', 'heels']):
|
335 |
+
# Closure
|
336 |
+
if 'lace' in desc_lower:
|
337 |
+
features.append("Lace-up closure")
|
338 |
+
elif 'buckle' in desc_lower:
|
339 |
+
features.append("Buckle closure")
|
340 |
+
elif 'slip' in desc_lower:
|
341 |
+
features.append("Slip-on style")
|
342 |
+
|
343 |
+
# Heel
|
344 |
+
if 'heel' in desc_lower:
|
345 |
+
features.append("Heeled")
|
346 |
+
elif 'flat' in desc_lower:
|
347 |
+
features.append("Flat sole")
|
348 |
+
|
349 |
+
# Style details
|
350 |
+
if 'stud' in desc_lower:
|
351 |
+
features.append("Studded details")
|
352 |
+
|
353 |
+
# General features
|
354 |
+
if 'zip' in desc_lower:
|
355 |
+
features.append("Zipper details")
|
356 |
+
|
357 |
+
return ', '.join(features) if features else "Standard design features"
|
358 |
+
|
359 |
+
def create_comprehensive_outfit_summary(self, detected_items, basic_description):
|
360 |
+
"""Create a comprehensive outfit summary paragraph"""
|
361 |
+
|
362 |
+
# Extract key elements
|
363 |
+
garment_types = [item['category'] for item in detected_items if item['confidence'] > 0.5]
|
364 |
+
colors = self.extract_colors(basic_description)
|
365 |
+
style = self.extract_style(basic_description)
|
366 |
+
pattern = self.extract_pattern(basic_description)
|
367 |
+
|
368 |
+
summary_sentences = []
|
369 |
+
|
370 |
+
# Opening statement about overall aesthetic
|
371 |
+
if garment_types:
|
372 |
+
if 'dress' in garment_types:
|
373 |
+
summary_sentences.append("This outfit centers around an elegant dress that serves as a complete styling solution, demonstrating the power of a well-chosen single piece.")
|
374 |
+
elif len(garment_types) > 1:
|
375 |
+
summary_sentences.append("This outfit showcases thoughtful coordination between multiple garment pieces, creating a cohesive and intentional look.")
|
376 |
+
else:
|
377 |
+
summary_sentences.append("This outfit highlights a key fashion piece with strong individual character and styling potential.")
|
378 |
+
else:
|
379 |
+
summary_sentences.append("This outfit demonstrates contemporary fashion sensibility with carefully considered design elements.")
|
380 |
+
|
381 |
+
# Color and pattern analysis
|
382 |
+
if 'neutral' in colors.lower():
|
383 |
+
summary_sentences.append("The neutral color palette provides exceptional versatility and sophisticated appeal, making it suitable for various occasions and easy to accessorize.")
|
384 |
+
elif 'warm' in colors.lower():
|
385 |
+
summary_sentences.append("The warm color tones create an approachable and energetic aesthetic that conveys confidence and positivity.")
|
386 |
+
elif 'cool' in colors.lower():
|
387 |
+
summary_sentences.append("The cool color palette conveys professionalism and calming elegance, perfect for both casual and semi-formal settings.")
|
388 |
+
|
389 |
+
if 'floral' in pattern.lower():
|
390 |
+
summary_sentences.append("The floral elements add feminine charm and seasonal freshness, bringing natural beauty and romantic appeal to the overall ensemble.")
|
391 |
+
elif 'solid' in pattern.lower():
|
392 |
+
summary_sentences.append("The solid construction maximizes styling flexibility and serves as an excellent foundation for accessory experimentation.")
|
393 |
+
elif 'striped' in pattern.lower():
|
394 |
+
summary_sentences.append("The striped pattern adds visual interest and classic appeal while maintaining timeless sophistication.")
|
395 |
+
|
396 |
+
# Style and occasion assessment
|
397 |
+
if 'casual' in style.lower():
|
398 |
+
summary_sentences.append("The casual styling makes this outfit perfect for everyday wear, weekend activities, and relaxed social occasions while maintaining a polished appearance.")
|
399 |
+
elif 'formal' in style.lower():
|
400 |
+
summary_sentences.append("The formal elements ensure this outfit meets professional standards and elegant occasion requirements with confidence and grace.")
|
401 |
+
else:
|
402 |
+
summary_sentences.append("The versatile design allows this outfit to transition seamlessly between different settings, from casual daytime events to more polished evening occasions.")
|
403 |
+
|
404 |
+
# Concluding statement about fashion-forward thinking
|
405 |
+
summary_sentences.append("The pieces work harmoniously together, reflecting contemporary fashion awareness and demonstrating how thoughtful styling choices can create an effortlessly chic and memorable appearance.")
|
406 |
+
|
407 |
+
return " ".join(summary_sentences)
|
408 |
+
|
409 |
def detect_fashion_objects(self, image):
|
410 |
"""Detect fashion objects using yainage90 fashion detection model"""
|
411 |
if self.detection_model is None or self.detection_processor is None:
|
|
|
480 |
detected_items = detection_results.get('detected_items', [])
|
481 |
detection_summary = self.summarize_detections(detected_items)
|
482 |
|
483 |
+
# Create structured clothing analysis
|
484 |
+
structured_analysis = self.create_structured_clothing_analysis(detected_items, basic_description)
|
485 |
+
|
486 |
# Create comprehensive analysis
|
487 |
analysis_template = f"""🎽 ADVANCED FASHION ANALYSIS REPORT
|
488 |
|
489 |
🔍 AI-POWERED OBJECT DETECTION:
|
490 |
{detection_summary}
|
491 |
|
492 |
+
📋 STRUCTURED CLOTHING ANALYSIS:
|
493 |
+
{structured_analysis}
|
494 |
+
|
495 |
📋 DETAILED GARMENT ANALYSIS:
|
496 |
{self.create_detailed_garment_analysis(detected_items, basic_description)}
|
497 |
|
|
|
514 |
|
515 |
return analysis_template
|
516 |
|
517 |
+
def create_structured_clothing_analysis(self, detected_items, basic_description):
|
518 |
+
"""Create structured clothing analysis in the requested format"""
|
519 |
+
|
520 |
+
# Categorize detected items
|
521 |
+
upper_items = []
|
522 |
+
lower_items = []
|
523 |
+
footwear_items = []
|
524 |
+
|
525 |
+
for item in detected_items:
|
526 |
+
category = item['category'].lower()
|
527 |
+
if category in ['top', 'shirt', 'blouse', 'outer', 'jacket', 'blazer', 'dress']:
|
528 |
+
upper_items.append(item)
|
529 |
+
elif category in ['bottom', 'pants', 'jeans', 'skirt']:
|
530 |
+
lower_items.append(item)
|
531 |
+
elif category in ['shoes']:
|
532 |
+
footwear_items.append(item)
|
533 |
+
|
534 |
+
analysis_parts = []
|
535 |
+
|
536 |
+
# Upper Garment Analysis
|
537 |
+
if upper_items or 'dress' in basic_description.lower() or any(word in basic_description.lower() for word in ['shirt', 'blouse', 'top', 'jacket']):
|
538 |
+
analysis_parts.append("UPPER GARMENT:")
|
539 |
+
if upper_items:
|
540 |
+
primary_upper = upper_items[0]
|
541 |
+
analysis_parts.append(f"Type: {primary_upper['category'].title()}")
|
542 |
+
else:
|
543 |
+
analysis_parts.append(f"Type: {self.extract_garment_type(basic_description)}")
|
544 |
+
|
545 |
+
analysis_parts.append(f"Color: {self.extract_colors(basic_description)}")
|
546 |
+
analysis_parts.append(f"Material: {self.extract_material(basic_description)}")
|
547 |
+
analysis_parts.append(f"Features: {self.extract_features(basic_description)}")
|
548 |
+
analysis_parts.append("")
|
549 |
+
|
550 |
+
# Lower Garment Analysis
|
551 |
+
if lower_items or any(word in basic_description.lower() for word in ['pants', 'jeans', 'skirt', 'shorts']):
|
552 |
+
analysis_parts.append("LOWER GARMENT:")
|
553 |
+
if lower_items:
|
554 |
+
primary_lower = lower_items[0]
|
555 |
+
analysis_parts.append(f"Type: {primary_lower['category'].title()}")
|
556 |
+
else:
|
557 |
+
# Infer from description
|
558 |
+
if 'jeans' in basic_description.lower():
|
559 |
+
analysis_parts.append("Type: Jeans")
|
560 |
+
elif 'pants' in basic_description.lower():
|
561 |
+
analysis_parts.append("Type: Pants")
|
562 |
+
elif 'skirt' in basic_description.lower():
|
563 |
+
analysis_parts.append("Type: Skirt")
|
564 |
+
else:
|
565 |
+
analysis_parts.append("Type: Lower garment")
|
566 |
+
|
567 |
+
analysis_parts.append(f"Color: {self.extract_colors(basic_description)}")
|
568 |
+
analysis_parts.append(f"Material: {self.extract_material(basic_description)}")
|
569 |
+
analysis_parts.append(f"Features: {self.extract_features(basic_description)}")
|
570 |
+
analysis_parts.append("")
|
571 |
+
|
572 |
+
# Footwear Analysis
|
573 |
+
if footwear_items or any(word in basic_description.lower() for word in ['shoes', 'boots', 'sneakers', 'heels']):
|
574 |
+
analysis_parts.append("FOOTWEAR:")
|
575 |
+
if footwear_items:
|
576 |
+
primary_footwear = footwear_items[0]
|
577 |
+
analysis_parts.append(f"Type: {primary_footwear['category'].title()}")
|
578 |
+
else:
|
579 |
+
# Infer from description
|
580 |
+
if 'sneakers' in basic_description.lower():
|
581 |
+
analysis_parts.append("Type: Sneakers")
|
582 |
+
elif 'boots' in basic_description.lower():
|
583 |
+
analysis_parts.append("Type: Boots")
|
584 |
+
elif 'heels' in basic_description.lower():
|
585 |
+
analysis_parts.append("Type: Heels")
|
586 |
+
else:
|
587 |
+
analysis_parts.append("Type: Shoes")
|
588 |
+
|
589 |
+
analysis_parts.append(f"Color: {self.extract_colors(basic_description)}")
|
590 |
+
analysis_parts.append(f"Material: {self.extract_material(basic_description)}")
|
591 |
+
analysis_parts.append(f"Features: {self.extract_features(basic_description)}")
|
592 |
+
analysis_parts.append("")
|
593 |
+
|
594 |
+
# Outfit Summary
|
595 |
+
analysis_parts.append("OUTFIT SUMMARY:")
|
596 |
+
outfit_summary = self.create_outfit_summary(detected_items, basic_description)
|
597 |
+
analysis_parts.append(outfit_summary)
|
598 |
+
|
599 |
+
return "\n".join(analysis_parts)
|
600 |
+
|
601 |
+
def create_outfit_summary(self, detected_items, basic_description):
|
602 |
+
"""Create a comprehensive outfit summary paragraph"""
|
603 |
+
|
604 |
+
# Extract key elements
|
605 |
+
garment_types = [item['category'] for item in detected_items if item['confidence'] > 0.5]
|
606 |
+
colors = self.extract_colors(basic_description)
|
607 |
+
style = self.extract_style(basic_description)
|
608 |
+
pattern = self.extract_pattern(basic_description)
|
609 |
+
|
610 |
+
summary_parts = []
|
611 |
+
|
612 |
+
# Start with overall style assessment
|
613 |
+
if garment_types:
|
614 |
+
if 'dress' in garment_types:
|
615 |
+
summary_parts.append("This outfit centers around an elegant dress that serves as a complete styling solution.")
|
616 |
+
elif 'top' in garment_types and 'bottom' in garment_types:
|
617 |
+
summary_parts.append("This outfit features a well-coordinated combination of separates that create a cohesive look.")
|
618 |
+
elif len(garment_types) > 1:
|
619 |
+
summary_parts.append("This outfit demonstrates thoughtful layering and coordination between multiple garment pieces.")
|
620 |
+
else:
|
621 |
+
summary_parts.append("This outfit showcases a key fashion piece with strong individual character.")
|
622 |
+
else:
|
623 |
+
summary_parts.append("This outfit demonstrates contemporary fashion sensibility with versatile appeal.")
|
624 |
+
|
625 |
+
# Add color and pattern insights
|
626 |
+
if 'neutral' in colors.lower():
|
627 |
+
summary_parts.append("The neutral color palette provides excellent versatility and sophisticated appeal.")
|
628 |
+
elif 'warm' in colors.lower():
|
629 |
+
summary_parts.append("The warm color tones create an approachable and energetic aesthetic.")
|
630 |
+
elif 'cool' in colors.lower():
|
631 |
+
summary_parts.append("The cool color palette conveys professionalism and calming elegance.")
|
632 |
+
|
633 |
+
if 'floral' in pattern.lower():
|
634 |
+
summary_parts.append("The floral elements add feminine charm and seasonal freshness to the overall look.")
|
635 |
+
elif 'solid' in pattern.lower():
|
636 |
+
summary_parts.append("The solid construction maximizes styling flexibility and accessory compatibility.")
|
637 |
+
|
638 |
+
# Add style context
|
639 |
+
if 'casual' in style.lower():
|
640 |
+
summary_parts.append("The casual styling makes this outfit perfect for everyday wear and relaxed social occasions.")
|
641 |
+
elif 'formal' in style.lower():
|
642 |
+
summary_parts.append("The formal elements ensure this outfit is suitable for professional and elegant occasions.")
|
643 |
+
elif 'versatile' in style.lower():
|
644 |
+
summary_parts.append("The versatile design allows this outfit to transition seamlessly between different settings and occasions.")
|
645 |
+
|
646 |
+
# Conclude with overall assessment
|
647 |
+
summary_parts.append("The pieces complement each other harmoniously, creating a polished and intentional appearance that reflects contemporary fashion awareness.")
|
648 |
+
|
649 |
+
return " ".join(summary_parts)
|
650 |
+
|
651 |
def summarize_detections(self, detected_items):
|
652 |
"""Summarize detected fashion items"""
|
653 |
if not detected_items:
|
|
|
1555 |
<div class="upload-area">
|
1556 |
<input type="file" id="imageInput" accept="image/*" style="margin: 10px;">
|
1557 |
<br>
|
1558 |
+
<button onclick="analyzeImage()" style="padding: 10px 20px; margin: 10px;">Analyze Fashion (Detailed)</button>
|
1559 |
+
<button onclick="analyzeStructured()" style="padding: 10px 20px; margin: 10px;">Analyze Fashion (Structured)</button>
|
1560 |
+
<br>
|
1561 |
+
<a href="/refined-prompt" target="_blank" style="color: #007bff; text-decoration: none;">View Refined Prompt Format</a>
|
1562 |
</div>
|
1563 |
|
1564 |
<div id="result" class="result" style="display: none;">
|
|
|
1570 |
async function analyzeImage() {
|
1571 |
const input = document.getElementById('imageInput');
|
1572 |
const file = input.files[0];
|
1573 |
+
|
1574 |
if (!file) {
|
1575 |
alert('Please select an image file');
|
1576 |
return;
|
1577 |
}
|
1578 |
+
|
1579 |
const formData = new FormData();
|
1580 |
formData.append('file', file);
|
1581 |
+
|
1582 |
document.getElementById('analysisText').textContent = 'Analyzing... Please wait...';
|
1583 |
document.getElementById('result').style.display = 'block';
|
1584 |
+
|
1585 |
try {
|
1586 |
const response = await fetch('/analyze-image', {
|
1587 |
method: 'POST',
|
1588 |
body: formData
|
1589 |
});
|
1590 |
+
|
1591 |
+
const result = await response.json();
|
1592 |
+
document.getElementById('analysisText').textContent = result.analysis;
|
1593 |
+
} catch (error) {
|
1594 |
+
document.getElementById('analysisText').textContent = 'Error: ' + error.message;
|
1595 |
+
}
|
1596 |
+
}
|
1597 |
+
|
1598 |
+
async function analyzeStructured() {
|
1599 |
+
const input = document.getElementById('imageInput');
|
1600 |
+
const file = input.files[0];
|
1601 |
+
|
1602 |
+
if (!file) {
|
1603 |
+
alert('Please select an image file');
|
1604 |
+
return;
|
1605 |
+
}
|
1606 |
+
|
1607 |
+
const formData = new FormData();
|
1608 |
+
formData.append('file', file);
|
1609 |
+
|
1610 |
+
document.getElementById('analysisText').textContent = 'Analyzing with structured format... Please wait...';
|
1611 |
+
document.getElementById('result').style.display = 'block';
|
1612 |
+
|
1613 |
+
try {
|
1614 |
+
const response = await fetch('/analyze-structured', {
|
1615 |
+
method: 'POST',
|
1616 |
+
body: formData
|
1617 |
+
});
|
1618 |
+
|
1619 |
const result = await response.json();
|
1620 |
document.getElementById('analysisText').textContent = result.analysis;
|
1621 |
} catch (error) {
|
|
|
1642 |
except Exception as e:
|
1643 |
raise HTTPException(status_code=500, detail=f"Error analyzing image: {str(e)}")
|
1644 |
|
1645 |
+
@app.post("/analyze-structured", response_model=AnalysisResponse)
|
1646 |
+
async def analyze_structured(file: UploadFile = File(...)):
|
1647 |
+
"""Analyze uploaded image with structured format"""
|
1648 |
+
try:
|
1649 |
+
# Read image bytes
|
1650 |
+
image_bytes = await file.read()
|
1651 |
+
|
1652 |
+
# Get structured analysis
|
1653 |
+
analysis = analyzer.analyze_clothing_structured_format(image_bytes)
|
1654 |
+
|
1655 |
+
return AnalysisResponse(analysis=analysis)
|
1656 |
+
|
1657 |
+
except Exception as e:
|
1658 |
+
raise HTTPException(status_code=500, detail=f"Error analyzing image: {str(e)}")
|
1659 |
+
|
1660 |
+
@app.get("/refined-prompt", response_class=PlainTextResponse)
|
1661 |
+
async def get_refined_prompt():
|
1662 |
+
"""Get the refined prompt for clothing analysis"""
|
1663 |
+
refined_prompt = """
|
1664 |
+
REFINED CLOTHING ANALYSIS PROMPT
|
1665 |
+
|
1666 |
+
This task involves analyzing an image of a person and providing a detailed description of their clothing, focusing on the upper garment, lower garment, and footwear. Your response should follow this structured format:
|
1667 |
+
|
1668 |
+
ANALYSIS STRUCTURE:
|
1669 |
+
|
1670 |
+
1. UPPER GARMENT:
|
1671 |
+
Type: [e.g., shirt, blouse, sweater, t-shirt, dress, jacket, blazer]
|
1672 |
+
Color: [Primary color and any secondary colors with color theory insights]
|
1673 |
+
Material: [Fabric type if visible, or intelligent inference based on garment type]
|
1674 |
+
Features: [Distinguishing features like patterns, buttons, collars, sleeves, neckline]
|
1675 |
+
|
1676 |
+
2. LOWER GARMENT:
|
1677 |
+
Type: [e.g., jeans, pants, skirt, shorts, trousers]
|
1678 |
+
Color: [Primary color and any secondary colors]
|
1679 |
+
Material: [Fabric type if visible, or intelligent inference]
|
1680 |
+
Features: [Distinguishing features like pockets, belt, pleats, fit, length]
|
1681 |
+
|
1682 |
+
3. FOOTWEAR:
|
1683 |
+
Type: [e.g., sneakers, heels, boots, flats, sandals]
|
1684 |
+
Color: [Primary color and any secondary colors]
|
1685 |
+
Material: [Material type if visible, or intelligent inference]
|
1686 |
+
Features: [Distinguishing features like laces, buckles, studs, heel height, style]
|
1687 |
+
|
1688 |
+
4. OUTFIT SUMMARY:
|
1689 |
+
Provide a comprehensive paragraph (3-5 sentences) that:
|
1690 |
+
- Describes the overall aesthetic and style of the outfit
|
1691 |
+
- Explains how the different pieces complement each other
|
1692 |
+
- Assesses the occasion appropriateness and versatility
|
1693 |
+
- Includes color harmony and pattern coordination analysis
|
1694 |
+
- Offers styling insights and fashion-forward observations
|
1695 |
+
|
1696 |
+
ANALYSIS GUIDELINES:
|
1697 |
+
|
1698 |
+
• For each field, provide detailed descriptions that capture both visible elements and professional fashion insights
|
1699 |
+
• Use fashion terminology appropriately (silhouette, drape, texture, etc.)
|
1700 |
+
• Include color theory analysis (warm/cool tones, neutrals, seasonal appropriateness)
|
1701 |
+
• Consider fit, proportion, and styling principles
|
1702 |
+
• Assess formality level and occasion suitability
|
1703 |
+
• Provide intelligent inferences when specific details aren't clearly visible
|
1704 |
+
• The Outfit Summary should be creative, informative, and demonstrate fashion expertise
|
1705 |
+
|
1706 |
+
OUTPUT FORMAT:
|
1707 |
+
Structure your response exactly as shown above, with clear section headers and consistent formatting. Each section should provide both factual observations and professional fashion analysis.
|
1708 |
+
|
1709 |
+
EXAMPLE OUTPUT FORMAT:
|
1710 |
+
|
1711 |
+
UPPER GARMENT:
|
1712 |
+
Type: Floral midi dress
|
1713 |
+
Color: Navy blue base with white and pink floral print (cool-toned palette, versatile for multiple seasons)
|
1714 |
+
Material: Lightweight cotton or cotton blend (suitable for comfort and drape)
|
1715 |
+
Features: Short sleeves, round neckline, fitted bodice with A-line skirt, all-over floral pattern
|
1716 |
+
|
1717 |
+
LOWER GARMENT:
|
1718 |
+
[Not applicable - dress serves as complete outfit]
|
1719 |
+
|
1720 |
+
FOOTWEAR:
|
1721 |
+
Type: White leather sneakers
|
1722 |
+
Color: Clean white with minimal accent details
|
1723 |
+
Material: Leather upper with rubber sole
|
1724 |
+
Features: Lace-up closure, low-profile design, classic athletic styling
|
1725 |
+
|
1726 |
+
OUTFIT SUMMARY:
|
1727 |
+
This outfit demonstrates a perfect balance between feminine charm and casual comfort through the floral midi dress paired with clean white sneakers. The navy blue base with delicate floral motifs creates visual interest while maintaining sophistication, making it suitable for daytime social events, casual dates, or weekend outings. The contrast between the dress's romantic aesthetic and the sneakers' sporty edge exemplifies modern mixed-styling approaches. The cool-toned color palette ensures versatility across seasons, while the comfortable silhouette and practical footwear choice reflect contemporary lifestyle needs. This combination successfully bridges the gap between dressed-up and dressed-down, creating an effortlessly chic appearance that's both approachable and stylish.
|
1728 |
+
"""
|
1729 |
+
return refined_prompt
|
1730 |
+
|
1731 |
@app.get("/health")
|
1732 |
async def health_check():
|
1733 |
"""Health check endpoint"""
|