Akhmad123 commited on
Commit
e11858e
·
verified ·
1 Parent(s): c16de2f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +191 -45
app.py CHANGED
@@ -2,7 +2,8 @@ import gradio as gr
2
  import numpy as np
3
  import random
4
  import torch
5
- from diffusers import DiffusionPipeline
 
6
 
7
  # -----------------------------
8
  # CPU MODE ONLY
@@ -10,35 +11,88 @@ from diffusers import DiffusionPipeline
10
  device = "cpu"
11
  torch_dtype = torch.float32
12
 
13
- MODEL_ID = "runwayml/stable-diffusion-v1-5" # model ringan & aman untuk CPU
14
 
15
- # Load pipeline
16
- pipe = DiffusionPipeline.from_pretrained(
17
  MODEL_ID,
18
  torch_dtype=torch_dtype,
19
  low_cpu_mem_usage=True,
20
  )
21
- pipe.to(device)
 
 
 
 
 
 
 
 
22
 
23
  MAX_SEED = np.iinfo(np.int32).max
24
 
25
 
26
- def build_prompt(prompt, style):
27
- styles = {
 
 
 
28
  "Tanpa gaya": "",
29
  "Studio": "product photography, clean studio background, soft lighting, high quality",
30
  "E-commerce": "white background, catalog photo, sharp, high quality, tokopedia, shopee",
31
  "Pastel": "pastel colors, soft light, aesthetic instagram style",
32
  "Lifestyle": "realistic lifestyle photography, natural light",
 
 
 
 
 
 
 
 
 
33
  }
34
- suffix = styles.get(style, "")
35
- return f"{prompt}, {suffix}" if suffix else prompt
36
 
 
 
37
 
38
- def infer(prompt, negative_prompt, seed, randomize_seed,
39
- width, height, guidance_scale, steps,
40
- style, num_images):
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  if not prompt:
43
  raise gr.Error("Prompt tidak boleh kosong.")
44
 
