cavargas10 commited on
Commit
16fc781
Β·
verified Β·
1 Parent(s): 7c7ca7a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -177
app.py CHANGED
@@ -11,64 +11,16 @@ import imageio
11
  from easydict import EasyDict as edict
12
  from PIL import Image, ImageOps
13
  from trellis.pipelines import TrellisImageTo3DPipeline
14
- from trellis.representations import MeshExtractResult
15
  from trellis.utils import render_utils, postprocessing_utils
16
  from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline, AutoencoderKL
17
  from diffusers import EulerAncestralDiscreteScheduler
18
- from huggingface_hub import HfApi
19
  from pathlib import Path
20
 
21
  style_list = [
22
- {
23
- "name": "(No style)",
24
- "prompt": "{prompt}",
25
- "negative_prompt": "longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality",
26
- },
27
- {
28
- "name": "Cinematic",
29
- "prompt": "cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy",
30
- "negative_prompt": "anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured",
31
- },
32
- {
33
- "name": "3D Model",
34
- "prompt": "professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting",
35
- "negative_prompt": "ugly, deformed, noisy, low poly, blurry, painting",
36
- },
37
- {
38
- "name": "Anime",
39
- "prompt": "anime artwork {prompt} . anime style, key visual, vibrant, studio anime, highly detailed",
40
- "negative_prompt": "photo, deformed, black and white, realism, disfigured, low contrast",
41
- },
42
- {
43
- "name": "Digital Art",
44
- "prompt": "concept art {prompt} . digital artwork, illustrative, painterly, matte painting, highly detailed",
45
- "negative_prompt": "photo, photorealistic, realism, ugly",
46
- },
47
- {
48
- "name": "Photographic",
49
- "prompt": "cinematic photo {prompt} . 35mm photograph, film, bokeh, professional, 4k, highly detailed",
50
- "negative_prompt": "drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly",
51
- },
52
- {
53
- "name": "Pixel art",
54
- "prompt": "pixel-art {prompt} . low-res, blocky, pixel art style, 8-bit graphics",
55
- "negative_prompt": "sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic",
56
- },
57
- {
58
- "name": "Fantasy art",
59
- "prompt": "ethereal fantasy concept art of {prompt} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy",
60
- "negative_prompt": "photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white",
61
- },
62
- {
63
- "name": "Neonpunk",
64
- "prompt": "neonpunk style {prompt} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional",
65
- "negative_prompt": "painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured",
66
- },
67
- {
68
- "name": "Manga",
69
- "prompt": "manga style {prompt} . vibrant, high-energy, detailed, iconic, Japanese comic style",
70
- "negative_prompt": "ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style",
71
- },
72
  ]
73
  styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
74
  STYLE_NAMES = list(styles.keys())
@@ -77,9 +29,6 @@ MAX_SEED = np.iinfo(np.int32).max
77
  TMP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
78
  os.makedirs(TMP_DIR, exist_ok=True)
79
 
80
- def reset_canvas():
81
- return gr.update(value={"background":Image.new("RGB", (512, 512), (255, 255, 255)), "layers":[Image.new("RGB", (512, 512), (255, 255, 255))], "composite":Image.new("RGB", (512, 512), (255, 255, 255))})
82
-
83
  def apply_style(style_name: str, positive: str, negative: str = "") -> tuple[str, str]:
84
  p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
85
  return p.replace("{prompt}", positive), n + negative
