devskale commited on
Commit
e997429
·
1 Parent(s): 8f00e6a

cropping update

Browse files
Files changed (2) hide show
  1. gradio_imager.py +1 -1
  2. image_processor.py +36 -166
gradio_imager.py CHANGED
@@ -201,7 +201,7 @@ with gr.Blocks(title="IMAGER ___ v0.2 Image Processing Tool") as demo:
201
  container=True
202
  )
203
  with gr.Row():
204
- crop = gr.Checkbox(label="Crop", container=True)
205
  remove_bg = gr.Checkbox(label="Remove Background", container=True)
206
 
207
  # Size and Background Settings
 
201
  container=True
202
  )
203
  with gr.Row():
204
+ crop = gr.Checkbox(label="Crop on Object", container=True)
205
  remove_bg = gr.Checkbox(label="Remove Background", container=True)
206
 
207
  # Size and Background Settings
image_processor.py CHANGED
@@ -44,6 +44,38 @@ def add_background(image, background, default_color="#FFFFFF"):
44
  return final_img
45
 
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  def autocrop_image(image):
48
  """
49
  Autocrops an image, focusing on the non-transparent pixels.
@@ -55,6 +87,7 @@ def autocrop_image(image):
55
  - PIL.Image.Image: The autocropped image.
56
  """
57
  bbox = image.getbbox()
 
58
  if bbox:
59
  return image.crop(bbox)
60
  return image
