Chingkheinganba commited on
Commit
8cf49d0
Β·
verified Β·
1 Parent(s): 124ec06

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -173
app.py CHANGED
@@ -1,156 +1,58 @@
1
  import gradio as gr
2
  import requests
3
  import os
4
- import time
5
  from PIL import Image, ImageFilter, ImageDraw, ImageFont
6
  import io
7
 
 
8
  # Configuration
 
9
  HF_TOKEN = os.getenv("HF_TOKEN")
 
 
 
10
 
11
  # Architectural styles
12
  ARCH_STYLES = [
13
- "Gothic Cathedral", "Japanese Zen", "Modern Minimalist",
14
  "Medieval Castle", "Art Deco", "Chinese Palace",
15
  "Brutalist", "Victorian", "Mediterranean", "Futuristic"
16
  ]
17
 
18
- def create_building_analysis(input_image):
19
- """Create building structure analysis"""
 
 
 
20
  if input_image is None:
21
  return create_info_image("Upload a building photo to start")
22
-
23
  try:
24
  img = input_image.resize((512, 512))
25
  grayscale = img.convert('L')
26
-
27
- # Edge detection
28
  edges = grayscale.filter(ImageFilter.FIND_EDGES)
29
  edges = edges.point(lambda x: 255 if x > 25 else 0)
30
-
31
- # Create blue edges on black background
32
  analysis_img = Image.new('RGB', (512, 512), 'black')
33
  edge_pixels = edges.load()
34
  analysis_pixels = analysis_img.load()
35
-
36
  for i in range(512):
37
  for j in range(512):
38
  if edge_pixels[i, j] > 50:
39
  analysis_pixels[i, j] = (0, 150, 255) # Blue
40
-
41
- return analysis_img
42
-
43
- except Exception as e:
44
- return create_info_image(f"Analysis error: {str(e)}")
45
-
46
-
47
- # βœ… FIXED FUNCTION
48
- def test_huggingface_api():
49
- """Test if Hugging Face API is working correctly"""
50
- if not HF_TOKEN:
51
- return False, "No HF_TOKEN found in environment variables"
52
-
53
- # Use an image model for testing
54
- API_URL = "https://api-inference.huggingface.co/models/google/vit-base-patch16-224"
55
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
56
-
57
- # βœ… Use a valid image URL instead of a text string
58
- payload = {"inputs": "https://huggingface.co/front/assets/huggingface_logo-noborder.svg"}
59
-
60
- try:
61
- response = requests.post(API_URL, headers=headers, json=payload, timeout=10)
62
- if response.status_code == 200:
63
- return True, "βœ… API is working!"
64
- else:
65
- return False, f"❌ API test failed: {response.status_code} - {response.text[:100]}"
66
- except Exception as e:
67
- return False, f"❌ API test error: {str(e)}"
68
-
69
-
70
- def generate_architectural_remix(original_image, style_choice):
71
- """Main pipeline"""
72
- if original_image is None:
73
- analysis_img = create_info_image("Please upload a building photo")
74
- status = "Waiting for building photo..."
75
- result_img = create_demo_building("Upload a photo to see magic!")
76
- return analysis_img, status, result_img
77
-
78
- try:
79
- # Test API first
80
- api_working, api_status = test_huggingface_api()
81
-
82
- # Create structure analysis
83
- building_analysis = create_building_analysis(original_image)
84
-
85
- style_name = ARCH_STYLES[style_choice] if style_choice is not None else ARCH_STYLES[0]
86
-
87
- if api_working:
88
- # Try to generate with API
89
- generated_image = generate_with_api(style_name)
90
- if generated_image:
91
- status = f"βœ… AI Generated: {style_name} | " + api_status
92
- return building_analysis, status, generated_image
93
- else:
94
- # API test passed but generation failed
95
- demo_img = create_demo_building(style_name)
96
- status = f"⚠ Generation failed, showing demo | " + api_status
97
- return building_analysis, status, demo_img
98
- else:
99
- # API not working
100
- demo_img = create_demo_building(style_name)
101
- status = f"🎨 Demo Mode: {style_name} | " + api_status
102
- return building_analysis, status, demo_img
103
-
104
- except Exception as e:
105
- error_img = create_info_image(f"Error: {str(e)}")
106
- status = f"❌ Pipeline error: {str(e)}"
107
- return building_analysis, status, error_img
108
 
 
109
 
