File size: 9,977 Bytes
27e4a6a
d4fba6d
4816388
9e8f5e5
 
4816388
9e8f5e5
 
 
 
bc1f498
9e8f5e5
 
 
 
 
 
 
d95dbe9
32fdddd
9e8f5e5
 
8b0fc18
 
9e8f5e5
980ffaa
481dde5
9e8f5e5
 
 
 
 
 
 
 
 
 
6b3d1c3
fc85da7
8b0fc18
 
9e8f5e5
 
7bf5a19
fc85da7
6b3d1c3
9e8f5e5
 
6b3d1c3
9e8f5e5
 
 
 
6b3d1c3
9e8f5e5
 
 
 
 
 
 
 
 
 
 
 
8fe1e3d
 
 
 
 
 
9e8f5e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7c78be7
9e8f5e5
7c78be7
 
9e8f5e5
7c78be7
 
6b3d1c3
9e8f5e5
 
 
 
 
 
 
 
 
 
 
 
 
8c1a558
9e8f5e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53635c2
9e8f5e5
 
 
8b0fc18
 
174c9a8
9e8f5e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53635c2
6b3d1c3
9e8f5e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99a5876
 
9e8f5e5
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
from pathlib import Path
from PIL import Image
import streamlit as st
import insightface
from insightface.app import FaceAnalysis
from huggingface_hub import InferenceClient, AsyncInferenceClient
import asyncio
import os
import random
import numpy as np
import yaml

try:
    with open("config.yaml", "r") as file:
        credentials = yaml.safe_load(file)
except Exception as e:
    st.error(f"Error al cargar el archivo de configuraci贸n: {e}")
    credentials = {"username": "", "password": ""}

MAX_SEED = np.iinfo(np.int32).max
client = AsyncInferenceClient()
llm_client = InferenceClient("mistralai/Mixtral-8x7B-Instruct-v0.1")
DATA_PATH = Path("./data")
DATA_PATH.mkdir(exist_ok=True)
PREDEFINED_SEED = random.randint(0, MAX_SEED)
HF_TOKEN_UPSCALER = os.environ.get("HF_TOKEN_UPSCALER")

def get_upscale_finegrain(prompt, img_path, upscale_factor):
    try:
        upscale_client = Client("finegrain/finegrain-image-enhancer", hf_token=HF_TOKEN_UPSCALER)
        result = upscale_client.predict(input_image=handle_file(img_path), prompt=prompt, upscale_factor=upscale_factor)
        return result[1] if isinstance(result, list) and len(result) > 1 else None
    except Exception:
        return None

def authenticate_user(username, password):
    return username == credentials["username"] and password == credentials["password"]

def prepare_face_app():
    app = FaceAnalysis(name='buffalo_l')
    app.prepare(ctx_id=0, det_size=(640, 640))
    swapper = insightface.model_zoo.get_model('onix.onnx')
    return app, swapper

app, swapper = prepare_face_app()

def sort_faces(faces):
    return sorted(faces, key=lambda x: x.bbox[0])

def get_face(faces, face_id):
    if not faces or len(faces) < face_id:
        raise ValueError("Rostro no disponible.")
    return faces[face_id - 1]

def swap_faces(source_image, source_face_index, destination_image, destination_face_index):
    faces = sort_faces(app.get(source_image))
    source_face = get_face(faces, source_face_index)
    
    res_faces = sort_faces(app.get(destination_image))
    if destination_face_index > len(res_faces) or destination_face_index < 1:
        raise ValueError("脥ndice de rostro de destino no v谩lido.")
    
    res_face = get_face(res_faces, destination_face_index)
    result = swapper.get(destination_image, res_face, source_face, paste_back=True)
    return result

async def generate_image(prompt, width, height, seed, model_name):
    if seed == -1:
        seed = random.randint(0, MAX_SEED)
    image = await client.text_to_image(prompt=prompt, height=height, width=width, model=model_name)
    return image, seed

async def gen(prompt, width, height, model_name):
    seed = PREDEFINED_SEED
    image, seed = await generate_image(prompt, width, height, seed, model_name)
    image_path = save_image(image, f"generated_image_{seed}.jpg", prompt)
    return str(image_path)

def list_saved_images():
    return list(DATA_PATH.glob("*.jpg"))

def display_gallery():
    st.header("Galer铆a de Im谩genes Guardadas")
    images = list_saved_images()
    if images:
        cols = st.columns(8)  
        for i, image_file in enumerate(images):
            with cols[i % 8]:  
                st.image(str(image_file), caption=image_file.name, use_column_width=True)
                prompt = get_prompt_for_image(image_file.name)  
                st.write(prompt[:300])  

                if st.button(f"Usar", key=f"select_{i}_{image_file.name}"):
                    st.session_state['generated_image_path'] = str(image_file)
                    st.success("Imagen seleccionada")

                if st.button(f"Borrar", key=f"delete_{i}_{image_file.name}"):
                    os.remove(image_file)
                    st.success("Imagen borrada")
                    display_gallery()
    else:
        st.info("No hay im谩genes guardadas.")

def save_prompt(prompt):
    with open(DATA_PATH / "prompts.txt", "a") as f:
        f.write(prompt + "\n")
        st.success("Prompt guardado.")

def run_async(func, *args):
    return asyncio.run(func(*args))