@@ -102,8 +135,10 @@ def process_image(img, crop=False, remove_bg=False, resize=None, padding=0, back
102
  if remove_bg:
103
  img = remove_bg_func(img)
104
 
105
- if crop:
106
  img = autocrop_image(img)
 
 
107
 
108
  if resize:
109
  img = resize_and_pad_image(img, resize, padding)
@@ -114,41 +149,6 @@ def process_image(img, crop=False, remove_bg=False, resize=None, padding=0, back
114
  return img
115
 
116
 
117
- def process_image2(image_data, crop=False, remove_bg=False, resize=None, padding=0, background=None):
118
- """
119
- Processes a single image based on the provided options.
120
-
121
- Args:
122
- - image_data (PIL.Image.Image): The input image.
123
- - crop (bool): Whether to autocrop the image.
124
- - remove_bg (bool): Whether to remove the background of the image.
125
- - resize (tuple): Optional dimensions (width, height) to resize the image.
126
- - padding (int): Number of padding pixels to add around the image.
127
- - background (str): Optional background color (hex code or name) or path to an image file to set as the background.
128
-
129
- Returns:
130
- - PIL.Image.Image: The processed image.
131
- """
132
- # Assume image_data is a PIL.Image.Image object
133
-
134
- if remove_bg:
135
- # Assuming remove_bg function returns a PIL image
136
- image_data = remove_bg_func(image_data)
137
-
138
- if crop:
139
- # Assuming autocrop_image function modifies the image in place or returns a new PIL image
140
- image_data = autocrop_image(image_data)
141
-
142
- if resize:
143
- # Assuming resize_and_pad_image function modifies the image in place or returns a new PIL image
144
- image_data = resize_and_pad_image(image_data, resize, padding)
145
-
146
- if background:
147
- # Assuming add_background function modifies the image in place or returns a new PIL image
148
- image_data = add_background(image_data, background)
149
-
150
- return image_data
151
-
152
 
153
  def resize_and_pad_image(image, dimensions, padding=0):
154
  """
@@ -235,47 +235,6 @@ def generate_output_filename(input_path, remove_bg=False, crop=False, resize=Non
235
  # Ensure to pass the crop argument to process_image and adjust the output filename generation accordingly
236
 
237
 
238
- def process_images2(input_dir="./input", output_dir="./output", crop=False, remove_bg=False, resize=None, padding=0, background=None):
239
- """
240
- Processes images in the specified directory based on the provided options.
241
-
242
- Args:
243
- - input_dir (str): Directory containing the images to be processed.
244
- - output_dir (str): Directory where processed images will be saved.
245
- - crop (bool): Whether to crop the images.
246
- - remove_bg (bool): Whether to remove the background of the images.
247
- - resize (tuple): Optional dimensions (width, height) to resize the image.
248
- - padding (int): Number of padding pixels to add around the image.
249
- - background (str): Optional background color (hex code or name) or path to an image file to set as the background.
250
- """
251
- processed_input_dir = os.path.join(input_dir, "processed")
252
- os.makedirs(processed_input_dir, exist_ok=True)
253
- os.makedirs(output_dir, exist_ok=True)
254
-
255
- inputs = [os.path.join(input_dir, f) for f in os.listdir(
256
- input_dir) if os.path.isfile(os.path.join(input_dir, f))]
257
-
258
- # if images are not in the input directory, print a message and return
259
- if not inputs:
260
- print("No images found in the input directory.")
261
- return
262
-
263
- for i, input_path in enumerate(inputs, start=1):
264
- filename = os.path.basename(input_path)
265
- output_filename = generate_output_filename(
266
- input_path, remove_bg=remove_bg, crop=crop, resize=resize, background=background)
267
- output_path = os.path.join(output_dir, output_filename)
268
- print(f"Processing image {i}/{len(inputs)}...{filename}")
269
-
270
- # Update the call to process_image with all parameters including background
271
- process_image(input_path, output_path, crop=crop, remove_bg=remove_bg,
272
- resize=resize, padding=padding, background=background)
273
-
274
- shutil.move(input_path, os.path.join(processed_input_dir, filename))
275
-
276
- print("All images have been processed.")
277
-
278
-
279
  def process_images(input_dir="./input", output_dir="./output", crop=False, remove_bg=False, resize=None, padding=0, background=None):
280
  """
281
  Processes images in the specified directory based on the provided options.
@@ -370,92 +329,3 @@ def save_image_with_format(image, output_path, format='webp', quality=90, custom
370
  raise ValueError(f"Unsupported format: {format}")
371
 
372
  return final_path
373
-
374
- """
375
- Saves the image in the specified format with appropriate settings.
376
-
377
- Args:
378
- - image (PIL.Image.Image): The image to save
379
- - output_path (str): Base path for the output file (without extension)
380
- - format (str): 'webp', 'png', 'png-transparent', or 'jpg'
381
- - quality (int): Quality setting for compression (1-100)
382
- - custom_filename (str): Optional custom filename for the output
383
- """
384
- # Get image dimensions for filename
385
- width, height = image.size
386
-
387
- # Generate the complete filename with path
388
- if custom_filename:
389
- base_dir = os.path.dirname(output_path)
390
- final_path = os.path.join(base_dir, f"{custom_filename}_{width}x{height}")
391
- else:
392
- final_path = output_path
393
-
394
- if format == 'webp':
395
- final_path = f"{final_path}.webp"
396
- image.save(final_path, 'webp', quality=quality)
397
- elif format == 'png-transparent':
398
- final_path = f"{final_path}.png"
399
- image.save(final_path, 'PNG', optimize=True)
400
- elif format == 'png':
401
- final_path = f"{final_path}.png"
402
- if image.mode in ('RGBA', 'LA'):
403
- background = Image.new('RGB', image.size, 'white')
404
- background.paste(image, mask=image.split()[-1])
405
- background.save(final_path, 'PNG', optimize=True)
406
- else:
407
- image.save(final_path, 'PNG', optimize=True)
408
- elif format == 'jpg':
409
- final_path = f"{final_path}.jpg"
410
- if image.mode in ('RGBA', 'LA'):
411
- background = Image.new('RGB', image.size, 'white')
412
- background.paste(image, mask=image.split()[-1])
413
- background.save(final_path, 'JPEG', quality=quality, optimize=True)
414
- else:
415
- image.convert('RGB').save(final_path, 'JPEG', quality=quality, optimize=True)
416
- else:
417
- raise ValueError(f"Unsupported format: {format}")
418
-
419
- return final_path
420
-
421
- """
422
- Saves the image in the specified format with appropriate settings.
423
-
424
- Args:
425
- - image (PIL.Image.Image): The image to save
426
- - output_path (str): Base path for the output file (without extension)
427
- - format (str): 'webp', 'png', 'png-transparent', or 'jpg'
428
- - quality (int): Quality setting for compression (1-100)
429
- """
430
- if format == 'webp':
431
- # Save as WebP with specified quality
432
- final_path = f"{output_path}.webp"
433
- image.save(final_path, 'webp', quality=quality)
434
- elif format == 'png-transparent':
435
- # Save as PNG with transparency
436
- final_path = f"{output_path}.png"
437
- image.save(final_path, 'PNG', optimize=True)
438
- elif format == 'png':
439
- # Save as PNG without transparency, with white background
440
- final_path = f"{output_path}.png"
441
- if image.mode in ('RGBA', 'LA'):
442
- background = Image.new('RGB', image.size, 'white')
443
- background.paste(image, mask=image.split()[-1])
444
- background.save(final_path, 'PNG', optimize=True)
445
- else:
446
- image.save(final_path, 'PNG', optimize=True)
447
- elif format == 'jpg':
448
- # Save as JPG with white background
449
- final_path = f"{output_path}.jpg"
450
- if image.mode in ('RGBA', 'LA'):
451
- # Convert transparent background to white for JPG
452
- background = Image.new('RGB', image.size, 'white')
453
- background.paste(image, mask=image.split()[-1])
454
- background.save(final_path, 'JPEG', quality=quality, optimize=True)
455
- else:
456
- # Save directly if no transparency
457
- image.convert('RGB').save(final_path, 'JPEG', quality=quality, optimize=True)
458
- else:
459
- raise ValueError(f"Unsupported format: {format}")
460
-
461
- return final_path
 
44
  return final_img
45
 
46
 
47
+ def cropnontrans(image, padding=0):
48
+ """
49
+ crops a nontransparent image
50
+
51
+ Args:
52
+ - image (PIL.Image.Image): Image to be cropped.
53
+
54
+ Returns:
55
+ - PIL.Image.Image: The autocropped image.
56
+ """
57
+ # first,
58
+ # Convert the PIL Image to bytes
59
+ img_byte_arr = io.BytesIO()
60
+ image.save(img_byte_arr, format='PNG')
61
+ img_byte_arr = img_byte_arr.getvalue()
62
+ # Use rembg to remove the background
63
+ result_bytes = remove(img_byte_arr)
64
+
65
+ # Convert the result bytes back to a PIL Image
66
+ transparent_image = Image.open(io.BytesIO(result_bytes))
67
+ bbox = transparent_image.getbbox()
68
+ # add padding area to the original bbox
69
+ if bbox:
70
+ bbox = (bbox[0]-padding, bbox[1]-padding, bbox[2]+padding, bbox[3]+padding)
71
+ #delimig the bbox to the image size
72
+ bbox = (max(0, bbox[0]), max(0, bbox[1]), min(transparent_image.width, bbox[2]), min(transparent_image.height, bbox[3]))
73
+ print(f"Bounding box: {bbox}")
74
+ return image.crop(bbox)
75
+ return image
76
+
77
+
78
+
79
  def autocrop_image(image):
80
  """
81
  Autocrops an image, focusing on the non-transparent pixels.
 
87
  - PIL.Image.Image: The autocropped image.
88
  """
89
  bbox = image.getbbox()
90
+ print(f"Bounding box: {bbox}")
91
  if bbox:
92
  return image.crop(bbox)
93
  return image
 
135
  if remove_bg:
136
  img = remove_bg_func(img)
137
 
138
+ if crop and remove_bg:
139
  img = autocrop_image(img)
140
+ if crop and not remove_bg:
141
+ img = cropnontrans(img, padding)
142
 
143
  if resize:
144
  img = resize_and_pad_image(img, resize, padding)
 
149
  return img
150
 
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
  def resize_and_pad_image(image, dimensions, padding=0):
154
  """
 
235
  # Ensure to pass the crop argument to process_image and adjust the output filename generation accordingly
236
 
237
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  def process_images(input_dir="./input", output_dir="./output", crop=False, remove_bg=False, resize=None, padding=0, background=None):
239
  """
240
  Processes images in the specified directory based on the provided options.
 
329
  raise ValueError(f"Unsupported format: {format}")
330
 
331
  return final_path