110
- def generate_with_api(style_name):
111
- """Try to generate image via API"""
112
- if not HF_TOKEN:
113
- return None
114
-
115
- # Simple prompt
116
- prompt = f"architectural rendering of a {style_name.lower()} building, professional photography"
117
-
118
- API_URL = "https://api-inference.huggingface.co/models/runwayml/stable-diffusion-v1-5"
119
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
120
-
121
- payload = {
122
- "inputs": prompt,
123
- "parameters": {
124
- "guidance_scale": 7.5,
125
- "num_inference_steps": 20,
126
- "width": 512,
127
- "height": 512
128
- }
129
- }
130
-
131
- try:
132
- print(f"Attempting to generate: {style_name}")
133
- response = requests.post(API_URL, headers=headers, json=payload, timeout=45)
134
- print(f"Response status: {response.status_code}")
135
-
136
- if response.status_code == 200:
137
- print("βœ… Image generated successfully!")
138
- return Image.open(io.BytesIO(response.content))
139
- elif response.status_code == 503:
140
- print("⚠ Model is loading...")
141
- return None
142
- else:
143
- print(f"❌ API error: {response.status_code} - {response.text[:200]}")
144
- return None
145
-
146
  except Exception as e:
147
- print(f"❌ Request error: {str(e)}")
148
- return None
149
 
150
 
151
- def create_demo_building(style_name):
152
- """Create a beautiful demo building"""
153
- # Style-based color schemes
154
  colors = {
155
  "Gothic Cathedral": ('#2C3E50', '#E74C3C', '#ECF0F1'),
156
  "Japanese Zen": ('#8B4513', '#2E8B57', '#F5F5DC'),
@@ -164,17 +66,18 @@ def create_demo_building(style_name):
164
  "Futuristic": ('#1ABC9C', '#9B59B6', '#34495E'),
165
  "Upload a photo to see magic!": ('#3498DB', '#2C3E50', '#ECF0F1')
166
  }
167
-
168
- bg_color, building_color, accent_color = colors.get(style_name, ('#3498DB', '#2C3E50', '#ECF0F1'))
169
-
170
- # Create image with gradient background
 
171
  img = Image.new('RGB', (512, 512), bg_color)
172
  draw = ImageDraw.Draw(img)
173
-
174
- # Add gradient effect
175
  for y in range(512):
176
- shade = int(200 + (y / 512) * 55)
177
- if bg_color == '#FFFFFF': # Modern
178
  draw.line([(0, y), (512, y)], fill=(shade, shade, shade))
179
  else:
180
  r, g, b = int(bg_color[1:3], 16), int(bg_color[3:5], 16), int(bg_color[5:7], 16)