@@ -87,26 +36,26 @@ def apply_style(style_name: str, positive: str, negative: str = "") -> tuple[str
87
  def start_session(req: gr.Request):
88
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
89
  os.makedirs(user_dir, exist_ok=True)
90
-
91
  def end_session(req: gr.Request):
92
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
93
  shutil.rmtree(user_dir)
94
 
95
  @spaces.GPU
96
  def preprocess_image(image: Image.Image,
97
- prompt: str = "",
98
- negative_prompt: str = "",
99
- style_name: str = "",
100
- num_steps: int = 25,
101
- guidance_scale: float = 5,
102
- controlnet_conditioning_scale: float = 1.0,
103
- ) -> Image.Image:
104
- width, height = image['composite'].size
105
- ratio = np.sqrt(1024. * 1024. / (width * height))
106
- new_width, new_height = int(width * ratio), int(height * ratio)
107
- image = image['composite'].resize((new_width, new_height))
108
- image = ImageOps.invert(image)
109
  prompt, negative_prompt = apply_style(style_name, prompt, negative_prompt)
 
110
  output = pipe_control(
111
  prompt=prompt,
112
  negative_prompt=negative_prompt,
@@ -114,10 +63,9 @@ def preprocess_image(image: Image.Image,
114
  num_inference_steps=num_steps,
115
  controlnet_conditioning_scale=controlnet_conditioning_scale,
116
  guidance_scale=guidance_scale,
117
- width=new_width,
118
- height=new_height).images[0]
119
- processed_image = pipeline.preprocess_image(output)
120
- return (image, processed_image)
121
 
122
  def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
123
  return {
@@ -134,8 +82,7 @@ def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
134
  'faces': mesh.faces.cpu().numpy(),
135
  },
136
  }
137
-
138
-
139
  def unpack_state(state: dict) -> Tuple[Gaussian, edict, str]:
140
  gs = Gaussian(
141
  aabb=state['gaussian']['aabb'],
@@ -158,9 +105,6 @@ def unpack_state(state: dict) -> Tuple[Gaussian, edict, str]:
158
 
159
  return gs, mesh
160
 
161
- def get_seed(randomize_seed: bool, seed: int) -> int:
162
- return np.random.randint(0, MAX_SEED) if randomize_seed else seed
163
-
164
  @spaces.GPU
165
  def image_to_3d(
166
  image: Image.Image,
@@ -173,10 +117,9 @@ def image_to_3d(
173
  ) -> Tuple[dict, str]:
174
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
175
  outputs = pipeline.run(
176
- image[1],
177
  seed=seed,
178
- formats=["mesh"],
179
- preprocess_image=False,
180
  sparse_structure_sampler_params={
181
  "steps": ss_sampling_steps,
182
  "cfg_strength": ss_guidance_strength,
@@ -186,10 +129,13 @@ def image_to_3d(
186
  "cfg_strength": slat_guidance_strength,
187
  },
188
  )
189
- video = render_utils.render_video(outputs['mesh'][0], num_frames=120)['normal']
 
 
 
190
  video_path = os.path.join(user_dir, 'sample.mp4')
191
  imageio.mimsave(video_path, video, fps=15)
192
- state = pack_state(outputs['mesh'][0])
193
  torch.cuda.empty_cache()
194
  return state, video_path
195
 
@@ -201,127 +147,88 @@ def extract_glb(
201
  req: gr.Request,
202
  ) -> str:
203
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
204
- mesh = unpack_state(state)
205
- glb = postprocessing_utils.to_glb(mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
206
  glb_path = os.path.join(user_dir, 'sample.glb')
207
  glb.export(glb_path)
208
  torch.cuda.empty_cache()
209
  return glb_path
210
 
211
- def reset_do_preprocess():
212
- return True
213
-
214
- with gr.Blocks(delete_cache=(600, 600)) as demo:
215
- gr.Markdown("""
216
- ## Sketch to 3D with TRELLIS
217
- 1. Fast sketch to image with SDXL Flash
218
- 2. Scalable and versatile image to 3D generation using [TRELLIS](https://trellis3d.github.io/)
219
- ### 🎨 Draw or upload a sketch and click "Generate" to create a 3D asset ✨
220
- """)
221
  with gr.Row():
222
  with gr.Column():
223
- image_prompt = gr.ImageMask(label="Input sketch", type="pil", image_mode="RGB", height=512, value=reset_canvas())
224
- with gr.Row():
225
- sketch_btn = gr.Button("Process sketch")
226
- generate_btn = gr.Button("Generate 3D")
227
- with gr.Row():
228
- prompt = gr.Textbox(label="Prompt")
229
- style = gr.Dropdown(label="Style", choices=STYLE_NAMES, value=DEFAULT_STYLE_NAME)
230
- with gr.Accordion(label="Generation Settings", open=False):
231
- with gr.Tab(label="sketch-to-image generation"):
232
- negative_prompt = gr.Textbox(label="Negative prompt")
233
- num_steps = gr.Slider(1, 20, label="Number of steps", value=8, step=1)
234
- guidance_scale = gr.Slider(0.1, 10.0, label="Guidance scale", value=5, step=0.1)
235
- controlnet_conditioning_scale = gr.Slider(0.5, 5.0, label="ControlNet conditioning scale", value=0.85, step=0.01)
236
- with gr.Tab(label="3D generation"):
237
- seed = gr.Slider(0, MAX_SEED, label="Seed", value=0, step=1)
238
- randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
239
- gr.Markdown("Stage 1: Sparse Structure Generation")
240
- with gr.Row():
241
- ss_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=7.5, step=0.1)
242
- ss_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
243
- gr.Markdown("Stage 2: Structured Latent Generation")
244
- with gr.Row():
245
- slat_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=3.0, step=0.1)
246
- slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
247
- with gr.Accordion(label="GLB Extraction Settings", open=False):
248
- mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify", value=0.95, step=0.01)
249
  texture_size = gr.Slider(512, 2048, label="Texture Size", value=1024, step=512)
250
- with gr.Row():
251
- extract_glb_btn = gr.Button("Extract GLB", interactive=False)
252
- gr.Markdown("")
253
-
254
  with gr.Column():
255
- video_output = gr.Video(label="Generated 3D Asset", autoplay=True, loop=True, height=300)
256
- image_prompt_processed = gr.Image(label="Processed sketch", interactive=False, type="pil", height=512)
257
- model_output = LitModel3D(label="Extracted GLB", exposure=10.0, height=300)
258
- download_glb = gr.DownloadButton(label="Download GLB", interactive=False)
259
-
260
- output_buf = gr.State()
261
- do_preprocess = gr.State(True)
262
 
263
- with gr.Row(visible=False) as single_image_example:
264
- examples = gr.Examples(
265
- examples=[f'assets/example_image/{image}' for image in os.listdir("assets/example_image")],
266
- inputs=[image_prompt],
267
- fn=preprocess_image,
268
- outputs=[image_prompt_processed],
269
- run_on_click=True,
270
- examples_per_page=64,
271
- )
272
 
273
  demo.load(start_session)
274
  demo.unload(end_session)
275
-
276
- image_prompt.clear(reset_canvas, outputs=[image_prompt])
277
-
278
- sketch_btn.click(
279
- get_seed,
280
  inputs=[randomize_seed, seed],
281
  outputs=[seed],
282
  ).then(
283
  preprocess_image,
284
- inputs=[image_prompt, prompt, negative_prompt, style, num_steps, guidance_scale, controlnet_conditioning_scale],
285
- outputs=[image_prompt_processed],
286
- )
287
-
288
- generate_btn.click(
289
- get_seed,
290
- inputs=[randomize_seed, seed],
291
- outputs=[seed],
292
  ).then(
293
  image_to_3d,
294
- inputs=[image_prompt_processed, seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps],
295
- outputs=[output_buf, video_output],
296
  ).then(
297
  lambda: gr.Button(interactive=True),
298
- outputs=[extract_glb_btn],
299
- )
300
-
301
- video_output.clear(
302
- lambda: gr.Button(interactive=False),
303
- outputs=[extract_glb_btn],
304
  )
305
 
306
- extract_glb_btn.click(
307
  extract_glb,
308
- inputs=[output_buf, mesh_simplify, texture_size],
309
- outputs=[model_output, download_glb],
310
  ).then(
311
  lambda: gr.Button(interactive=True),
312
- outputs=[download_glb],
313
- )
314
-
315
- model_output.clear(
316
- lambda: gr.Button(interactive=False),
317
- outputs=[download_glb],
318
  )
319
 
320
  if __name__ == "__main__":
 
321
  pipeline = TrellisImageTo3DPipeline.from_pretrained("JeffreyXiang/TRELLIS-image-large")
322
  pipeline.cuda()
323
- device = "cuda" if torch.cuda.is_available() else "cpu"
324
 
 
325
  controlnet = ControlNetModel.from_pretrained(
326
  "xinsir/controlnet-scribble-sdxl-1.0",
327
  torch_dtype=torch.float16
@@ -334,11 +241,6 @@ if __name__ == "__main__":
334
  torch_dtype=torch.float16,
335
  )
336
  pipe_control.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe_control.scheduler.config)
337
- pipe_control.to(device)
338
-
339
- try:
340
- pipeline.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8)))
341
- except:
342
- pass
343
 
