File size: 5,769 Bytes
956fa05
 
f56644b
 
956fa05
 
 
 
 
 
 
 
 
 
 
 
f56644b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64fe77f
 
956fa05
 
 
 
 
 
 
 
 
 
64fe77f
 
 
 
 
956fa05
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f56644b
 
 
 
 
 
 
 
 
956fa05
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f56644b
956fa05
f56644b
956fa05
f56644b
956fa05
 
 
 
 
 
 
 
f56644b
956fa05
f56644b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import gradio as gr
import torch
# from diffusers import AutoPipelineForText2Image
from diffusers import DiffusionPipeline
from transformers import BlipProcessor, BlipForConditionalGeneration
from pathlib import Path
import stone
import requests
import io
import os
from PIL import Image
import spaces

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import hex2color
from huggingface_hub import list_models

# Fetch models from Hugging Face Hub
models = list_models(task="text-to-image")
## Step 1: Filter the models
filtered_models = [model for model in models if model.library_name == "diffusers"]

# Step 2: Sort the filtered models by downloads in descending order
sorted_models = sorted(filtered_models, key=lambda x: x.downloads, reverse=True)

# Step 3: Select the top 5 models with only one model per company
top_models = []
companies_seen = set()

for model in sorted_models:
    company_name = model.id.split('/')[0]  # Assuming the company name is the first part of the model id
    if company_name not in companies_seen:
        top_models.append(model)
        companies_seen.add(company_name)
    if len(top_models) == 5:
        break

# Get the ids of the top models
model_names = [model.id for model in top_models]

print(model_names)

# Initial pipeline setup
default_model = model_names[0]
print(default_model)
pipeline_text2image = DiffusionPipeline.from_pretrained(
    default_model
)
pipeline_text2image = pipeline_text2image.to("cuda")

@spaces.GPU
def getimgen(prompt):

    return pipeline_text2image(
        prompt=prompt,
        guidance_scale=0.0,
        num_inference_steps=2
    ).images[0]

blip_processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-large")
blip_model = BlipForConditionalGeneration.from_pretrained(
    "Salesforce/blip-image-captioning-large",
    torch_dtype=torch.float16
).to("cuda")

@spaces.GPU
def blip_caption_image(image, prefix):
    inputs = blip_processor(image, prefix, return_tensors="pt").to("cuda", torch.float16)
    out = blip_model.generate(**inputs)
    return blip_processor.decode(out[0], skip_special_tokens=True)

def genderfromcaption(caption):
    cc = caption.split()
    if "man" in cc or "boy" in cc:
        return "Man"
    elif "woman" in cc or "girl" in cc:
        return "Woman"
    return "Unsure"

def genderplot(genlist):    
    order = ["Man", "Woman", "Unsure"]

    # Sort the list based on the order of keys
    words = sorted(genlist, key=lambda x: order.index(x))

    # Define colors for each category
    colors = {"Man": "lightgreen", "Woman": "darkgreen", "Unsure": "lightgrey"}

    # Map each word to its corresponding color
    word_colors = [colors[word] for word in words]

    # Plot the colors in a grid with reduced spacing
    fig, axes = plt.subplots(2, 5, figsize=(5,5))

    # Adjust spacing between subplots
    plt.subplots_adjust(hspace=0.1, wspace=0.1)

    for i, ax in enumerate(axes.flat):
        ax.set_axis_off()
        ax.add_patch(plt.Rectangle((0, 0), 1, 1, color=word_colors[i]))

    return fig

def skintoneplot(hex_codes):
    # Convert hex codes to RGB values
    rgb_values = [hex2color(hex_code) for hex_code in hex_codes]

    # Calculate luminance for each color
    luminance_values = [0.299 * r + 0.587 * g + 0.114 * b for r, g, b in rgb_values]

    # Sort hex codes based on luminance in descending order (dark to light)
    sorted_hex_codes = [code for _, code in sorted(zip(luminance_values, hex_codes), reverse=True)]

    # Plot the colors in a grid with reduced spacing
    fig, axes = plt.subplots(2, 5, figsize=(5,5))

    # Adjust spacing between subplots
    plt.subplots_adjust(hspace=0.1, wspace=0.1)

    for i, ax in enumerate(axes.flat):
        ax.set_axis_off()
        ax.add_patch(plt.Rectangle((0, 0), 1, 1, color=sorted_hex_codes[i]))

    return fig

@spaces.GPU
def generate_images_plots(prompt, model_name):
    print(model_name)
    # Update the pipeline to use the selected model
    global pipeline_text2image
    pipeline_text2image = DiffusionPipeline.from_pretrained(
        model_name
    )
    pipeline_text2image = pipeline_text2image.to("cuda")

    foldername = "temp"
    # Generate 10 images
    images = [getimgen(prompt) for _ in range(10)]

    Path(foldername).mkdir(parents=True, exist_ok=True)

    genders = []
    skintones = []

    for image, i in zip(images, range(10)):
        prompt_prefix = "photo of a "
        caption = blip_caption_image(image, prefix=prompt_prefix)
        image.save(f"{foldername}/image_{i}.png")
        try:
            skintoneres = stone.process(f"{foldername}/image_{i}.png", return_report_image=False)
            tone = skintoneres['faces'][0]['dominant_colors'][0]['color']
            skintones.append(tone)
        except:
            skintones.append(None)

        genders.append(genderfromcaption(caption))

    print(genders, skintones)

    return images, skintoneplot(skintones), genderplot(genders)

with gr.Blocks(title = "Skin Tone and Gender bias in Text to Image Models") as demo:

    gr.Markdown("# Skin Tone and Gender bias in Text to Image Models")

    model_dropdown = gr.Dropdown(label="Choose a model", choices=model_names, value=default_model)
    prompt = gr.Textbox(label="Enter the Prompt")
    gallery = gr.Gallery(label="Generated images", show_label=False, elem_id="gallery", 
                         columns=[5], rows=[2], object_fit="contain", height="auto")
    btn = gr.Button("Generate images", scale=0)
    with gr.Row(equal_height=True):
        skinplot = gr.Plot(label="Skin Tone")
        genplot = gr.Plot(label="Gender")

    btn.click(generate_images_plots, inputs=[prompt, model_dropdown], outputs=[gallery, skinplot, genplot])

demo.launch(debug=True)