File size: 13,016 Bytes
c290e43
c645839
6ff0647
c645839
 
 
 
2bc8286
c645839
6ff0647
 
 
89f7e0d
6ff0647
c645839
 
6ff0647
c645839
6ff0647
89f7e0d
c645839
 
 
6ff0647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c645839
6ff0647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c645839
 
6ff0647
c645839
 
6ff0647
 
 
 
 
 
 
 
 
 
 
d20b726
6ff0647
 
 
 
 
 
 
 
 
 
 
 
c645839
 
 
6ff0647
5647bfd
c645839
6ff0647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33d4d20
6ff0647
 
 
 
 
 
 
 
d20b726
6ff0647
 
 
 
d20b726
6ff0647
aa12eaa
6ff0647
 
c645839
 
6ff0647
c645839
6ff0647
 
 
 
 
 
 
 
c645839
d20b726
c645839
6ff0647
 
 
 
 
 
c645839
 
 
 
 
 
 
6ff0647
c645839
 
6ff0647
 
c645839
6ff0647
 
 
 
 
d20b726
 
6ff0647
 
d20b726
c645839
6ff0647
 
c645839
 
6ff0647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c645839
 
6ff0647
c645839
 
 
 
6ff0647
 
c645839
 
 
 
6ff0647
c645839
6ff0647
c645839
 
 
6ff0647
 
c645839
6ff0647
 
 
 
c645839
 
6ff0647
c645839
6ff0647
5647bfd
6ff0647
 
 
 
c645839
6ff0647
 
 
 
5647bfd
aa12eaa
6ff0647
c645839
6ff0647
5647bfd
c645839
 
6ff0647
 
 
5647bfd
6ff0647
 
 
 
 
5647bfd
aa12eaa
6ff0647
c645839
6ff0647
 
c645839
6ff0647
 
 
 
 
 
 
 
 
c645839
6ff0647
 
aa12eaa
6ff0647
 
 
 
 
 
5647bfd
6ff0647
b09f3fe
6ff0647
2bc8286
6ff0647
c645839
 
6ff0647
c645839
6ff0647
c645839
6ff0647
c645839
 
 
 
 
6ff0647
c645839
2bc8286
aa12eaa
c645839
 
c290e43
 
c645839
d6bf8a7
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
import gradio as gr
import os
from PIL import Image, ImageEnhance, ImageFilter
import requests
import io
import gc
import json
import logging
from dotenv import load_dotenv
from typing import Tuple, Optional, Dict, Any, List
import numpy as np
from dataclasses import dataclass

# Configuration avancée du logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger("EquityArtisan")

# Chargement des variables d'environnement
load_dotenv()

@dataclass
class RenderingParams:
    """Paramètres de rendu avancés pour le contrôle fin de la génération"""
    steps: int  # Nombre d'étapes d'inférence
    cfg_scale: float  # Échelle de guidance
    width: int  # Largeur
    height: int  # Hauteur
    sampler: str  # Méthode d'échantillonnage
    seed: Optional[int]  # Seed pour la reproductibilité

@dataclass
class StyleConfig:
    """Configuration complète d'un style artistique"""
    prompt_prefix: str
    negative_prompt: str
    quality_modifiers: List[str]
    detail_modifiers: List[str]
    composition_rules: List[str]

# Styles artistiques enrichis
ART_STYLES = {
    "Ultra Photoréaliste": StyleConfig(
        prompt_prefix="masterpiece, ultra realistic photograph, octane render, unreal engine 5 rendering, ray tracing, global illumination, subsurface scattering, volumetric lighting, 8k uhd, photorealistic",
        negative_prompt="cartoon, illustration, painting, drawing, sketch, anime, low quality, blurry, noise, grain, deformed, ugly, disfigured",
        quality_modifiers=["hyperdetailed", "photographic", "award winning photography"],
        detail_modifiers=["intricate details", "sharp focus", "professional lighting"],
        composition_rules=["rule of thirds", "golden ratio", "perfect composition"]
    ),
    "Cinématique": StyleConfig(
        prompt_prefix="cinematic scene, anamorphic lens, movie still, dramatic lighting, high production value, professional cinematography, ARRI camera",
        negative_prompt="amateur, low budget, poor lighting, webcam, phone camera",
        quality_modifiers=["film grain", "color grading", "bokeh effect"],
        detail_modifiers=["depth of field", "motion blur", "lens flare"],
        composition_rules=["wide aspect ratio", "leading lines", "frame within frame"]
    ),
    # ... [Autres styles similaires] ...
}