344
  demo.launch()
 
11
  from easydict import EasyDict as edict
12
  from PIL import Image, ImageOps
13
  from trellis.pipelines import TrellisImageTo3DPipeline
14
+ from trellis.representations import Gaussian, MeshExtractResult
15
  from trellis.utils import render_utils, postprocessing_utils
16
  from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline, AutoencoderKL
17
  from diffusers import EulerAncestralDiscreteScheduler
 
18
  from pathlib import Path
19
 
20
  style_list = [
21
+ {"name": "(No style)", "prompt": "{prompt}", "negative_prompt": ""},
22
+ {"name": "Cinematic", "prompt": "cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy", "negative_prompt": "anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured"},
23
+ {"name": "3D Model", "prompt": "professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting", "negative_prompt": "ugly, deformed, noisy, low poly, blurry, painting"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  ]
25
  styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
26
  STYLE_NAMES = list(styles.keys())
 
29
  TMP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
30
  os.makedirs(TMP_DIR, exist_ok=True)
31
 
 
 
 
32
  def apply_style(style_name: str, positive: str, negative: str = "") -> tuple[str, str]:
33
  p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
34
  return p.replace("{prompt}", positive), n + negative
 
36
  def start_session(req: gr.Request):
37
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
38
  os.makedirs(user_dir, exist_ok=True)
39
+
40
  def end_session(req: gr.Request):
41
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
42
  shutil.rmtree(user_dir)
43
 
44
  @spaces.GPU
45
  def preprocess_image(image: Image.Image,
46
+ prompt: str,
47
+ negative_prompt: str,
48
+ style_name: str,
49
+ num_steps: int,
50
+ guidance_scale: float,
51
+ controlnet_conditioning_scale: float) -> Image.Image:
52
+ width, height = image.size
53
+ ratio = np.sqrt(1024 * 1024 / (width * height))
54
+ new_size = (int(width * ratio), int(height * ratio))
55
+ image = image.resize(new_size)
56
+
 
57
  prompt, negative_prompt = apply_style(style_name, prompt, negative_prompt)
58
+
59
  output = pipe_control(
60
  prompt=prompt,
61
  negative_prompt=negative_prompt,
 
63
  num_inference_steps=num_steps,
64
  controlnet_conditioning_scale=controlnet_conditioning_scale,
65
  guidance_scale=guidance_scale,
66
+ ).images[0]
67
+
68
+ return pipeline.preprocess_image(output)
 
69
 
70
  def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
71
  return {
 
82
  'faces': mesh.faces.cpu().numpy(),
83
  },
84
  }
