def add_shapes( background: PIL.Image.Image, shape_img: PIL.Image.Image, shape_params, ) -> Tuple[List[Tuple[int, int, int, int, int]], PIL.Image.Image]: """Paste shapes onto background and return bboxes""" shape_bboxes: List[Tuple[int, int, int, int, int]] = [] for i, shape_param in enumerate(shape_params): x = shape_param[-2] y = shape_param[-1] x1, y1, x2, y2 = shape_img.getbbox() bg_at_shape = background.crop((x1 + x, y1 + y, x2 + x, y2 + y)) bg_at_shape.paste(shape_img, (0, 0), shape_img) background.paste(bg_at_shape, (x, y)) # Slightly expand the bounding box in order to simulate variability with # the detection boxes. Always make the crop larger than needed because training # augmentations will only be able to crop down. dx = random.randint(0, int(0.1 * (x2 - x1))) dy = random.randint(0, int(0.1 * (y2 - y1))) x1 -= dx x2 += dx y1 -= dy y2 += dy background = background.crop((x1 + x, y1 + y, x2 + x, y2 + y)) background = background.filter(ImageFilter.SMOOTH_MORE) return background.convert("RGB")
def grid(image: PIL.Image.Image, grid_size, overlap) -> List[List[PIL.Image.Image]]: the_grid = [] w, h = image.size for x in range(0, w, grid_size): row = [] for y in range(0, h, grid_size): row.append( image.crop((x - overlap // 2, y - overlap // 2, x + grid_size + overlap // 2, y + grid_size + overlap // 2))) the_grid.append(row) return the_grid
def strip_image(image: PIL.Image.Image) -> PIL.Image.Image: """Remove white and black edges""" for x in range(image.width): for y in range(image.height): r, g, b, _ = image.getpixel((x, y)) if r > 247 and g > 247 and b > 247: image.putpixel((x, y), (0, 0, 0, 0)) image = image.crop(image.getbbox()) return image
def add_shapes( background: PIL.Image.Image, shape_imgs: PIL.Image.Image, shape_params, blur_radius: int, ) -> Tuple[List[Tuple[int, int, int, int, int]], PIL.Image.Image]: """Paste shapes onto background and return bboxes""" shape_bboxes: List[Tuple[int, int, int, int, int]] = [] for i, shape_param in enumerate(shape_params): x = shape_param[-2] y = shape_param[-1] shape_img = shape_imgs[i] shape_img = shape_img.filter(ImageFilter.GaussianBlur(1)) x1, y1, x2, y2 = shape_img.getbbox() bg_at_shape = background.crop((x1 + x, y1 + y, x2 + x, y2 + y)) bg_at_shape.paste(shape_img, (0, 0), shape_img) bg_at_shape = bg_at_shape.filter(ImageFilter.SMOOTH_MORE) background.paste(bg_at_shape, (x, y)) im_w, im_h = background.size x /= im_w y /= im_h w = (x2 - x1) / im_w h = (y2 - y1) / im_h shape_bboxes.append((CLASSES.index(shape_param[0]), x, y, w, h)) """ shape_bboxes.append( ( CLASSES.index(shape_param[2]), x + (0.1 * w), y + (0.1 * h), 0.8 * w, 0.8 * h, ) ) """ return shape_bboxes, background.convert("RGB")
def _trim_image( img: PIL.Image.Image, border_color: typing.Tuple[int] = None, ) -> PIL.Image.Image: if border_color is None: trimmed = img for xy in itertools.product(range(2), range(2)): trimmed = _trim_image( img=trimmed, border_color=img.getpixel(xy), ) return trimmed bg = PIL.Image.new(img.mode, img.size, border_color) diff = PIL.ImageChops.difference(img, bg) bbox = diff.getbbox() if bbox: return img.crop(bbox) else: # found no content raise ValueError("cannot trim; image was empty")