File size: 9,247 Bytes
876015b
ea5bac5
74e68b0
 
 
876015b
ea5bac5
876015b
ea5bac5
 
ce517d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876015b
ea5bac5
 
 
 
 
876015b
ea5bac5
 
 
 
 
 
 
 
 
 
 
ce517d1
ea5bac5
ce517d1
 
ea5bac5
876015b
 
ea5bac5
 
ce517d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876015b
ea5bac5
 
 
876015b
ea5bac5
 
876015b
4af07c3
 
ea5bac5
 
 
ce517d1
876015b
 
 
ea5bac5
 
 
ce517d1
876015b
ea5bac5
ce517d1
 
876015b
ea5bac5
4af07c3
 
ea5bac5
 
876015b
 
 
ce517d1
ea5bac5
 
 
 
4af07c3
502749c
ea5bac5
 
876015b
ea5bac5
 
6595ea4
ce517d1
 
ea5bac5
ce517d1
 
6595ea4
ea5bac5
ce517d1
502749c
6595ea4
 
ea5bac5
6595ea4
ea5bac5
 
 
 
 
 
 
 
 
 
ce517d1
ea5bac5
 
 
ce517d1
ea5bac5
 
 
 
 
ce517d1
 
 
 
 
ea5bac5
 
 
 
 
876015b
 
ea5bac5
 
 
 
ce517d1
 
ea5bac5
 
 
 
 
 
876015b
 
ea5bac5
 
876015b
ea5bac5
ce517d1
 
 
 
 
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
import random
import gradio as gr
from data import fashion_elements, PhotoReal

negative_prompt_fusion = "blurry, deformed, ugly, mutilated, disfigured, extra limbs, extra fingers, poorly drawn hands, poorly drawn feet, mutated hands, mutation, deformed, bad anatomy, bad proportions, extra arms, extra legs, fused fingers, too many fingers, long neck, username, watermark, signature, overexposed, underexposed, bad lighting, distorted face, low quality, artifacts"

class FashionPromptGenerator:
    def __init__(self):
        self.previous_prompts = set()
        self.photo_real = PhotoReal()
        
        # Asegurarse de que todos los atributos necesarios existan
        self._ensure_attributes()

    def _ensure_attributes(self):
        """Asegura que todos los atributos necesarios existan en photo_real"""
        if not hasattr(self.photo_real, 'STOCKINGS'):
            self.photo_real.STOCKINGS = "realistic sheer stockings with authentic fabric weave"
        if not hasattr(self.photo_real, 'HEELS'):
            self.photo_real.HEELS = "classic black leather heels"
        if not hasattr(self.photo_real, 'CAMERA'):
            self.photo_real.CAMERA = "photorealistic 8K vertical capture 9:16 aspect"
        if not hasattr(self.photo_real, 'SENSUAL_POSES'):
            self.photo_real.SENSUAL_POSES = [
                {"pose": "standing confidently", "view": "frontal"},
                {"pose": "leaning forward", "view": "frontal"}
            ]

    def generate_unique_prompts(self, subject_name, num_prompts=5):
        """Genera una lista de prompts únicos."""
        if not subject_name or subject_name.isspace():
            subject_name = "a beautiful woman"
        
        prompts = []
        max_attempts = num_prompts * 10
        attempts = 0

        while len(prompts) < num_prompts and attempts < max_attempts:
            prompt = self._build_fused_prompt(subject_name)
            prompt_hash = hash(prompt)
            if prompt_hash not in self.previous_prompts:
                self.previous_prompts.add(prompt_hash)
                prompts.append(prompt)
            attempts += 1
        
        # Si no se logran suficientes prompts únicos, rellena con algunos aleatorios
        while len(prompts) < num_prompts:
            prompt = self._build_fused_prompt(subject_name)
            prompts.append(prompt)
            
        return prompts

    def _build_fused_prompt(self, subject_name):
        """Construye un prompt fusionando los estilos photorealistic y voyeuristic."""
        try:
            # --- Elementos de Photorealistic ---
            role = random.choice(self.photo_real.ROLES)
            body = random.choice(self.photo_real.BODY)
            skin = random.choice(self.photo_real.SKIN)
            hair = random.choice(self.photo_real.HAIR)
            expression = random.choice(self.photo_real.EXPRESSION)
            sensual_pose = random.choice(self.photo_real.SENSUAL_POSES)
            
            # --- Elementos de Voyeuristic ---
            primary_color = random.choice(fashion_elements["colors"])
            discovery_moment = random.choice(fashion_elements["discovery_moments"])
            reveal_action = random.choice(fashion_elements["lingerie_reveal_actions"])
            background = random.choice(fashion_elements["backgrounds"])
            lighting = random.choice(fashion_elements["lighting"])
            
            # --- Construcción del Prompt ---
            prompt = (
                f"Photorealistic portrait of {subject_name} as a {role['role']}, "
                f"captured from an extreme low angle, floor-level perspective, shooting upward. "
                f"The composition focuses on a moment of discovery, {discovery_moment}. "
                f"She is {reveal_action}, creating a natural and unposed exposure.\n\n"
                f"**Body & Appearance:**\n"
                f"- **Physique:** {body} with {skin}.\n"
                f"- **Hair:** {hair}.\n"
                f"- **Expression:** {expression}.\n"
                f"- **Outfit:** She wears {role['outfit']} over {primary_color} lingerie. "
                f"Complemented by {self.photo_real.STOCKINGS} and {self.photo_real.HEELS}.\n\n"
                f"**Scene & Atmosphere:**\n"
                f"- **Setting:** {background} with {lighting}.\n"
                f"- **Pose:** {sensual_pose['pose']} ({sensual_pose['view']} view), emphasizing a sensual and captivating stance.\n"
                f"- **Mood:** Intimate, sensual, and elegantly composed.\n\n"
                f"**Technical Details:**\n"
                f"- **Camera:** {self.photo_real.CAMERA}.\n"
                f"- **Quality:** Ultra HD, professional retouching, sharp focus on intimate details and facial expression.\n\n"
                f"The image captures a fleeting, intimate moment that feels both spontaneous and beautifully composed, emphasizing the sensual discovery of hidden lingerie through natural movement and expert framing. "
                f"--ar 9:16 --v 6 --q 2 --style raw --stylize 100"
            )
            return prompt.strip()
        except Exception as e:
            # Fallback en caso de error
            return f"Photorealistic portrait of {subject_name} in an elegant setting, captured from a low angle with intimate lighting. --ar 9:16 --v 6"

    def clear_history(self):
        """Limpia el historial de prompts generados."""
        self.previous_prompts.clear()