@@ -182,81 +85,192 @@ def create_demo_building(style_name):
182
  new_g = max(0, min(255, g + (y // 20)))
183
  new_b = max(0, min(255, b + (y // 20)))
184
  draw.line([(0, y), (512, y)], fill=(new_r, new_g, new_b))
185
-
186
- # Draw building
187
  draw.rectangle([150, 200, 362, 450], fill=building_color, outline=accent_color, width=3)
188
-
189
- # Draw windows
190
  window_colors = ['#F1C40F', '#E74C3C', '#1ABC9C', '#9B59B6']
191
  for i, color in enumerate(window_colors):
192
  x_pos = 170 + (i % 3) * 70
193
  y_pos = 230 + (i // 3) * 70
194
  draw.rectangle([x_pos, y_pos, x_pos + 40, y_pos + 50], fill=color)
195
-
196
- # Draw roof
197
  if "Gothic" in style_name:
198
  draw.polygon([(150, 200), (256, 150), (362, 200)], fill=accent_color)
199
  elif "Japanese" in style_name:
200
  draw.polygon([(150, 200), (256, 170), (362, 200)], fill=accent_color)
201
  else:
202
  draw.rectangle([150, 190, 362, 200], fill=accent_color)
203
-
204
- # Add text
205
  try:
206
  font = ImageFont.load_default()
207
  text = f"{style_name}"
208
  bbox = draw.textbbox((0, 0), text, font=font)
209
  text_width = bbox[2] - bbox[0]
210
  x = (512 - text_width) // 2
211
- draw.text((x, 50), text, fill='white', stroke_width=2, stroke_fill='black')
212
-
213
  if "Upload" not in style_name:
214
- draw.text((180, 470), "Architectural AI Demo", fill='white')
215
- except:
216
  draw.text((200, 50), style_name, fill='white')
217
-
218
  return img
219
 
220
 
221
- def create_info_image(message):
222
- """Create informational image"""
223
  img = Image.new('RGB', (512, 512), color='#2C3E50')
224
  draw = ImageDraw.Draw(img)
225
-
226
  try:
227
  font = ImageFont.load_default()
228
- lines = message.split(' ')
229
  current_line = ""
230
  y_text = 200
231
- for word in lines:
 
232
  test_line = current_line + word + " "
233
  bbox = draw.textbbox((0, 0), test_line, font=font)
234
  text_width = bbox[2] - bbox[0]
235
-
236
  if text_width < 500:
237
  current_line = test_line
238
  else:
239
  draw.text((10, y_text), current_line, fill='white', font=font)
240
  y_text += 30
241
  current_line = word + " "
242
-
243
  if current_line:
244
  draw.text((10, y_text), current_line, fill='white', font=font)
245
- except:
246
  draw.text((50, 250), message, fill='white')
247
-
248
  return img
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
- # Create Gradio interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
253
  gr.Markdown("""
254
  # πŸ› Architectural Style Remix
255
- *AI-Powered Building Transformation*
256
-
257
  Upload a building β†’ AI analyzes structure β†’ Generates new style
258
  """)
259
-
260
  with gr.Row():
261
  with gr.Column():
262
  input_image = gr.Image(
@@ -264,38 +278,37 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
264
  type="pil",
265
  height=300
266
  )
267
-
268
  style_dropdown = gr.Dropdown(
269
  choices=ARCH_STYLES,
270
  label="🎨 Select Architectural Style",
271
  value=ARCH_STYLES[2],
272
  type="index"
273
  )
274
-
275
- generate_btn = gr.Button("✨ Generate Style Remix", variant="primary", size="lg")
276
-
277
- # Add API test button
278
  test_api_btn = gr.Button("πŸ” Test API Connection", variant="secondary")
279
  api_status = gr.Textbox(label="API Status", interactive=False)
280
-
281
  with gr.Column():
282
  structure_output = gr.Image(
283
  label="πŸ“ Building Structure Analysis",
284
  height=300
285
  )
286
-
287
  status_text = gr.Textbox(
288
  label="Generation Status",
289
  value="Ready - Upload a building photo to start!",
290
  interactive=False
291
  )
292
-
293
  result_image = gr.Image(
294
- label="🎭 Generated Building",
295
  height=300
296
  )
297
-
298
- # Examples
299
  gr.Markdown("### πŸ— Try These Building Examples:")
300
  gr.Examples(
301
  examples=[
@@ -308,28 +321,28 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
308
  fn=generate_architectural_remix,
309
  cache_examples=False
310
  )
311
-
312
  # Button actions
313
  generate_btn.click(
314
  fn=generate_architectural_remix,
315
  inputs=[input_image, style_dropdown],
316
  outputs=[structure_output, status_text, result_image]
317
  )
318
-
319
  test_api_btn.click(
320
  fn=test_huggingface_api,
321
  outputs=api_status
322
  )
323
-
324
  gr.Markdown("""
325
  ### 🎯 Project Features:
326
- - *Structure Analysis*: AI detects architectural features
327
- - *Style Transformation*: AI generates buildings in selected styles
328
- - *Demo Mode*: Beautiful fallback images when API is unavailable
329
- - *API Testing*: Check Hugging Face connection status
330
-
331
  Note: Free Hugging Face API has rate limits. Demo mode ensures the project always works!
332
  """)
333
 
334
  if __name__ == "__main__":
335
- demo.launch(debug=True)
 
1
  import gradio as gr
2
  import requests
3
  import os
 
4
  from PIL import Image, ImageFilter, ImageDraw, ImageFont
5
  import io
6
 
7
+ # =========================================================
8
  # Configuration
9
+ # =========================================================
10
  HF_TOKEN = os.getenv("HF_TOKEN")
11
+ GEN_MODEL_ID = "runwayml/stable-diffusion-v1-5"
12
+ GEN_API_URL = f"https://api-inference.huggingface.co/models/{GEN_MODEL_ID}?wait_for_model=true"
13
+ GEN_STATUS_URL = f"https://api-inference.huggingface.co/status/{GEN_MODEL_ID}"
14
 
15
  # Architectural styles
16
  ARCH_STYLES = [
17
+ "Gothic Cathedral", "Japanese Zen", "Modern Minimalist",
18
  "Medieval Castle", "Art Deco", "Chinese Palace",
19
  "Brutalist", "Victorian", "Mediterranean", "Futuristic"
20
  ]
21
 
22
+ # =========================================================
23
+ # Image utilities
24
+ # =========================================================
25
+ def create_building_analysis(input_image: Image.Image) -> Image.Image:
26
+ """Create a simple 'edge map' structure analysis visualization."""
27
  if input_image is None:
28
  return create_info_image("Upload a building photo to start")
29
+
30
  try:
31
  img = input_image.resize((512, 512))
32
  grayscale = img.convert('L')
33
+
34
+ # Edge detection and threshold
35
  edges = grayscale.filter(ImageFilter.FIND_EDGES)
36
  edges = edges.point(lambda x: 255 if x > 25 else 0)
37
+
38
+ # Blue edges on black background
39
  analysis_img = Image.new('RGB', (512, 512), 'black')
40
  edge_pixels = edges.load()
41
  analysis_pixels = analysis_img.load()
42
+
43
  for i in range(512):
44
  for j in range(512):
45
  if edge_pixels[i, j] > 50:
46
  analysis_pixels[i, j] = (0, 150, 255) # Blue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ return analysis_img
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  except Exception as e:
51
+ return create_info_image(f"Analysis error: {str(e)}")
 
52
 
53
 
54
+ def create_demo_building(style_name: str) -> Image.Image:
55
+ """Create a decorative demo image when API is unavailable or generation fails."""
 
56
  colors = {
57
  "Gothic Cathedral": ('#2C3E50', '#E74C3C', '#ECF0F1'),
58
  "Japanese Zen": ('#8B4513', '#2E8B57', '#F5F5DC'),
 
66
  "Futuristic": ('#1ABC9C', '#9B59B6', '#34495E'),
67
  "Upload a photo to see magic!": ('#3498DB', '#2C3E50', '#ECF0F1')
68
  }
69
+
70
+ bg_color, building_color, accent_color = colors.get(
71
+ style_name, ('#3498DB', '#2C3E50', '#ECF0F1')
72
+ )
73
+
74
  img = Image.new('RGB', (512, 512), bg_color)
75
  draw = ImageDraw.Draw(img)
76
+
77
+ # Gradient background
78
  for y in range(512):
79
+ if bg_color == '#FFFFFF': # Modern Minimalist special case
80
+ shade = int(200 + (y / 512) * 55)
81
  draw.line([(0, y), (512, y)], fill=(shade, shade, shade))
82
  else:
83
  r, g, b = int(bg_color[1:3], 16), int(bg_color[3:5], 16), int(bg_color[5:7], 16)
 
85
  new_g = max(0, min(255, g + (y // 20)))
86
  new_b = max(0, min(255, b + (y // 20)))
87
  draw.line([(0, y), (512, y)], fill=(new_r, new_g, new_b))
88
+
89
+ # Building body
90
  draw.rectangle([150, 200, 362, 450], fill=building_color, outline=accent_color, width=3)
91
+
92
+ # Windows
93
  window_colors = ['#F1C40F', '#E74C3C', '#1ABC9C', '#9B59B6']
94
  for i, color in enumerate(window_colors):
95
  x_pos = 170 + (i % 3) * 70
96
  y_pos = 230 + (i // 3) * 70
97
  draw.rectangle([x_pos, y_pos, x_pos + 40, y_pos + 50], fill=color)
98
+
99
+ # Roof
100
  if "Gothic" in style_name:
101
  draw.polygon([(150, 200), (256, 150), (362, 200)], fill=accent_color)
102
  elif "Japanese" in style_name:
103
  draw.polygon([(150, 200), (256, 170), (362, 200)], fill=accent_color)
104
  else:
105
  draw.rectangle([150, 190, 362, 200], fill=accent_color)
106
+
107
+ # Titles
108
  try:
109
  font = ImageFont.load_default()
110
  text = f"{style_name}"
111
  bbox = draw.textbbox((0, 0), text, font=font)
112
  text_width = bbox[2] - bbox[0]
113
  x = (512 - text_width) // 2
114
+ draw.text((x, 50), text, fill='white', stroke_width=2, stroke_fill='black', font=font)
115
+
116
  if "Upload" not in style_name:
117
+ draw.text((180, 470), "Architectural AI Demo", fill='white', font=font)
118
+ except Exception:
119
  draw.text((200, 50), style_name, fill='white')
120
+
121
  return img
122
 
123
 
124
+ def create_info_image(message: str) -> Image.Image:
125
+ """Create a plain info panel image with wrapped text."""
126
  img = Image.new('RGB', (512, 512), color='#2C3E50')
127
  draw = ImageDraw.Draw(img)
 
128
  try:
129
  font = ImageFont.load_default()
130
+ words = message.split(' ')
131
  current_line = ""
132
  y_text = 200
133
+
134
+ for word in words:
135
  test_line = current_line + word + " "
136
  bbox = draw.textbbox((0, 0), test_line, font=font)
137
  text_width = bbox[2] - bbox[0]
138
+
139
  if text_width < 500:
140
  current_line = test_line
141
  else:
142
  draw.text((10, y_text), current_line, fill='white', font=font)
143
  y_text += 30
144
  current_line = word + " "
145
+
146
  if current_line:
147
  draw.text((10, y_text), current_line, fill='white', font=font)
148
+ except Exception:
149
  draw.text((50, 250), message, fill='white')
150
+
151
  return img
152
 
153
+ # =========================================================
154
+ # HF API helpers
155
+ # =========================================================
156
+ def test_huggingface_api() -> str:
157
+ """Return a single string suitable for a Textbox with model status."""
158
+ if not HF_TOKEN:
159
+ return "❌ No HF_TOKEN found in environment variables."
160
+
161
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
162
+ try:
163
+ r = requests.get(GEN_STATUS_URL, headers=headers, timeout=10)
164
+ if r.status_code == 200:
165
+ j = r.json()
166
+ loaded = j.get("loaded")
167
+ state = j.get("state")
168
+ qlen = (j.get("queue") or {}).get("length")
169
+ return f"βœ… API reachable. loaded={loaded}, state={state}, queue_length={qlen}"
170
+ elif r.status_code == 404:
171
+ return "❌ Model not found or gated (check access to runwayml/stable-diffusion-v1-5)."
172
+ else:
173
+ return f"❌ API error {r.status_code}: {r.text[:180]}"
174
+ except Exception as e:
175
+ return f"❌ API test error: {e}"
176
+
177
+
178
+ def generate_with_api(style_name: str):
179
+ """Try to generate image via HF Inference API. Returns PIL.Image or None."""
180
+ if not HF_TOKEN:
181
+ return None
182
+
183
+ prompt = f"architectural rendering of a {style_name.lower()} building, professional photography"
184
+ headers = {
185
+ "Authorization": f"Bearer {HF_TOKEN}",
186
+ "Accept": "image/png"
187
+ }
188
+ payload = {
189
+ "inputs": prompt,
190
+ "parameters": {
191
+ "guidance_scale": 7.5,
192
+ "num_inference_steps": 20
193
+ # Width/height may not be supported across all deployments:
194
+ # "width": 512,
195
+ # "height": 512
196
+ }
197
+ }
198
+
199
+ try:
200
+ response = requests.post(GEN_API_URL, headers=headers, json=payload, timeout=60)
201
+ ctype = response.headers.get("content-type", "")
202
+ if response.status_code == 200 and ctype.startswith("image/"):
203
+ return Image.open(io.BytesIO(response.content))
204
+ elif response.status_code == 503:
205
+ # Model loading or warming up
206
+ return None
207
+ else:
208
+ # Likely JSON error; log a snippet
209
+ print(f"❌ API error {response.status_code}: {response.text[:200]}")
210
+ return None
211
+ except Exception as e:
212
+ print(f"❌ Request error: {e}")
213
+ return None
214
+
215
+ # =========================================================
216
+ # Main pipeline
217
+ # =========================================================
218
+ def generate_architectural_remix(original_image, style_choice):
219
+ """Pipeline: test API β†’ analyze structure β†’ generate or show demo."""
220
+ if original_image is None:
221
+ analysis_img = create_info_image("Please upload a building photo")
222
+ status = "Waiting for building photo..."
223
+ result_img = create_demo_building("Upload a photo to see magic!")
224
+ return analysis_img, status, result_img
225
 
226
+ # Always keep a safe default analysis ready
227
+ safe_analysis = create_info_image("Analysis unavailable")
228
+
229
+ try:
230
+ # 1) API status (returns a string now)
231
+ api_status = test_huggingface_api()
232
+ api_working = api_status.startswith("βœ…")
233
+
234
+ # 2) Structure analysis (guard any failure)
235
+ try:
236
+ building_analysis = create_building_analysis(original_image)
237
+ except Exception:
238
+ building_analysis = safe_analysis
239
+
240
+ # 3) Style name
241
+ style_name = ARCH_STYLES[style_choice] if style_choice is not None else ARCH_STYLES[0]
242
+
243
+ # 4) Generation (or demo fallback)
244
+ if api_working:
245
+ generated_image = generate_with_api(style_name)
246
+ if generated_image:
247
+ status = f"βœ… AI Generated: {style_name} | {api_status}"
248
+ return building_analysis, status, generated_image
249
+ else:
250
+ demo_img = create_demo_building(style_name)
251
+ status = f"⚠ Generation failed or model loading, showing demo | {api_status}"
252
+ return building_analysis, status, demo_img
253
+ else:
254
+ demo_img = create_demo_building(style_name)
255
+ status = f"🎨 Demo Mode: {style_name} | {api_status}"
256
+ return building_analysis, status, demo_img
257
+
258
+ except Exception as e:
259
+ error_img = create_info_image(f"Error: {str(e)}")
260
+ status = f"❌ Pipeline error: {str(e)}"
261
+ return safe_analysis, status, error_img
262
+
263
+ # =========================================================
264
+ # Gradio UI
265
+ # =========================================================
266
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
267
  gr.Markdown("""
268
  # πŸ› Architectural Style Remix
269
+ AI-Powered Building Transformation
270
+
271
  Upload a building β†’ AI analyzes structure β†’ Generates new style
272
  """)
273
+
274
  with gr.Row():
275
  with gr.Column():
276
  input_image = gr.Image(
 
278
  type="pil",
279
  height=300
280
  )
281
+
282
  style_dropdown = gr.Dropdown(
283
  choices=ARCH_STYLES,
284
  label="🎨 Select Architectural Style",
285
  value=ARCH_STYLES[2],
286
  type="index"
287
  )
288
+
289
+ generate_btn = gr.Button("✨ Generate Style Remix", variant="primary")
290
+
291
+ # API test
292
  test_api_btn = gr.Button("πŸ” Test API Connection", variant="secondary")
293
  api_status = gr.Textbox(label="API Status", interactive=False)
294
+
295
  with gr.Column():
296
  structure_output = gr.Image(
297
  label="πŸ“ Building Structure Analysis",
298
  height=300
299
  )
300
+
301
  status_text = gr.Textbox(
302
  label="Generation Status",
303
  value="Ready - Upload a building photo to start!",
304
  interactive=False
305
  )
306
+
307
  result_image = gr.Image(
308
+ label="🎭 Generated Building",
309
  height=300
310
  )
311
+
 
312
  gr.Markdown("### πŸ— Try These Building Examples:")
313
  gr.Examples(
314
  examples=[
 
321
  fn=generate_architectural_remix,
322
  cache_examples=False
323
  )
324
+
325
  # Button actions
326
  generate_btn.click(
327
  fn=generate_architectural_remix,
328
  inputs=[input_image, style_dropdown],
329
  outputs=[structure_output, status_text, result_image]
330
  )
331
+
332
  test_api_btn.click(
333
  fn=test_huggingface_api,
334
  outputs=api_status
335
  )
336
+
337
  gr.Markdown("""
338
  ### 🎯 Project Features:
339
+ - Structure Analysis: AI detects architectural features
340
+ - Style Transformation: AI generates buildings in selected styles
341
+ - Demo Mode: Beautiful fallback images when API is unavailable
342
+ - API Testing: Check Hugging Face connection status
343
+
344
  Note: Free Hugging Face API has rate limits. Demo mode ensures the project always works!
345
  """)
346
 
347
  if __name__ == "__main__":
348
+ demo.launch(debug=True)