85
+
 
86
  def unpack_state(state: dict) -> Tuple[Gaussian, edict, str]:
87
  gs = Gaussian(
88
  aabb=state['gaussian']['aabb'],
 
105
 
106
  return gs, mesh
107
 
 
 
 
108
  @spaces.GPU
109
  def image_to_3d(
110
  image: Image.Image,
 
117
  ) -> Tuple[dict, str]:
118
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
119
  outputs = pipeline.run(
120
+ image,
121
  seed=seed,
122
+ formats=["gaussian", "mesh"],
 
123
  sparse_structure_sampler_params={
124
  "steps": ss_sampling_steps,
125
  "cfg_strength": ss_guidance_strength,
 
129
  "cfg_strength": slat_guidance_strength,
130
  },
131
  )
132
+
133
+ video = render_utils.render_video(outputs['gaussian'][0], num_frames=120)['color']
134
+ video_geo = render_utils.render_video(outputs['mesh'][0], num_frames=120)['normal']
135
+ video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
136
  video_path = os.path.join(user_dir, 'sample.mp4')
137
  imageio.mimsave(video_path, video, fps=15)
138
+ state = pack_state(outputs['gaussian'][0], outputs['mesh'][0])
139
  torch.cuda.empty_cache()
140
  return state, video_path
141
 
 
147
  req: gr.Request,
148
  ) -> str:
149
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
150
+ gs, mesh = unpack_state(state)
151
+ glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size)
152
  glb_path = os.path.join(user_dir, 'sample.glb')
153
  glb.export(glb_path)
154
  torch.cuda.empty_cache()
155
  return glb_path
156
 
157
+ with gr.Blocks() as demo:
158
+ gr.Markdown("# Sketch to 3D with TRELLIS")
 
 
 
 
 
 
 
 
159
  with gr.Row():
