Spaces:
Runtime error
Runtime error
import gradio as gr | |
import requests | |
from PIL import Image | |
import base64 | |
from io import BytesIO | |
import logging | |
# Set up logging | |
logging.basicConfig(level=logging.DEBUG) | |
logger = logging.getLogger(__name__) | |
# Define the API endpoints | |
skin_metrics_url = 'http://127.0.1:5000/upload' | |
recommendation_url = 'http://127.0.1:5000/recommend' | |
def capture_face_image(file): | |
try: | |
if file is None: | |
return "Please upload an image", None | |
# Open the uploaded image file (directly using the file object passed from Gradio) | |
image = Image.open(file) | |
# Convert image to base64 | |
buffered = BytesIO() | |
image.save(buffered, format="PNG") | |
img_str = base64.b64encode(buffered.getvalue()).decode('utf-8') | |
# Send to backend for skin analysis | |
try: | |
response = requests.put( | |
skin_metrics_url, | |
json={'file': img_str}, | |
timeout=10 # Add timeout | |
) | |
response.raise_for_status() # Raise exception for bad status codes | |
skin_data = response.json() # Skin analysis data from backend | |
return skin_data, image # Return both the analysis data and image | |
except requests.exceptions.RequestException as e: | |
logger.error(f"API request failed: {str(e)}") | |
return f"Error in skin analysis: {str(e)}", image | |
except Exception as e: | |
logger.error(f"Image processing error: {str(e)}") | |
return f"Error processing image: {str(e)}", None | |
def get_recommendations(tone, skin_type, concerns): | |
try: | |
# Define the full list of features that the model expects (18 in total) | |
all_features = [ | |
'normal', 'dry', 'oily', 'combination', 'acne', 'sensitive', 'fine lines', 'wrinkles', 'redness', | |
'dull', 'pore', 'pigmentation', 'blackheads', 'whiteheads', 'blemishes', 'dark circles', 'eye bags', 'dark spots' | |
] | |
# Prepare the features dict with all the values set to 0 initially | |
features_dict = {feature: 0 for feature in all_features} | |
# Update the dictionary with features selected by the user | |
for concern in concerns: | |
if concern in features_dict: | |
features_dict[concern] = 1 | |
# Prepare the data to send to the backend | |
data = { | |
'tone': tone, | |
'type': skin_type, | |
'features': features_dict # Send the full features dictionary | |
} | |
# Log the data being sent to the backend | |
logger.info(f"Sending recommendation request with data: {data}") | |
# Make a request to the backend for recommendations | |
try: | |
response = requests.put( | |
recommendation_url, | |
json=data, | |
timeout=10 # Add timeout | |
) | |
response.raise_for_status() | |
# Log the response status code and content | |
logger.info(f"Recommendation API response status: {response.status_code}") | |
recommendations = response.json() # Receive recommendations from backend | |
# Log the recommendations received from the backend | |
logger.info(f"Received recommendations: {recommendations}") | |
# Generate HTML content for cards | |
product_cards = "" | |
if recommendations.get("general"): | |
for category, products in recommendations["general"].items(): | |
for product in products: | |
card_html = f""" | |
<div style="border: 1px solid #ddd; padding: 10px; width: calc(33.33% - 20px); text-align: center; margin: 10px; border-radius: 10px; box-sizing: border-box; display: inline-block;"> | |
<img src="{product['img']}" alt="{product['name']}" style="width: 100%; height: auto; border-radius: 10px;"> | |
<h3>{product['name']}</h3> | |
<p>{product['brand']}</p> | |
<p><strong>{product['price']}</strong></p> | |
<a href="{product['url']}" target="_blank" style="display: inline-block; background-color: #1E90FF; color: white; padding: 10px 15px; border-radius: 5px; text-decoration: none;">Buy Now</a> | |
</div> | |
""" | |
product_cards += card_html | |
# Wrap the product cards in a responsive grid | |
grid_html = f""" | |
<div style="display: flex; flex-wrap: wrap; justify-content: space-around;"> | |
{product_cards} | |
</div> | |
""" | |
return grid_html # Return the HTML formatted product cards in a responsive grid | |
except requests.exceptions.RequestException as e: | |
logger.error(f"Recommendation API request failed: {str(e)}") | |
return {"error": f"Error fetching recommendations: {str(e)}"} | |
except Exception as e: | |
logger.error(f"Recommendation processing error: {str(e)}") | |
return {"error": str(e)} | |
# Build the Gradio interface | |
with gr.Blocks() as demo: | |
# Image upload section | |
with gr.Row(): | |
with gr.Column(): | |
image_input = gr.Image( | |
label="Upload Face Image", | |
type="file", # Type 'file' for image file upload | |
interactive=True | |
) | |
submit_button = gr.Button("Analyze Face") | |
# Form section | |
with gr.Row(): | |
with gr.Column(): | |
tone_input = gr.Slider( | |
minimum=1, | |
maximum=6, | |
label="Skin Tone", | |
value=5, | |
step=1 | |
) | |
skin_type_input = gr.Radio( | |
choices=["All", "Oily", "Normal", "Dry"], | |
label="Skin Type", | |
value="All" | |
) | |
acne_input = gr.Radio( | |
choices=['Low', 'Moderate', 'Severe'], | |
label="Acne Severity", | |
value="Moderate", # Default selected value | |
interactive=True # Make sure interactive is properly set | |
) | |
concerns_input = gr.CheckboxGroup( | |
choices=[ | |
'normal', 'dry', 'oily', 'combination', 'acne', 'sensitive', 'fine lines', 'wrinkles', 'redness', | |
'dull', 'pore', 'pigmentation', 'blackheads', 'whiteheads', 'blemishes', 'dark circles', 'eye bags', 'dark spots' | |
], | |
label="Skin Concerns" | |
) | |
form_submit_button = gr.Button("Get Recommendations") | |
# Output section | |
with gr.Row(): | |
recommendation_output = gr.HTML(label="Recommended Products") | |
# Event handlers | |
submit_button.click( | |
fn=capture_face_image, | |
inputs=image_input, | |
outputs=[recommendation_output, image_input] | |
) | |
form_submit_button.click( | |
fn=get_recommendations, | |
inputs=[tone_input, skin_type_input, concerns_input], | |
outputs=recommendation_output | |
) | |
# Launch the interface | |
demo.launch( | |
server_name="127.0.1", | |
server_port=7863, | |
debug=True | |
) | |
gr.close_all() | |