Zeph27 commited on
Commit
39887c3
·
1 Parent(s): f1ca872
Files changed (11) hide show
  1. Task1-2.zip +3 -0
  2. app-v1.py +307 -0
  3. app.py +94 -32
  4. image_filenames.py +27 -0
  5. image_filenames.txt +120 -0
  6. output.png +0 -0
  7. pixel_border.py +3 -3
  8. requirements.txt +2 -1
  9. slider.py +24 -0
  10. stample.png +0 -0
  11. test.py +43 -0
Task1-2.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:98299bfa9112b782fa4d66e06930e89e54930a8cd937ffd59e578909af2dde2e
3
+ size 625294
app-v1.py ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import zipfile
3
+ import shutil
4
+ import time
5
+ from PIL import Image
6
+ import io
7
+ from rembg import remove
8
+ import gradio as gr
9
+ from concurrent.futures import ThreadPoolExecutor
10
+ from transformers import pipeline
11
+
12
+ def colors_within_tolerance(color1, color2, tolerance):
13
+ return all(abs(c1 - c2) <= tolerance for c1, c2 in zip(color1, color2))
14
+
15
+ def check_border_colors(image_path, tolerance):
16
+ image = Image.open(image_path)
17
+ pixels = image.load()
18
+
19
+ width, height = image.size
20
+
21
+ left_border_color = pixels[0, 0]
22
+ right_border_color = pixels[width - 1, 0]
23
+
24
+ for y in range(height):
25
+ if not colors_within_tolerance(pixels[0, y], left_border_color, tolerance):
26
+ return False
27
+ if not colors_within_tolerance(pixels[width - 1, y], right_border_color, tolerance):
28
+ return False
29
+
30
+ return True
31
+
32
+ def resize_and_crop_image(image_path, target_size=(1080, 1080), crop_mode='center'):
33
+ print(f"Resizing and cropping image: {image_path}")
34
+ with Image.open(image_path) as img:
35
+ width, height = img.size
36
+ print(f"Original image size: {width}x{height}")
37
+
38
+ scaling_factor = max(target_size[0] / width, target_size[1] / height)
39
+
40
+ new_size = (int(width * scaling_factor), int(height * scaling_factor))
41
+ resized_img = img.resize(new_size, Image.LANCZOS)
42
+ print(f"Resized image size: {new_size}")
43
+
44
+ if crop_mode == 'center':
45
+ left = (resized_img.width - target_size[0]) / 2
46
+ top = (resized_img.height - target_size[1]) / 2
47
+ elif crop_mode == 'top':
48
+ left = (resized_img.width - target_size[0]) / 2
49
+ top = 0
50
+ elif crop_mode == 'bottom':
51
+ left = (resized_img.width - target_size[0]) / 2
52
+ top = resized_img.height - target_size[1]
53
+ elif crop_mode == 'left':
54
+ left = 0
55
+ top = (resized_img.height - target_size[1]) / 2
56
+ elif crop_mode == 'right':
57
+ left = resized_img.width - target_size[0]
58
+ top = (resized_img.height - target_size[1]) / 2
59
+
60
+ right = left + target_size[0]
61
+ bottom = top + target_size[1]
62
+
63
+ cropped_img = resized_img.crop((left, top, right, bottom))
64
+ print(f"Cropped image size: {cropped_img.size}")
65
+
66
+ return cropped_img
67
+
68
+ def remove_background_rembg(input_path):
69
+ print(f"Removing background using rembg for image: {input_path}")
70
+ with open(input_path, 'rb') as i:
71
+ input_image = i.read()
72
+ output_image = remove(input_image)
73
+ img = Image.open(io.BytesIO(output_image)).convert("RGBA")
74
+ return img
75
+
76
+ def remove_background_bria(input_path):
77
+ print(f"Removing background using bria for image: {input_path}")
78
+ pipe = pipeline("image-segmentation", model="briaai/RMBG-1.4", trust_remote_code=True, device=0)
79
+ pillow_image = pipe(input_path)
80
+ return pillow_image
81
+
82
+ def process_single_image(image_path, output_folder, crop_mode, bg_method, output_format, bg_choice, custom_color, watermark_path=None):
83
+ filename = os.path.basename(image_path)
84
+ try:
85
+ print(f"Processing image: {filename}")
86
+ if bg_method == 'rembg':
87
+ image_with_no_bg = remove_background_rembg(image_path)
88
+ elif bg_method == 'bria':
89
+ image_with_no_bg = remove_background_bria(image_path)
90
+
91
+ temp_image_path = os.path.join(output_folder, f"temp_{filename}")
92
+ image_with_no_bg.save(temp_image_path, format='PNG')
93
+
94
+ if check_border_colors(temp_image_path, tolerance=50):
95
+ print(f"Border colors are the same for image: {filename}")
96
+ if bg_choice == 'transparent':
97
+ new_image = Image.new("RGBA", (1080, 1080), (255, 255, 255, 0))
98
+ else:
99
+ new_image = Image.new("RGBA", (1080, 1080), custom_color)
100
+
101
+ width, height = image_with_no_bg.size
102
+ scaling_factor = min(1080 / width, 1080 / height)
103
+ new_size = (int(width * scaling_factor), int(height * scaling_factor))
104
+ resized_img = image_with_no_bg.resize(new_size, Image.LANCZOS)
105
+ print(f"Resized image size: {new_size}")
106
+ new_image.paste(resized_img, ((1080 - resized_img.width) // 2, (1080 - resized_img.height) // 2))
107
+ else:
108
+ print(f"Border colors are different for image: {filename}")
109
+ new_image = resize_and_crop_image(temp_image_path, crop_mode=crop_mode)
110
+
111
+ if bg_choice == 'white':
112
+ new_image = new_image.convert("RGBA")
113
+ white_bg = Image.new("RGBA", new_image.size, "WHITE")
114
+ new_image = Image.alpha_composite(white_bg, new_image)
115
+ elif bg_choice == 'custom':
116
+ new_image = new_image.convert("RGBA")
117
+ custom_bg = Image.new("RGBA", new_image.size, custom_color)
118
+ new_image = Image.alpha_composite(custom_bg, new_image)
119
+
120
+ images_paths = []
121
+
122
+ output_ext = 'jpg' if output_format == 'JPG' else 'png'
123
+ output_path_without_watermark = os.path.join(output_folder, f"without_watermark_{os.path.splitext(filename)[0]}.{output_ext}")
124
+ if output_format == 'JPG':
125
+ new_image.convert('RGB').save(output_path_without_watermark, format='JPEG')
126
+ else:
127
+ new_image.save(output_path_without_watermark, format='PNG')
128
+ images_paths.append((output_path_without_watermark, image_path))
129
+
130
+ if watermark_path:
131
+ watermark = Image.open(watermark_path).convert("RGBA")
132
+ new_image_with_watermark = new_image.copy()
133
+ new_image_with_watermark.paste(watermark, (0, 0), watermark)
134
+ output_path_with_watermark = os.path.join(output_folder, f"with_watermark_{os.path.splitext(filename)[0]}.{output_ext}")
135
+ if output_format == 'JPG':
136
+ new_image_with_watermark.convert('RGB').save(output_path_with_watermark, format='JPEG')
137
+ else:
138
+ new_image_with_watermark.save(output_path_with_watermark, format='PNG')
139
+ images_paths.append((output_path_with_watermark, image_path))
140
+
141
+ os.remove(temp_image_path)
142
+
143
+ print(f"Processed image paths: {images_paths}")
144
+ return images_paths
145
+
146
+ except Exception as e:
147
+ print(f"Error processing {filename}: {e}")
148
+ return None
149
+
150
+ def process_images(input_files, crop_mode='center', bg_method='rembg', watermark_path=None, output_format='PNG', bg_choice='transparent', custom_color="#ffffff", num_workers=4, progress=gr.Progress()):
151
+ start_time = time.time()
152
+
153
+ output_folder = "temp_output"
154
+ if os.path.exists(output_folder):
155
+ shutil.rmtree(output_folder)
156
+ os.makedirs(output_folder)
157
+
158
+ processed_images = []
159
+ original_images = []
160
+
161
+ if isinstance(input_files, str) and input_files.lower().endswith(('.zip', '.rar')):
162
+ input_folder = "temp_input"
163
+ if os.path.exists(input_folder):
164
+ shutil.rmtree(input_folder)
165
+ os.makedirs(input_folder)
166
+
167
+ try:
168
+ with zipfile.ZipFile(input_files, 'r') as zip_ref:
169
+ zip_ref.extractall(input_folder)
170
+ except zipfile.BadZipFile as e:
171
+ print(f"Error extracting zip file: {e}")
172
+ return [], None, 0
173
+
174
+ image_files = [os.path.join(input_folder, f) for f in os.listdir(input_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'))]
175
+ else:
176
+ image_files = [f.name for f in input_files]
177
+
178
+ total_images = len(image_files)
179
+ print(f"Total images to process: {total_images}")
180
+
181
+ avg_processing_time = 0
182
+ with ThreadPoolExecutor(max_workers=num_workers) as executor:
183
+ future_to_image = {executor.submit(process_single_image, image_path, output_folder, crop_mode, bg_method, output_format, bg_choice, custom_color, watermark_path): image_path for image_path in image_files}
184
+ for idx, future in enumerate(future_to_image):
185
+ try:
186
+ start_time_image = time.time()
187
+ result = future.result()
188
+ end_time_image = time.time()
189
+ image_processing_time = end_time_image - start_time_image
190
+
191
+ # Update average processing time
192
+ avg_processing_time = (avg_processing_time * idx + image_processing_time) / (idx + 1)
193
+
194
+ if result:
195
+ processed_images.extend(result)
196
+ original_images.append(future_to_image[future])
197
+
198
+ # Estimate remaining time
199
+ remaining_images = total_images - (idx + 1)
200
+ estimated_remaining_time = remaining_images * avg_processing_time
201
+
202
+ progress((idx + 1) / total_images, f"{idx + 1}/{total_images} images processed. Estimated time remaining: {estimated_remaining_time:.2f} seconds")
203
+ except Exception as e:
204
+ print(f"Error processing image {future_to_image[future]}: {e}")
205
+
206
+ output_zip_path = "processed_images.zip"
207
+ with zipfile.ZipFile(output_zip_path, 'w') as zipf:
208
+ for file, _ in processed_images:
209
+ if "with_watermark" in file:
210
+ zipf.write(file, os.path.join("with_watermark", os.path.basename(file)))
211
+ else:
212
+ zipf.write(file, os.path.join("without_watermark", os.path.basename(file)))
213
+
214
+ end_time = time.time()
215
+ processing_time = end_time - start_time
216
+ print(f"Processing time: {processing_time} seconds")
217
+
218
+ return original_images, processed_images, output_zip_path, processing_time
219
+
220
+ def gradio_interface(input_type, input_files, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers):
221
+ progress = gr.Progress()
222
+ watermark_path = watermark.name if watermark else None
223
+
224
+ if input_type == "zip_rar":
225
+ return process_images(input_files.name, crop_mode, bg_method, watermark_path, output_format, bg_choice, custom_color, num_workers, progress)
226
+ else:
227
+ return process_images(input_files, crop_mode, bg_method, watermark_path, output_format, bg_choice, custom_color, num_workers, progress)
228
+
229
+ def show_color_picker(bg_choice):
230
+ if bg_choice == 'custom':
231
+ return gr.update(visible=True)
232
+ return gr.update(visible=False)
233
+
234
+ def update_slider(evt: gr.SelectData):
235
+ if isinstance(evt.value, dict) and 'caption' in evt.value:
236
+ input_path = evt.value['caption']
237
+ output_path = evt.value['image']['path']
238
+ input_path = input_path.split("Input: ")[-1]
239
+
240
+ # Open the original and processed images
241
+ original_img = Image.open(input_path)
242
+ processed_img = Image.open(output_path)
243
+
244
+ # Calculate the aspect ratios
245
+ original_ratio = f"{original_img.width}x{original_img.height}"
246
+ processed_ratio = f"{processed_img.width}x{processed_img.height}"
247
+
248
+ return gr.update(value=input_path), gr.update(value=output_path), gr.update(value=original_ratio), gr.update(value=processed_ratio)
249
+ else:
250
+ print("No caption found in selection")
251
+ return gr.update(value=None), gr.update(value=None), gr.update(value=None), gr.update(value=None)
252
+
253
+ def process(input_type, input_files, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers):
254
+ _, processed_images, zip_path, time_taken = gradio_interface(input_type, input_files, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers)
255
+ processed_images_with_captions = [(img, f"Input: {caption}") for img, caption in processed_images]
256
+ return processed_images_with_captions, zip_path, f"{time_taken:.2f} seconds"
257
+
258
+ def update_input_type(choice):
259
+ if choice == "zip_rar":
260
+ return gr.update(visible=True), gr.update(visible=False)
261
+ else:
262
+ return gr.update(visible=False), gr.update(visible=True)
263
+
264
+ with gr.Blocks() as iface:
265
+ gr.Markdown("# Image Background Removal and Resizing with Optional Watermark")
266
+ gr.Markdown("Choose to upload multiple images or a ZIP/RAR file, select the crop mode, optionally upload a watermark image, and choose the output format.")
267
+
268
+ input_type = gr.Radio(choices=["multiple_images", "zip_rar"], label="Input Type", value="multiple_images")
269
+
270
+ with gr.Row():
271
+ zip_file = gr.File(label="Upload ZIP/RAR file of images", file_types=[".zip", ".rar"], visible=False)
272
+ multiple_images = gr.File(label="Upload multiple images", file_types=["image"], file_count="multiple")
273
+
274
+ watermark = gr.File(label="Upload Watermark Image (Optional)", file_types=[".png"])
275
+
276
+ with gr.Row():
277
+ crop_mode = gr.Radio(choices=["center", "top", "bottom", "left", "right"], label="Crop Mode", value="center")
278
+ output_format = gr.Radio(choices=["PNG", "JPG"], label="Output Format", value="JPG")
279
+ num_workers = gr.Slider(minimum=1, maximum=16, step=1, label="Number of Workers", value=5)
280
+
281
+ with gr.Row():
282
+ bg_method = gr.Radio(choices=["bria", "rembg"], label="Background Removal Method", value="bria")
283
+ bg_choice = gr.Radio(choices=["transparent", "white", "custom"], label="Background Choice", value="white")
284
+ custom_color = gr.ColorPicker(label="Custom Background Color", value="#ffffff", visible=False)
285
+
286
+ with gr.Row():
287
+ gallery_processed = gr.Gallery(label="Processed Images")
288
+ with gr.Row():
289
+ image_original = gr.Image(label="Original Images", interactive=False)
290
+ image_processed = gr.Image(label="Processed Images", interactive=False)
291
+ with gr.Row():
292
+ original_ratio = gr.Textbox(label="Original Ratio")
293
+ processed_ratio = gr.Textbox(label="Processed Ratio")
294
+ with gr.Row():
295
+ output_zip = gr.File(label="Download Processed Images as ZIP")
296
+ processing_time = gr.Textbox(label="Processing Time (seconds)")
297
+
298
+ input_type.change(update_input_type, inputs=input_type, outputs=[zip_file, multiple_images])
299
+
300
+ bg_choice.change(show_color_picker, inputs=bg_choice, outputs=custom_color)
301
+
302
+ process_button = gr.Button("Process Images")
303
+ process_button.click(process, inputs=[input_type, multiple_images, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers], outputs=[gallery_processed, output_zip, processing_time])
304
+
305
+ gallery_processed.select(update_slider, outputs=[image_original, image_processed, original_ratio, processed_ratio])
306
+
307
+ iface.launch()
app.py CHANGED
@@ -75,7 +75,7 @@ def remove_background_rembg(input_path):
75
 
76
  def remove_background_bria(input_path):
77
  print(f"Removing background using bria for image: {input_path}")
78
- pipe = pipeline("image-segmentation", model="briaai/RMBG-1.4", trust_remote_code=True)
79
  pillow_image = pipe(input_path)
80
  return pillow_image
81
 
@@ -125,7 +125,7 @@ def process_single_image(image_path, output_folder, crop_mode, bg_method, output
125
  new_image.convert('RGB').save(output_path_without_watermark, format='JPEG')
126
  else:
127
  new_image.save(output_path_without_watermark, format='PNG')
128
- images_paths.append(output_path_without_watermark)
129
 
130
  if watermark_path:
131
  watermark = Image.open(watermark_path).convert("RGBA")
@@ -136,7 +136,7 @@ def process_single_image(image_path, output_folder, crop_mode, bg_method, output
136
  new_image_with_watermark.convert('RGB').save(output_path_with_watermark, format='JPEG')
137
  else:
138
  new_image_with_watermark.save(output_path_with_watermark, format='PNG')
139
- images_paths.append(output_path_with_watermark)
140
 
141
  os.remove(temp_image_path)
142
 
@@ -147,46 +147,65 @@ def process_single_image(image_path, output_folder, crop_mode, bg_method, output
147
  print(f"Error processing {filename}: {e}")
148
  return None
149
 
150
- def process_images(zip_file, crop_mode='center', bg_method='rembg', watermark_path=None, output_format='PNG', bg_choice='transparent', custom_color="#ffffff", num_workers=4, progress=gr.Progress()):
151
  start_time = time.time()
152
 
153
- input_folder = "temp_input"
154
  output_folder = "temp_output"
155
- if os.path.exists(input_folder):
156
- shutil.rmtree(input_folder)
157
  if os.path.exists(output_folder):
158
  shutil.rmtree(output_folder)
159
- os.makedirs(input_folder)
160
  os.makedirs(output_folder)
161
 
162
- try:
163
- with zipfile.ZipFile(zip_file, 'r') as zip_ref:
164
- zip_ref.extractall(input_folder)
165
- except zipfile.BadZipFile as e:
166
- print(f"Error extracting zip file: {e}")
167
- return [], None, 0
168
-
169
  processed_images = []
170
  original_images = []
171
- image_files = [os.path.join(input_folder, f) for f in os.listdir(input_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  total_images = len(image_files)
173
  print(f"Total images to process: {total_images}")
174
 
 
175
  with ThreadPoolExecutor(max_workers=num_workers) as executor:
176
  future_to_image = {executor.submit(process_single_image, image_path, output_folder, crop_mode, bg_method, output_format, bg_choice, custom_color, watermark_path): image_path for image_path in image_files}
177
  for idx, future in enumerate(future_to_image):
178
  try:
 
179
  result = future.result()
 
 
 
 
 
 
180
  if result:
181
  processed_images.extend(result)
182
  original_images.append(future_to_image[future])
 
 
 
 
 
 
183
  except Exception as e:
184
  print(f"Error processing image {future_to_image[future]}: {e}")
185
- progress((idx + 1) / total_images, f"{idx + 1}/{total_images} images processed")
186
 
187
  output_zip_path = "processed_images.zip"
188
  with zipfile.ZipFile(output_zip_path, 'w') as zipf:
189
- for file in processed_images:
190
  if "with_watermark" in file:
191
  zipf.write(file, os.path.join("with_watermark", os.path.basename(file)))
192
  else:
@@ -198,48 +217,91 @@ def process_images(zip_file, crop_mode='center', bg_method='rembg', watermark_pa
198
 
199
  return original_images, processed_images, output_zip_path, processing_time
200
 
201
- def gradio_interface(zip_file, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers):
202
  progress = gr.Progress()
203
  watermark_path = watermark.name if watermark else None
204
- return process_images(zip_file.name, crop_mode, bg_method, watermark_path, output_format, bg_choice, custom_color, num_workers, progress)
 
 
 
 
205
 
206
  def show_color_picker(bg_choice):
207
  if bg_choice == 'custom':
208
  return gr.update(visible=True)
209
  return gr.update(visible=False)
210
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  with gr.Blocks() as iface:
212
  gr.Markdown("# Image Background Removal and Resizing with Optional Watermark")
213
- gr.Markdown("Upload a ZIP or RAR file containing images, choose the crop mode, optionally upload a watermark image, and select the output format.")
214
 
 
 
215
  with gr.Row():
216
- zip_file = gr.File(label="Upload ZIP/RAR file of images", file_types=[".zip", ".rar"])
217
- watermark = gr.File(label="Upload Watermark Image (Optional)", file_types=[".png"])
 
 
218
 
219
  with gr.Row():
220
  crop_mode = gr.Radio(choices=["center", "top", "bottom", "left", "right"], label="Crop Mode", value="center")
221
- output_format = gr.Radio(choices=["PNG", "JPG"], label="Output Format", value="PNG")
222
- num_workers = gr.Slider(minimum=1, maximum=16, step=1, label="Number of Workers", value=2)
223
 
224
  with gr.Row():
225
  bg_method = gr.Radio(choices=["bria", "rembg"], label="Background Removal Method", value="bria")
226
- bg_choice = gr.Radio(choices=["transparent", "white", "custom"], label="Background Choice", value="transparent")
227
  custom_color = gr.ColorPicker(label="Custom Background Color", value="#ffffff", visible=False)
228
 
229
  with gr.Row():
230
- gallery_original = gr.Gallery(label="Original Images")
231
  gallery_processed = gr.Gallery(label="Processed Images")
 
 
 
 
 
 
232
  with gr.Row():
233
  output_zip = gr.File(label="Download Processed Images as ZIP")
234
  processing_time = gr.Textbox(label="Processing Time (seconds)")
235
 
236
- bg_choice.change(show_color_picker, inputs=bg_choice, outputs=custom_color)
237
 
238
- def process(zip_file, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers):
239
- original_images, processed_images, zip_path, time_taken = gradio_interface(zip_file, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers)
240
- return original_images, processed_images, zip_path, f"{time_taken:.2f} seconds"
241
 
242
  process_button = gr.Button("Process Images")
243
- process_button.click(process, inputs=[zip_file, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers], outputs=[gallery_original, gallery_processed, output_zip, processing_time])
 
 
244
 
245
  iface.launch()
 
75
 
76
  def remove_background_bria(input_path):
77
  print(f"Removing background using bria for image: {input_path}")
78
+ pipe = pipeline("image-segmentation", model="briaai/RMBG-1.4", trust_remote_code=True, device=0)
79
  pillow_image = pipe(input_path)
80
  return pillow_image
81
 
 
125
  new_image.convert('RGB').save(output_path_without_watermark, format='JPEG')
126
  else:
127
  new_image.save(output_path_without_watermark, format='PNG')
128
+ images_paths.append((output_path_without_watermark, image_path))
129
 
130
  if watermark_path:
131
  watermark = Image.open(watermark_path).convert("RGBA")
 
136
  new_image_with_watermark.convert('RGB').save(output_path_with_watermark, format='JPEG')
137
  else:
138
  new_image_with_watermark.save(output_path_with_watermark, format='PNG')
139
+ images_paths.append((output_path_with_watermark, image_path))
140
 
141
  os.remove(temp_image_path)
142
 
 
147
  print(f"Error processing {filename}: {e}")
148
  return None
149
 
150
+ def process_images(input_files, crop_mode='center', bg_method='rembg', watermark_path=None, output_format='PNG', bg_choice='transparent', custom_color="#ffffff", num_workers=4, progress=gr.Progress()):
151
  start_time = time.time()
152
 
 
153
  output_folder = "temp_output"
 
 
154
  if os.path.exists(output_folder):
155
  shutil.rmtree(output_folder)
 
156
  os.makedirs(output_folder)
157
 
 
 
 
 
 
 
 
158
  processed_images = []
159
  original_images = []
160
+
161
+ if isinstance(input_files, str) and input_files.lower().endswith(('.zip', '.rar')):
162
+ input_folder = "temp_input"
163
+ if os.path.exists(input_folder):
164
+ shutil.rmtree(input_folder)
165
+ os.makedirs(input_folder)
166
+
167
+ try:
168
+ with zipfile.ZipFile(input_files, 'r') as zip_ref:
169
+ zip_ref.extractall(input_folder)
170
+ except zipfile.BadZipFile as e:
171
+ print(f"Error extracting zip file: {e}")
172
+ return [], None, 0
173
+
174
+ image_files = [os.path.join(input_folder, f) for f in os.listdir(input_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'))]
175
+ else:
176
+ image_files = [f.name for f in input_files]
177
+
178
  total_images = len(image_files)
179
  print(f"Total images to process: {total_images}")
180
 
181
+ avg_processing_time = 0
182
  with ThreadPoolExecutor(max_workers=num_workers) as executor:
183
  future_to_image = {executor.submit(process_single_image, image_path, output_folder, crop_mode, bg_method, output_format, bg_choice, custom_color, watermark_path): image_path for image_path in image_files}
184
  for idx, future in enumerate(future_to_image):
185
  try:
186
+ start_time_image = time.time()
187
  result = future.result()
188
+ end_time_image = time.time()
189
+ image_processing_time = end_time_image - start_time_image
190
+
191
+ # Update average processing time
192
+ avg_processing_time = (avg_processing_time * idx + image_processing_time) / (idx + 1)
193
+
194
  if result:
195
  processed_images.extend(result)
196
  original_images.append(future_to_image[future])
197
+
198
+ # Estimate remaining time
199
+ remaining_images = total_images - (idx + 1)
200
+ estimated_remaining_time = remaining_images * avg_processing_time
201
+
202
+ progress((idx + 1) / total_images, f"{idx + 1}/{total_images} images processed. Estimated time remaining: {estimated_remaining_time:.2f} seconds")
203
  except Exception as e:
204
  print(f"Error processing image {future_to_image[future]}: {e}")
 
205
 
206
  output_zip_path = "processed_images.zip"
207
  with zipfile.ZipFile(output_zip_path, 'w') as zipf:
208
+ for file, _ in processed_images:
209
  if "with_watermark" in file:
210
  zipf.write(file, os.path.join("with_watermark", os.path.basename(file)))
211
  else:
 
217
 
218
  return original_images, processed_images, output_zip_path, processing_time
219
 
220
+ def gradio_interface(input_type, input_files, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers):
221
  progress = gr.Progress()
222
  watermark_path = watermark.name if watermark else None
223
+
224
+ if input_type == "zip_rar":
225
+ return process_images(input_files.name, crop_mode, bg_method, watermark_path, output_format, bg_choice, custom_color, num_workers, progress)
226
+ else:
227
+ return process_images(input_files, crop_mode, bg_method, watermark_path, output_format, bg_choice, custom_color, num_workers, progress)
228
 
229
  def show_color_picker(bg_choice):
230
  if bg_choice == 'custom':
231
  return gr.update(visible=True)
232
  return gr.update(visible=False)
233
 
234
+ def update_slider(evt: gr.SelectData):
235
+ if isinstance(evt.value, dict) and 'caption' in evt.value:
236
+ input_path = evt.value['caption']
237
+ output_path = evt.value['image']['path']
238
+ input_path = input_path.split("Input: ")[-1]
239
+
240
+ # Open the original and processed images
241
+ original_img = Image.open(input_path)
242
+ processed_img = Image.open(output_path)
243
+
244
+ # Calculate the aspect ratios
245
+ original_ratio = f"{original_img.width}x{original_img.height}"
246
+ processed_ratio = f"{processed_img.width}x{processed_img.height}"
247
+
248
+ return gr.update(value=input_path), gr.update(value=output_path), gr.update(value=original_ratio), gr.update(value=processed_ratio)
249
+ else:
250
+ print("No caption found in selection")
251
+ return gr.update(value=None), gr.update(value=None), gr.update(value=None), gr.update(value=None)
252
+
253
+ def process(input_type, input_files, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers):
254
+ _, processed_images, zip_path, time_taken = gradio_interface(input_type, input_files, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers)
255
+ processed_images_with_captions = [(img, f"Input: {caption}") for img, caption in processed_images]
256
+ return processed_images_with_captions, zip_path, f"{time_taken:.2f} seconds"
257
+
258
+ def update_input_type(choice):
259
+ if choice == "zip_rar":
260
+ return gr.update(visible=True), gr.update(visible=False)
261
+ else:
262
+ return gr.update(visible=False), gr.update(visible=True)
263
+
264
  with gr.Blocks() as iface:
265
  gr.Markdown("# Image Background Removal and Resizing with Optional Watermark")
266
+ gr.Markdown("Choose to upload multiple images or a ZIP/RAR file, select the crop mode, optionally upload a watermark image, and choose the output format.")
267
 
268
+ input_type = gr.Radio(choices=["multiple_images", "zip_rar"], label="Input Type", value="multiple_images")
269
+
270
  with gr.Row():
271
+ zip_file = gr.File(label="Upload ZIP/RAR file of images", file_types=[".zip", ".rar"], visible=False)
272
+ multiple_images = gr.File(label="Upload multiple images", file_types=["image"], file_count="multiple")
273
+
274
+ watermark = gr.File(label="Upload Watermark Image (Optional)", file_types=[".png"])
275
 
276
  with gr.Row():
277
  crop_mode = gr.Radio(choices=["center", "top", "bottom", "left", "right"], label="Crop Mode", value="center")
278
+ output_format = gr.Radio(choices=["PNG", "JPG"], label="Output Format", value="JPG")
279
+ num_workers = gr.Slider(minimum=1, maximum=16, step=1, label="Number of Workers", value=5)
280
 
281
  with gr.Row():
282
  bg_method = gr.Radio(choices=["bria", "rembg"], label="Background Removal Method", value="bria")
283
+ bg_choice = gr.Radio(choices=["transparent", "white", "custom"], label="Background Choice", value="white")
284
  custom_color = gr.ColorPicker(label="Custom Background Color", value="#ffffff", visible=False)
285
 
286
  with gr.Row():
 
287
  gallery_processed = gr.Gallery(label="Processed Images")
288
+ with gr.Row():
289
+ image_original = gr.Image(label="Original Images", interactive=False)
290
+ image_processed = gr.Image(label="Processed Images", interactive=False)
291
+ with gr.Row():
292
+ original_ratio = gr.Textbox(label="Original Ratio")
293
+ processed_ratio = gr.Textbox(label="Processed Ratio")
294
  with gr.Row():
295
  output_zip = gr.File(label="Download Processed Images as ZIP")
296
  processing_time = gr.Textbox(label="Processing Time (seconds)")
297
 
298
+ input_type.change(update_input_type, inputs=input_type, outputs=[zip_file, multiple_images])
299
 
300
+ bg_choice.change(show_color_picker, inputs=bg_choice, outputs=custom_color)
 
 
301
 
302
  process_button = gr.Button("Process Images")
303
+ process_button.click(process, inputs=[input_type, multiple_images, crop_mode, bg_method, watermark, output_format, bg_choice, custom_color, num_workers], outputs=[gallery_processed, output_zip, processing_time])
304
+
305
+ gallery_processed.select(update_slider, outputs=[image_original, image_processed, original_ratio, processed_ratio])
306
 
307
  iface.launch()
image_filenames.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import glob
3
+
4
+ def get_image_filenames(folder_path, output_file):
5
+ # Define the image file extensions you want to include
6
+ image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.gif', '*.bmp', '*.tiff']
7
+
8
+ # Create an empty list to store filenames
9
+ image_filenames = []
10
+
11
+ # Iterate over each extension and gather the filenames
12
+ for extension in image_extensions:
13
+ image_filenames.extend(glob.glob(os.path.join(folder_path, extension)))
14
+
15
+ # Write the filenames to the output file
16
+ with open(output_file, 'w') as file:
17
+ for filename in image_filenames:
18
+ file.write(os.path.basename(filename) + '\n')
19
+
20
+ # Specify the folder containing images and the output text file
21
+ folder_path = 'D:\Ardha\Kerja\AISensum\ROX\Input\Task 1'
22
+ output_file = 'image_filenames.txt'
23
+
24
+ # Call the function to get image filenames and save them to a text file
25
+ get_image_filenames(folder_path, output_file)
26
+
27
+ print(f"Image filenames have been saved to {output_file}")
image_filenames.txt ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1000416735_01.jpg
2
+ 1000416735_02.jpg
3
+ 1000416735_03.jpg
4
+ 1000416735_04.jpg
5
+ 1000448771_01.jpg
6
+ 1000448771_02.jpg
7
+ 1000448771_03.jpg
8
+ 1000485022_01.jpg
9
+ 1000485022_02.jpg
10
+ 1000485022_03.jpg
11
+ 1000485026_01.jpg
12
+ 1000485026_02.jpg
13
+ 1000485030_01.jpg
14
+ 1000485030_02.jpg
15
+ 1000485030_03.jpg
16
+ 1000485035_01.jpg
17
+ 1000485035_02.jpg
18
+ 1000485035_03.jpg
19
+ 1000485063_01.jpg
20
+ 1000485063_02.jpg
21
+ 1000485063_03.jpg
22
+ 1000485080_01.jpg
23
+ 1000485080_02.jpg
24
+ 1000485080_03.jpg
25
+ 1000485080_04.jpg
26
+ 1000485101_01.jpg
27
+ 1000485101_02.jpg
28
+ 1000485101_03.jpg
29
+ 1000485101_04.jpg
30
+ 1000485116_01.jpg
31
+ 1000485116_02.jpg
32
+ 1000485116_03.jpg
33
+ 1000485116_04.jpg
34
+ 1000485119_01.jpg
35
+ 1000485119_02.jpg
36
+ 1000485119_03.jpg
37
+ 1000485119_04.jpg
38
+ 1000485122_01.jpg
39
+ 1000485122_02.jpg
40
+ 1000485122_03.jpg
41
+ 1000485125_01.jpg
42
+ 1000485125_02.jpg
43
+ 1000485125_03.jpg
44
+ 1000485125_04.jpg
45
+ 1000485159_01.jpg
46
+ 1000485159_02.jpg
47
+ 1000485159_03.jpg
48
+ 1000485159_04.jpg
49
+ 1000485162_01.jpg
50
+ 1000485162_02.jpg
51
+ 1000485162_03.jpg
52
+ 1000485162_04.jpg
53
+ 1000485165_01.jpg
54
+ 1000485165_02.jpg
55
+ 1000485165_03.jpg
56
+ 1000485168_01.jpg
57
+ 1000485168_02.jpg
58
+ 1000485168_03.jpg
59
+ 1000485171_01.jpg
60
+ 1000485171_02.jpg
61
+ 1000485171_03.jpg
62
+ 1000485383_01.jpg
63
+ 1000485383_02.jpg
64
+ 1000485383_03.jpg
65
+ 1000485417_01.jpg
66
+ 1000485417_02.jpg
67
+ 1000485417_03.jpg
68
+ 1000485428_01.jpg
69
+ 1000485428_02.jpg
70
+ 1000485428_03.jpg
71
+ 1000485521_01.jpg
72
+ 1000485521_02.jpg
73
+ 1000485521_03.jpg
74
+ 1000485531_01.jpg
75
+ 1000485531_02.jpg
76
+ 1000485531_03.jpg
77
+ 1000485551_01.jpg
78
+ 1000485551_02.jpg
79
+ 1000485551_03.jpg
80
+ 1000485665_01.jpg
81
+ 1000485665_02.jpg
82
+ 1000485665_03.jpg
83
+ 1000485665_04.jpg
84
+ 1000485737_01.jpg
85
+ 1000485737_02.jpg
86
+ 1000485737_03.jpg
87
+ 1000485764_01.jpg
88
+ 1000485764_02.jpg
89
+ 1000485764_03.jpg
90
+ 1000485780_01.jpg
91
+ 1000485780_02.jpg
92
+ 1000485780_03.jpg
93
+ 1000485788_01.jpg
94
+ 1000485788_02.jpg
95
+ 1000485788_03.jpg
96
+ 1000485791_01.jpg
97
+ 1000485791_02.jpg
98
+ 1000485791_03.jpg
99
+ 1000485791_04.jpg
100
+ 1000485795_01.jpg
101
+ 1000485795_02.jpg
102
+ 1000485795_03.jpg
103
+ 1000485795_04.jpg
104
+ 1000485799_01.jpg
105
+ 1000485799_02.jpg
106
+ 1000485799_03.jpg
107
+ 1000485799_04.jpg
108
+ 1000485799_05.jpg
109
+ 1000485831_01.jpg
110
+ 1000485831_02.jpg
111
+ 1000485831_03.jpg
112
+ 1000485831_04.jpg
113
+ 1000485834_01.jpg
114
+ 1000485834_02.jpg
115
+ 1000485834_03.jpg
116
+ 1000485834_04.jpg
117
+ 1000485834_05.jpg
118
+ 1000485842_01.jpg
119
+ 1000485842_02.jpg
120
+ 1000485842_03.jpg
output.png ADDED
pixel_border.py CHANGED
@@ -42,9 +42,9 @@ def process_images(input_folder, output_folder_same, output_folder_different, to
42
  shutil.copy(image_path, os.path.join(output_folder_different, filename))
43
 
44
  # Example usage
45
- input_folder = 'D:\Ardha\Kerja\AISensum\ROX\Task 1'
46
- output_folder_same = 'D:\Ardha\Kerja\AISensum\ROX\Task 1\warna_sama'
47
- output_folder_different = 'D:\Ardha\Kerja\AISensum\ROX\Task 1\warna_berbeda'
48
  tolerance = 50 # Adjust the tolerance value as needed
49
 
50
  process_images(input_folder, output_folder_same, output_folder_different, tolerance)
 
42
  shutil.copy(image_path, os.path.join(output_folder_different, filename))
43
 
44
  # Example usage
45
+ input_folder = 'D:\Ardha\Kerja\AISensum\ROX\Input\Task 1'
46
+ output_folder_same = 'D:\Ardha\Kerja\AISensum\ROX\Input\Task 1\warna_sama'
47
+ output_folder_different = 'D:\Ardha\Kerja\AISensum\ROX\Input\Task 1\warna_berbeda'
48
  tolerance = 50 # Adjust the tolerance value as needed
49
 
50
  process_images(input_folder, output_folder_same, output_folder_different, tolerance)
requirements.txt CHANGED
@@ -7,4 +7,5 @@ numpy==1.26.4
7
  typing==3.7.4.3
8
  scikit-image==0.24.0
9
  huggingface_hub==0.23.4
10
- transformers==4.42.4
 
 
7
  typing==3.7.4.3
8
  scikit-image==0.24.0
9
  huggingface_hub==0.23.4
10
+ transformers==4.42.4
11
+ gradio_imageslider==0.0.20
slider.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from gradio_imageslider import ImageSlider
3
+
4
+ def compare_images(img1, img2):
5
+ if not img1 or not img2:
6
+ return None
7
+ return (img1, img2)
8
+
9
+ with gr.Blocks() as demo:
10
+ with gr.Group():
11
+ with gr.Row():
12
+ image_input1 = gr.Image(label="Upload Image 1", type="pil")
13
+ image_input2 = gr.Image(label="Upload Image 2", type="pil")
14
+
15
+ slider = ImageSlider(label="Compare Images", type="pil", slider_color="pink", width=600)
16
+
17
+ def update_slider(img1, img2):
18
+ return gr.update(value=(img1, img2))
19
+
20
+ image_input1.change(update_slider, inputs=[image_input1, image_input2], outputs=slider)
21
+ image_input2.change(update_slider, inputs=[image_input1, image_input2], outputs=slider)
22
+
23
+ if __name__ == "__main__":
24
+ demo.launch()
stample.png ADDED
test.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+
3
+ def remove_blank_zone(image_path, output_path):
4
+ image = Image.open(image_path)
5
+ image = image.convert("RGBA")
6
+
7
+ # Get the bounding box of the non-blank area
8
+ bbox = image.getbbox()
9
+
10
+ if bbox:
11
+ # Crop the image to the bounding box
12
+ image = image.crop(bbox)
13
+
14
+ # Calculate the new size to expand the image until one side touches the padding
15
+ padding = 125
16
+ target_size = 1080 - 2 * padding
17
+ aspect_ratio = image.width / image.height
18
+
19
+ if image.width > image.height:
20
+ new_width = target_size
21
+ new_height = int(target_size / aspect_ratio)
22
+ else:
23
+ new_height = target_size
24
+ new_width = int(target_size * aspect_ratio)
25
+
26
+ # Resize the image
27
+ image = image.resize((new_width, new_height), Image.LANCZOS)
28
+
29
+ # Create a new 1080x1080 canvas with a white background
30
+ canvas = Image.new("RGBA", (1080, 1080), (255, 255, 255, 255))
31
+
32
+ # Calculate the position to paste the resized image onto the canvas
33
+ x = (1080 - new_width) // 2
34
+ y = (1080 - new_height) // 2
35
+
36
+ # Paste the resized image onto the canvas
37
+ canvas.paste(image, (x, y), image)
38
+
39
+ # Save the final image
40
+ canvas.save(output_path)
41
+
42
+ # Example usage
43
+ remove_blank_zone("stample.png", "output.png")