def create_gradio_interface():
    generator = FashionPromptGenerator()

    with gr.Blocks() as demo:
        
        gr.Markdown("""
        # 🎭 Advanced Fashion Prompt Generator
        *Create photorealistic, discovery-focused prompts with a single, powerful style.*
        """)
        
        with gr.Row():
            with gr.Column(scale=2):
                celebrity_input = gr.Textbox(
                    label="Celebrity Name (Optional)",
                    placeholder="Enter a name or leave blank for 'a beautiful woman'",
                    value=""
                )
                num_prompts_slider = gr.Slider(
                    minimum=1, maximum=10, value=5, step=1, 
                    label="Number of Prompts to Generate"
                )
            with gr.Column(scale=1):
                generate_btn = gr.Button("✨ Generate Prompts", variant="primary")
                clear_btn = gr.Button("🗑️ Clear History", variant="secondary")

        gr.Markdown("---")
        
        with gr.Row():
            with gr.Column():
                gr.Markdown("### Negative Prompt")
                negative_prompt_output = gr.Textbox(
                    value=negative_prompt_fusion,
                    label="",
                    lines=4,
                    interactive=False
                )

        gr.Markdown("## Generated Prompts")
        
        output_columns = []
        output_prompts = []
        copy_buttons = []
        
        # Crear 10 columnas (máximo)
        for i in range(10):
            with gr.Column(visible=(i < 5)) as col:  # Mostrar solo 5 inicialmente
                gr.Markdown(f"### 🎯 Prompt {i+1}")
                
                prompt_output = gr.Textbox(
                    label="", 
                    lines=12,
                    interactive=False,
                    show_copy_button=True  # Esto agrega el botón de copia integrado
                )
                
                output_columns.append(col)
                output_prompts.append(prompt_output)

        def generate_and_display(celebrity_name, num_prompts):
            num_prompts = int(num_prompts)
            prompts = generator.generate_unique_prompts(celebrity_name, num_prompts)
            
            updates = []
            for i in range(10):
                if i < num_prompts:
                    # Mostrar columna y establecer valor
                    updates.append(gr.update(visible=True))
                    updates.append(gr.update(value=prompts[i]))
                else:
                    # Ocultar columna y limpiar valor
                    updates.append(gr.update(visible=False))
                    updates.append(gr.update(value=""))
            
            return updates

        # Aplanar la lista de outputs para Gradio
        flat_outputs = []
        for i in range(10):
            flat_outputs.append(output_columns[i])
            flat_outputs.append(output_prompts[i])

        generate_btn.click(
            fn=generate_and_display,
            inputs=[celebrity_input, num_prompts_slider],
            outputs=flat_outputs
        )
        
        def clear_history_and_outputs():
            generator.clear_history()
            updates = []
            for i in range(10):
                updates.append(gr.update(visible=(i < 5)))  # Mostrar solo 5 por defecto
                updates.append(gr.update(value=""))
            return updates

        clear_btn.click(
            fn=clear_history_and_outputs,
            inputs=None,
            outputs=flat_outputs
        )

    return demo

if __name__ == "__main__":
    demo = create_gradio_interface()
    demo.launch(
        share=True,
        server_name="0.0.0.0",
        server_port=7860
    )