mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
3c195d74a5
Still need to fix this somehow
61 lines
2.4 KiB
Python
61 lines
2.4 KiB
Python
from typing import Tuple
|
|
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
|
|
def infill_mosaic(
|
|
image: Image.Image,
|
|
tile_shape: Tuple[int, int] = (64, 64),
|
|
min_color: Tuple[int, int, int, int] = (0, 0, 0, 0),
|
|
max_color: Tuple[int, int, int, int] = (255, 255, 255, 0),
|
|
) -> Image.Image:
|
|
"""
|
|
image:PIL - A PIL Image
|
|
tile_shape: Tuple[int,int] - Tile width & Tile Height
|
|
min_color: Tuple[int,int,int] - RGB values for the lowest color to clip to (0-255)
|
|
max_color: Tuple[int,int,int] - RGB values for the highest color to clip to (0-255)
|
|
"""
|
|
|
|
np_image = np.array(image) # Convert image to np array
|
|
alpha = np_image[:, :, 3] # Get the mask from the alpha channel of the image
|
|
non_transparent_pixels = np_image[alpha != 0, :3] # List of non-transparent pixels
|
|
|
|
# Create color tiles to paste in the empty areas of the image
|
|
tile_width, tile_height = tile_shape
|
|
|
|
# Clip the range of colors in the image to a particular spectrum only
|
|
r_min, g_min, b_min, _ = min_color
|
|
r_max, g_max, b_max, _ = max_color
|
|
non_transparent_pixels[:, 0] = np.clip(non_transparent_pixels[:, 0], r_min, r_max)
|
|
non_transparent_pixels[:, 1] = np.clip(non_transparent_pixels[:, 1], g_min, g_max)
|
|
non_transparent_pixels[:, 2] = np.clip(non_transparent_pixels[:, 2], b_min, b_max)
|
|
|
|
tiles = []
|
|
for _ in range(256):
|
|
color = non_transparent_pixels[np.random.randint(len(non_transparent_pixels))]
|
|
tile = np.zeros((tile_height, tile_width, 3), dtype=np.uint8)
|
|
tile[:, :] = color
|
|
tiles.append(tile)
|
|
|
|
# Fill the transparent area with tiles
|
|
filled_image = np.zeros((image.height, image.width, 3), dtype=np.uint8)
|
|
|
|
for x in range(image.width):
|
|
for y in range(image.height):
|
|
tile = tiles[np.random.randint(len(tiles))]
|
|
try:
|
|
filled_image[
|
|
y - (y % tile_height) : y - (y % tile_height) + tile_height,
|
|
x - (x % tile_width) : x - (x % tile_width) + tile_width,
|
|
] = tile
|
|
except ValueError:
|
|
# Need to handle edge cases - literally
|
|
pass
|
|
|
|
filled_image = Image.fromarray(filled_image) # Convert the filled tiles image to PIL
|
|
image = Image.composite(
|
|
image, filled_image, image.split()[-1]
|
|
) # Composite the original image on top of the filled tiles
|
|
return image
|