160
  with gr.Column():
161
+ image_prompt = gr.Image(label="Sketch Input", type="pil", image_mode="RGBA", height=512)
162
+ prompt = gr.Textbox(label="Prompt", placeholder="Describe tu modelo 3D")
163
+ style = gr.Dropdown(label="Style", choices=STYLE_NAMES, value=DEFAULT_STYLE_NAME)
164
+
165
+ with gr.Accordion("Generation Settings", open=False):
166
+ num_steps = gr.Slider(1, 20, label="Steps", value=8, step=1)
167
+ guidance_scale = gr.Slider(0.1, 10.0, label="Guidance Scale", value=5.0, step=0.1)
168
+ controlnet_scale = gr.Slider(0.5, 5.0, label="ControlNet Scale", value=0.85, step=0.01)
169
+ seed = gr.Slider(0, MAX_SEED, label="Seed", value=0, step=1)
170
+ randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
171
+
172
+ with gr.Group():
173
+ gr.Markdown("#### Stage 1: Structure")
174
+ ss_guidance = gr.Slider(0.0, 10.0, label="Guidance", value=7.5, step=0.1)
175
+ ss_steps = gr.Slider(1, 50, label="Steps", value=12, step=1)
176
+
177
+ with gr.Group():
178
+ gr.Markdown("#### Stage 2: Detail")
179
+ slat_guidance = gr.Slider(0.0, 10.0, label="Guidance", value=3.0, step=0.1)
180
+ slat_steps = gr.Slider(1, 50, label="Steps", value=12, step=1)
181
+
182
+ generate_btn = gr.Button("Generate 3D Model", variant="primary")
183
+
184
+ with gr.Accordion("Export Settings", open=False):
185
+ mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify Mesh", value=0.95, step=0.01)
 
186
  texture_size = gr.Slider(512, 2048, label="Texture Size", value=1024, step=512)
187
+
188
+ extract_btn = gr.Button("Export GLB", interactive=False)
189
+
 
190
  with gr.Column():
191
+ video_output = gr.Video(label="3D Preview", autoplay=True, loop=True, height=300)
192
+ model_viewer = LitModel3D(label="3D Model Viewer", height=400)
193
+ download_btn = gr.DownloadButton("Download GLB", interactive=False)
 
 
 
 
194
 
195
+ output_state = gr.State()
 
 
 
 
 
 
 
 
196
 
197
  demo.load(start_session)
198
  demo.unload(end_session)
199
+
200
+ generate_btn.click(
201
+ lambda rand, s: np.random.randint(0, MAX_SEED) if rand else s,
 
 
202
  inputs=[randomize_seed, seed],
203
  outputs=[seed],
204
  ).then(
205
  preprocess_image,
206
+ inputs=[image_prompt, prompt, gr.Textbox(), style, num_steps, guidance_scale, controlnet_scale],
207
+ outputs=[image_prompt],
 
 
 
 
 
 
208
  ).then(
209
  image_to_3d,
210
+ inputs=[image_prompt, seed, ss_guidance, ss_steps, slat_guidance, slat_steps],
211
+ outputs=[output_state, video_output],
212
  ).then(
213
  lambda: gr.Button(interactive=True),
214
+ outputs=[extract_btn],
 
 
 
 
 
215
  )
216
 
217
+ extract_btn.click(
218
  extract_glb,
219
+ inputs=[output_state, mesh_simplify, texture_size],
220
+ outputs=[model_viewer, download_btn],
221
  ).then(
222
  lambda: gr.Button(interactive=True),
223
+ outputs=[download_btn],
 
 
 
 
 
224
  )
225
 
226
  if __name__ == "__main__":
227
+ # TRELLIS pipeline
228
  pipeline = TrellisImageTo3DPipeline.from_pretrained("JeffreyXiang/TRELLIS-image-large")
229
  pipeline.cuda()
 
230
 
231
+ # ControlNet y SDXL
232
  controlnet = ControlNetModel.from_pretrained(
233
  "xinsir/controlnet-scribble-sdxl-1.0",
234
  torch_dtype=torch.float16
 
241
  torch_dtype=torch.float16,
242
  )
243
  pipe_control.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe_control.scheduler.config)
244
+ pipe_control.to("cuda")
 
 
 
 
 
245
 
246
  demo.launch()