From 1294834c57592e92faa2251710a7ecc3c7f5390d Mon Sep 17 00:00:00 2001 From: Avya Rathod <27121364+AvyaRathod@users.noreply.github.com> Date: Sat, 1 Mar 2025 00:31:36 +0530 Subject: [PATCH] bug fixes --- App/src/assets/pants.png | Bin 0 -> 5683 bytes App/src/navigation/AiToolsTabNavigator.tsx | 8 +- App/src/navigation/TabNavigator.tsx | 3 +- App/src/screens/HomeScreen.tsx | 70 ++++----- .../colourTheory/ColorAnalysisResults.tsx | 132 +++++++++++++++++ .../colourTheory/ColorPaletteScreen.tsx | 90 ++++++++++++ .../colourTheory/InstructionScreen.tsx | 138 +++++++++++++----- App/src/screens/colourTheory/selfieScreen.tsx | 13 ++ .../generateOutfits/GenerateOutfitsScreen.tsx | 38 ++--- Segment/api/routers/outfits.py | 74 ++++++---- 10 files changed, 442 insertions(+), 124 deletions(-) create mode 100644 App/src/assets/pants.png create mode 100644 App/src/screens/colourTheory/ColorAnalysisResults.tsx create mode 100644 App/src/screens/colourTheory/ColorPaletteScreen.tsx diff --git a/App/src/assets/pants.png b/App/src/assets/pants.png new file mode 100644 index 0000000000000000000000000000000000000000..65dcd033b64d1b15a76c092cd3e8cc4d3b51f927 GIT binary patch literal 5683 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 A2><{9 literal 0 HcmV?d00001 diff --git a/App/src/navigation/AiToolsTabNavigator.tsx b/App/src/navigation/AiToolsTabNavigator.tsx index a5133bd..339b6f8 100644 --- a/App/src/navigation/AiToolsTabNavigator.tsx +++ b/App/src/navigation/AiToolsTabNavigator.tsx @@ -7,9 +7,9 @@ import { useTheme } from 'react-native-paper'; import GenerateOutfitsScreen from '../screens/generateOutfits/GenerateOutfitsScreen'; import OutfitCheckScreen from '../screens/outfitCheck/OutfitCheckScreen'; import MixAndMatchScreen from '../screens/mixAndMatch/MixAndMatchScreen'; -import ColorTheoryScreen from '../screens/colourTheory/ColorTherapy'; import useNavigationStore from '../store/useNavigationStore'; +import SelfieAnalysisScreen from '../screens/colourTheory/selfieScreen'; const AiTab = createBottomTabNavigator(); @@ -83,10 +83,10 @@ const AiToolsTabNavigator: React.FC = () => { } as BottomTabNavigationOptions} /> , } as BottomTabNavigationOptions} /> diff --git a/App/src/navigation/TabNavigator.tsx b/App/src/navigation/TabNavigator.tsx index cbbb125..9630897 100644 --- a/App/src/navigation/TabNavigator.tsx +++ b/App/src/navigation/TabNavigator.tsx @@ -7,6 +7,7 @@ import useNavigationStore from '../store/useNavigationStore'; import HomeScreen from '../screens/HomeScreen'; import InstructionsScreen from '../screens/colourTheory/InstructionScreen'; import WardrobeScreen from '../screens/WardrobeScreen'; +import SelfieAnalysisScreen from '../screens/colourTheory/selfieScreen'; const MainTab = createBottomTabNavigator(); @@ -67,7 +68,7 @@ const MainTabNavigator: React.FC = () => { /> , diff --git a/App/src/screens/HomeScreen.tsx b/App/src/screens/HomeScreen.tsx index 6e3d0fb..72feb28 100644 --- a/App/src/screens/HomeScreen.tsx +++ b/App/src/screens/HomeScreen.tsx @@ -144,10 +144,11 @@ const styles = StyleSheet.create({ borderRadius: 8, justifyContent: 'center', alignItems: 'center', - shadowRadius: 5, - shadowOpacity: 0.3, - shadowOffset: { width: 0, height: 2 }, - elevation: 5, + shadowColor: "#000", + shadowRadius: 6, + shadowOpacity: 0.4, // Increased opacity + shadowOffset: { width: 0, height: 3 }, // More shadow at the bottom + elevation: 8, // Higher elevation for Android }, bannerText: { fontSize: 18, @@ -175,11 +176,11 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', position: 'relative', - overflow: 'hidden', // Allow cropping - shadowRadius: 5, - shadowOpacity: 0.3, - shadowOffset: { width: 0, height: 2 }, - elevation: 5, + shadowColor: "#000", + shadowRadius: 6, + shadowOpacity: 0.4, // Increased for better visibility + shadowOffset: { width: 0, height: 3 }, + elevation: 8, }, // RIGHT COLUMN @@ -196,11 +197,11 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', position: 'relative', - overflow: 'hidden', - shadowRadius: 5, - shadowOpacity: 0.3, - shadowOffset: { width: 0, height: 2 }, - elevation: 5, + shadowColor: "#000", + shadowRadius: 6, + shadowOpacity: 0.4, // More opacity for better visibility + shadowOffset: { width: 0, height: 3 }, + elevation: 8, }, mixMatchBox: { backgroundColor: '#FFFFFF', @@ -209,11 +210,11 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', position: 'relative', - overflow: 'hidden', - shadowRadius: 5, - shadowOpacity: 0.3, - shadowOffset: { width: 0, height: 2 }, - elevation: 5, + shadowColor: "#000", + shadowRadius: 6, + shadowOpacity: 0.4, + shadowOffset: { width: 0, height: 3 }, + elevation: 8, }, // FULL-WIDTH: COLOUR ANALYSIS @@ -224,12 +225,12 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', position: 'relative', - overflow: 'hidden', - shadowRadius: 5, - shadowOpacity: 0.3, - shadowOffset: { width: 0, height: 2 }, - elevation: 5, - + shadowColor: "#000", + shadowRadius: 6, + shadowOpacity: 0.4, + shadowOffset: { width: 0, height: 3 }, + elevation: 8, + }, // TEXT INSIDE BOXES @@ -248,32 +249,33 @@ const styles = StyleSheet.create({ position: 'absolute', bottom: 5, right: 3, - width: 125, // Adjust based on need - height: 100, // Adjust based on need + width: 125, + height: 100, resizeMode: 'contain', }, CheckOutfitImage: { position: 'absolute', bottom: -1, right: -3, - width: 90, // Adjust based on need - height:85, // Adjust based on need + width: 90, + height: 85, resizeMode: 'contain', }, MixandMatchImage: { position: 'absolute', bottom: -1, right: -3, - width: 90, // Adjust based on need - height:85, // Adjust based on need + width: 90, + height: 85, resizeMode: 'contain', }, ColourAnalysisImage: { position: 'absolute', bottom: -3, right: -5, - width: 100, // Adjust based on need - height:100, // Adjust based on need - resizeMode: 'contain', + width: 100, + height: 100, + resizeMode: 'cover', + }, }); diff --git a/App/src/screens/colourTheory/ColorAnalysisResults.tsx b/App/src/screens/colourTheory/ColorAnalysisResults.tsx new file mode 100644 index 0000000..fcf5f49 --- /dev/null +++ b/App/src/screens/colourTheory/ColorAnalysisResults.tsx @@ -0,0 +1,132 @@ +import React from "react"; +import { View, Text, StyleSheet, Pressable } from "react-native"; +import { useRoute, useNavigation } from "@react-navigation/native"; + +const ColorAnalysisResultScreen: React.FC = () => { + const route = useRoute(); + const navigation = useNavigation(); + const { data } = route.params || {}; + + if (!data) { + return ( + + No Data Available + + ); + } + + return ( + + {/* Title */} + Your Color Analysis Result + + {/* Seasonal Color Type */} + + {data.seasonal_color_type} + {getSeasonDescription(data.seasonal_color_type)} + + + {/* User's Detected Features */} + + 🌟 **Skin Tone:** {data.skin_tone} + ✨ **Undertone:** {data.undertone} + πŸ’‡ **Hair Color:** {data.hair_color} + πŸ‘€ **Eye Color:** {data.eye_color} + + + {/* Button to Color Palette Screen */} + navigation.navigate("ColorPaletteScreen", { colors: data.clothing_color_palette })} + > + View Your Color Palette + + + ); +}; + +export default ColorAnalysisResultScreen; + +// Function to return background color based on the season +const getSeasonalColor = (season: string) => { + switch (season) { + case "Spring": return "#FFDAB9"; + case "Summer": return "#87CEEB"; + case "Autumn": return "#FF8C00"; + case "Winter": return "#4682B4"; + default: return "#DDD"; + } +}; + +// Function to return season description +const getSeasonDescription = (season: string) => { + const descriptions: Record = { + Spring: "Bright and warm colors suit you best.", + Summer: "Cool, soft, and muted tones enhance your features.", + Autumn: "Rich, earthy, and warm colors are ideal for you.", + Winter: "Deep, bold, and contrasting shades complement your complexion." + }; + return descriptions[season] || "No description available."; +}; + +// Styles +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#FAFAFA", + padding: 20, + justifyContent: "center", + }, + title: { + fontSize: 22, + fontWeight: "bold", + textAlign: "center", + marginBottom: 16, + color: "#333", + }, + card: { + padding: 16, + borderRadius: 12, + alignItems: "center", + marginBottom: 20, + }, + seasonText: { + fontSize: 20, + fontWeight: "bold", + color: "#FFF", + }, + seasonDesc: { + fontSize: 14, + textAlign: "center", + color: "#FFF", + marginTop: 8, + }, + detailsContainer: { + backgroundColor: "#FFF", + padding: 16, + borderRadius: 12, + elevation: 2, + marginBottom: 20, + }, + detailText: { + fontSize: 16, + color: "#333", + marginBottom: 6, + }, + button: { + backgroundColor: "#843CA7", + paddingVertical: 16, + borderRadius: 32, + alignItems: "center", + }, + buttonText: { + color: "#FFF", + fontSize: 16, + fontWeight: "bold", + }, + errorText: { + fontSize: 18, + color: "#FF0000", + textAlign: "center", + }, +}); diff --git a/App/src/screens/colourTheory/ColorPaletteScreen.tsx b/App/src/screens/colourTheory/ColorPaletteScreen.tsx new file mode 100644 index 0000000..966e518 --- /dev/null +++ b/App/src/screens/colourTheory/ColorPaletteScreen.tsx @@ -0,0 +1,90 @@ +import React from "react"; +import { View, Text, FlatList, StyleSheet, Pressable } from "react-native"; +import { useRoute, useNavigation } from "@react-navigation/native"; + +const ColorPaletteScreen: React.FC = () => { + const route = useRoute(); + const navigation = useNavigation(); + const { colors } = route.params || {}; + + if (!colors || colors.length === 0) { + return ( + + No Colors Available + + ); + } + + return ( + + Your Personalized Color Palette + + {/* Color Palette List */} + item.hex} + renderItem={({ item }) => ( + + {item.name} + {item.hex} + + )} + /> + + {/* Back Button */} + navigation.goBack()}> + Back + + + ); +}; + +export default ColorPaletteScreen; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#FAFAFA", + padding: 20, + justifyContent: "center", + }, + title: { + fontSize: 22, + fontWeight: "bold", + textAlign: "center", + marginBottom: 16, + color: "#333", + }, + colorBox: { + padding: 16, + borderRadius: 12, + marginBottom: 12, + alignItems: "center", + }, + colorName: { + fontSize: 16, + fontWeight: "bold", + color: "#FFF", + }, + colorHex: { + fontSize: 14, + color: "#FFF", + }, + button: { + backgroundColor: "#843CA7", + paddingVertical: 16, + borderRadius: 32, + alignItems: "center", + marginTop: 20, + }, + buttonText: { + color: "#FFF", + fontSize: 16, + fontWeight: "bold", + }, + errorText: { + fontSize: 18, + color: "#FF0000", + textAlign: "center", + }, +}); diff --git a/App/src/screens/colourTheory/InstructionScreen.tsx b/App/src/screens/colourTheory/InstructionScreen.tsx index ed224c3..d888fdb 100644 --- a/App/src/screens/colourTheory/InstructionScreen.tsx +++ b/App/src/screens/colourTheory/InstructionScreen.tsx @@ -2,64 +2,122 @@ import React, { useState } from 'react'; import { View, Text, Image, StyleSheet, Pressable, Platform, ActionSheetIOS, Modal } from 'react-native'; -import { useNavigation } from '@react-navigation/native'; -import { launchCamera, launchImageLibrary } from 'react-native-image-picker'; +import { launchCamera, launchImageLibrary, ImageLibraryOptions,CameraOptions } from 'react-native-image-picker'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; +import { api } from "../../utils/api"; +import { Asset } from "react-native-image-picker"; +import { AuthState, useAuthStore } from "../../store/authStore"; +import { NavigationProp } from '../../types/types'; +import { useNavigation } from '@react-navigation/native'; + + + const InstructionScreen = () => { const navigation = useNavigation(); const [modalVisible, setModalVisible] = useState(false); - const [selectedImage, setSelectedImage] = useState(null); + const [selectedImage, setSelectedImage] = useState(''); + const token = useAuthStore((state: AuthState) => state.token); + - const openFrontCamera = () => { - launchCamera( - { - mediaType: 'photo', - cameraType: 'front', - saveToPhotos: false, - }, - (response) => { - if (response.assets && response.assets.length > 0) { - const imageUri = response.assets[0].uri; - setSelectedImage(imageUri); - navigation.navigate("ColorTheory", { imageUri }); // Pass imageUri directly - } + const openCamera = async () => { + const options: CameraOptions = { + mediaType: "photo", + includeBase64: false, + saveToPhotos: true, + cameraType: "front", + }; + + try { + const response = await launchCamera(options); + if (response.didCancel) { + console.log("User cancelled camera"); + } else if (response.errorCode) { + console.log("Camera Error: ", response.errorMessage); + } else if (response.assets && response.assets[0]) { + await handleSumbit(response.assets[0]); } - ); + } catch (error) { + console.log("Error using camera: ", error); + } }; - const openGallery = () => { - launchImageLibrary( - { + + const openGallery = async () => { + const options: ImageLibraryOptions = { mediaType: 'photo', - }, - (response) => { - if (response.assets && response.assets.length > 0) { - const imageUri = response.assets[0].uri; - setSelectedImage(imageUri); - navigation.navigate("ColorTheory", { imageUri }); // Pass imageUri directly + includeBase64: false, + maxHeight: 2000, + maxWidth: 2000, + selectionLimit: 1, + quality: 1, + }; + + try { + const response = await launchImageLibrary(options); + if (response.didCancel) { + console.log('User cancelled image picker'); + } else if (response.errorCode) { + console.log('ImagePicker Error: ', response.errorMessage); + } else if (response.assets && response.assets[0]) { + await handleSumbit(response.assets[0]); } + } catch (error) { + console.log('Error picking image: ', error); } - ); + }; + + const handleSumbit = async (file: Asset) => { + const formData = new FormData(); + const image = { + uri: file.uri, + type: file.type || 'image/jpeg', + name: file.fileName || 'image.jpg' + }; + formData.append('file', image); + // setLoading(true); + + try { + const res = await api.post( + '/api/v1/outfit/colortherapy', + formData, + { + headers: { + Authorization: `Bearer ${token}`, + 'Content-type': 'multipart/form-data', + }, + } + ); + if (res.status !== 200) { + throw Error(res.statusText); + } + navigation.navigate("ColorAnalysisResult", { data: res.data}); + } catch (error: any) { + console.error('Upload error:', error.response?.data || error.message); + } finally { + // setLoading(false); + } }; + // Handle button click based on platform const handleScanFacePress = () => { if (Platform.OS === 'ios') { - ActionSheetIOS.showActionSheetWithOptions( - { - options: ['Cancel', 'Take a Selfie', 'Select from Gallery'], - cancelButtonIndex: 0, - }, - (buttonIndex) => { - if (buttonIndex === 1) openFrontCamera(); - else if (buttonIndex === 2) openGallery(); + ActionSheetIOS.showActionSheetWithOptions( + { + options: ['Cancel', 'Take Picture', 'Select Picture(s)'], + cancelButtonIndex: 0, + }, + buttonIndex => { + if (buttonIndex === 1) { + openCamera(); + } else if (buttonIndex === 2) { + openGallery(); + } + }, + ); } - ); - } else { - setModalVisible(true); // Open modal for Android - } }; return ( @@ -103,7 +161,7 @@ const InstructionScreen = () => { > - { openFrontCamera(); setModalVisible(false); }}> + { openCamera(); setModalVisible(false); }}> Take a Selfie diff --git a/App/src/screens/colourTheory/selfieScreen.tsx b/App/src/screens/colourTheory/selfieScreen.tsx index fa09c50..842762c 100644 --- a/App/src/screens/colourTheory/selfieScreen.tsx +++ b/App/src/screens/colourTheory/selfieScreen.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { View, Text, Image, StyleSheet, Pressable } from 'react-native'; +import {IconButton } from 'react-native-paper'; import { useNavigation } from '@react-navigation/native'; const SelfieAnalysisScreen = () => { @@ -8,6 +9,11 @@ const SelfieAnalysisScreen = () => { return ( {/* Title & Description */} + + {navigation.canGoBack() && ( + navigation.goBack()} /> + )} + It’s time to unlock your style formula! With a selfie, we will analyze your facial features and complexion to determine your @@ -43,6 +49,13 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, justifyContent: 'center', }, + header: { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 8, + marginBottom: 16, + alignContent:'center' + }, title: { fontSize: 22, fontWeight: 'bold', diff --git a/App/src/screens/generateOutfits/GenerateOutfitsScreen.tsx b/App/src/screens/generateOutfits/GenerateOutfitsScreen.tsx index 70a72cd..bab9c2a 100644 --- a/App/src/screens/generateOutfits/GenerateOutfitsScreen.tsx +++ b/App/src/screens/generateOutfits/GenerateOutfitsScreen.tsx @@ -41,7 +41,7 @@ const GenerateOutfitsScreen = () => { const clothingItems: SelectedClothing[] = [ { type: 'hat', Icon: 'hat-fedora', Size: 48 }, { type: 'top', Icon: 'tshirt-crew', Size: 64 }, - { type: 'bottom', Icon: 'lingerie', Size: 64 }, + { type: 'bottom', Icon: '../../assets/pants.svg', Size: 64 }, { type: 'shoe', Icon: 'shoe-formal', Size: 48 }, ]; @@ -85,7 +85,7 @@ const GenerateOutfitsScreen = () => { const isSelected = !!selectedItem; const hasWardrobe = !!selectedItem; const hasURL = !!selectedItem?.url; - + return ( { styles.clothingItem, isSelected && styles.selectedItem, hasWardrobe && styles.wardrobeItem, - ]}> - {loading ? - - - - :(hasURL ? ( + ]} + > + {loading ? ( + + + + ) : hasURL ? ( - + - + - ) : ( - - ))} + ) : ( + + )} ); }; @@ -256,6 +255,7 @@ const styles = StyleSheet.create({ alignItems: 'center', paddingHorizontal: 8, marginBottom: 16, + alignContent:'center' }, headerText: { color: '#666', diff --git a/Segment/api/routers/outfits.py b/Segment/api/routers/outfits.py index 70df485..1f00c02 100644 --- a/Segment/api/routers/outfits.py +++ b/Segment/api/routers/outfits.py @@ -131,34 +131,56 @@ async def color_therapy( raise HTTPException( status_code=400, detail="Uploaded file is empty") prompt = """ - Provided below is the image of a person, based on Color Therapy principles, i.e based on their facial structure, skin color, hair color, eye color, suggest them outfits from the clothes data given below. Suggestion must only include the ID's of clothes. + Analyze the provided image to determine the user's seasonal color type (Spring, Summer, Autumn, or Winter) based on their skin tone, undertone, hair color, and eye color. Then, generate a custom clothing color palette with hex codes that complement their season. + ### **Steps for Analysis:** + 1. **Skin Analysis**: + - Detect the skin tone (Fair, Light, Medium, Tan, Deep). + - Identify undertones (Warm, Cool, Neutral, Olive). - An outfit contains the following types of clothing article: - - top - - bottom - - shoe - - hat - - you will output the outfit combinations like the following: - [ - { - top : , - bottom : , - shoe: , - hat: , - description: - }, - ...] - make sure you don't exceed more than 10 combinations, no repetition. - only use the given clothing articles, meaning, ID must be from the given only. - given articles will be JSON. - if there's no clothing article for a particular type, you may enter a '-1' in there. - Try not to give single clothing outfit recommendations if possible. - - The reply must be an array of JSON. - - Here's the Clothing Articles: + 2. **Hair Analysis**: + - Identify the natural hair color. + - Determine whether the hair has warm, cool, or neutral tones. + + 3. **Eye Analysis**: + - Identify the user's eye color. + - Determine if it has warm or cool tones. + + 4. **Determine Seasonal Color Type**: + - Based on the above features, classify the user into one of the four Korean seasonal color types: + - **Spring** (Warm & Light) + - **Summer** (Cool & Light) + - **Autumn** (Warm & Deep) + - **Winter** (Cool & Deep) + + 5. **Generate a Custom Color Palette**: + - Provide a **clothing color palette** with **at least 10 colors** best suited for the user's season. + - Each color should include: + - **Name** (e.g., Soft Peach, Cool Lilac) + - **Hex Code** (e.g., `#F4A7B9`) + + 6. **Output the Results in JSON Format**: + - The JSON should have the following structure: + ```json + { + "seasonal_color_type": "Spring", + "skin_tone": "Light", + "undertone": "Warm", + "hair_color": "Golden Brown", + "eye_color": "Hazel", + "clothing_color_palette": [ + {"name": "Soft Peach", "hex": "#FFDAB9"}, + {"name": "Warm Coral", "hex": "#FF6F61"}, + {"name": "Golden Beige", "hex": "#F5DEB3"}, + {"name": "Apricot", "hex": "#E9967A"}, + {"name": "Mint Green", "hex": "#98FB98"}, + {"name": "Sky Blue", "hex": "#87CEEB"}, + {"name": "Light Periwinkle", "hex": "#C3CDE6"}, + {"name": "Sunflower Yellow", "hex": "#FFC300"} + ] + } + ``` + """ response: dict = await gpt_request(**LLM, prompt=prompt+Data, img=file_content, filename=file.filename)