@@ -46,58 +100,150 @@ def infer(prompt, negative_prompt, seed, randomize_seed,
46
  seed = random.randint(0, MAX_SEED)
47
 
48
  generator = torch.Generator(device=device).manual_seed(seed)
49
- full_prompt = build_prompt(prompt, style)
50
 
51
  images = []
52
- for _ in range(num_images):
53
- out = pipe(
54
- prompt=full_prompt,
55
- negative_prompt=negative_prompt or None,
56
- width=width,
57
- height=height,
58
- guidance_scale=guidance_scale,
59
- num_inference_steps=steps,
60
- generator=generator,
61
- )
62
- images.append(out.images[0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  return images, seed
65
 
66
 
67
- with gr.Blocks(title="RuangAI CPU Mode") as demo:
68
- gr.Markdown("# 🧴 RuangAI – Product Visualizer (CPU Mode)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  with gr.Row():
71
- prompt = gr.Textbox(label="Prompt", placeholder="Deskripsi produk...")
72
- run_btn = gr.Button("Generate ")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  with gr.Row():
75
  style = gr.Dropdown(
76
- ["Tanpa gaya", "Studio", "E-commerce", "Pastel", "Lifestyle"],
77
  value="Studio",
78
- label="Gaya visual"
 
 
 
79
  )
80
- num_images = gr.Slider(1, 3, value=1, step=1, label="Jumlah gambar")
81
 
82
- gallery = gr.Gallery(label="Hasil", columns=2, height=512)
 
 
 
 
83
 
84
  with gr.Accordion("Advanced Settings", open=False):
85
- negative_prompt = gr.Textbox(label="Negative prompt")
86
- seed = gr.Slider(0, MAX_SEED, value=0, step=1, label="Seed")
87
- randomize_seed = gr.Checkbox(True, label="Randomize seed")
88
- width = gr.Slider(256, 768, value=512, step=32, label="Width")
89
- height = gr.Slider(256, 768, value=512, step=32, label="Height")
90
- guidance_scale = gr.Slider(0, 10, value=7, step=0.5, label="Guidance")
91
- steps = gr.Slider(5, 40, value=25, step=1, label="Steps")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  run_btn.click(
94
- infer,
95
  inputs=[
96
- prompt, negative_prompt, seed, randomize_seed,
97
- width, height, guidance_scale, steps,
98
- style, num_images
 
 
 
 
 
 
 
 
 
 
 
99
  ],
100
- outputs=[gallery, seed]
101
  )
102
 
103
- demo.launch()
 
 
2
  import numpy as np
3
  import random
4
  import torch
5
+ from diffusers import DiffusionPipeline, StableDiffusionImg2ImgPipeline
6
+ from PIL import Image
7
 
8
  # -----------------------------
9
  # CPU MODE ONLY
 
11
  device = "cpu"
12
  torch_dtype = torch.float32
13
 
14
+ MODEL_ID = "runwayml/stable-diffusion-v1-5"
15
 
16
+ # txt2img pipeline
17
+ txt2img_pipe = DiffusionPipeline.from_pretrained(
18
  MODEL_ID,
19
  torch_dtype=torch_dtype,
20
  low_cpu_mem_usage=True,
21
  )
22
+ txt2img_pipe.to(device)
23
+
24
+ # img2img pipeline
25
+ img2img_pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
26
+ MODEL_ID,
27
+ torch_dtype=torch_dtype,
28
+ low_cpu_mem_usage=True,
29
+ )
30
+ img2img_pipe.to(device)
31
 
32
  MAX_SEED = np.iinfo(np.int32).max
33
 
34
 
35
+ # -----------------------------
36
+ # Prompt builder
37
+ # -----------------------------
38
+ def build_prompt(prompt: str, style: str, category: str) -> str:
39
+ style_map = {
40
  "Tanpa gaya": "",
41
  "Studio": "product photography, clean studio background, soft lighting, high quality",
42
  "E-commerce": "white background, catalog photo, sharp, high quality, tokopedia, shopee",
43
  "Pastel": "pastel colors, soft light, aesthetic instagram style",
44
  "Lifestyle": "realistic lifestyle photography, natural light",
45
+ "Model Talent": "professional model, commercial photoshoot, studio lighting, natural pose, realistic skin texture, high quality",
46
+ }
47
+
48
+ category_map = {
49
+ "Umum": "",
50
+ "Skincare": "skincare product, glossy bottle, premium lighting, beauty aesthetic",
51
+ "Makanan/Minuman": "food photography, appetizing, vibrant lighting, splash effect",
52
+ "Fashion": "fashion product, textile detail, clean lighting",
53
+ "Elektronik": "electronic product, reflective surface, studio lighting",
54
  }
 
 
55
 
56
+ s = style_map.get(style, "")
57
+ c = category_map.get(category, "")
58
 
59
+ parts = [prompt, s, c]
60
+ return ", ".join([p for p in parts if p])
 
61
 
62
+
63
+ # -----------------------------
64
+ # Auto prompt generator
65
+ # -----------------------------
66
+ def auto_prompt(category: str) -> str:
67
+ templates = {
68
+ "Skincare": "Serum skincare botol kaca premium, tampilan mewah, cocok untuk iklan Instagram",
69
+ "Makanan/Minuman": "Minuman energi rasa lemon, efek splash, gaya promosi e-commerce",
70
+ "Fashion": "Sepatu running sport, tampilan katalog, background putih bersih",
71
+ "Elektronik": "Headphone wireless modern, lighting studio, tampilan premium",
72
+ "Umum": "Produk premium dengan lighting studio dan background bersih",
73
+ }
74
+ return templates.get(category, "Produk premium dengan lighting studio dan background bersih")
75
+
76
+
77
+ # -----------------------------
78
+ # Inference
79
+ # -----------------------------
80
+ def generate(
81
+ mode,
82
+ prompt,
83
+ negative_prompt,
84
+ seed,
85
+ randomize_seed,
86
+ width,
87
+ height,
88
+ guidance_scale,
89
+ steps,
90
+ style,
91
+ category,
92
+ num_images,
93
+ init_image,
94
+ strength,
95
+ ):
96
  if not prompt:
97
  raise gr.Error("Prompt tidak boleh kosong.")
98
 
 
100
  seed = random.randint(0, MAX_SEED)
101
 
102
  generator = torch.Generator(device=device).manual_seed(seed)
103
+ full_prompt = build_prompt(prompt, style, category)
104
 
105
  images = []
106
+
107
+ if mode == "Text to Image":
108
+ for _ in range(num_images):
109
+ out = txt2img_pipe(
110
+ prompt=full_prompt,
111
+ negative_prompt=negative_prompt or None,
112
+ width=width,
113
+ height=height,
114
+ guidance_scale=guidance_scale,
115
+ num_inference_steps=steps,
116
+ generator=generator,
117
+ )
118
+ images.append(out.images[0])
119
+ else: # Image to Image
120
+ if init_image is None:
121
+ raise gr.Error("Upload gambar produk terlebih dahulu.")
122
+
123
+ init_image = init_image.convert("RGB").resize((width, height))
124
+
125
+ for _ in range(num_images):
126
+ out = img2img_pipe(
127
+ prompt=full_prompt,
128
+ negative_prompt=negative_prompt or None,
129
+ image=init_image,
130
+ strength=strength,
131
+ guidance_scale=guidance_scale,
132
+ num_inference_steps=steps,
133
+ generator=generator,
134
+ )
135
+ images.append(out.images[0])
136
 
137
  return images, seed
138
 
139
 
140
+ # -----------------------------
141
+ # UI
142
+ # -----------------------------
143
+ with gr.Blocks(title="RuangAI – Product Visualizer CPU") as demo:
144
+ gr.Markdown(
145
+ """
146
+ # 🧴 RuangAI – Product Visualizer (CPU Mode)
147
+
148
+ - **Text to Image**: buat visual produk dari deskripsi
149
+ - **Image to Image**: upload foto produk lalu buat versi promosi
150
+ - Pilih **gaya visual** dan **kategori produk**
151
+ - Gaya **Model Talent** akan menambahkan visualisasi seorang model di hasil gambar
152
+ """
153
+ )
154
+
155
+ mode = gr.Radio(
156
+ ["Text to Image", "Image to Image"],
157
+ value="Text to Image",
158
+ label="Mode",
159
+ )
160
 
161
  with gr.Row():
162
+ category = gr.Dropdown(
163
+ ["Umum", "Skincare", "Makanan/Minuman", "Fashion", "Elektronik"],
164
+ value="Umum",
165
+ label="Kategori Produk",
166
+ )
167
+ auto_btn = gr.Button("Auto Prompt ✨")
168
+
169
+ prompt = gr.Textbox(
170
+ label="Prompt",
171
+ placeholder="Deskripsi produk / ide visual...",
172
+ lines=3,
173
+ )
174
+
175
+ auto_btn.click(auto_prompt, inputs=[category], outputs=[prompt])
176
+
177
+ init_image = gr.Image(
178
+ label="Upload Gambar (untuk Image to Image)",
179
+ type="pil",
180
+ )
181
 
182
  with gr.Row():
183
  style = gr.Dropdown(
184
+ ["Tanpa gaya", "Studio", "E-commerce", "Pastel", "Lifestyle", "Model Talent"],
185
  value="Studio",
186
+ label="Gaya visual",
187
+ )
188
+ num_images = gr.Slider(
189
+ 1, 4, value=1, step=1, label="Jumlah gambar"
190
  )
 
191
 
192
+ gallery = gr.Gallery(
193
+ label="Hasil",
194
+ columns=2,
195
+ height=512,
196
+ )
197
 
198
  with gr.Accordion("Advanced Settings", open=False):
199
+ negative_prompt = gr.Textbox(
200
+ label="Negative prompt",
201
+ placeholder="Contoh: blur, low quality, watermark, text, logo",
202
+ )
203
+ seed = gr.Slider(
204
+ 0, MAX_SEED, value=0, step=1, label="Seed"
205
+ )
206
+ randomize_seed = gr.Checkbox(
207
+ True, label="Randomize seed"
208
+ )
209
+ width = gr.Slider(
210
+ 256, 768, value=512, step=32, label="Width"
211
+ )
212
+ height = gr.Slider(
213
+ 256, 768, value=512, step=32, label="Height"
214
+ )
215
+ guidance_scale = gr.Slider(
216
+ 0, 10, value=7, step=0.5, label="Guidance"
217
+ )
218
+ steps = gr.Slider(
219
+ 5, 40, value=25, step=1, label="Steps"
220
+ )
221
+ strength = gr.Slider(
222
+ 0.1, 1.0, value=0.6, step=0.05, label="Strength (img2img)"
223
+ )
224
+
225
+ run_btn = gr.Button("Generate 🚀")
226
 
227
  run_btn.click(
228
+ generate,
229
  inputs=[
230
+ mode,
231
+ prompt,
232
+ negative_prompt,
233
+ seed,
234
+ randomize_seed,
235
+ width,
236
+ height,
237
+ guidance_scale,
238
+ steps,
239
+ style,
240
+ category,
241
+ num_images,
242
+ init_image,
243
+ strength,
244
  ],
245
+ outputs=[gallery, seed],
246
  )
247
 
248
+ if __name__ == "__main__":
249
+ demo.launch()