Update app.py
Browse files
app.py
CHANGED
@@ -4,147 +4,140 @@ from PIL import Image, ImageDraw, ImageFont
|
|
4 |
import requests
|
5 |
import io
|
6 |
|
7 |
-
#
|
8 |
-
|
9 |
-
"
|
10 |
-
"
|
11 |
-
"
|
12 |
-
"
|
13 |
-
"negative_prompt": "blurry, low quality, flat lighting, cartoon, modern"
|
14 |
-
},
|
15 |
-
"Impressionnisme": {
|
16 |
-
"prompt_prefix": "impressionist art style, vibrant brushstrokes, atmospheric lighting, monet-like technique",
|
17 |
-
"guidance": 12.0,
|
18 |
-
"steps": 65,
|
19 |
-
"negative_prompt": "sharp details, photorealistic, digital art"
|
20 |
-
},
|
21 |
-
"Art Moderne": {
|
22 |
-
"prompt_prefix": "modern art composition, bold geometric shapes, abstract elements, strong visual impact",
|
23 |
-
"guidance": 11.0,
|
24 |
-
"steps": 60,
|
25 |
-
"negative_prompt": "realistic, traditional, detailed texture"
|
26 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
"Illustration Pro": {
|
28 |
-
"prompt_prefix": "professional
|
|
|
29 |
"guidance": 13.5,
|
30 |
"steps": 70,
|
31 |
-
"negative_prompt": "amateur,
|
32 |
},
|
33 |
-
"
|
34 |
-
"prompt_prefix": "vintage poster
|
|
|
35 |
"guidance": 12.5,
|
36 |
"steps": 65,
|
37 |
-
"negative_prompt": "modern, digital,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
},
|
39 |
-
"
|
40 |
-
"prompt_prefix": "
|
|
|
41 |
"guidance": 14.0,
|
42 |
"steps": 75,
|
43 |
-
"negative_prompt": "
|
44 |
},
|
45 |
"Pop Art": {
|
46 |
-
"prompt_prefix": "pop art style, bold
|
|
|
47 |
"guidance": 11.5,
|
48 |
"steps": 60,
|
49 |
-
"negative_prompt": "realistic, painterly,
|
50 |
-
},
|
51 |
-
"Dark Fantasy": {
|
52 |
-
"prompt_prefix": "dark fantasy art, atmospheric mood, dramatic lighting, mythological elements",
|
53 |
-
"guidance": 13.0,
|
54 |
-
"steps": 70,
|
55 |
-
"negative_prompt": "bright, cheerful, realistic photo"
|
56 |
}
|
57 |
}
|
58 |
|
59 |
-
# Collections thématiques
|
60 |
-
COLLECTIONS = {
|
61 |
-
"Nature Artistique": {
|
62 |
-
"prompts": ["artistic nature illustration", "stylized botanical elements"],
|
63 |
-
"styles": ["organic composition", "natural textures", "dynamic flow"],
|
64 |
-
"negative": "artificial, synthetic, urban"
|
65 |
-
},
|
66 |
-
"Portraits Expressifs": {
|
67 |
-
"prompts": ["expressive portrait art", "emotional character illustration"],
|
68 |
-
"styles": ["dramatic lighting", "powerful expression", "artistic interpretation"],
|
69 |
-
"negative": "flat lighting, emotionless, stiff pose"
|
70 |
-
},
|
71 |
-
"Urbain Stylisé": {
|
72 |
-
"prompts": ["stylized urban art", "city aesthetic interpretation"],
|
73 |
-
"styles": ["architectural elements", "urban textures", "street art influence"],
|
74 |
-
"negative": "rural, natural, realistic photo"
|
75 |
-
},
|
76 |
-
"Fantaisie Épique": {
|
77 |
-
"prompts": ["epic fantasy artwork", "mythological interpretation"],
|
78 |
-
"styles": ["magical elements", "dramatic atmosphere", "legendary creatures"],
|
79 |
-
"negative": "mundane, realistic, modern"
|
80 |
-
}
|
81 |
-
}
|
82 |
-
|
83 |
-
# CSS personnalisé
|
84 |
CUSTOM_CSS = """
|
85 |
.container { max-width: 1200px; margin: auto; }
|
86 |
.welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
|
87 |
.quality-controls { margin: 10px 0; padding: 10px; background: #2d3748; border-radius: 5px; }
|
|
|
88 |
"""
|
89 |
|
90 |
-
def
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
if
|
101 |
-
|
102 |
-
|
103 |
-
base_height = 1024
|
104 |
-
else:
|
105 |
-
if format_size in ["A4", "A3"]:
|
106 |
-
base_width = 1024
|
107 |
-
base_height = 768
|
108 |
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
collection_data = COLLECTIONS[collection]
|
115 |
-
collection_elements = collection_data["prompts"] + collection_data["styles"]
|
116 |
-
enhanced_prompt += f", {', '.join(collection_elements)}"
|
117 |
-
negative_prompt = f"{style_config['negative_prompt']}, {collection_data['negative']}"
|
118 |
-
else:
|
119 |
-
negative_prompt = style_config['negative_prompt']
|
120 |
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
}
|
131 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
if response.status_code == 200:
|
138 |
-
image = Image.open(io.BytesIO(response.content))
|
139 |
-
return image, f"✨ Création {style} réussie!"
|
140 |
-
else:
|
141 |
-
print(f"Erreur API: {response.text}")
|
142 |
-
return None, f"⚠️ Erreur {response.status_code}: Ajustez les paramètres"
|
143 |
-
|
144 |
-
except Exception as e:
|
145 |
-
print(f"Exception: {str(e)}")
|
146 |
-
return None, f"⚠️ Erreur: {str(e)}"
|
147 |
|
|
|
148 |
with gr.Blocks(css=CUSTOM_CSS) as app:
|
149 |
gr.HTML("""
|
150 |
<div class="welcome">
|
@@ -177,20 +170,23 @@ def create_interface():
|
|
177 |
with gr.Column():
|
178 |
style = gr.Dropdown(
|
179 |
choices=list(ART_STYLES.keys()),
|
180 |
-
value="
|
181 |
-
label="Style artistique"
|
|
|
182 |
)
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
label="
|
187 |
-
|
|
|
188 |
)
|
189 |
|
190 |
-
|
191 |
-
lines=
|
192 |
-
label="
|
193 |
-
placeholder="
|
|
|
194 |
)
|
195 |
|
196 |
with gr.Group(elem_classes="quality-controls"):
|
@@ -233,11 +229,11 @@ def create_interface():
|
|
233 |
inputs=[
|
234 |
format_choice,
|
235 |
orientation,
|
236 |
-
|
237 |
style,
|
238 |
quality,
|
239 |
creativity,
|
240 |
-
|
241 |
],
|
242 |
outputs=[image_output, status]
|
243 |
)
|
|
|
4 |
import requests
|
5 |
import io
|
6 |
|
7 |
+
# Dictionnaire de sujets spécifiques
|
8 |
+
SUBJECT_PROMPTS = {
|
9 |
+
"insectes": {
|
10 |
+
"libellule": "hyper realistic dragonfly in flight with translucent wings, iridescent body, macro photography, detailed insect illustration, natural lighting, entomological precision",
|
11 |
+
"papillon": "detailed butterfly with intricate wing patterns, highly detailed macro photography, precise lepidoptera illustration",
|
12 |
+
"scarabée": "detailed beetle with shiny carapace, precise entomological macro photography"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
},
|
14 |
+
"animaux": {
|
15 |
+
"loup": "majestic wolf portrait, detailed fur texture, highly detailed wild canine features, expressive eyes, professional wildlife photography",
|
16 |
+
"lion": "majestic lion portrait, detailed mane, powerful feline features, dramatic lighting, professional wildlife photography",
|
17 |
+
"renard": "elegant fox portrait, detailed fur texture, cunning vulpine features, professional wildlife photography"
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
# Styles artistiques améliorés
|
22 |
+
ART_STYLES = {
|
23 |
"Illustration Pro": {
|
24 |
+
"prompt_prefix": "professional high-end illustration, perfect composition, editorial quality artwork",
|
25 |
+
"style_modifiers": "sharp clean lines, elegant design, magazine quality finish",
|
26 |
"guidance": 13.5,
|
27 |
"steps": 70,
|
28 |
+
"negative_prompt": "amateur, sketchy, rough, unfinished, low quality"
|
29 |
},
|
30 |
+
"Neo Vintage": {
|
31 |
+
"prompt_prefix": "vintage style poster art, retro illustration, classic design aesthetic",
|
32 |
+
"style_modifiers": "halftone texture, limited color palette, aged paper effect, vintage typography",
|
33 |
"guidance": 12.5,
|
34 |
"steps": 65,
|
35 |
+
"negative_prompt": "modern, digital, glossy, contemporary"
|
36 |
+
},
|
37 |
+
"Art Moderne": {
|
38 |
+
"prompt_prefix": "modern art style, contemporary design, abstract artistic interpretation",
|
39 |
+
"style_modifiers": "geometric shapes, bold colors, minimalist composition",
|
40 |
+
"guidance": 11.0,
|
41 |
+
"steps": 60,
|
42 |
+
"negative_prompt": "classical, photorealistic, traditional"
|
43 |
},
|
44 |
+
"Dark Fantasy": {
|
45 |
+
"prompt_prefix": "dark fantasy art style, atmospheric mood, dramatic fantasy illustration",
|
46 |
+
"style_modifiers": "mystical atmosphere, dramatic lighting, ethereal quality",
|
47 |
"guidance": 14.0,
|
48 |
"steps": 75,
|
49 |
+
"negative_prompt": "cheerful, bright, realistic photo, mundane"
|
50 |
},
|
51 |
"Pop Art": {
|
52 |
+
"prompt_prefix": "pop art style illustration, bold graphic design, comic book aesthetic",
|
53 |
+
"style_modifiers": "vibrant colors, halftone dots, bold outlines, Warhol-inspired",
|
54 |
"guidance": 11.5,
|
55 |
"steps": 60,
|
56 |
+
"negative_prompt": "realistic, subtle, painterly, traditional"
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
}
|
58 |
}
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
CUSTOM_CSS = """
|
61 |
.container { max-width: 1200px; margin: auto; }
|
62 |
.welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
|
63 |
.quality-controls { margin: 10px 0; padding: 10px; background: #2d3748; border-radius: 5px; }
|
64 |
+
.style-info { padding: 10px; background: #2d3748; border-radius: 5px; margin-top: 10px; }
|
65 |
"""
|
66 |
|
67 |
+
def enhance_prompt(subject, style, additional_details=""):
|
68 |
+
"""Améliore le prompt avec des détails spécifiques"""
|
69 |
+
# Recherche dans le dictionnaire de sujets
|
70 |
+
base_prompt = None
|
71 |
+
for category, subjects in SUBJECT_PROMPTS.items():
|
72 |
+
if subject.lower() in subjects:
|
73 |
+
base_prompt = subjects[subject.lower()]
|
74 |
+
break
|
75 |
+
|
76 |
+
if not base_prompt:
|
77 |
+
base_prompt = f"highly detailed {subject}"
|
78 |
+
|
79 |
+
# Ajout des détails spécifiques
|
80 |
+
if additional_details:
|
81 |
+
base_prompt = f"{base_prompt}, {additional_details}"
|
82 |
+
|
83 |
+
# Application du style
|
84 |
+
style_config = ART_STYLES[style]
|
85 |
+
final_prompt = f"{style_config['prompt_prefix']}, {base_prompt}, {style_config['style_modifiers']}"
|
86 |
+
|
87 |
+
return final_prompt, style_config['negative_prompt']
|
88 |
+
|
89 |
+
def generate_image(format_size, orientation, subject, style, quality, creativity, additional_details=""):
|
90 |
+
API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
|
91 |
+
headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_TOKEN')}"}
|
92 |
+
|
93 |
+
try:
|
94 |
+
# Dimensions de base optimisées
|
95 |
+
base_width = 1024
|
96 |
+
base_height = 1024
|
97 |
|
98 |
+
if orientation == "Portrait":
|
99 |
+
if format_size in ["A4", "A3"]:
|
100 |
+
base_width = 768
|
101 |
+
base_height = 1024
|
102 |
+
else:
|
103 |
+
if format_size in ["A4", "A3"]:
|
104 |
+
base_width = 1024
|
105 |
+
base_height = 768
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
+
# Construction du prompt optimisé
|
108 |
+
enhanced_prompt, negative_prompt = enhance_prompt(subject, style, additional_details)
|
109 |
+
|
110 |
+
print(f"Prompt final: {enhanced_prompt}") # Debug
|
111 |
+
print(f"Prompt négatif: {negative_prompt}") # Debug
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
+
# Configuration de la requête
|
114 |
+
payload = {
|
115 |
+
"inputs": enhanced_prompt,
|
116 |
+
"parameters": {
|
117 |
+
"negative_prompt": negative_prompt,
|
118 |
+
"num_inference_steps": int(ART_STYLES[style]['steps'] * (quality/100)),
|
119 |
+
"guidance_scale": ART_STYLES[style]['guidance'] * (creativity/10),
|
120 |
+
"width": base_width,
|
121 |
+
"height": base_height
|
|
|
122 |
}
|
123 |
+
}
|
124 |
+
|
125 |
+
print(f"Paramètres de génération: {payload}") # Debug
|
126 |
+
|
127 |
+
response = requests.post(API_URL, headers=headers, json=payload, timeout=60)
|
128 |
+
|
129 |
+
if response.status_code == 200:
|
130 |
+
image = Image.open(io.BytesIO(response.content))
|
131 |
+
return image, f"✨ Création {style} réussie!"
|
132 |
+
else:
|
133 |
+
print(f"Erreur API: {response.text}") # Debug
|
134 |
+
return None, f"⚠️ Erreur {response.status_code}: Ajustez les paramètres"
|
135 |
|
136 |
+
except Exception as e:
|
137 |
+
print(f"Exception: {str(e)}") # Debug
|
138 |
+
return None, f"⚠️ Erreur: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
|
140 |
+
def create_interface():
|
141 |
with gr.Blocks(css=CUSTOM_CSS) as app:
|
142 |
gr.HTML("""
|
143 |
<div class="welcome">
|
|
|
170 |
with gr.Column():
|
171 |
style = gr.Dropdown(
|
172 |
choices=list(ART_STYLES.keys()),
|
173 |
+
value="Illustration Pro",
|
174 |
+
label="Style artistique",
|
175 |
+
info="Choisissez votre style d'illustration"
|
176 |
)
|
177 |
|
178 |
+
subject = gr.Textbox(
|
179 |
+
lines=1,
|
180 |
+
label="Sujet principal",
|
181 |
+
placeholder="Ex: libellule, loup, paysage...",
|
182 |
+
info="Décrivez le sujet principal"
|
183 |
)
|
184 |
|
185 |
+
additional_details = gr.Textbox(
|
186 |
+
lines=2,
|
187 |
+
label="Détails additionnels (optionnel)",
|
188 |
+
placeholder="Ajoutez des détails spécifiques pour enrichir l'image...",
|
189 |
+
info="Plus de détails = meilleur résultat"
|
190 |
)
|
191 |
|
192 |
with gr.Group(elem_classes="quality-controls"):
|
|
|
229 |
inputs=[
|
230 |
format_choice,
|
231 |
orientation,
|
232 |
+
subject,
|
233 |
style,
|
234 |
quality,
|
235 |
creativity,
|
236 |
+
additional_details
|
237 |
],
|
238 |
outputs=[image_output, status]
|
239 |
)
|