Rifaa commited on
Commit
3ffc184
·
verified ·
1 Parent(s): 339c413

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +256 -0
app.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from diffusers import StableDiffusionPipeline, StableDiffusionControlNetPipeline, ControlNetModel, EulerDiscreteScheduler
4
+ from jinja2 import Template
5
+ import numpy as np
6
+ import cv2
7
+ from PIL import Image
8
+ import time
9
+
10
+ # Load models from Hugging Face
11
+ sd_model_id = "bhoomikagp/sd2-interior-model-version2" ## test
12
+ # sd_model_id = "bhoomikagp/sd3-interior-model" ## SD3 model issue loading
13
+ controlnet_model_id = "lllyasviel/sd-controlnet-mlsd"
14
+ # Load Stable Diffusion pipeline CUDA
15
+ scheduler = EulerDiscreteScheduler.from_pretrained(sd_model_id, subfolder="scheduler")
16
+ sd_pipeline = StableDiffusionPipeline.from_pretrained(sd_model_id, torch_dtype=torch.float16,scheduler=scheduler).to("cuda")
17
+ # Load ControlNet and Stable Diffusion ControlNet pipeline
18
+ controlnet = ControlNetModel.from_pretrained(controlnet_model_id, torch_dtype=torch.float16).to("cuda")
19
+ controlnet_pipeline = StableDiffusionControlNetPipeline.from_pretrained(
20
+ sd_model_id,
21
+ controlnet=controlnet,
22
+ scheduler=scheduler,
23
+ torch_dtype=torch.float16
24
+ ).to("cuda")
25
+
26
+ # choices lists
27
+ option_choices = ["living_room", "bedroom", "kitchen"]
28
+ adj_1_choices = [
29
+ "spacious", "cozy", "minimalist", "elegant", "modern", "rustic",
30
+ "luxurious", "inviting", "airy", "sophisticated", "bright", "warm",
31
+ "serene", "chic", "contemporary"
32
+ ]
33
+ architecture_style_choices = [
34
+ "modern", "contemporary", "traditional", "industrial", "scandinavian",
35
+ "mid-century", "colonial", "art deco", "neo-classical", "mediterranean",
36
+ "gothic", "baroque", "japanese", "brutalist", "tropical"
37
+ ]
38
+ aesthetic_choices = [
39
+ "bohemian", "vintage", "minimalist", "luxurious", "eclectic",
40
+ "mid-century", "art deco", "modern farmhouse", "industrial chic",
41
+ "shabby chic", "rustic elegance", "coastal", "urban", "transitional",
42
+ "contemporary classic"
43
+ ]
44
+ primary_color_choices = [
45
+ "blue", "green", "beige", "grey", "white", "black",
46
+ "cream", "brown", "taupe", "burgundy", "mustard",
47
+ "terracotta", "olive", "peach", "navy"
48
+ ]
49
+ wood_finish_choices = [
50
+ "dark oak", "walnut", "mahogany", "teak", "maple",
51
+ "cherry", "pine", "birch", "ash", "rosewood",
52
+ "ebony", "cedar", "hickory", "elm", "red oak"
53
+ ]
54
+ wall_color_choices = [
55
+ "cream", "off-white", "charcoal", "sage green", "navy blue",
56
+ "taupe", "light grey", "soft pink", "mustard yellow", "deep teal",
57
+ "warm beige", "pearl white", "slate blue", "coral", "mint green"
58
+ ]
59
+ tiles_choices = [
60
+ "marble", "ceramic", "porcelain", "slate", "wooden-look",
61
+ "mosaic", "granite", "terracotta", "cement", "quartz",
62
+ "limestone", "onyx", "travertine", "glass", "encaustic"
63
+ ]
64
+
65
+
66
+ # Templates for each room type
67
+ templates = {
68
+ "living_room": """
69
+ High quality, High resolution, Interior, Architecture, Revit, Autocad, Realistic 3D Render, vray, lumion, raytracing,
70
+ of a {{ adj_1 }} living room, in {{ architecture_style }} architecture, with {{ aesthetic }} style,
71
+ painted in {{ wall_color }} with {{ primary_color }} accents, {{ wood_finish }} wood finishes, and {{ tiles }} flooring.
72
+ """,
73
+ "bedroom": """
74
+ High quality, High resolution, Interior, Architecture, Revit, Autocad, Realistic 3D Render, vray, lumion, raytracing,
75
+ of a {{ adj_1 }} bedroom, in {{ architecture_style }} architecture, with {{ aesthetic }} style,
76
+ painted in {{ wall_color }} with {{ primary_color }} accents, {{ wood_finish }} wood finishes, and {{ tiles }} flooring.
77
+ """,
78
+ "kitchen": """
79
+ High quality, High resolution, Interior, Architecture, Revit, Autocad, Realistic 3D Render, vray, lumion, raytracing,
80
+ of a {{ adj_1 }} kitchen, in {{ architecture_style }} architecture, with {{ aesthetic }} style,
81
+ painted in {{ wall_color }} with {{ primary_color }} accents, {{ wood_finish }} cabinetry, and {{ tiles }} flooring.
82
+ """
83
+ }
84
+
85
+ def generate_prompt(option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles):
86
+ # Validate inputs
87
+ if adj_1 not in adj_1_choices:
88
+ raise ValueError(f"Invalid adjective: '{adj_1}'. Accepted options are {adj_1_choices}")
89
+ if architecture_style not in architecture_style_choices:
90
+ raise ValueError(f"Invalid architecture style: '{architecture_style}'. Accepted options are {architecture_style_choices}")
91
+ if aesthetic not in aesthetic_choices:
92
+ raise ValueError(f"Invalid aesthetic style: '{aesthetic}'. Accepted options are {aesthetic_choices}")
93
+ if primary_color not in primary_color_choices:
94
+ raise ValueError(f"Invalid primary color: '{primary_color}'. Accepted options are {primary_color_choices}")
95
+ if wood_finish not in wood_finish_choices:
96
+ raise ValueError(f"Invalid wood finish: '{wood_finish}'. Accepted options are {wood_finish_choices}")
97
+ if wall_color not in wall_color_choices:
98
+ raise ValueError(f"Invalid wall color: '{wall_color}'. Accepted options are {wall_color_choices}")
99
+ if tiles not in tiles_choices:
100
+ raise ValueError(f"Invalid tiles: '{tiles}'. Accepted options are {tiles_choices}")
101
+
102
+ # Select the template based on the room type option
103
+ template_str = templates.get(option.lower())
104
+ if not template_str:
105
+ raise ValueError(f"Invalid option: '{option}'. Available options are {option_choices}")
106
+
107
+ # Render the template
108
+ template = Template(template_str)
109
+ return template.render(
110
+ adj_1=adj_1,
111
+ architecture_style=architecture_style,
112
+ aesthetic=aesthetic,
113
+ primary_color=primary_color,
114
+ wood_finish=wood_finish,
115
+ wall_color=wall_color,
116
+ tiles=tiles
117
+ )
118
+
119
+ # Function to generate initial image
120
+ def generate_initial_image(n_images=1, option='living_room', adj_1="spacious", architecture_style="modern", aesthetic="minimalist",
121
+ primary_color="neutral", wood_finish="oak", wall_color="off-white", tiles="marble"):
122
+ # Generate the prompt from choices
123
+ gen_prompt = generate_prompt(option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles)
124
+
125
+ images = [] # List to store generated images along with seeds
126
+ for i in range(n_images):
127
+ # Generate a random seed for reproducibility
128
+ seed = torch.randint(0, 2**32, (1,)).item()
129
+ generator = torch.manual_seed(seed)
130
+
131
+ # Generate the image with the prompt and Stable Diffusion pipeline
132
+ cfg = 8 # Configuring guidance scale
133
+ steps = 30 # Number of inference steps
134
+ width, height = 640, 512
135
+ # pipeline without controlnet
136
+ img = sd_pipeline(prompt=gen_prompt, guidance_scale=cfg, num_inference_steps=steps, width=width, height=height, generator=generator).images[0]
137
+
138
+ # Append the seed and image to the list for tracking
139
+ images.append((seed, img))
140
+ return images
141
+
142
+ # Function to modify image using ControlNet pipeline
143
+ def modify_image_with_controlnet(selected_image, additional_prompt, option='living_room', adj_1="spacious", architecture_style="modern", aesthetic="minimalist",
144
+ primary_color="brown", wood_finish="walnut", wall_color="beige", tiles="ceramic"):
145
+ gen_prompt = generate_prompt(option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles)
146
+ gen_prompt += '(('+additional_prompt+'))'
147
+ seed = selected_image[0]
148
+ generator = torch.manual_seed(seed)
149
+ cfg = 8 # Configuring guidance scale
150
+ steps = 30 # Number of inference steps
151
+ width, height = 640, 512
152
+ # preprocessig for control net
153
+ img = np.array(selected_image[1])
154
+ gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
155
+ edges = cv2.Canny(gray, 100, 200)
156
+ edges_image = Image.fromarray(edges)
157
+ controlnet_strength = 0.85
158
+ image = controlnet_pipeline(prompt=gen_prompt, image=edges_image, guidance_scale=cfg, width=width, height=height,
159
+ controlnet_conditioning_scale=controlnet_strength, num_inference_steps=steps, generator=generator).images[0]
160
+ return image
161
+
162
+ # Gradio app logic
163
+ def generate_image(option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles, n_images, progress=gr.Progress()):
164
+ generated_images = generate_initial_image(
165
+ n_images=n_images,
166
+ option=option,
167
+ adj_1=adj_1,
168
+ architecture_style=architecture_style,
169
+ aesthetic=aesthetic,
170
+ primary_color=primary_color,
171
+ wood_finish=wood_finish,
172
+ wall_color=wall_color,
173
+ tiles=tiles
174
+ )
175
+
176
+ display_images = [img.resize((640, 512)) for _, img in generated_images] # Resize only for display
177
+ image_identifiers = [f"Image-{i+1}" for i in range(n_images)]
178
+
179
+ return display_images, generated_images, image_identifiers
180
+
181
+
182
+ def modify_image(selected_image_id, additional_prompt, option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles, images):
183
+ # Parse selected image identifier to get the index
184
+ image_index = int(selected_image_id.split("-")[1]) - 1
185
+ selected_image = images[image_index] # Retrieve the (seed, original_img) tuple without resizing
186
+
187
+ # Modify image using ControlNet
188
+ modified_image = modify_image_with_controlnet(
189
+ selected_image=selected_image,
190
+ additional_prompt=additional_prompt,
191
+ option=option,
192
+ adj_1=adj_1,
193
+ architecture_style=architecture_style,
194
+ aesthetic=aesthetic,
195
+ primary_color=primary_color,
196
+ wood_finish=wood_finish,
197
+ wall_color=wall_color,
198
+ tiles=tiles
199
+ )
200
+ return modified_image
201
+
202
+ # Interface
203
+ with gr.Blocks() as app:
204
+ gr.Markdown("# Interior Design Image Generation and Modification")
205
+
206
+ # Image generation options
207
+ with gr.Row():
208
+ option = gr.Radio(label="Room Type", choices=option_choices, value="living_room")
209
+ adj_1 = gr.Radio(label="Primary Adjective", choices=adj_1_choices, value="spacious")
210
+ architecture_style = gr.Radio(label="Architecture Style", choices=architecture_style_choices, value="modern")
211
+
212
+ with gr.Row():
213
+ aesthetic = gr.Radio(label="Aesthetic", choices=aesthetic_choices, value="minimalist")
214
+ primary_color = gr.Radio(label="Primary Color", choices=primary_color_choices, value="neutral")
215
+ wood_finish = gr.Radio(label="Wood Finish", choices=wood_finish_choices, value="oak")
216
+
217
+ with gr.Row():
218
+ wall_color = gr.Radio(label="Wall Color", choices=wall_color_choices, value="off-white")
219
+ tiles = gr.Radio(label="Tile Type", choices=tiles_choices, value="marble")
220
+
221
+ n_images = gr.Slider(label="Number of Images to Generate", minimum=1, maximum=5, step=1, value=1)
222
+
223
+ # Button to generate images
224
+ generate_btn = gr.Button("Generate Images")
225
+ output_images = gr.Gallery(label="Generated Images", columns=5) # Display resized images in gallery layout
226
+ output_generated_images = gr.State() # Hidden state to store original (unmodified) images data
227
+ output_identifiers = gr.State() # Hidden state for image identifiers
228
+
229
+ # Image selection and modification
230
+ selected_image_id = gr.Radio(label="Select an Image for Modification", choices=[])
231
+ additional_prompt = gr.Textbox(label="Additional Prompt for Modification", placeholder="OPTIONAL")
232
+ modify_btn = gr.Button("Modify Image")
233
+ modified_image = gr.Image(label="Modified Image")
234
+
235
+ # Button actions
236
+ generate_btn.click(
237
+ fn=generate_image,
238
+ inputs=[option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles, n_images],
239
+ outputs=[output_images, output_generated_images, output_identifiers]
240
+ )
241
+
242
+ # Update radio button options after images are generated
243
+ output_images.change(
244
+ fn=lambda identifiers: gr.update(choices=identifiers, visible=True), # Populate with image identifiers
245
+ inputs=[output_identifiers],
246
+ outputs=[selected_image_id]
247
+ )
248
+
249
+ # Trigger modification on button click
250
+ modify_btn.click(
251
+ fn=modify_image,
252
+ inputs=[selected_image_id, additional_prompt, option, adj_1, architecture_style, aesthetic, primary_color, wood_finish, wall_color, tiles, output_generated_images],
253
+ outputs=modified_image
254
+ )
255
+
256
+ app.launch(debug=True)