# Paramètres de qualité avancés
QUALITY_PRESETS = {
    "Standard": RenderingParams(
        steps=30,
        cfg_scale=7.5,
        width=768,
        height=768,
        sampler="Euler a",
        seed=None
    ),
    "Haute Qualité": RenderingParams(
        steps=40,
        cfg_scale=8.5,
        width=1024,
        height=1024,
        sampler="DPM++ 2M Karras",
        seed=None
    ),
    "Ultra Qualité": RenderingParams(
        steps=50,
        cfg_scale=9.0,
        width=1536,
        height=1536,
        sampler="DPM++ SDE Karras",
        seed=None
    )
}

# Enrichissement des paramètres de composition
COMPOSITION_PARAMS = {
    "Layouts": {
        "Dynamique": {
            "description": "Composition dynamique avec lignes de force",
            "modifiers": ["dynamic composition", "leading lines", "visual flow"],
            "weights": {"foreground": 1.2, "background": 0.8}
        },
        "Équilibré": {
            "description": "Composition harmonieuse et équilibrée",
            "modifiers": ["balanced composition", "symmetrical layout", "visual harmony"],
            "weights": {"foreground": 1.0, "background": 1.0}
        }
        # ... [Autres layouts] ...
    },
    "Éclairages": {
        "Studio": {
            "description": "Éclairage professionnel type studio",
            "modifiers": ["professional studio lighting", "three-point lighting", "soft boxes"],
            "technical_params": {"contrast": 1.2, "highlights": 1.1}
        },
        "Naturel": {
            "description": "Éclairage naturel avec lumière ambiante",
            "modifiers": ["natural lighting", "golden hour", "ambient occlusion"],
            "technical_params": {"contrast": 0.9, "shadows": 0.8}
        }
        # ... [Autres éclairages] ...
    }
}

class AdvancedImageGenerator:
    def __init__(self):
        self.API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
        self.token = os.getenv('HUGGINGFACE_TOKEN')
        if not self.token:
            raise EnvironmentError("HUGGINGFACE_TOKEN non configuré")
        self.headers = {"Authorization": f"Bearer {self.token}"}
        
        # Initialisation du cache pour les paramètres optimaux
        self.optimization_cache = {}
        logger.info("AdvancedImageGenerator initialisé avec paramètres enrichis")

    def _optimize_prompt(self, base_prompt: str, style_config: StyleConfig, params: Dict[str, Any]) -> str:
        """Optimisation avancée du prompt avec analyse sémantique"""
        components = [
            style_config.prompt_prefix,
            base_prompt
        ]

        # Ajout des modificateurs de qualité selon le niveau demandé
        quality_level = params.get("quality", 50)
        if quality_level > 40:
            components.extend(style_config.quality_modifiers)
        
        # Ajout des règles de composition
        components.extend(style_config.composition_rules)

        # Optimisation contextuelle basée sur le sujet
        if "portrait" in base_prompt.lower():
            components.extend([
                "perfect facial features",
                "detailed skin texture",
                "professional portrait lighting"
            ])
        elif "paysage" in base_prompt.lower():
            components.extend([
                "atmospheric perspective",
                "perfect weather conditions",
                "golden hour lighting"
            ])

        return ", ".join(components)

    def _apply_advanced_processing(self, image: Image.Image, params: Dict[str, Any]) -> Image.Image:
        """Application de traitements avancés post-génération"""
        try:
            # Amélioration des détails
            if params.get("detail_enhancement", True):
                image = image.filter(ImageFilter.DETAIL)
            
            # Optimisation du contraste local
            if params.get("local_contrast", True):
                enhancer = ImageEnhance.Contrast(image)
                image = enhancer.enhance(1.2)
            
            # Ajustement des couleurs
            if params.get("color_optimization", True):
                enhancer = ImageEnhance.Color(image)
                image = enhancer.enhance(1.1)
            
            return image
        except Exception as e:
            logger.error(f"Erreur lors du post-traitement: {e}")
            return image

    def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
        """Génération d'image avec paramètres avancés"""
        try:
            logger.info(f"Démarrage génération avec paramètres: {json.dumps(params, indent=2)}")
            
            style_config = ART_STYLES[params["style"]]
            prompt = self._optimize_prompt(params["subject"], style_config, params)
            
            # Sélection des paramètres de rendu
            quality_preset = QUALITY_PRESETS["Ultra Qualité" if params["quality"] > 45 else "Haute Qualité"]
            
            payload = {
                "inputs": prompt,
                "parameters": {
                    "negative_prompt": style_config.negative_prompt,
                    "num_inference_steps": quality_preset.steps,
                    "guidance_scale": quality_preset.cfg_scale,
                    "width": quality_preset.width,
                    "height": quality_preset.height,
                    "sampler": quality_preset.sampler
                }
            }

            response = requests.post(
                self.API_URL,
                headers=self.headers,
                json=payload,
                timeout=60
            )

            if response.status_code != 200:
                raise Exception(f"Erreur API: {response.status_code}")

            # Traitement et optimisation de l'image générée
            image = Image.open(io.BytesIO(response.content))
            image = self._apply_advanced_processing(image, params)
            
            return image, "✨ Génération réussie avec paramètres optimaux!"

        except Exception as e:
            logger.exception("Erreur pendant la génération:")
            return None, f"⚠️ Erreur: {str(e)}"

