Update app.py
Browse files
app.py
CHANGED
@@ -1,55 +1,39 @@
|
|
1 |
-
# -*- coding: utf-8 -*-
|
2 |
|
3 |
import gradio as gr
|
4 |
-
#
|
5 |
-
|
6 |
-
from PIL import Image, ImageOps # Dodajemy ImageOps do skalowania
|
7 |
import io
|
8 |
import os
|
9 |
import traceback
|
10 |
-
# Poprawny import dla gradio_client
|
11 |
from gradio_client import Client, file
|
12 |
-
import uuid
|
13 |
-
import shutil
|
14 |
-
# Dodajemy obsługę wyjątków specyficznych dla gradio_client
|
15 |
from gradio_client.exceptions import AppError
|
16 |
|
17 |
print("--- Plik app.py - Start ładowania ---")
|
18 |
|
19 |
# --- Konfiguracja ---
|
20 |
-
# Odczytanie sekretu (API Token) ustawionego w Space
|
21 |
API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
|
22 |
-
|
23 |
-
# Sprawdzenie, czy token został załadowany
|
24 |
if not API_TOKEN:
|
25 |
print("!!! OSTRZEŻENIE: Nie znaleziono sekretu HUGGINGFACE_API_TOKEN. Klient Gradio spróbuje połączyć się anonimowo (mogą obowiązywać limity). !!!")
|
26 |
else:
|
27 |
print("--- Sekret HUGGINGFACE_API_TOKEN załadowany. ---")
|
28 |
|
29 |
-
# Profesjonalny prompt, który chcemy uzyskać
|
30 |
LINKEDIN_PROMPT = (
|
31 |
"linkedin professional profile photo, corporate headshot, high quality, realistic photograph, "
|
32 |
-
"person wearing a dark business suit or elegant blouse, plain white background, "
|
33 |
"soft studio lighting, sharp focus, looking at camera, slight smile, natural skin texture"
|
34 |
)
|
35 |
-
|
36 |
-
# Identyfikator publicznego Space'a z InstantID dla gradio_client
|
37 |
TARGET_SPACE_ID = "InstantX/InstantID"
|
38 |
-
|
39 |
-
# Kontrolny print
|
40 |
print(f"--- Konfiguracja załadowana. Cel dla gradio_client: {TARGET_SPACE_ID} ---")
|
41 |
|
42 |
|
43 |
# --- Logika aplikacji ---
|
44 |
def generate_photo(input_selfie, current_prompt):
|
45 |
-
"""
|
46 |
-
Główna funkcja wywoływana po kliknięciu przycisku.
|
47 |
-
Skaluje obraz wejściowy, łączy się ze zdalnym Space'em InstantID
|
48 |
-
za pomocą gradio_client, wysyła dane, odbiera wynik i zwraca obrazek.
|
49 |
-
"""
|
50 |
print("\n--- Funkcja generate_photo (gradio_client) została wywołana ---")
|
51 |
|
52 |
-
# 1. Walidacja
|
53 |
if input_selfie is None:
|
54 |
print("BŁĄD: Nie wgrano zdjęcia wejściowego.")
|
55 |
raise gr.Error("Proszę najpierw wgrać swoje selfie!")
|
@@ -62,13 +46,11 @@ def generate_photo(input_selfie, current_prompt):
|
|
62 |
print(f"Otrzymano obrazek typu: {type(input_selfie)}, Oryginalny rozmiar: {input_selfie.size}")
|
63 |
print(f"Otrzymano prompt (początek): {current_prompt[:100]}...")
|
64 |
|
65 |
-
# 2.
|
66 |
-
input_selfie_resized = None
|
67 |
try:
|
68 |
-
max_size = (1024, 1024)
|
69 |
-
# Pracujemy na kopii, aby nie modyfikować oryginalnego obiektu
|
70 |
input_selfie_resized = input_selfie.copy()
|
71 |
-
# Używamy thumbnail do proporcjonalnego zmniejszenia, jeśli obraz jest większy niż max_size
|
72 |
input_selfie_resized.thumbnail(max_size, Image.Resampling.LANCZOS)
|
73 |
print(f"Obrazek przeskalowany do (maksymalnie) {max_size}. Nowy rozmiar: {input_selfie_resized.size}")
|
74 |
except Exception as e_resize:
|
@@ -76,14 +58,12 @@ def generate_photo(input_selfie, current_prompt):
|
|
76 |
traceback.print_exc()
|
77 |
raise gr.Error(f"Nie można przeskalować obrazka wejściowego: {e_resize}")
|
78 |
|
79 |
-
# 3. Przygotowanie pliku tymczasowego
|
80 |
-
temp_dir = f"temp_input_{uuid.uuid4()}"
|
81 |
-
input_image_path = None
|
82 |
try:
|
83 |
os.makedirs(temp_dir, exist_ok=True)
|
84 |
input_image_path = os.path.join(temp_dir, "input_selfie.jpg")
|
85 |
-
|
86 |
-
# Upewnijmy się, że przeskalowany obraz jest w RGB przed zapisem jako JPEG
|
87 |
rgb_image = input_selfie_resized
|
88 |
if rgb_image.mode == 'RGBA':
|
89 |
print("Konwertuję przeskalowany obraz RGBA na RGB z białym tłem...")
|
@@ -93,37 +73,27 @@ def generate_photo(input_selfie, current_prompt):
|
|
93 |
print(f"Konwertuję przeskalowany obraz z trybu {rgb_image.mode} na RGB...")
|
94 |
final_image = rgb_image.convert('RGB')
|
95 |
else:
|
96 |
-
final_image = rgb_image
|
97 |
-
|
98 |
-
# Zapisz finalny obraz jako JPEG
|
99 |
final_image.save(input_image_path, format="JPEG")
|
100 |
print(f"Przeskalowany obrazek wejściowy zapisany tymczasowo w: {input_image_path}")
|
101 |
-
|
102 |
except Exception as e_save:
|
103 |
print(f"BŁĄD podczas zapisywania obrazu tymczasowego: {e_save}")
|
104 |
traceback.print_exc()
|
105 |
-
# Spróbuj posprzątać, jeśli się da
|
106 |
if os.path.exists(temp_dir):
|
107 |
-
try:
|
108 |
-
|
109 |
-
print(f"Folder tymczasowy {temp_dir} usunięty po błędzie zapisu.")
|
110 |
-
except Exception as e_clean:
|
111 |
-
print(f"OSTRZEŻENIE: Nie udało się usunąć folderu tymczasowego {temp_dir} po błędzie zapisu: {e_clean}")
|
112 |
raise gr.Error(f"Problem z przygotowaniem obrazu do wysłania: {e_save}")
|
113 |
|
114 |
-
# 4. Wywołanie zdalnego API Gradio
|
115 |
-
output_image = None
|
116 |
-
client = None
|
117 |
try:
|
118 |
-
# Używamy TARGET_SPACE_ID zdefiniowanej globalnie
|
119 |
print(f"Łączenie z docelowym Space Gradio: {TARGET_SPACE_ID}")
|
120 |
-
# Inicjalizacja klienta
|
121 |
client = Client(TARGET_SPACE_ID, hf_token=API_TOKEN)
|
122 |
-
|
|
|
123 |
|
124 |
print("Próbuję wywołać funkcję na zdalnym Space...")
|
125 |
-
|
126 |
-
# Konfiguracja parametrów dla InstantX/InstantID
|
127 |
negative_prompt = "ugly, deformed, noisy, blurry, low contrast, text, signature, watermark, duplicate, multiple people, cartoon, drawing, illustration, sketch, bad anatomy, worst quality, low quality"
|
128 |
style_name = "Realistic"
|
129 |
cn_scale = 0.8
|
@@ -138,31 +108,28 @@ def generate_photo(input_selfie, current_prompt):
|
|
138 |
print(f" ControlNet Scale: {cn_scale}")
|
139 |
print(f" IP-Adapter Scale: {ip_scale}")
|
140 |
|
141 |
-
#
|
142 |
-
#
|
143 |
-
#
|
144 |
result = client.predict(
|
145 |
-
file(input_image_path),
|
146 |
-
None,
|
147 |
-
current_prompt,
|
148 |
-
negative_prompt,
|
149 |
-
style_name,
|
150 |
-
cn_scale,
|
151 |
-
ip_scale,
|
152 |
-
api_name=api_endpoint_name
|
153 |
)
|
154 |
|
155 |
-
# Przetwarzanie wyniku
|
156 |
print(f"Otrzymano wynik od klienta: {type(result)}")
|
157 |
-
print(f"Wynik (fragment): {str(result)[:500]}")
|
158 |
|
159 |
-
# Sprawdzamy, czy wynik jest listą ścieżek do plików
|
160 |
if isinstance(result, list) and len(result) > 0 and isinstance(result[0], str) and os.path.exists(result[0]):
|
161 |
output_file_path = result[0]
|
162 |
print(f"Przetwarzam pierwszy obrazek wynikowy ze ścieżki: {output_file_path}")
|
163 |
output_image = Image.open(output_file_path)
|
164 |
print(f"Obrazek wynikowy załadowany pomyślnie. Rozmiar: {output_image.size}")
|
165 |
-
# Sprawdzamy, czy wynik jest pojedynczą ścieżką
|
166 |
elif isinstance(result, str) and os.path.exists(result):
|
167 |
output_file_path = result
|
168 |
print(f"Przetwarzam obrazek wynikowy ze ścieżki: {output_file_path}")
|
@@ -172,16 +139,12 @@ def generate_photo(input_selfie, current_prompt):
|
|
172 |
print(f"BŁĄD: Otrzymano nieoczekiwany format wyniku od gradio_client: {type(result)}")
|
173 |
raise gr.Error(f"Nie udało się przetworzyć wyniku ze zdalnego API. Otrzymano: {str(result)[:200]}")
|
174 |
|
175 |
-
# --- Obsługa Błędów ---
|
176 |
except AppError as e:
|
177 |
-
# Błąd zgłoszony przez zdalną aplikację Gradio
|
178 |
print(f"BŁĄD APLIKACJI ZDALNEJ (AppError): {e}")
|
179 |
traceback.print_exc()
|
180 |
-
# Bardziej pomocny komunikat dla użytkownika
|
181 |
error_message = f"Zdalny serwis ({TARGET_SPACE_ID}) zgłosił wewnętrzny błąd. Może to być spowodowane problemami z obrazkiem (np. brak wykrytej twarzy, nietypowy format), niedostępnością modelu lub przeciążeniem serwisu. Spróbuj z innym, wyraźnym zdjęciem twarzy lub spróbuj ponownie później."
|
182 |
raise gr.Error(error_message)
|
183 |
except ValueError as e:
|
184 |
-
# Potencjalnie błąd "Could not fetch config" lub inny ValueError
|
185 |
print(f"BŁĄD WARTOŚCI (ValueError): {e}")
|
186 |
traceback.print_exc()
|
187 |
error_message = f"Wystąpił błąd wartości: {e}. "
|
@@ -189,7 +152,6 @@ def generate_photo(input_selfie, current_prompt):
|
|
189 |
error_message = f"Nie można pobrać konfiguracji zdalnego serwisu ({TARGET_SPACE_ID}). Może być chwilowo niedostępny, niekompatybilny lub wymagać logowania. Sprawdź status serwisu lub spróbuj później."
|
190 |
raise gr.Error(error_message)
|
191 |
except Exception as e:
|
192 |
-
# Inne, ogólne błędy (np. problem sieciowy, błąd w naszym kodzie)
|
193 |
print(f"NIEOCZEKIWANY BŁĄD: {e}")
|
194 |
traceback.print_exc()
|
195 |
error_message = f"Wystąpił nieoczekiwany błąd: {e}. Sprawdź logi aplikacji."
|
@@ -198,25 +160,22 @@ def generate_photo(input_selfie, current_prompt):
|
|
198 |
elif "queue full" in str(e).lower():
|
199 |
error_message = "Kolejka w zdalnym serwisie jest pełna. Spróbuj ponownie za chwilę."
|
200 |
raise gr.Error(error_message)
|
201 |
-
# ------------------------
|
202 |
|
203 |
finally:
|
204 |
-
# 5. Sprzątanie
|
205 |
-
if input_image_path and os.path.exists(temp_dir):
|
206 |
try:
|
207 |
shutil.rmtree(temp_dir)
|
208 |
print(f"Folder tymczasowy {temp_dir} usunięty.")
|
209 |
except Exception as e_clean:
|
210 |
print(f"OSTRZEŻENIE: Nie udało się usunąć folderu tymczasowego {temp_dir}: {e_clean}")
|
211 |
|
212 |
-
# 6. Zwróć wynik
|
213 |
if output_image:
|
214 |
print("Zwracam wygenerowany obrazek do interfejsu Gradio.")
|
215 |
return output_image
|
216 |
else:
|
217 |
-
# Jeśli doszliśmy tutaj bez błędu, ale nie ma obrazka, to coś jest bardzo źle
|
218 |
print("BŁĄD KRYTYCZNY: Brak obrazka wynikowego, a nie zgłoszono błędu.")
|
219 |
-
# Zwróćmy błąd do UI, chociaż idealnie obsługa błędów powinna to wyłapać wcześniej
|
220 |
raise gr.Error("Nie udało się uzyskać obrazka wynikowego z nieznanego powodu.")
|
221 |
|
222 |
|
@@ -233,40 +192,23 @@ with gr.Blocks(css="footer {display: none !important;}", title="Generator Zdję
|
|
233 |
* Generowanie może potrwać **od 30 sekund do kilku minut** (zwłaszcza za pierwszym razem). Bądź cierpliwy!
|
234 |
"""
|
235 |
)
|
236 |
-
|
237 |
with gr.Row():
|
238 |
with gr.Column(scale=1):
|
239 |
-
input_image = gr.Image(
|
240 |
-
|
241 |
-
|
242 |
-
# Określmy źródła dla bezpieczeństwa i wygody
|
243 |
-
sources=["upload", "webcam"]
|
244 |
-
)
|
245 |
-
prompt_input = gr.Textbox(
|
246 |
-
label="2. Opis pożądanego zdjęcia (prompt)",
|
247 |
-
value=LINKEDIN_PROMPT,
|
248 |
-
lines=4
|
249 |
-
)
|
250 |
-
generate_button = gr.Button("✨ Generuj Zdjęcie Biznesowe ✨", variant="primary", scale=1) # Przycisk rozciągnięty
|
251 |
-
|
252 |
with gr.Column(scale=1):
|
253 |
-
output_image = gr.Image(
|
254 |
-
label="Oto Twoje wygenerowane zdjęcie:",
|
255 |
-
type="pil"
|
256 |
-
)
|
257 |
|
258 |
-
# --- Podłączenie akcji do przycisku ---
|
259 |
generate_button.click(
|
260 |
-
fn=generate_photo,
|
261 |
-
inputs=[input_image, prompt_input],
|
262 |
-
outputs=[output_image]
|
263 |
)
|
264 |
-
|
265 |
print("--- Interfejs Gradio zdefiniowany ---")
|
266 |
|
267 |
# --- Uruchomienie aplikacji ---
|
268 |
if __name__ == "__main__":
|
269 |
print("--- Uruchamianie demo.launch() ---")
|
270 |
-
|
271 |
-
|
272 |
-
print("--- Aplikacja Gradio zakończyła działanie (jeśli serwer nie jest trwały) ---")
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
|
3 |
import gradio as gr
|
4 |
+
# import requests # Nadal nieużywany bezpośrednio
|
5 |
+
from PIL import Image, ImageOps
|
|
|
6 |
import io
|
7 |
import os
|
8 |
import traceback
|
|
|
9 |
from gradio_client import Client, file
|
10 |
+
import uuid
|
11 |
+
import shutil
|
|
|
12 |
from gradio_client.exceptions import AppError
|
13 |
|
14 |
print("--- Plik app.py - Start ładowania ---")
|
15 |
|
16 |
# --- Konfiguracja ---
|
|
|
17 |
API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
|
|
|
|
|
18 |
if not API_TOKEN:
|
19 |
print("!!! OSTRZEŻENIE: Nie znaleziono sekretu HUGGINGFACE_API_TOKEN. Klient Gradio spróbuje połączyć się anonimowo (mogą obowiązywać limity). !!!")
|
20 |
else:
|
21 |
print("--- Sekret HUGGINGFACE_API_TOKEN załadowany. ---")
|
22 |
|
|
|
23 |
LINKEDIN_PROMPT = (
|
24 |
"linkedin professional profile photo, corporate headshot, high quality, realistic photograph, "
|
25 |
+
"person wearing a dark business suit or elegant blouse, plain white background, "
|
26 |
"soft studio lighting, sharp focus, looking at camera, slight smile, natural skin texture"
|
27 |
)
|
|
|
|
|
28 |
TARGET_SPACE_ID = "InstantX/InstantID"
|
|
|
|
|
29 |
print(f"--- Konfiguracja załadowana. Cel dla gradio_client: {TARGET_SPACE_ID} ---")
|
30 |
|
31 |
|
32 |
# --- Logika aplikacji ---
|
33 |
def generate_photo(input_selfie, current_prompt):
|
|
|
|
|
|
|
|
|
|
|
34 |
print("\n--- Funkcja generate_photo (gradio_client) została wywołana ---")
|
35 |
|
36 |
+
# 1. Walidacja
|
37 |
if input_selfie is None:
|
38 |
print("BŁĄD: Nie wgrano zdjęcia wejściowego.")
|
39 |
raise gr.Error("Proszę najpierw wgrać swoje selfie!")
|
|
|
46 |
print(f"Otrzymano obrazek typu: {type(input_selfie)}, Oryginalny rozmiar: {input_selfie.size}")
|
47 |
print(f"Otrzymano prompt (początek): {current_prompt[:100]}...")
|
48 |
|
49 |
+
# 2. Skalowanie obrazka
|
50 |
+
input_selfie_resized = None
|
51 |
try:
|
52 |
+
max_size = (1024, 1024)
|
|
|
53 |
input_selfie_resized = input_selfie.copy()
|
|
|
54 |
input_selfie_resized.thumbnail(max_size, Image.Resampling.LANCZOS)
|
55 |
print(f"Obrazek przeskalowany do (maksymalnie) {max_size}. Nowy rozmiar: {input_selfie_resized.size}")
|
56 |
except Exception as e_resize:
|
|
|
58 |
traceback.print_exc()
|
59 |
raise gr.Error(f"Nie można przeskalować obrazka wejściowego: {e_resize}")
|
60 |
|
61 |
+
# 3. Przygotowanie pliku tymczasowego
|
62 |
+
temp_dir = f"temp_input_{uuid.uuid4()}"
|
63 |
+
input_image_path = None
|
64 |
try:
|
65 |
os.makedirs(temp_dir, exist_ok=True)
|
66 |
input_image_path = os.path.join(temp_dir, "input_selfie.jpg")
|
|
|
|
|
67 |
rgb_image = input_selfie_resized
|
68 |
if rgb_image.mode == 'RGBA':
|
69 |
print("Konwertuję przeskalowany obraz RGBA na RGB z białym tłem...")
|
|
|
73 |
print(f"Konwertuję przeskalowany obraz z trybu {rgb_image.mode} na RGB...")
|
74 |
final_image = rgb_image.convert('RGB')
|
75 |
else:
|
76 |
+
final_image = rgb_image
|
|
|
|
|
77 |
final_image.save(input_image_path, format="JPEG")
|
78 |
print(f"Przeskalowany obrazek wejściowy zapisany tymczasowo w: {input_image_path}")
|
|
|
79 |
except Exception as e_save:
|
80 |
print(f"BŁĄD podczas zapisywania obrazu tymczasowego: {e_save}")
|
81 |
traceback.print_exc()
|
|
|
82 |
if os.path.exists(temp_dir):
|
83 |
+
try: shutil.rmtree(temp_dir)
|
84 |
+
except Exception as e_clean: print(f"OSTRZEŻENIE: Nie udało się usunąć {temp_dir}: {e_clean}")
|
|
|
|
|
|
|
85 |
raise gr.Error(f"Problem z przygotowaniem obrazu do wysłania: {e_save}")
|
86 |
|
87 |
+
# 4. Wywołanie zdalnego API Gradio
|
88 |
+
output_image = None
|
89 |
+
client = None
|
90 |
try:
|
|
|
91 |
print(f"Łączenie z docelowym Space Gradio: {TARGET_SPACE_ID}")
|
|
|
92 |
client = Client(TARGET_SPACE_ID, hf_token=API_TOKEN)
|
93 |
+
# Usunięto odwołanie do client.space_host, zastąpiono prostszym printem:
|
94 |
+
print(f"Połączono z {TARGET_SPACE_ID}. Klient zainicjalizowany.")
|
95 |
|
96 |
print("Próbuję wywołać funkcję na zdalnym Space...")
|
|
|
|
|
97 |
negative_prompt = "ugly, deformed, noisy, blurry, low contrast, text, signature, watermark, duplicate, multiple people, cartoon, drawing, illustration, sketch, bad anatomy, worst quality, low quality"
|
98 |
style_name = "Realistic"
|
99 |
cn_scale = 0.8
|
|
|
108 |
print(f" ControlNet Scale: {cn_scale}")
|
109 |
print(f" IP-Adapter Scale: {ip_scale}")
|
110 |
|
111 |
+
# UWAGA: file() jest przestarzałe. Jeśli pojawią się błędy, spróbuj Client(..., serialize=False)
|
112 |
+
# i przekazuj pełną ścieżkę jako string: input_image_path zamiast file(input_image_path)
|
113 |
+
# Ale na razie zostawiamy file()
|
114 |
result = client.predict(
|
115 |
+
file(input_image_path),
|
116 |
+
None,
|
117 |
+
current_prompt,
|
118 |
+
negative_prompt,
|
119 |
+
style_name,
|
120 |
+
cn_scale,
|
121 |
+
ip_scale,
|
122 |
+
api_name=api_endpoint_name
|
123 |
)
|
124 |
|
|
|
125 |
print(f"Otrzymano wynik od klienta: {type(result)}")
|
126 |
+
print(f"Wynik (fragment): {str(result)[:500]}")
|
127 |
|
|
|
128 |
if isinstance(result, list) and len(result) > 0 and isinstance(result[0], str) and os.path.exists(result[0]):
|
129 |
output_file_path = result[0]
|
130 |
print(f"Przetwarzam pierwszy obrazek wynikowy ze ścieżki: {output_file_path}")
|
131 |
output_image = Image.open(output_file_path)
|
132 |
print(f"Obrazek wynikowy załadowany pomyślnie. Rozmiar: {output_image.size}")
|
|
|
133 |
elif isinstance(result, str) and os.path.exists(result):
|
134 |
output_file_path = result
|
135 |
print(f"Przetwarzam obrazek wynikowy ze ścieżki: {output_file_path}")
|
|
|
139 |
print(f"BŁĄD: Otrzymano nieoczekiwany format wyniku od gradio_client: {type(result)}")
|
140 |
raise gr.Error(f"Nie udało się przetworzyć wyniku ze zdalnego API. Otrzymano: {str(result)[:200]}")
|
141 |
|
|
|
142 |
except AppError as e:
|
|
|
143 |
print(f"BŁĄD APLIKACJI ZDALNEJ (AppError): {e}")
|
144 |
traceback.print_exc()
|
|
|
145 |
error_message = f"Zdalny serwis ({TARGET_SPACE_ID}) zgłosił wewnętrzny błąd. Może to być spowodowane problemami z obrazkiem (np. brak wykrytej twarzy, nietypowy format), niedostępnością modelu lub przeciążeniem serwisu. Spróbuj z innym, wyraźnym zdjęciem twarzy lub spróbuj ponownie później."
|
146 |
raise gr.Error(error_message)
|
147 |
except ValueError as e:
|
|
|
148 |
print(f"BŁĄD WARTOŚCI (ValueError): {e}")
|
149 |
traceback.print_exc()
|
150 |
error_message = f"Wystąpił błąd wartości: {e}. "
|
|
|
152 |
error_message = f"Nie można pobrać konfiguracji zdalnego serwisu ({TARGET_SPACE_ID}). Może być chwilowo niedostępny, niekompatybilny lub wymagać logowania. Sprawdź status serwisu lub spróbuj później."
|
153 |
raise gr.Error(error_message)
|
154 |
except Exception as e:
|
|
|
155 |
print(f"NIEOCZEKIWANY BŁĄD: {e}")
|
156 |
traceback.print_exc()
|
157 |
error_message = f"Wystąpił nieoczekiwany błąd: {e}. Sprawdź logi aplikacji."
|
|
|
160 |
elif "queue full" in str(e).lower():
|
161 |
error_message = "Kolejka w zdalnym serwisie jest pełna. Spróbuj ponownie za chwilę."
|
162 |
raise gr.Error(error_message)
|
|
|
163 |
|
164 |
finally:
|
165 |
+
# 5. Sprzątanie
|
166 |
+
if input_image_path and os.path.exists(temp_dir):
|
167 |
try:
|
168 |
shutil.rmtree(temp_dir)
|
169 |
print(f"Folder tymczasowy {temp_dir} usunięty.")
|
170 |
except Exception as e_clean:
|
171 |
print(f"OSTRZEŻENIE: Nie udało się usunąć folderu tymczasowego {temp_dir}: {e_clean}")
|
172 |
|
173 |
+
# 6. Zwróć wynik
|
174 |
if output_image:
|
175 |
print("Zwracam wygenerowany obrazek do interfejsu Gradio.")
|
176 |
return output_image
|
177 |
else:
|
|
|
178 |
print("BŁĄD KRYTYCZNY: Brak obrazka wynikowego, a nie zgłoszono błędu.")
|
|
|
179 |
raise gr.Error("Nie udało się uzyskać obrazka wynikowego z nieznanego powodu.")
|
180 |
|
181 |
|
|
|
192 |
* Generowanie może potrwać **od 30 sekund do kilku minut** (zwłaszcza za pierwszym razem). Bądź cierpliwy!
|
193 |
"""
|
194 |
)
|
|
|
195 |
with gr.Row():
|
196 |
with gr.Column(scale=1):
|
197 |
+
input_image = gr.Image(label="1. Wgraj swoje selfie (JPG/PNG)", type="pil", sources=["upload", "webcam"])
|
198 |
+
prompt_input = gr.Textbox(label="2. Opis pożądanego zdjęcia (prompt)", value=LINKEDIN_PROMPT, lines=4)
|
199 |
+
generate_button = gr.Button("✨ Generuj Zdjęcie Biznesowe ✨", variant="primary", scale=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
with gr.Column(scale=1):
|
201 |
+
output_image = gr.Image(label="Oto Twoje wygenerowane zdjęcie:", type="pil")
|
|
|
|
|
|
|
202 |
|
|
|
203 |
generate_button.click(
|
204 |
+
fn=generate_photo,
|
205 |
+
inputs=[input_image, prompt_input],
|
206 |
+
outputs=[output_image]
|
207 |
)
|
|
|
208 |
print("--- Interfejs Gradio zdefiniowany ---")
|
209 |
|
210 |
# --- Uruchomienie aplikacji ---
|
211 |
if __name__ == "__main__":
|
212 |
print("--- Uruchamianie demo.launch() ---")
|
213 |
+
demo.launch()
|
214 |
+
print("--- Aplikacja Gradio zakończyła działanie ---")
|
|