async def improve_prompt(prompt):
    try:
        instruction = ("With this idea, describe in English a detailed txt2img prompt in 500 characters at most, add illumination, atmosphere, cinematic elements, and characters if needed...")
        formatted_prompt = f"{prompt}: {instruction}"
        response = llm_client.text_generation(formatted_prompt, max_new_tokens=500)
        return response['generated_text'][:500] if 'generated_text' in response else response.strip()
    except Exception as e:
        return f"Error mejorando el prompt: {e}"

def save_image(image, file_name, prompt=None):
    image_path = DATA_PATH / file_name
    if image_path.exists():
        st.warning(f"La imagen '{file_name}' ya existe en la galer铆a. No se guard贸.")
        return None 
    else:
        image.save(image_path, format="JPEG")
        if prompt:
            save_prompt(f"{file_name}: {prompt}")  
        return image_path

def get_prompt_for_image(image_name):
    prompts = {}
    try:
        with open(DATA_PATH / "prompts.txt", "r") as f:
            for line in f:
                if line.startswith(image_name):
                    prompts[image_name] = line.split(": ", 1)[1].strip()
    except FileNotFoundError:
        return "No hay prompt asociado."
    
    return prompts.get(image_name, "No hay prompt asociado.")

def login_form():
    st.title("Iniciar Sesi贸n")
    username = st.text_input("Usuario", value="admin")
    password = st.text_input("Contrase帽a", value="flux3x", type="password") 
    if st.button("Iniciar Sesi贸n"):
        if authenticate_user(username, password):
            st.success("Autenticaci贸n exitosa.")
            st.session_state['authenticated'] = True
        else:
            st.error("Credenciales incorrectas. Intenta de nuevo.")

def upload_image_to_gallery():
    uploaded_image = st.file_uploader("Sube una imagen a la galer铆a", type=["jpg", "jpeg", "png"])
    if uploaded_image:
        image = Image.open(uploaded_image)
        image_path = save_image(image, f"{uploaded_image.name}")
        if image_path:
            save_prompt("uploaded by user")
            st.success(f"Imagen subida: {image_path}")

def main():
    st.set_page_config(layout="wide")

    if 'authenticated' not in st.session_state or not st.session_state['authenticated']:
        login_form()
        return

    st.title("Flux +Upscale +Prompt Enhancer +FaceSwap")
    generated_image_path = st.session_state.get('generated_image_path')
    st.header("Generador de Im谩genes")
    prompt = st.sidebar.text_area("Descripci贸n de la imagen", height=150, max_chars=500)
    format_option = st.sidebar.selectbox("Formato", ["9:16", "16:9"])
    model_option = st.sidebar.selectbox("Modelo", ["black-forest-labs/FLUX.1-schnell", "black-forest-labs/FLUX.1-dev"])
    prompt_checkbox = st.sidebar.checkbox("Prompt Enhancer")
    upscale_checkbox = st.sidebar.checkbox("Escalar imagen")
    width, height = (720, 1280) if format_option == "9:16" else (1280, 720)
    upload_image_to_gallery()

    if prompt_checkbox:
        with st.spinner("Mejorando el prompt..."):
            try:
                improved_prompt = run_async(improve_prompt, prompt)
            except Exception as e:
                st.error(f"Error al mejorar el prompt: {str(e)}")
                improved_prompt = prompt
    else:
        improved_prompt = prompt

    if st.sidebar.button("Generar Imagen"):
        with st.spinner("Generando imagen..."):
            try:
                result = run_async(gen, improved_prompt, width, height, model_option)  # Usar el improved_prompt
                st.session_state['generated_image_path'] = result
                st.image(result, caption="Imagen Generada")
            except Exception as e:
                st.error(f"Error al generar la imagen: {str(e)}")

    if generated_image_path:
        if upscale_checkbox:
            with st.spinner("Escalando imagen..."):
                try:
                    upscale_image_path = get_upscale_finegrain("Upscale", generated_image_path, 2)
                    if upscale_image_path:
                        st.image(upscale_image_path, caption="Imagen Escalada")
                except Exception as e:
                    st.error(f"Error al escalar la imagen: {str(e)}")

        st.header("Intercambio de Rostros")
        source_image_file = st.file_uploader("Imagen de Origen", type=["jpg", "jpeg", "png"])

        if source_image_file is not None:
            try:
                source_image = Image.open(source_image_file)
            except Exception as e:
                st.error(f"Error al cargar la imagen de origen: {str(e)}")
                source_image = None
        else:
            source_image = Image.open("face.jpg")

        source_face_index = st.number_input('Posici贸n del Rostro', min_value=1, value=1, key="source_face_index")
        destination_face_index = st.number_input('Posici贸n del Rostro de Destino', min_value=1, value=1, key="destination_face_index")

        if st.button("Intercambiar Rostros"):
            try:
                destination_image = Image.open(generated_image_path)
                result_image = swap_faces(np.array(source_image), source_face_index, np.array(destination_image), destination_face_index)
                swapped_image = Image.fromarray(result_image)
                
                swapped_image_path = save_image(swapped_image, f"swapped_image_{PREDEFINED_SEED}.jpg")
                if swapped_image_path:
                    st.image(swapped_image, caption="Intercambio de Rostro")
                    os.remove(generated_image_path)
                else:
                    st.warning("La imagen intercambiada ya existe en la galer铆a.")
            except Exception as e:
                st.error(f"Ocurri贸 un error al intercambiar rostros: {str(e)}")

    display_gallery()

if __name__ == "__main__":
    main()