def create_interface():
    """Création de l'interface utilisateur enrichie"""
    logger.info("Initialisation de l'interface avancée")

    css = """
    .container { max-width: 1400px; margin: auto; padding: 20px; }
    .welcome { 
        text-align: center; 
        margin: 20px 0; 
        padding: 30px;
        background: linear-gradient(135deg, #1e293b, #334155);
        border-radius: 15px;
        color: white;
    }
    .controls-group { 
        background: #2d3748; 
        padding: 20px;
        border-radius: 10px;
        margin: 15px 0;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }
    """

    generator = AdvancedImageGenerator()

    with gr.Blocks(css=css) as app:
        gr.HTML("""
            <div class="welcome">
                <h1>🎨 Equity Artisan 4.0 Pro</h1>
                <p>Studio de Création Visuelle Avancé</p>
            </div>
        """)

        with gr.Column(elem_classes="container"):
            # Configuration principale
            with gr.Group(elem_classes="controls-group"):
                gr.Markdown("### 🎭 Style et Composition")
                with gr.Row():
                    style = gr.Dropdown(
                        choices=list(ART_STYLES.keys()),
                        value="Ultra Photoréaliste",
                        label="Style Artistique"
                    )
                    quality_preset = gr.Dropdown(
                        choices=list(QUALITY_PRESETS.keys()),
                        value="Haute Qualité",
                        label="Preset de Qualité"
                    )

            # Paramètres créatifs
            with gr.Group(elem_classes="controls-group"):
                gr.Markdown("### 🎨 Paramètres Créatifs")
                with gr.Row():
                    subject = gr.Textbox(
                        label="Description",
                        placeholder="Décrivez votre vision en détail...",
                        lines=3
                    )
                    composition = gr.Dropdown(
                        choices=list(COMPOSITION_PARAMS["Layouts"].keys()),
                        value="Dynamique",
                        label="Type de Composition"
                    )

            # Contrôles techniques
            with gr.Group(elem_classes="controls-group"):
                gr.Markdown("### ⚙️ Paramètres Techniques")
                with gr.Row():
                    quality = gr.Slider(
                        minimum=30,
                        maximum=100,
                        value=75,
                        label="Niveau de Qualité"
                    )
                    detail_level = gr.Slider(
                        minimum=1,
                        maximum=10,
                        value=8,
                        label="Niveau de Détail"
                    )

            # Génération
            with gr.Row():
                generate_btn = gr.Button("✨ Générer", variant="primary", size="lg")
                clear_btn = gr.Button("🗑️ Réinitialiser", variant="secondary")

            # Résultats
            image_output = gr.Image(
                label="Aperçu",
                elem_classes="result-image"
            )
            status = gr.Textbox(
                label="Statut",
                interactive=False
            )

        # Logique de génération
        def generate_image(*args):
            params = {
                "style": args[0],
                "quality_preset": args[1],
                "subject": args[2],
                "composition": args[3],
                "quality": args[4],
                "detail_level": args[5]
            }
            return generator.generate(params)

        # Événements
        generate_btn.click(
            generate_image,
            inputs=[
                style,
                quality_preset,
                subject,
                composition,
                quality,
                detail_level
            ],
            outputs=[image_output, status]
        )

        clear_btn.click(
            lambda: (None, "🔄 Interface réinitialisée"),
            outputs=[image_output, status]
        )

    logger.info("Interface créée avec succès")
    return app

if __name__ == "__main__":
    app = create_interface()
    app.launch()