Spaces:
Sleeping
Sleeping
Commit
Β·
bb71884
1
Parent(s):
d7e6224
Add enhanced fashion analysis features with refined prompt
Browse files- Introduced a new endpoint `/analyze-enhanced` for detailed fashion analysis.
- Created a comprehensive README detailing the enhanced analysis capabilities.
- Developed a demo script `demo_enhanced_analysis.py` to showcase new features.
- Implemented enhanced analysis methods in `fast.py` for improved feature extraction.
- Added a test script `test_enhanced_analysis.py` to validate the new analysis methods.
- ENHANCED_ANALYSIS_README.md +156 -0
- demo_enhanced_analysis.py +174 -0
- fast.py +563 -64
- test_enhanced_analysis.py +139 -0
ENHANCED_ANALYSIS_README.md
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Enhanced Fashion Analysis with Refined Prompt
|
2 |
+
|
3 |
+
This document describes the enhanced fashion analysis capabilities that have been integrated into the Vestiq system, featuring a refined prompt optimized for better feature extraction and outfit recommendation.
|
4 |
+
|
5 |
+
## π New Features
|
6 |
+
|
7 |
+
### Enhanced Analysis Endpoint
|
8 |
+
- **Endpoint**: `/analyze-enhanced`
|
9 |
+
- **Method**: POST
|
10 |
+
- **Input**: Image file
|
11 |
+
- **Output**: Detailed fashion analysis using the refined prompt format
|
12 |
+
|
13 |
+
### Refined Prompt Format
|
14 |
+
The enhanced analysis uses a sophisticated prompt structure that includes:
|
15 |
+
|
16 |
+
1. **Fashion-specific vocabulary** (oversized, tailored, cropped, monochromatic, muted tones)
|
17 |
+
2. **Color theory analysis** (harmony/contrast, seasonal suitability, tone warmth)
|
18 |
+
3. **Formality level inference** (smart casual, athleisure, streetwear, semi-formal)
|
19 |
+
4. **Fit and silhouette analysis** (slim-fit, relaxed, boxy, flowy)
|
20 |
+
5. **Comprehensive feature extraction** with context and styling insights
|
21 |
+
|
22 |
+
## π Analysis Structure
|
23 |
+
|
24 |
+
### 1. Upper Garment
|
25 |
+
- **Type**: Specific garment identification
|
26 |
+
- **Color**: Primary color + tone category (warm, cool, neutral)
|
27 |
+
- **Material**: Fabric type with texture details
|
28 |
+
- **Features**: Detailed styling elements and construction details
|
29 |
+
|
30 |
+
### 2. Lower Garment
|
31 |
+
- **Type**: Bottom wear identification
|
32 |
+
- **Color**: Color coordination with upper garment
|
33 |
+
- **Material**: Fabric inference with care considerations
|
34 |
+
- **Features**: Cut, fit, and styling details
|
35 |
+
|
36 |
+
### 3. Footwear
|
37 |
+
- **Type**: Shoe category and style
|
38 |
+
- **Color**: Color harmony with outfit
|
39 |
+
- **Material**: Material quality and durability insights
|
40 |
+
- **Features**: Construction and styling details
|
41 |
+
|
42 |
+
### 4. Outfit Summary
|
43 |
+
A comprehensive 3-5 sentence analysis covering:
|
44 |
+
- Overall style and fashion intent
|
45 |
+
- Color, texture, and silhouette interaction
|
46 |
+
- Cohesion and balance between garments
|
47 |
+
- Occasion suitability assessment
|
48 |
+
- Fashion-forward observations
|
49 |
+
|
50 |
+
## π§ Enhanced Extraction Methods
|
51 |
+
|
52 |
+
### Color Analysis (`extract_enhanced_colors`)
|
53 |
+
- Tone categorization (warm, cool, neutral)
|
54 |
+
- Seasonal appropriateness
|
55 |
+
- Styling context and versatility
|
56 |
+
- Color harmony assessment
|
57 |
+
|
58 |
+
### Material Analysis (`extract_enhanced_material`)
|
59 |
+
- Texture descriptions
|
60 |
+
- Care requirements
|
61 |
+
- Quality indicators
|
62 |
+
- Garment-appropriate fabric inference
|
63 |
+
|
64 |
+
### Feature Analysis (`extract_enhanced_features`)
|
65 |
+
- Detailed construction elements
|
66 |
+
- Styling implications
|
67 |
+
- Fashion terminology
|
68 |
+
- Fit and silhouette descriptions
|
69 |
+
|
70 |
+
## π― Usage Examples
|
71 |
+
|
72 |
+
### Basic Usage
|
73 |
+
```bash
|
74 |
+
# Start the server
|
75 |
+
python fast.py
|
76 |
+
|
77 |
+
# Test with an image
|
78 |
+
python test_enhanced_analysis.py path/to/your/image.jpg
|
79 |
+
```
|
80 |
+
|
81 |
+
### API Usage
|
82 |
+
```python
|
83 |
+
import requests
|
84 |
+
|
85 |
+
# Enhanced analysis
|
86 |
+
with open('image.jpg', 'rb') as f:
|
87 |
+
files = {'file': f}
|
88 |
+
response = requests.post('http://localhost:7861/analyze-enhanced', files=files)
|
89 |
+
analysis = response.text
|
90 |
+
print(analysis)
|
91 |
+
```
|
92 |
+
|
93 |
+
### Compare Analysis Methods
|
94 |
+
```bash
|
95 |
+
# Compare all analysis methods
|
96 |
+
python test_enhanced_analysis.py image.jpg
|
97 |
+
```
|
98 |
+
|
99 |
+
## π Comparison with Existing Methods
|
100 |
+
|
101 |
+
| Feature | Basic Analysis | Structured Analysis | Enhanced Analysis |
|
102 |
+
|---------|---------------|-------------------|------------------|
|
103 |
+
| Fashion Vocabulary | Basic | Moderate | Advanced |
|
104 |
+
| Color Theory | Limited | Basic | Comprehensive |
|
105 |
+
| Material Inference | Basic | Moderate | Detailed |
|
106 |
+
| Feature Extraction | Simple | Structured | Sophisticated |
|
107 |
+
| Styling Context | Minimal | Some | Extensive |
|
108 |
+
| Output Format | Text | JSON/Text | Formatted Text |
|
109 |
+
|
110 |
+
## π¨ Key Improvements
|
111 |
+
|
112 |
+
1. **Fashion-Forward Language**: Uses professional fashion terminology
|
113 |
+
2. **Color Theory Integration**: Includes tone analysis and seasonal context
|
114 |
+
3. **Material Intelligence**: Provides texture, care, and quality insights
|
115 |
+
4. **Comprehensive Features**: Detailed construction and styling elements
|
116 |
+
5. **Sophisticated Summaries**: Fashion-expert level outfit analysis
|
117 |
+
6. **Better Structure**: Clear, consistent formatting for easy parsing
|
118 |
+
|
119 |
+
## π Integration with Existing System
|
120 |
+
|
121 |
+
The enhanced analysis integrates seamlessly with the existing yainage90 models:
|
122 |
+
- Uses the same object detection pipeline
|
123 |
+
- Leverages existing feature extraction
|
124 |
+
- Maintains compatibility with current API structure
|
125 |
+
- Adds new endpoint without breaking existing functionality
|
126 |
+
|
127 |
+
## π Benefits for Outfit Recommendation
|
128 |
+
|
129 |
+
1. **Better Feature Extraction**: More detailed garment characteristics
|
130 |
+
2. **Style Context**: Understanding of fashion intent and occasion
|
131 |
+
3. **Color Harmony**: Better color coordination recommendations
|
132 |
+
4. **Material Awareness**: Fabric-appropriate styling suggestions
|
133 |
+
5. **Professional Insights**: Fashion-expert level analysis quality
|
134 |
+
|
135 |
+
## π οΈ Technical Implementation
|
136 |
+
|
137 |
+
The enhanced analysis is implemented through:
|
138 |
+
- New analysis method: `analyze_clothing_enhanced_prompt_format()`
|
139 |
+
- Enhanced extraction methods with fashion context
|
140 |
+
- Sophisticated outfit summary generation
|
141 |
+
- Professional fashion terminology integration
|
142 |
+
- Improved color and material analysis
|
143 |
+
|
144 |
+
## π Future Enhancements
|
145 |
+
|
146 |
+
Potential improvements could include:
|
147 |
+
- Integration with fashion trend data
|
148 |
+
- Seasonal styling recommendations
|
149 |
+
- Body type considerations
|
150 |
+
- Brand and price point analysis
|
151 |
+
- Sustainability and care instructions
|
152 |
+
- Cultural and regional style preferences
|
153 |
+
|
154 |
+
---
|
155 |
+
|
156 |
+
This enhanced analysis system provides a significant upgrade to the fashion analysis capabilities, offering professional-level insights that can power sophisticated outfit recommendation systems.
|
demo_enhanced_analysis.py
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Demo script showing the enhanced fashion analysis capabilities
|
4 |
+
"""
|
5 |
+
|
6 |
+
import requests
|
7 |
+
import json
|
8 |
+
from pathlib import Path
|
9 |
+
|
10 |
+
def demo_enhanced_analysis():
|
11 |
+
"""Demonstrate the enhanced analysis features"""
|
12 |
+
|
13 |
+
server_url = "http://localhost:7861"
|
14 |
+
|
15 |
+
print("π½ Enhanced Fashion Analysis Demo")
|
16 |
+
print("=" * 60)
|
17 |
+
|
18 |
+
# First, show the refined prompt
|
19 |
+
print("\nπ 1. Refined Prompt Structure")
|
20 |
+
print("-" * 40)
|
21 |
+
|
22 |
+
try:
|
23 |
+
response = requests.get(f"{server_url}/refined-prompt")
|
24 |
+
if response.status_code == 200:
|
25 |
+
prompt = response.text
|
26 |
+
# Show just the key sections
|
27 |
+
lines = prompt.split('\n')
|
28 |
+
for i, line in enumerate(lines):
|
29 |
+
if i < 50: # Show first 50 lines
|
30 |
+
print(line)
|
31 |
+
print("... (truncated for demo)")
|
32 |
+
else:
|
33 |
+
print(f"β Error getting prompt: {response.status_code}")
|
34 |
+
except Exception as e:
|
35 |
+
print(f"β Error: {e}")
|
36 |
+
|
37 |
+
print("\nπ 2. Analysis Capabilities")
|
38 |
+
print("-" * 40)
|
39 |
+
|
40 |
+
# Show the different endpoints available
|
41 |
+
endpoints = [
|
42 |
+
("/analyze-enhanced", "Enhanced Prompt Analysis", "Advanced fashion analysis with detailed insights"),
|
43 |
+
("/analyze-structured", "Structured Analysis", "JSON format with structured data"),
|
44 |
+
("/analyze", "Basic Analysis", "Standard fashion analysis"),
|
45 |
+
("/detect-objects", "Object Detection", "Fashion item detection only"),
|
46 |
+
("/extract-features", "Feature Extraction", "Fashion feature vectors")
|
47 |
+
]
|
48 |
+
|
49 |
+
for endpoint, name, description in endpoints:
|
50 |
+
print(f"β’ {name}: {endpoint}")
|
51 |
+
print(f" {description}")
|
52 |
+
|
53 |
+
print("\nπ¨ 3. Enhanced Features")
|
54 |
+
print("-" * 40)
|
55 |
+
|
56 |
+
features = [
|
57 |
+
"Fashion-specific vocabulary (oversized, tailored, cropped, monochromatic)",
|
58 |
+
"Color theory analysis (warm/cool tones, seasonal suitability)",
|
59 |
+
"Formality level inference (smart casual, athleisure, streetwear)",
|
60 |
+
"Fit and silhouette analysis (slim-fit, relaxed, boxy, flowy)",
|
61 |
+
"Material intelligence (texture, care, quality insights)",
|
62 |
+
"Comprehensive feature extraction with styling context",
|
63 |
+
"Professional outfit summaries with fashion expertise"
|
64 |
+
]
|
65 |
+
|
66 |
+
for feature in features:
|
67 |
+
print(f"β {feature}")
|
68 |
+
|
69 |
+
print("\nπ 4. Sample Analysis Structure")
|
70 |
+
print("-" * 40)
|
71 |
+
|
72 |
+
sample_analysis = """
|
73 |
+
**UPPER GARMENT**
|
74 |
+
|
75 |
+
**Type**: Button-down chambray shirt
|
76 |
+
**Color**: Light denim blue (cool tone) with faded areas on collar and seams
|
77 |
+
**Material**: Chambray (lightweight woven cotton)
|
78 |
+
**Features**: Long sleeves rolled to elbows, pointed collar, front patch pockets, relaxed fit, visible stitching
|
79 |
+
|
80 |
+
---
|
81 |
+
|
82 |
+
**LOWER GARMENT**
|
83 |
+
|
84 |
+
**Type**: Black slim-fit chinos
|
85 |
+
**Color**: Solid black (neutral tone)
|
86 |
+
**Material**: Stretch cotton twill
|
87 |
+
**Features**: Flat front, minimal pockets, cropped ankle length, clean silhouette
|
88 |
+
|
89 |
+
---
|
90 |
+
|
91 |
+
**FOOTWEAR**
|
92 |
+
|
93 |
+
**Type**: White minimalist sneakers
|
94 |
+
**Color**: White with subtle grey accents on heel tab
|
95 |
+
**Material**: Leather upper with rubber sole
|
96 |
+
**Features**: Lace-up closure, low-profile design, round toe
|
97 |
+
|
98 |
+
---
|
99 |
+
|
100 |
+
**OUTFIT SUMMARY**
|
101 |
+
|
102 |
+
This outfit channels effortless smart-casual style with its blend of soft textures and minimal structure. The chambray shirt introduces a laid-back, workwear-inspired vibe, complemented by the refined edge of slim black chinos. The white sneakers tie the look together with understated coolness, ensuring comfort without sacrificing polish. The color palette of light blue, black, and white reflects balance and neutrality, making the outfit adaptable for casual office settings, social outings, or relaxed dates. The overall silhouette is clean and streamlined, making it modern, versatile, and easy to accessorize.
|
103 |
+
"""
|
104 |
+
|
105 |
+
print(sample_analysis)
|
106 |
+
|
107 |
+
print("\nπ 5. Usage Instructions")
|
108 |
+
print("-" * 40)
|
109 |
+
|
110 |
+
usage_instructions = [
|
111 |
+
"1. Start the server: python fast.py",
|
112 |
+
"2. Test with image: python test_enhanced_analysis.py your_image.jpg",
|
113 |
+
"3. Use API endpoint: POST /analyze-enhanced with image file",
|
114 |
+
"4. Compare methods: python test_enhanced_analysis.py image.jpg",
|
115 |
+
"5. Get refined prompt: GET /refined-prompt"
|
116 |
+
]
|
117 |
+
|
118 |
+
for instruction in usage_instructions:
|
119 |
+
print(instruction)
|
120 |
+
|
121 |
+
print("\nπ‘ 6. Benefits for Outfit Recommendation")
|
122 |
+
print("-" * 40)
|
123 |
+
|
124 |
+
benefits = [
|
125 |
+
"Better feature extraction for recommendation algorithms",
|
126 |
+
"Style context understanding for occasion-based suggestions",
|
127 |
+
"Color harmony analysis for coordinated outfit building",
|
128 |
+
"Material awareness for fabric-appropriate styling",
|
129 |
+
"Professional-level fashion insights for quality recommendations"
|
130 |
+
]
|
131 |
+
|
132 |
+
for benefit in benefits:
|
133 |
+
print(f"β’ {benefit}")
|
134 |
+
|
135 |
+
print("\n" + "=" * 60)
|
136 |
+
print("π― Ready to test! Use the test script with your fashion images.")
|
137 |
+
print("=" * 60)
|
138 |
+
|
139 |
+
def check_server_status():
|
140 |
+
"""Check if the server is running"""
|
141 |
+
|
142 |
+
server_url = "http://localhost:7861"
|
143 |
+
|
144 |
+
try:
|
145 |
+
response = requests.get(f"{server_url}/health")
|
146 |
+
if response.status_code == 200:
|
147 |
+
data = response.json()
|
148 |
+
print(f"β
Server is running: {data}")
|
149 |
+
return True
|
150 |
+
else:
|
151 |
+
print(f"β Server health check failed: {response.status_code}")
|
152 |
+
return False
|
153 |
+
except requests.exceptions.ConnectionError:
|
154 |
+
print("β Server is not running. Start it with: python fast.py")
|
155 |
+
return False
|
156 |
+
except Exception as e:
|
157 |
+
print(f"β Error checking server: {e}")
|
158 |
+
return False
|
159 |
+
|
160 |
+
def main():
|
161 |
+
"""Main demo function"""
|
162 |
+
|
163 |
+
print("π Checking server status...")
|
164 |
+
if check_server_status():
|
165 |
+
print("\n")
|
166 |
+
demo_enhanced_analysis()
|
167 |
+
else:
|
168 |
+
print("\nπ To start the demo:")
|
169 |
+
print("1. Run: python fast.py")
|
170 |
+
print("2. Wait for server to start")
|
171 |
+
print("3. Run: python demo_enhanced_analysis.py")
|
172 |
+
|
173 |
+
if __name__ == "__main__":
|
174 |
+
main()
|
fast.py
CHANGED
@@ -201,6 +201,26 @@ class HuggingFaceFashionAnalyzer:
|
|
201 |
except Exception as e:
|
202 |
return f"Error analyzing image: {str(e)}"
|
203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
def create_refined_structured_analysis(self, detection_results, basic_description):
|
205 |
"""Create analysis in the exact refined format requested"""
|
206 |
|
@@ -311,6 +331,129 @@ class HuggingFaceFashionAnalyzer:
|
|
311 |
|
312 |
return "\n".join(analysis_parts)
|
313 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
def extract_comprehensive_features(self, description, garment_type):
|
315 |
"""Extract comprehensive features based on garment type"""
|
316 |
desc_lower = description.lower()
|
@@ -1571,6 +1714,317 @@ class HuggingFaceFashionAnalyzer:
|
|
1571 |
found_features = [feature for feature in feature_keywords if feature in description_lower]
|
1572 |
return ', '.join(found_features).title() if found_features else "Specific features not clearly visible"
|
1573 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1574 |
def extract_style(self, description):
|
1575 |
"""Extract style information with intelligent inference"""
|
1576 |
description_lower = description.lower()
|
@@ -2029,7 +2483,20 @@ async def analyze_structured(file: UploadFile = File(...)):
|
|
2029 |
except Exception as e:
|
2030 |
raise HTTPException(status_code=500, detail=f"Error analyzing image: {str(e)}")
|
2031 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2032 |
|
|
|
|
|
|
|
|
|
2033 |
|
2034 |
@app.post("/detect-objects", response_model=Dict[str, Any])
|
2035 |
async def detect_objects(file: UploadFile = File(...)):
|
@@ -2071,70 +2538,102 @@ async def extract_features(file: UploadFile = File(...)):
|
|
2071 |
async def get_refined_prompt():
|
2072 |
"""Get the refined prompt for clothing analysis"""
|
2073 |
refined_prompt = """
|
2074 |
-
|
2075 |
-
|
2076 |
-
|
2077 |
-
|
2078 |
-
|
2079 |
-
|
2080 |
-
|
2081 |
-
|
2082 |
-
|
2083 |
-
|
2084 |
-
|
2085 |
-
|
2086 |
-
|
2087 |
-
|
2088 |
-
|
2089 |
-
|
2090 |
-
|
2091 |
-
|
2092 |
-
|
2093 |
-
|
2094 |
-
|
2095 |
-
|
2096 |
-
|
2097 |
-
|
2098 |
-
|
2099 |
-
|
2100 |
-
|
2101 |
-
|
2102 |
-
|
2103 |
-
|
2104 |
-
|
2105 |
-
|
2106 |
-
|
2107 |
-
|
2108 |
-
|
2109 |
-
|
2110 |
-
|
2111 |
-
|
2112 |
-
|
2113 |
-
|
2114 |
-
|
2115 |
-
|
2116 |
-
|
2117 |
-
|
2118 |
-
|
2119 |
-
|
2120 |
-
|
2121 |
-
|
2122 |
-
|
2123 |
-
|
2124 |
-
|
2125 |
-
|
2126 |
-
|
2127 |
-
|
2128 |
-
|
2129 |
-
|
2130 |
-
|
2131 |
-
|
2132 |
-
|
2133 |
-
|
2134 |
-
|
2135 |
-
|
2136 |
-
|
2137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2138 |
"""
|
2139 |
return refined_prompt
|
2140 |
|
|
|
201 |
except Exception as e:
|
202 |
return f"Error analyzing image: {str(e)}"
|
203 |
|
204 |
+
def analyze_clothing_enhanced_prompt_format(self, image_bytes):
|
205 |
+
"""Analyze clothing using the enhanced prompt format optimized for feature extraction"""
|
206 |
+
try:
|
207 |
+
# Process image
|
208 |
+
image = self.process_image_from_bytes(image_bytes)
|
209 |
+
|
210 |
+
# Get fashion object detection results
|
211 |
+
detection_results = self.detect_fashion_objects(image)
|
212 |
+
|
213 |
+
# Get basic image description as fallback
|
214 |
+
basic_description = self.get_basic_description(image)
|
215 |
+
|
216 |
+
# Create enhanced analysis using the refined prompt structure
|
217 |
+
analysis = self.create_enhanced_prompt_analysis(detection_results, basic_description)
|
218 |
+
|
219 |
+
return analysis
|
220 |
+
|
221 |
+
except Exception as e:
|
222 |
+
return f"Error analyzing image: {str(e)}"
|
223 |
+
|
224 |
def create_refined_structured_analysis(self, detection_results, basic_description):
|
225 |
"""Create analysis in the exact refined format requested"""
|
226 |
|
|
|
331 |
|
332 |
return "\n".join(analysis_parts)
|
333 |
|
334 |
+
def create_enhanced_prompt_analysis(self, detection_results, basic_description):
|
335 |
+
"""Create analysis using the enhanced prompt format optimized for feature extraction"""
|
336 |
+
|
337 |
+
# Process detection results
|
338 |
+
detected_items = detection_results.get('detected_items', [])
|
339 |
+
|
340 |
+
# Categorize detected items
|
341 |
+
upper_items = []
|
342 |
+
lower_items = []
|
343 |
+
footwear_items = []
|
344 |
+
|
345 |
+
for item in detected_items:
|
346 |
+
category = item['category'].lower()
|
347 |
+
if category in ['top', 'shirt', 'blouse', 'outer', 'jacket', 'blazer', 'dress']:
|
348 |
+
upper_items.append(item)
|
349 |
+
elif category in ['bottom', 'pants', 'jeans', 'skirt']:
|
350 |
+
lower_items.append(item)
|
351 |
+
elif category in ['shoes']:
|
352 |
+
footwear_items.append(item)
|
353 |
+
|
354 |
+
analysis_parts = []
|
355 |
+
|
356 |
+
# UPPER GARMENT
|
357 |
+
analysis_parts.append("**UPPER GARMENT**")
|
358 |
+
analysis_parts.append("")
|
359 |
+
if upper_items or 'dress' in basic_description.lower() or any(word in basic_description.lower() for word in ['shirt', 'blouse', 'top', 'jacket']):
|
360 |
+
if upper_items:
|
361 |
+
primary_upper = upper_items[0]
|
362 |
+
garment_type = primary_upper['category'].title()
|
363 |
+
else:
|
364 |
+
garment_type = self.extract_garment_type(basic_description)
|
365 |
+
|
366 |
+
analysis_parts.append(f"**Type**: {garment_type}")
|
367 |
+
analysis_parts.append(f"**Color**: {self.extract_enhanced_colors(basic_description)}")
|
368 |
+
analysis_parts.append(f"**Material**: {self.extract_enhanced_material(basic_description, garment_type)}")
|
369 |
+
analysis_parts.append(f"**Features**: {self.extract_enhanced_features(basic_description, garment_type)}")
|
370 |
+
else:
|
371 |
+
analysis_parts.append("**Type**: Not clearly visible in image")
|
372 |
+
analysis_parts.append("**Color**: Unable to determine")
|
373 |
+
analysis_parts.append("**Material**: Unable to determine")
|
374 |
+
analysis_parts.append("**Features**: Unable to determine")
|
375 |
+
|
376 |
+
analysis_parts.append("")
|
377 |
+
analysis_parts.append("---")
|
378 |
+
analysis_parts.append("")
|
379 |
+
|
380 |
+
# LOWER GARMENT
|
381 |
+
analysis_parts.append("**LOWER GARMENT**")
|
382 |
+
analysis_parts.append("")
|
383 |
+
if 'dress' in basic_description.lower() and not lower_items:
|
384 |
+
analysis_parts.append("**Type**: Not applicable - dress serves as complete outfit")
|
385 |
+
analysis_parts.append("**Color**: N/A")
|
386 |
+
analysis_parts.append("**Material**: N/A")
|
387 |
+
analysis_parts.append("**Features**: N/A")
|
388 |
+
elif lower_items or any(word in basic_description.lower() for word in ['pants', 'jeans', 'skirt', 'shorts']):
|
389 |
+
if lower_items:
|
390 |
+
primary_lower = lower_items[0]
|
391 |
+
garment_type = primary_lower['category'].title()
|
392 |
+
else:
|
393 |
+
# Infer from description
|
394 |
+
if 'jeans' in basic_description.lower():
|
395 |
+
garment_type = "Jeans"
|
396 |
+
elif 'pants' in basic_description.lower():
|
397 |
+
garment_type = "Pants"
|
398 |
+
elif 'skirt' in basic_description.lower():
|
399 |
+
garment_type = "Skirt"
|
400 |
+
else:
|
401 |
+
garment_type = "Lower garment"
|
402 |
+
|
403 |
+
analysis_parts.append(f"**Type**: {garment_type}")
|
404 |
+
analysis_parts.append(f"**Color**: {self.extract_enhanced_colors(basic_description)}")
|
405 |
+
analysis_parts.append(f"**Material**: {self.extract_enhanced_material(basic_description, garment_type)}")
|
406 |
+
analysis_parts.append(f"**Features**: {self.extract_enhanced_features(basic_description, garment_type)}")
|
407 |
+
else:
|
408 |
+
analysis_parts.append("**Type**: Not clearly visible in image")
|
409 |
+
analysis_parts.append("**Color**: Unable to determine")
|
410 |
+
analysis_parts.append("**Material**: Unable to determine")
|
411 |
+
analysis_parts.append("**Features**: Unable to determine")
|
412 |
+
|
413 |
+
analysis_parts.append("")
|
414 |
+
analysis_parts.append("---")
|
415 |
+
analysis_parts.append("")
|
416 |
+
|
417 |
+
# FOOTWEAR
|
418 |
+
analysis_parts.append("**FOOTWEAR**")
|
419 |
+
analysis_parts.append("")
|
420 |
+
if footwear_items or any(word in basic_description.lower() for word in ['shoes', 'boots', 'sneakers', 'heels']):
|
421 |
+
if footwear_items:
|
422 |
+
primary_footwear = footwear_items[0]
|
423 |
+
footwear_type = primary_footwear['category'].title()
|
424 |
+
else:
|
425 |
+
# Infer from description
|
426 |
+
if 'sneakers' in basic_description.lower():
|
427 |
+
footwear_type = "Sneakers"
|
428 |
+
elif 'boots' in basic_description.lower():
|
429 |
+
footwear_type = "Boots"
|
430 |
+
elif 'heels' in basic_description.lower():
|
431 |
+
footwear_type = "Heels"
|
432 |
+
else:
|
433 |
+
footwear_type = "Shoes"
|
434 |
+
|
435 |
+
analysis_parts.append(f"**Type**: {footwear_type}")
|
436 |
+
analysis_parts.append(f"**Color**: {self.extract_enhanced_colors(basic_description)}")
|
437 |
+
analysis_parts.append(f"**Material**: {self.extract_enhanced_material(basic_description, footwear_type)}")
|
438 |
+
analysis_parts.append(f"**Features**: {self.extract_enhanced_features(basic_description, footwear_type)}")
|
439 |
+
else:
|
440 |
+
analysis_parts.append("**Type**: Not clearly visible in image")
|
441 |
+
analysis_parts.append("**Color**: Unable to determine")
|
442 |
+
analysis_parts.append("**Material**: Unable to determine")
|
443 |
+
analysis_parts.append("**Features**: Unable to determine")
|
444 |
+
|
445 |
+
analysis_parts.append("")
|
446 |
+
analysis_parts.append("---")
|
447 |
+
analysis_parts.append("")
|
448 |
+
|
449 |
+
# OUTFIT SUMMARY
|
450 |
+
analysis_parts.append("**OUTFIT SUMMARY**")
|
451 |
+
analysis_parts.append("")
|
452 |
+
outfit_summary = self.create_enhanced_outfit_summary(detected_items, basic_description)
|
453 |
+
analysis_parts.append(outfit_summary)
|
454 |
+
|
455 |
+
return "\n".join(analysis_parts)
|
456 |
+
|
457 |
def extract_comprehensive_features(self, description, garment_type):
|
458 |
"""Extract comprehensive features based on garment type"""
|
459 |
desc_lower = description.lower()
|
|
|
1714 |
found_features = [feature for feature in feature_keywords if feature in description_lower]
|
1715 |
return ', '.join(found_features).title() if found_features else "Specific features not clearly visible"
|
1716 |
|
1717 |
+
def extract_enhanced_colors(self, description):
|
1718 |
+
"""Enhanced color extraction with tone analysis and fashion context"""
|
1719 |
+
description_lower = description.lower()
|
1720 |
+
|
1721 |
+
# Enhanced color detection with tone analysis
|
1722 |
+
color_analysis = {
|
1723 |
+
'black': {'name': 'Black', 'tone': 'neutral', 'context': 'timeless and versatile'},
|
1724 |
+
'white': {'name': 'White', 'tone': 'neutral', 'context': 'clean and minimalist'},
|
1725 |
+
'blue': {'name': 'Blue', 'tone': 'cool', 'context': 'calming and professional'},
|
1726 |
+
'navy': {'name': 'Navy blue', 'tone': 'neutral', 'context': 'sophisticated and classic'},
|
1727 |
+
'red': {'name': 'Red', 'tone': 'warm', 'context': 'bold and energetic'},
|
1728 |
+
'green': {'name': 'Green', 'tone': 'cool', 'context': 'natural and refreshing'},
|
1729 |
+
'yellow': {'name': 'Yellow', 'tone': 'warm', 'context': 'cheerful and optimistic'},
|
1730 |
+
'pink': {'name': 'Pink', 'tone': 'warm', 'context': 'feminine and soft'},
|
1731 |
+
'purple': {'name': 'Purple', 'tone': 'cool', 'context': 'creative and luxurious'},
|
1732 |
+
'orange': {'name': 'Orange', 'tone': 'warm', 'context': 'vibrant and playful'},
|
1733 |
+
'brown': {'name': 'Brown', 'tone': 'warm', 'context': 'earthy and grounded'},
|
1734 |
+
'gray': {'name': 'Gray', 'tone': 'neutral', 'context': 'sophisticated and balanced'},
|
1735 |
+
'grey': {'name': 'Grey', 'tone': 'neutral', 'context': 'sophisticated and balanced'},
|
1736 |
+
'beige': {'name': 'Beige', 'tone': 'neutral', 'context': 'warm neutral and versatile'},
|
1737 |
+
'cream': {'name': 'Cream', 'tone': 'warm', 'context': 'soft and elegant'},
|
1738 |
+
'tan': {'name': 'Tan', 'tone': 'warm', 'context': 'natural and casual'},
|
1739 |
+
'khaki': {'name': 'Khaki', 'tone': 'neutral', 'context': 'utilitarian and relaxed'}
|
1740 |
+
}
|
1741 |
+
|
1742 |
+
detected_colors = []
|
1743 |
+
tone_categories = []
|
1744 |
+
|
1745 |
+
for color_key, color_info in color_analysis.items():
|
1746 |
+
if color_key in description_lower:
|
1747 |
+
detected_colors.append(color_info['name'])
|
1748 |
+
tone_categories.append(color_info['tone'])
|
1749 |
+
|
1750 |
+
if detected_colors:
|
1751 |
+
primary_color = detected_colors[0]
|
1752 |
+
primary_tone = tone_categories[0]
|
1753 |
+
|
1754 |
+
if len(detected_colors) > 1:
|
1755 |
+
color_description = f"{primary_color} with {', '.join(detected_colors[1:])} accents ({primary_tone} tone palette)"
|
1756 |
+
else:
|
1757 |
+
color_description = f"{primary_color} ({primary_tone} tone)"
|
1758 |
+
|
1759 |
+
# Add seasonal and styling context
|
1760 |
+
if primary_tone == 'neutral':
|
1761 |
+
color_description += " - versatile for all seasons and easy to style"
|
1762 |
+
elif primary_tone == 'warm':
|
1763 |
+
color_description += " - energetic warm tone, ideal for autumn/winter"
|
1764 |
+
elif primary_tone == 'cool':
|
1765 |
+
color_description += " - calming cool tone, perfect for spring/summer"
|
1766 |
+
|
1767 |
+
return color_description
|
1768 |
+
|
1769 |
+
# Fallback color inference
|
1770 |
+
if any(word in description_lower for word in ['dark', 'deep']):
|
1771 |
+
return "Dark tones (sophisticated and formal)"
|
1772 |
+
elif any(word in description_lower for word in ['light', 'pale', 'soft']):
|
1773 |
+
return "Light tones (fresh and approachable)"
|
1774 |
+
elif any(word in description_lower for word in ['bright', 'vibrant']):
|
1775 |
+
return "Bright tones (energetic and eye-catching)"
|
1776 |
+
|
1777 |
+
return "Color not clearly specified (likely neutral or muted tones)"
|
1778 |
+
|
1779 |
+
def extract_enhanced_material(self, description, garment_type):
|
1780 |
+
"""Enhanced material extraction with texture and quality insights"""
|
1781 |
+
description_lower = description.lower()
|
1782 |
+
garment_lower = garment_type.lower()
|
1783 |
+
|
1784 |
+
# Enhanced material detection with context
|
1785 |
+
material_analysis = {
|
1786 |
+
'cotton': {'name': 'Cotton', 'texture': 'soft and breathable', 'care': 'easy-care'},
|
1787 |
+
'denim': {'name': 'Denim', 'texture': 'structured and durable', 'care': 'low-maintenance'},
|
1788 |
+
'silk': {'name': 'Silk', 'texture': 'smooth and luxurious', 'care': 'delicate'},
|
1789 |
+
'wool': {'name': 'Wool', 'texture': 'warm and textured', 'care': 'special care'},
|
1790 |
+
'polyester': {'name': 'Polyester', 'texture': 'smooth and wrinkle-resistant', 'care': 'easy-care'},
|
1791 |
+
'leather': {'name': 'Leather', 'texture': 'smooth and structured', 'care': 'special care'},
|
1792 |
+
'linen': {'name': 'Linen', 'texture': 'crisp and breathable', 'care': 'wrinkle-prone'},
|
1793 |
+
'chiffon': {'name': 'Chiffon', 'texture': 'flowing and delicate', 'care': 'delicate'},
|
1794 |
+
'satin': {'name': 'Satin', 'texture': 'smooth and lustrous', 'care': 'delicate'},
|
1795 |
+
'velvet': {'name': 'Velvet', 'texture': 'plush and luxurious', 'care': 'special care'},
|
1796 |
+
'knit': {'name': 'Knit fabric', 'texture': 'stretchy and comfortable', 'care': 'easy-care'},
|
1797 |
+
'jersey': {'name': 'Jersey', 'texture': 'soft and stretchy', 'care': 'easy-care'},
|
1798 |
+
'tweed': {'name': 'Tweed', 'texture': 'textured and structured', 'care': 'dry clean'},
|
1799 |
+
'chambray': {'name': 'Chambray', 'texture': 'lightweight and soft', 'care': 'easy-care'},
|
1800 |
+
'flannel': {'name': 'Flannel', 'texture': 'soft and warm', 'care': 'easy-care'}
|
1801 |
+
}
|
1802 |
+
|
1803 |
+
detected_materials = []
|
1804 |
+
for material_key, material_info in material_analysis.items():
|
1805 |
+
if material_key in description_lower:
|
1806 |
+
detected_materials.append(f"{material_info['name']} ({material_info['texture']})")
|
1807 |
+
|
1808 |
+
if detected_materials:
|
1809 |
+
return ', '.join(detected_materials)
|
1810 |
+
|
1811 |
+
# Intelligent material inference based on garment type
|
1812 |
+
if any(word in garment_lower for word in ['jeans', 'denim']):
|
1813 |
+
return "Denim (structured cotton weave, durable and versatile)"
|
1814 |
+
elif any(word in garment_lower for word in ['t-shirt', 'tee']):
|
1815 |
+
return "Cotton jersey (soft, breathable, and comfortable)"
|
1816 |
+
elif any(word in garment_lower for word in ['dress', 'blouse']):
|
1817 |
+
if 'formal' in description_lower or 'elegant' in description_lower:
|
1818 |
+
return "Silk or silk-blend (smooth drape, elegant finish)"
|
1819 |
+
else:
|
1820 |
+
return "Cotton or cotton blend (comfortable and versatile)"
|
1821 |
+
elif any(word in garment_lower for word in ['blazer', 'jacket']):
|
1822 |
+
return "Wool blend or structured fabric (tailored appearance, professional)"
|
1823 |
+
elif any(word in garment_lower for word in ['sweater', 'pullover']):
|
1824 |
+
return "Knit wool or cotton blend (warm, textured, cozy)"
|
1825 |
+
elif any(word in garment_lower for word in ['shoes', 'boots']):
|
1826 |
+
return "Leather or synthetic leather (durable, structured)"
|
1827 |
+
elif any(word in garment_lower for word in ['sneakers']):
|
1828 |
+
return "Canvas, mesh, or synthetic materials (lightweight, breathable)"
|
1829 |
+
|
1830 |
+
return "Material not clearly visible (likely standard garment-appropriate fabric)"
|
1831 |
+
|
1832 |
+
def extract_enhanced_features(self, description, garment_type):
|
1833 |
+
"""Enhanced feature extraction with detailed fashion analysis"""
|
1834 |
+
desc_lower = description.lower()
|
1835 |
+
garment_lower = garment_type.lower()
|
1836 |
+
|
1837 |
+
features = []
|
1838 |
+
|
1839 |
+
# Detailed feature detection with fashion context
|
1840 |
+
feature_mapping = {
|
1841 |
+
'button': 'Button closure (classic and adjustable)',
|
1842 |
+
'zip': 'Zipper details (modern and functional)',
|
1843 |
+
'pocket': 'Functional pockets (practical and stylish)',
|
1844 |
+
'belt': 'Belt or waist definition (silhouette-enhancing)',
|
1845 |
+
'hood': 'Hood detail (casual and functional)',
|
1846 |
+
'collar': 'Collar design (structured and polished)',
|
1847 |
+
'sleeve': 'Distinctive sleeve styling',
|
1848 |
+
'pattern': 'Patterned design (visual interest)',
|
1849 |
+
'print': 'Printed motifs (decorative elements)',
|
1850 |
+
'embroidered': 'Embroidered details (artisanal touch)',
|
1851 |
+
'lace': 'Lace accents (feminine and delicate)',
|
1852 |
+
'ruffle': 'Ruffle details (romantic and textured)',
|
1853 |
+
'pleat': 'Pleated construction (structured movement)',
|
1854 |
+
'gather': 'Gathered fabric (soft volume)',
|
1855 |
+
'tuck': 'Tucked details (tailored precision)'
|
1856 |
+
}
|
1857 |
+
|
1858 |
+
for keyword, feature_desc in feature_mapping.items():
|
1859 |
+
if keyword in desc_lower:
|
1860 |
+
features.append(feature_desc)
|
1861 |
+
|
1862 |
+
# Garment-specific feature analysis
|
1863 |
+
if any(word in garment_lower for word in ['shirt', 'blouse']):
|
1864 |
+
# Neckline analysis
|
1865 |
+
if 'v-neck' in desc_lower:
|
1866 |
+
features.append("V-neckline (elongating and flattering)")
|
1867 |
+
elif 'crew' in desc_lower or 'round' in desc_lower:
|
1868 |
+
features.append("Round neckline (classic and versatile)")
|
1869 |
+
elif 'scoop' in desc_lower:
|
1870 |
+
features.append("Scoop neckline (feminine and soft)")
|
1871 |
+
|
1872 |
+
# Sleeve analysis
|
1873 |
+
if 'long sleeve' in desc_lower:
|
1874 |
+
features.append("Long sleeves (coverage and sophistication)")
|
1875 |
+
elif 'short sleeve' in desc_lower:
|
1876 |
+
features.append("Short sleeves (casual and comfortable)")
|
1877 |
+
elif 'sleeveless' in desc_lower:
|
1878 |
+
features.append("Sleeveless design (modern and airy)")
|
1879 |
+
|
1880 |
+
# Fit analysis
|
1881 |
+
if 'fitted' in desc_lower or 'slim' in desc_lower:
|
1882 |
+
features.append("Fitted silhouette (body-conscious and modern)")
|
1883 |
+
elif 'loose' in desc_lower or 'relaxed' in desc_lower:
|
1884 |
+
features.append("Relaxed fit (comfortable and casual)")
|
1885 |
+
elif 'oversized' in desc_lower:
|
1886 |
+
features.append("Oversized fit (contemporary and comfortable)")
|
1887 |
+
|
1888 |
+
elif any(word in garment_lower for word in ['pants', 'jeans', 'trousers']):
|
1889 |
+
# Fit analysis
|
1890 |
+
if 'skinny' in desc_lower:
|
1891 |
+
features.append("Skinny fit (body-hugging and modern)")
|
1892 |
+
elif 'slim' in desc_lower:
|
1893 |
+
features.append("Slim fit (tailored and flattering)")
|
1894 |
+
elif 'straight' in desc_lower:
|
1895 |
+
features.append("Straight leg (classic and versatile)")
|
1896 |
+
elif 'wide' in desc_lower or 'flare' in desc_lower:
|
1897 |
+
features.append("Wide leg (flowing and dramatic)")
|
1898 |
+
|
1899 |
+
# Rise analysis
|
1900 |
+
if 'high-waisted' in desc_lower or 'high waist' in desc_lower:
|
1901 |
+
features.append("High-waisted (vintage-inspired and flattering)")
|
1902 |
+
elif 'low-rise' in desc_lower:
|
1903 |
+
features.append("Low-rise (casual and relaxed)")
|
1904 |
+
|
1905 |
+
# Length analysis
|
1906 |
+
if 'cropped' in desc_lower or 'ankle' in desc_lower:
|
1907 |
+
features.append("Cropped length (modern and versatile)")
|
1908 |
+
|
1909 |
+
elif any(word in garment_lower for word in ['dress']):
|
1910 |
+
# Length analysis
|
1911 |
+
if 'mini' in desc_lower:
|
1912 |
+
features.append("Mini length (youthful and bold)")
|
1913 |
+
elif 'midi' in desc_lower:
|
1914 |
+
features.append("Midi length (elegant and versatile)")
|
1915 |
+
elif 'maxi' in desc_lower:
|
1916 |
+
features.append("Maxi length (dramatic and flowing)")
|
1917 |
+
|
1918 |
+
# Silhouette analysis
|
1919 |
+
if 'a-line' in desc_lower:
|
1920 |
+
features.append("A-line silhouette (universally flattering)")
|
1921 |
+
elif 'bodycon' in desc_lower or 'fitted' in desc_lower:
|
1922 |
+
features.append("Fitted silhouette (body-conscious and sleek)")
|
1923 |
+
elif 'shift' in desc_lower:
|
1924 |
+
features.append("Shift silhouette (modern and comfortable)")
|
1925 |
+
|
1926 |
+
elif any(word in garment_lower for word in ['shoes', 'sneakers', 'boots']):
|
1927 |
+
# Closure analysis
|
1928 |
+
if 'lace' in desc_lower:
|
1929 |
+
features.append("Lace-up closure (adjustable and secure)")
|
1930 |
+
elif 'slip-on' in desc_lower:
|
1931 |
+
features.append("Slip-on style (convenient and streamlined)")
|
1932 |
+
elif 'buckle' in desc_lower:
|
1933 |
+
features.append("Buckle closure (decorative and functional)")
|
1934 |
+
|
1935 |
+
# Heel analysis
|
1936 |
+
if 'heel' in desc_lower:
|
1937 |
+
if 'high' in desc_lower:
|
1938 |
+
features.append("High heel (elegant and formal)")
|
1939 |
+
elif 'low' in desc_lower:
|
1940 |
+
features.append("Low heel (comfortable and versatile)")
|
1941 |
+
else:
|
1942 |
+
features.append("Heeled design (elevated and polished)")
|
1943 |
+
elif 'flat' in desc_lower:
|
1944 |
+
features.append("Flat sole (comfortable and casual)")
|
1945 |
+
|
1946 |
+
# Style details
|
1947 |
+
if 'platform' in desc_lower:
|
1948 |
+
features.append("Platform sole (height and comfort)")
|
1949 |
+
if 'pointed' in desc_lower:
|
1950 |
+
features.append("Pointed toe (sleek and sophisticated)")
|
1951 |
+
elif 'round' in desc_lower:
|
1952 |
+
features.append("Round toe (classic and comfortable)")
|
1953 |
+
|
1954 |
+
# General styling features
|
1955 |
+
if 'layered' in desc_lower:
|
1956 |
+
features.append("Layered styling (dimensional and interesting)")
|
1957 |
+
if 'textured' in desc_lower:
|
1958 |
+
features.append("Textured fabric (tactile and visual interest)")
|
1959 |
+
if 'structured' in desc_lower:
|
1960 |
+
features.append("Structured construction (tailored and polished)")
|
1961 |
+
if 'flowing' in desc_lower:
|
1962 |
+
features.append("Flowing silhouette (graceful and feminine)")
|
1963 |
+
|
1964 |
+
return ', '.join(features) if features else "Clean, minimalist design with standard construction details"
|
1965 |
+
|
1966 |
+
def create_enhanced_outfit_summary(self, detected_items, basic_description):
|
1967 |
+
"""Create enhanced outfit summary with sophisticated fashion analysis"""
|
1968 |
+
|
1969 |
+
# Extract key elements for analysis
|
1970 |
+
garment_types = [item['category'] for item in detected_items if item['confidence'] > 0.5]
|
1971 |
+
colors = self.extract_enhanced_colors(basic_description)
|
1972 |
+
style_elements = self.extract_style(basic_description)
|
1973 |
+
pattern_info = self.extract_pattern(basic_description)
|
1974 |
+
|
1975 |
+
summary_components = []
|
1976 |
+
|
1977 |
+
# Opening statement about overall aesthetic and fashion intent
|
1978 |
+
if 'dress' in garment_types:
|
1979 |
+
summary_components.append("This outfit showcases the power of a well-chosen dress as a complete styling solution, demonstrating how a single piece can create a sophisticated and intentional look.")
|
1980 |
+
elif len(garment_types) >= 2:
|
1981 |
+
summary_components.append("This outfit exemplifies thoughtful coordination between multiple garment pieces, creating a harmonious ensemble that reflects contemporary fashion sensibility.")
|
1982 |
+
else:
|
1983 |
+
summary_components.append("This outfit highlights the impact of a key fashion piece, demonstrating how individual garments can make a strong style statement.")
|
1984 |
+
|
1985 |
+
# Color, texture, and silhouette interaction analysis
|
1986 |
+
if 'neutral' in colors.lower():
|
1987 |
+
summary_components.append("The neutral color palette creates exceptional versatility and timeless appeal, allowing for easy accessorizing and seamless integration into various settings.")
|
1988 |
+
elif 'warm' in colors.lower():
|
1989 |
+
summary_components.append("The warm color tones generate an approachable and energetic aesthetic that conveys confidence and optimism, perfect for making a positive impression.")
|
1990 |
+
elif 'cool' in colors.lower():
|
1991 |
+
summary_components.append("The cool color palette establishes a calming and professional presence, ideal for both casual sophistication and semi-formal occasions.")
|
1992 |
+
else:
|
1993 |
+
summary_components.append("The color choices demonstrate thoughtful consideration for both visual impact and wearability across different contexts.")
|
1994 |
+
|
1995 |
+
# Pattern and design element analysis
|
1996 |
+
if 'floral' in pattern_info.lower():
|
1997 |
+
summary_components.append("The floral elements introduce natural beauty and romantic charm, adding feminine appeal while maintaining contemporary relevance.")
|
1998 |
+
elif 'striped' in pattern_info.lower():
|
1999 |
+
summary_components.append("The striped pattern provides classic visual interest and timeless sophistication, creating structure and movement within the design.")
|
2000 |
+
elif 'solid' in pattern_info.lower() or 'minimal' in pattern_info.lower():
|
2001 |
+
summary_components.append("The solid construction maximizes styling flexibility and serves as an excellent foundation for creative accessorizing and layering.")
|
2002 |
+
|
2003 |
+
# Cohesion and balance assessment
|
2004 |
+
if len(garment_types) > 1:
|
2005 |
+
summary_components.append("The pieces work together harmoniously, demonstrating an understanding of proportion, balance, and color coordination that creates visual cohesion.")
|
2006 |
+
|
2007 |
+
# Occasion suitability and versatility analysis
|
2008 |
+
if 'casual' in style_elements.lower():
|
2009 |
+
summary_components.append("The casual styling approach makes this outfit perfect for everyday wear, weekend activities, and relaxed social gatherings while maintaining a polished appearance.")
|
2010 |
+
elif 'formal' in style_elements.lower() or 'business' in style_elements.lower():
|
2011 |
+
summary_components.append("The formal elements ensure this outfit meets professional standards and elegant occasion requirements with confidence and sophistication.")
|
2012 |
+
elif 'versatile' in style_elements.lower():
|
2013 |
+
summary_components.append("The versatile design allows this outfit to transition seamlessly between different settings, from casual daytime events to more polished evening occasions.")
|
2014 |
+
else:
|
2015 |
+
summary_components.append("The styling choices reflect adaptability and modern lifestyle needs, suitable for multiple occasions and settings.")
|
2016 |
+
|
2017 |
+
# Fashion-forward observations and concluding statement
|
2018 |
+
if any(word in basic_description.lower() for word in ['layered', 'mixed', 'contrast']):
|
2019 |
+
summary_components.append("The layering techniques and contrast elements showcase contemporary fashion awareness, demonstrating how modern styling can create depth and visual interest while maintaining wearability.")
|
2020 |
+
elif any(word in basic_description.lower() for word in ['minimalist', 'clean', 'simple']):
|
2021 |
+
summary_components.append("The minimalist approach reflects current fashion trends toward refined simplicity, proving that thoughtful restraint can create maximum impact and enduring style.")
|
2022 |
+
else:
|
2023 |
+
summary_components.append("The overall composition reflects contemporary fashion intelligence, combining classic principles with modern sensibilities to create an effortlessly chic and memorable appearance.")
|
2024 |
+
|
2025 |
+
# Combine components into flowing paragraph
|
2026 |
+
return " ".join(summary_components)
|
2027 |
+
|
2028 |
def extract_style(self, description):
|
2029 |
"""Extract style information with intelligent inference"""
|
2030 |
description_lower = description.lower()
|
|
|
2483 |
except Exception as e:
|
2484 |
raise HTTPException(status_code=500, detail=f"Error analyzing image: {str(e)}")
|
2485 |
|
2486 |
+
@app.post("/analyze-enhanced", response_class=PlainTextResponse)
|
2487 |
+
async def analyze_clothing_enhanced(file: UploadFile = File(...)):
|
2488 |
+
"""Analyze clothing using enhanced prompt format optimized for feature extraction"""
|
2489 |
+
try:
|
2490 |
+
# Read image bytes
|
2491 |
+
image_bytes = await file.read()
|
2492 |
+
|
2493 |
+
# Analyze clothing using enhanced prompt format
|
2494 |
+
analysis = analyzer.analyze_clothing_enhanced_prompt_format(image_bytes)
|
2495 |
|
2496 |
+
return analysis
|
2497 |
+
|
2498 |
+
except Exception as e:
|
2499 |
+
raise HTTPException(status_code=500, detail=f"Error analyzing image: {str(e)}")
|
2500 |
|
2501 |
@app.post("/detect-objects", response_model=Dict[str, Any])
|
2502 |
async def detect_objects(file: UploadFile = File(...)):
|
|
|
2538 |
async def get_refined_prompt():
|
2539 |
"""Get the refined prompt for clothing analysis"""
|
2540 |
refined_prompt = """
|
2541 |
+
π **CLOTHING ANALYSIS INSTRUCTION PROMPT β OPTIMIZED FOR OUTFIT RECOMMENDATION AI**
|
2542 |
+
|
2543 |
+
You are an expert fashion stylist and computer vision analyst. Your task is to **analyze a photo of a person** and produce a **detailed, structured breakdown** of their outfit. Focus on identifying visible garments and extracting features relevant to **style, fit, color theory, material, and occasion**.
|
2544 |
+
|
2545 |
+
Use the following **strict format** and ensure each field is filled with accurate, professional fashion insights. When unsure, make reasonable inferences based on visual clues and fashion knowledge.
|
2546 |
+
|
2547 |
+
---
|
2548 |
+
|
2549 |
+
### π§© **RESPONSE STRUCTURE**:
|
2550 |
+
|
2551 |
+
---
|
2552 |
+
|
2553 |
+
### **1. UPPER GARMENT**
|
2554 |
+
|
2555 |
+
* **Type**: *(e.g., t-shirt, shirt, blouse, jacket, coat, dress, blazer, hoodie)*
|
2556 |
+
* **Color**: *(Primary color + notable accents; include tone category β warm, cool, neutral)*
|
2557 |
+
* **Material**: *(Visually identifiable or inferred β cotton, denim, knit, silk, etc.)*
|
2558 |
+
* **Features**: *(e.g., sleeve length, neckline, collar, fit, embellishments, print/pattern, texture)*
|
2559 |
+
|
2560 |
+
---
|
2561 |
+
|
2562 |
+
### **2. LOWER GARMENT**
|
2563 |
+
|
2564 |
+
* **Type**: *(e.g., jeans, trousers, skirt, shorts, joggers, culottes)*
|
2565 |
+
* **Color**: *(Primary + secondary tones; match to upper color context)*
|
2566 |
+
* **Material**: *(e.g., denim, polyester, linen; infer if not obvious)*
|
2567 |
+
* **Features**: *(e.g., cut, length, waist rise, fit, pleats, pockets, fasteners, patterns)*
|
2568 |
+
|
2569 |
+
---
|
2570 |
+
|
2571 |
+
### **3. FOOTWEAR**
|
2572 |
+
|
2573 |
+
* **Type**: *(e.g., sneakers, boots, sandals, loafers, heels, formal shoes)*
|
2574 |
+
* **Color**: *(Main color + accent details; match to outfit tones if relevant)*
|
2575 |
+
* **Material**: *(e.g., leather, suede, canvas, mesh β inferred if unclear)*
|
2576 |
+
* **Features**: *(e.g., laces, buckles, platform, heel height, style, sole type)*
|
2577 |
+
|
2578 |
+
---
|
2579 |
+
|
2580 |
+
### **4. OUTFIT SUMMARY**
|
2581 |
+
|
2582 |
+
Write a **3β5 sentence paragraph** that:
|
2583 |
+
|
2584 |
+
* Evaluates the **overall style and fashion intent** of the outfit
|
2585 |
+
* Describes how **color, texture, and silhouette** interact
|
2586 |
+
* Comments on **cohesion and balance** between garments
|
2587 |
+
* Assesses **occasion suitability** (e.g., casual, business casual, streetwear, evening)
|
2588 |
+
* Provides **fashion-forward observations** (e.g., layering techniques, contrast, minimalism, etc.)
|
2589 |
+
|
2590 |
+
---
|
2591 |
+
|
2592 |
+
### β
**GUIDELINES FOR THE MODEL**:
|
2593 |
+
|
2594 |
+
* Use **fashion-specific vocabulary** (e.g., oversized, tailored, cropped, monochromatic, muted tones)
|
2595 |
+
* Apply **color theory**: mention harmony/contrast, seasonal suitability, or tone warmth
|
2596 |
+
* Infer **formality level** (e.g., smart casual, athleisure, streetwear, semi-formal)
|
2597 |
+
* Mention **fit and silhouette** if visible (e.g., slim-fit, relaxed, boxy, flowy)
|
2598 |
+
* If a garment is partially occluded, describe what's visible and make plausible inferences
|
2599 |
+
* Use consistent structure and complete all sections unless a category is **not applicable**
|
2600 |
+
|
2601 |
+
---
|
2602 |
+
|
2603 |
+
### π **EXAMPLE OUTPUT FORMAT**:
|
2604 |
+
|
2605 |
+
---
|
2606 |
+
|
2607 |
+
#### **UPPER GARMENT**
|
2608 |
+
|
2609 |
+
**Type**: Button-down chambray shirt
|
2610 |
+
**Color**: Light denim blue (cool tone) with faded areas on collar and seams
|
2611 |
+
**Material**: Chambray (lightweight woven cotton)
|
2612 |
+
**Features**: Long sleeves rolled to elbows, pointed collar, front patch pockets, relaxed fit, visible stitching
|
2613 |
+
|
2614 |
+
---
|
2615 |
+
|
2616 |
+
#### **LOWER GARMENT**
|
2617 |
+
|
2618 |
+
**Type**: Black slim-fit chinos
|
2619 |
+
**Color**: Solid black (neutral tone)
|
2620 |
+
**Material**: Stretch cotton twill
|
2621 |
+
**Features**: Flat front, minimal pockets, cropped ankle length, clean silhouette
|
2622 |
+
|
2623 |
+
---
|
2624 |
+
|
2625 |
+
#### **FOOTWEAR**
|
2626 |
+
|
2627 |
+
**Type**: White minimalist sneakers
|
2628 |
+
**Color**: White with subtle grey accents on heel tab
|
2629 |
+
**Material**: Leather upper with rubber sole
|
2630 |
+
**Features**: Lace-up closure, low-profile design, round toe
|
2631 |
+
|
2632 |
+
---
|
2633 |
+
|
2634 |
+
#### **OUTFIT SUMMARY**
|
2635 |
+
|
2636 |
+
This outfit channels effortless smart-casual style with its blend of soft textures and minimal structure. The chambray shirt introduces a laid-back, workwear-inspired vibe, complemented by the refined edge of slim black chinos. The white sneakers tie the look together with understated coolness, ensuring comfort without sacrificing polish. The color palette of light blue, black, and white reflects balance and neutrality, making the outfit adaptable for casual office settings, social outings, or relaxed dates. The overall silhouette is clean and streamlined, making it modern, versatile, and easy to accessorize.
|
2637 |
"""
|
2638 |
return refined_prompt
|
2639 |
|
test_enhanced_analysis.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Test script for the enhanced fashion analysis with refined prompt
|
4 |
+
"""
|
5 |
+
|
6 |
+
import requests
|
7 |
+
import json
|
8 |
+
import sys
|
9 |
+
from pathlib import Path
|
10 |
+
|
11 |
+
def test_enhanced_analysis(image_path, server_url="http://localhost:7861"):
|
12 |
+
"""Test the enhanced analysis endpoint"""
|
13 |
+
|
14 |
+
if not Path(image_path).exists():
|
15 |
+
print(f"Error: Image file {image_path} not found")
|
16 |
+
return
|
17 |
+
|
18 |
+
# Test the enhanced analysis endpoint
|
19 |
+
print("π Testing Enhanced Fashion Analysis")
|
20 |
+
print("=" * 50)
|
21 |
+
|
22 |
+
try:
|
23 |
+
with open(image_path, 'rb') as f:
|
24 |
+
files = {'file': f}
|
25 |
+
response = requests.post(f"{server_url}/analyze-enhanced", files=files)
|
26 |
+
|
27 |
+
if response.status_code == 200:
|
28 |
+
print("β
Enhanced Analysis Results:")
|
29 |
+
print("-" * 30)
|
30 |
+
print(response.text)
|
31 |
+
print("-" * 30)
|
32 |
+
else:
|
33 |
+
print(f"β Error: {response.status_code} - {response.text}")
|
34 |
+
|
35 |
+
except requests.exceptions.ConnectionError:
|
36 |
+
print(f"β Error: Could not connect to server at {server_url}")
|
37 |
+
print("Make sure the FastAPI server is running with: python fast.py")
|
38 |
+
except Exception as e:
|
39 |
+
print(f"β Error: {str(e)}")
|
40 |
+
|
41 |
+
def compare_analysis_methods(image_path, server_url="http://localhost:7861"):
|
42 |
+
"""Compare different analysis methods"""
|
43 |
+
|
44 |
+
if not Path(image_path).exists():
|
45 |
+
print(f"Error: Image file {image_path} not found")
|
46 |
+
return
|
47 |
+
|
48 |
+
print("π Comparing Analysis Methods")
|
49 |
+
print("=" * 50)
|
50 |
+
|
51 |
+
endpoints = [
|
52 |
+
("/analyze-enhanced", "Enhanced Prompt Analysis"),
|
53 |
+
("/analyze-structured", "Structured Analysis"),
|
54 |
+
("/analyze", "Basic Analysis")
|
55 |
+
]
|
56 |
+
|
57 |
+
for endpoint, name in endpoints:
|
58 |
+
print(f"\nπ {name}")
|
59 |
+
print("-" * 30)
|
60 |
+
|
61 |
+
try:
|
62 |
+
with open(image_path, 'rb') as f:
|
63 |
+
files = {'file': f}
|
64 |
+
response = requests.post(f"{server_url}{endpoint}", files=files)
|
65 |
+
|
66 |
+
if response.status_code == 200:
|
67 |
+
if endpoint == "/analyze-structured":
|
68 |
+
# This returns JSON
|
69 |
+
try:
|
70 |
+
data = response.json()
|
71 |
+
print(json.dumps(data, indent=2))
|
72 |
+
except:
|
73 |
+
print(response.text)
|
74 |
+
else:
|
75 |
+
print(response.text)
|
76 |
+
else:
|
77 |
+
print(f"β Error: {response.status_code} - {response.text}")
|
78 |
+
|
79 |
+
except requests.exceptions.ConnectionError:
|
80 |
+
print(f"β Error: Could not connect to server at {server_url}")
|
81 |
+
break
|
82 |
+
except Exception as e:
|
83 |
+
print(f"β Error: {str(e)}")
|
84 |
+
|
85 |
+
def test_refined_prompt(server_url="http://localhost:7861"):
|
86 |
+
"""Test the refined prompt endpoint"""
|
87 |
+
|
88 |
+
print("π Testing Refined Prompt")
|
89 |
+
print("=" * 50)
|
90 |
+
|
91 |
+
try:
|
92 |
+
response = requests.get(f"{server_url}/refined-prompt")
|
93 |
+
|
94 |
+
if response.status_code == 200:
|
95 |
+
print("β
Refined Prompt:")
|
96 |
+
print("-" * 30)
|
97 |
+
print(response.text)
|
98 |
+
print("-" * 30)
|
99 |
+
else:
|
100 |
+
print(f"β Error: {response.status_code} - {response.text}")
|
101 |
+
|
102 |
+
except requests.exceptions.ConnectionError:
|
103 |
+
print(f"β Error: Could not connect to server at {server_url}")
|
104 |
+
except Exception as e:
|
105 |
+
print(f"β Error: {str(e)}")
|
106 |
+
|
107 |
+
def main():
|
108 |
+
"""Main function"""
|
109 |
+
|
110 |
+
if len(sys.argv) < 2:
|
111 |
+
print("Usage: python test_enhanced_analysis.py <image_path> [server_url]")
|
112 |
+
print("Example: python test_enhanced_analysis.py test_image.jpg")
|
113 |
+
print("Example: python test_enhanced_analysis.py test_image.jpg http://localhost:7861")
|
114 |
+
return
|
115 |
+
|
116 |
+
image_path = sys.argv[1]
|
117 |
+
server_url = sys.argv[2] if len(sys.argv) > 2 else "http://localhost:7861"
|
118 |
+
|
119 |
+
print("π½ Enhanced Fashion Analysis Test")
|
120 |
+
print("=" * 50)
|
121 |
+
print(f"Image: {image_path}")
|
122 |
+
print(f"Server: {server_url}")
|
123 |
+
print("=" * 50)
|
124 |
+
|
125 |
+
# Test the refined prompt first
|
126 |
+
test_refined_prompt(server_url)
|
127 |
+
|
128 |
+
print("\n")
|
129 |
+
|
130 |
+
# Test enhanced analysis
|
131 |
+
test_enhanced_analysis(image_path, server_url)
|
132 |
+
|
133 |
+
print("\n")
|
134 |
+
|
135 |
+
# Compare all methods
|
136 |
+
compare_analysis_methods(image_path, server_url)
|
137 |
+
|
138 |
+
if __name__ == "__main__":
|
139 |
+
main()
|