import gradio as gr import cv2 import numpy as np from PIL import Image from src.skin_analyzer import analyze_skin_function from src.image import ImageBundle import plotly.express as px import plotly.graph_objects as go import matplotlib.pyplot as plt import io def resize_image(image, height=512): # Calculate the new width to maintain the aspect ratio aspect_ratio = image.width / image.height new_width = int(height * aspect_ratio) return image.resize((new_width, height), Image.Resampling.LANCZOS) def create_histogram(data, title): fig = px.histogram(data, nbins=30, title=title) fig.update_layout(title=dict(y=0.9)) fig.update_xaxes(title_text="Value") fig.update_yaxes(title_text="Frequency") return fig # Function to create pie chart using Plotly def create_pie_chart(data, title): fig = px.pie(values=data.values(), names=data.keys(), title=title) fig.update_layout(title=dict(y=0.9)) return fig # Function to create bar chart using Plotly def create_bar_chart(data, title, top_n=None): sorted_data = dict(sorted(data.items(), key=lambda item: item[1], reverse=True)) colors = ( ["red" if i < top_n else "blue" for i in range(len(sorted_data))] if top_n and top_n < len(sorted_data) else "blue" ) fig = px.bar(x=list(sorted_data.keys()), y=list(sorted_data.values()), title=title) fig.update_traces(marker_color=colors) fig.update_layout( title=dict(y=0.9), xaxis_title=None, yaxis_title="Counts", showlegend=False ) fig.update_xaxes(tickangle=45) return fig def process_image( image, l_min_skin, l_max_skin, l_min_tonality, l_max_tonality, chroma_thresh, analyze_skin, analyze_eyes, analyze_hair, ): """ Process the uploaded image and return the analysis results based on selected analyses. :param image: Uploaded image. :param analyze_skin: Whether to perform skin analysis. :param analyze_eyes: Whether to perform eye analysis. :param analyze_hair: Whether to perform hair analysis. :return: Analysis results. """ image_bundle = ImageBundle(image_array=image) # Detect faces and landmarks face_data = image_bundle.detect_faces_and_landmarks() landmarks = image_bundle.detect_face_landmarks() # Perform segmentation segmentation_maps = image_bundle.segment_image() analysis_results = {} # overlay_images = [] # if analyze_hair: # hair_mask = segmentation_maps["hair_mask"] # # analysis_results['hair_analysis'] = analyze_hair_function(image, hair_mask) # overlay_images.append(segmentation_maps["hair_mask"]) if analyze_skin: skin_mask = segmentation_maps["face_skin_mask"] skin_analysis = analyze_skin_function( image, skin_mask, l_min_skin, l_max_skin, l_min_tonality, l_max_tonality, chroma_thresh, ) if "filtered_skin_mask" in skin_analysis: filtered_skin_mask = skin_analysis["filtered_skin_mask"] del skin_analysis["filtered_skin_mask"] if "l_hist" in skin_analysis: l_hist = skin_analysis["l_hist"] del skin_analysis["l_hist"] if "tonality_l_hist" in skin_analysis: tonality_l_hist = skin_analysis["tonality_l_hist"] del skin_analysis["tonality_l_hist"] if "chroma_hist" in skin_analysis: chroma_hist = skin_analysis["chroma_hist"] del skin_analysis["chroma_hist"] # analysis_results["skin_analysis"] = skin_analysis # Create bar charts for analysis results chroma_chart = create_pie_chart(skin_analysis["chroma_counts"], "Chroma Counts") undertone_chart = create_pie_chart( skin_analysis["undertone_counts"], "Undertone Counts" ) overtone_chart = create_bar_chart( skin_analysis["overtone_counts"], "Overtone Counts", 1 ) tonality_chart = create_pie_chart( skin_analysis["tonality_counts"], "Tonality Counts" ) season_chart = create_bar_chart( skin_analysis["season_counts"], "Season Counts", 3 ) # overlay_images.append(skin_analysis["overlay_image"]) # if analyze_eyes: # eye_mask = segmentation_maps["right_iris_mask"] | segmentation_maps["left_iris_mask"] # # analysis_results['eye_analysis'] = analyze_eye_function(image, eye_mask) # overlay_images.append(eye_mask) # Combine overlay images overlay = image.copy() overlay[filtered_skin_mask > 0] = (0, 0, 255) # Red for skin overlay = cv2.addWeighted(image, 0.85, overlay, 0.15, 0) # Convert combined_overlay to PIL Image for display combined_overlay = Image.fromarray(overlay) # Resize images before returning combined_overlay = resize_image(combined_overlay) # l_hist = resize_image(l_hist) # tonality_l_hist = resize_image(tonality_l_hist) # chroma_hist = resize_image(chroma_hist) # chroma_chart = resize_image(chroma_chart) # undertone_chart = resize_image(undertone_chart) # overtone_chart = resize_image(overtone_chart) # tonality_chart = resize_image(tonality_chart) # season_chart = resize_image(season_chart) return ( combined_overlay, l_hist, tonality_l_hist, chroma_hist, # analysis_results, chroma_chart, undertone_chart, overtone_chart, tonality_chart, season_chart, ) with gr.Blocks() as demo: with gr.Row(): with gr.Column(): skin_checkbox = gr.Checkbox(label="Skin Analysis", value=True) submit_button = gr.Button("Submit") with gr.Column(): eye_checkbox = gr.Checkbox(label="Eye Analysis", value=False) hair_checkbox = gr.Checkbox(label="Hair Analysis", value=False) with gr.Row(): with gr.Column(): upload_image = gr.Image(type="numpy", label="Upload an Image") with gr.Column(): l_min_slider = gr.Slider( minimum=0, maximum=100, value=10, label="L(%) Min Skin" ) l_max_slider = gr.Slider( minimum=0, maximum=100, value=90, label="L(%) Max Skin" ) l_hist_output = gr.Plot(label="L Histogram") # processed_image_output = gr.Image(type="pil", label="Processed Image") with gr.Row(): with gr.Column(): processed_image_output = gr.Image(type="pil", label="Processed Image") with gr.Column(): undertone_chart_output = gr.Plot(label="Undertone Counts") with gr.Row(): with gr.Column(): tonality_min_slider = gr.Slider( minimum=0, maximum=100, value=50, label="L(%) Min Tonality" ) tonality_max_slider = gr.Slider( minimum=0, maximum=100, value=70, label="L(%) Max Tonality" ) tonality_hist_output = gr.Plot(label="Tonality L Histogram") with gr.Column(): tonality_chart_output = gr.Plot(label="Tonality Counts") # with gr.Row(): # submit_button = gr.Button("Submit") with gr.Row(): with gr.Column(): chroma_slider = gr.Slider( minimum=0, maximum=100, value=50, label="Chroma(%) Threshold" ) chroma_hist_output = gr.Plot(label="Chroma Histogram") with gr.Column(): chroma_chart_output = gr.Plot(label="Chroma Counts") with gr.Row(): with gr.Column(): overtone_chart_output = gr.Plot(label="Overtone Counts") with gr.Column(): season_chart_output = gr.Plot(label="Season Counts") inputs = [ upload_image, l_min_slider, l_max_slider, tonality_min_slider, tonality_max_slider, chroma_slider, skin_checkbox, eye_checkbox, hair_checkbox, ] outputs = [ processed_image_output, l_hist_output, tonality_hist_output, chroma_hist_output, chroma_chart_output, undertone_chart_output, overtone_chart_output, tonality_chart_output, season_chart_output, ] # Set up change event triggers for the sliders l_min_slider.change(process_image, inputs=inputs, outputs=outputs) l_max_slider.change(process_image, inputs=inputs, outputs=outputs) tonality_min_slider.change(process_image, inputs=inputs, outputs=outputs) tonality_max_slider.change(process_image, inputs=inputs, outputs=outputs) chroma_slider.change(process_image, inputs=inputs, outputs=outputs) # upload_image.change(process_image, inputs=inputs, outputs=outputs) skin_checkbox.change(process_image, inputs=inputs, outputs=outputs) eye_checkbox.change(process_image, inputs=inputs, outputs=outputs) hair_checkbox.change(process_image, inputs=inputs, outputs=outputs) # Link the submit button to the analyze_image function submit_button.click(process_image, inputs=inputs, outputs=outputs) demo.launch()