- Even_spilt overlap renamed to overlap_fraction

- min_overlap removed * restrictions and round_to_8
- min_overlap handles tile size > image size by clipping the num tiles to 1.
- Updated assert test on min_overlap.
This commit is contained in:
skunkworxdark 2023-12-11 16:55:27 +00:00
parent 4c97b619fb
commit fefb78795f
4 changed files with 23 additions and 28 deletions

View File

@ -88,7 +88,7 @@ class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
ge=1, ge=1,
description="Number of tiles to divide image into on the y axis", description="Number of tiles to divide image into on the y axis",
) )
overlap: float = InputField( overlap_fraction: float = InputField(
default=0.25, default=0.25,
ge=0, ge=0,
lt=1, lt=1,
@ -101,7 +101,7 @@ class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
image_width=self.image_width, image_width=self.image_width,
num_tiles_x=self.num_tiles_x, num_tiles_x=self.num_tiles_x,
num_tiles_y=self.num_tiles_y, num_tiles_y=self.num_tiles_y,
overlap=self.overlap, overlap_fraction=self.overlap_fraction,
) )
return CalculateImageTilesOutput(tiles=tiles) return CalculateImageTilesOutput(tiles=tiles)
@ -120,18 +120,9 @@ class CalculateImageTilesMinimumOverlapInvocation(BaseInvocation):
image_height: int = InputField( image_height: int = InputField(
ge=1, default=1024, description="The image height, in pixels, to calculate tiles for." ge=1, default=1024, description="The image height, in pixels, to calculate tiles for."
) )
tile_width: int = InputField(ge=1, default=576, multiple_of=8, description="The tile width, in pixels.") tile_width: int = InputField(ge=1, default=576, description="The tile width, in pixels.")
tile_height: int = InputField(ge=1, default=576, multiple_of=8, description="The tile height, in pixels.") tile_height: int = InputField(ge=1, default=576, description="The tile height, in pixels.")
min_overlap: int = InputField( min_overlap: int = InputField(default=128, ge=0, description="Minimum overlap between adjacent tiles, in pixels.")
default=128,
ge=0,
multiple_of=8,
description="Minimum overlap between adjacent tiles, in pixels(must be a multiple of 8).",
)
round_to_8: bool = InputField(
default=False,
description="Round outputs down to the nearest 8 (for pulling from a large noise field)",
)
def invoke(self, context: InvocationContext) -> CalculateImageTilesOutput: def invoke(self, context: InvocationContext) -> CalculateImageTilesOutput:
tiles = calc_tiles_min_overlap( tiles = calc_tiles_min_overlap(
@ -140,7 +131,6 @@ class CalculateImageTilesMinimumOverlapInvocation(BaseInvocation):
tile_height=self.tile_height, tile_height=self.tile_height,
tile_width=self.tile_width, tile_width=self.tile_width,
min_overlap=self.min_overlap, min_overlap=self.min_overlap,
round_to_8=self.round_to_8,
) )
return CalculateImageTilesOutput(tiles=tiles) return CalculateImageTilesOutput(tiles=tiles)

View File

@ -102,7 +102,7 @@ def calc_tiles_with_overlap(
def calc_tiles_even_split( def calc_tiles_even_split(
image_height: int, image_width: int, num_tiles_x: int, num_tiles_y: int, overlap: float = 0 image_height: int, image_width: int, num_tiles_x: int, num_tiles_y: int, overlap_fraction: float = 0
) -> list[Tile]: ) -> list[Tile]:
"""Calculate the tile coordinates for a given image shape with the number of tiles requested. """Calculate the tile coordinates for a given image shape with the number of tiles requested.
@ -111,7 +111,7 @@ def calc_tiles_even_split(
image_width (int): The image width in px. image_width (int): The image width in px.
num_x_tiles (int): The number of tile to split the image into on the X-axis. num_x_tiles (int): The number of tile to split the image into on the X-axis.
num_y_tiles (int): The number of tile to split the image into on the Y-axis. num_y_tiles (int): The number of tile to split the image into on the Y-axis.
overlap (float, optional): The target overlap amount of the tiles size. Defaults to 0. overlap_fraction (float, optional): The target overlap as fraction of the tiles size. Defaults to 0.
Returns: Returns:
list[Tile]: A list of tiles that cover the image shape. Ordered from left-to-right, top-to-bottom. list[Tile]: A list of tiles that cover the image shape. Ordered from left-to-right, top-to-bottom.
@ -119,11 +119,15 @@ def calc_tiles_even_split(
# Ensure tile size is divisible by 8 # Ensure tile size is divisible by 8
if image_width % LATENT_SCALE_FACTOR != 0 or image_height % LATENT_SCALE_FACTOR != 0: if image_width % LATENT_SCALE_FACTOR != 0 or image_height % LATENT_SCALE_FACTOR != 0:
raise ValueError(f"image size (({image_width}, {image_height})) must be divisible by 8") raise ValueError(f"image size (({image_width}, {image_height})) must be divisible by {LATENT_SCALE_FACTOR}")
# Calculate the overlap size based on the percentage and adjust it to be divisible by 8 (rounding up) # Calculate the overlap size based on the percentage and adjust it to be divisible by 8 (rounding up)
overlap_x = LATENT_SCALE_FACTOR * math.ceil(int((image_width / num_tiles_x) * overlap) / LATENT_SCALE_FACTOR) overlap_x = LATENT_SCALE_FACTOR * math.ceil(
overlap_y = LATENT_SCALE_FACTOR * math.ceil(int((image_height / num_tiles_y) * overlap) / LATENT_SCALE_FACTOR) int((image_width / num_tiles_x) * overlap_fraction) / LATENT_SCALE_FACTOR
)
overlap_y = LATENT_SCALE_FACTOR * math.ceil(
int((image_height / num_tiles_y) * overlap_fraction) / LATENT_SCALE_FACTOR
)
# Calculate the tile size based on the number of tiles and overlap, and ensure it's divisible by 8 (rounding down) # Calculate the tile size based on the number of tiles and overlap, and ensure it's divisible by 8 (rounding down)
tile_size_x = LATENT_SCALE_FACTOR * math.floor( tile_size_x = LATENT_SCALE_FACTOR * math.floor(
@ -184,11 +188,11 @@ def calc_tiles_min_overlap(
Returns: Returns:
list[Tile]: A list of tiles that cover the image shape. Ordered from left-to-right, top-to-bottom. list[Tile]: A list of tiles that cover the image shape. Ordered from left-to-right, top-to-bottom.
""" """
assert image_height >= tile_height
assert image_width >= tile_width
assert min_overlap < tile_height assert min_overlap < tile_height
assert min_overlap < tile_width assert min_overlap < tile_width
# The If Else catches the case when the tile size is larger than the images size and just clips the number of tiles to 1
num_tiles_x = math.ceil((image_width - min_overlap) / (tile_width - min_overlap)) if tile_width < image_width else 1 num_tiles_x = math.ceil((image_width - min_overlap) / (tile_width - min_overlap)) if tile_width < image_width else 1
num_tiles_y = ( num_tiles_y = (
math.ceil((image_height - min_overlap) / (tile_height - min_overlap)) if tile_height < image_height else 1 math.ceil((image_height - min_overlap) / (tile_height - min_overlap)) if tile_height < image_height else 1
@ -200,14 +204,10 @@ def calc_tiles_min_overlap(
# Calculate tile coordinates. (Ignore overlap values for now.) # Calculate tile coordinates. (Ignore overlap values for now.)
for tile_idx_y in range(num_tiles_y): for tile_idx_y in range(num_tiles_y):
top = (tile_idx_y * (image_height - tile_height)) // (num_tiles_y - 1) if num_tiles_y > 1 else 0 top = (tile_idx_y * (image_height - tile_height)) // (num_tiles_y - 1) if num_tiles_y > 1 else 0
if round_to_8:
top = LATENT_SCALE_FACTOR * (top // LATENT_SCALE_FACTOR)
bottom = top + tile_height bottom = top + tile_height
for tile_idx_x in range(num_tiles_x): for tile_idx_x in range(num_tiles_x):
left = (tile_idx_x * (image_width - tile_width)) // (num_tiles_x - 1) if num_tiles_x > 1 else 0 left = (tile_idx_x * (image_width - tile_width)) // (num_tiles_x - 1) if num_tiles_x > 1 else 0
if round_to_8:
left = LATENT_SCALE_FACTOR * (left // LATENT_SCALE_FACTOR)
right = left + tile_width right = left + tile_width
tile = Tile( tile = Tile(

View File

@ -74,6 +74,9 @@ def seam_blend(ia1: np.ndarray, ia2: np.ndarray, blend_amount: int, x_seam: bool
return result return result
# Assume RGB and convert to grey # Assume RGB and convert to grey
# Could offer other options for the luminance conversion
# BT.709 [0.2126, 0.7152, 0.0722], BT.2020 [0.2627, 0.6780, 0.0593])
# it might not have a huge impact due to the blur that is applied over the seam
iag1 = np.dot(ia1, [0.2989, 0.5870, 0.1140]) # BT.601 perceived brightness iag1 = np.dot(ia1, [0.2989, 0.5870, 0.1140]) # BT.601 perceived brightness
iag2 = np.dot(ia2, [0.2989, 0.5870, 0.1140]) iag2 = np.dot(ia2, [0.2989, 0.5870, 0.1140])
@ -92,6 +95,7 @@ def seam_blend(ia1: np.ndarray, ia2: np.ndarray, blend_amount: int, x_seam: bool
min_x = gutter min_x = gutter
# Calc the energy in the difference # Calc the energy in the difference
# Could offer different energy calculations e.g. Sobel or Scharr
energy = np.abs(np.gradient(ia, axis=0)) + np.abs(np.gradient(ia, axis=1)) energy = np.abs(np.gradient(ia, axis=0)) + np.abs(np.gradient(ia, axis=1))
# Find the starting position of the seam # Find the starting position of the seam
@ -107,6 +111,7 @@ def seam_blend(ia1: np.ndarray, ia2: np.ndarray, blend_amount: int, x_seam: bool
lowest_energy_line[max_y - 1] = np.argmin(res[max_y - 1, min_x : max_x - 1]) lowest_energy_line[max_y - 1] = np.argmin(res[max_y - 1, min_x : max_x - 1])
# Calc the path of the seam # Calc the path of the seam
# could offer options for larger search than just 1 pixel by adjusting lpos and rpos
for ypos in range(max_y - 2, -1, -1): for ypos in range(max_y - 2, -1, -1):
lowest_pos = lowest_energy_line[ypos + 1] lowest_pos = lowest_energy_line[ypos + 1]
lpos = lowest_pos - 1 lpos = lowest_pos - 1

View File

@ -371,8 +371,8 @@ def test_calc_tiles_min_overlap_difficult_size_div8():
(128, 128, 128, 128, 127, False), # OK (128, 128, 128, 128, 127, False), # OK
(128, 128, 128, 128, 0, False), # OK (128, 128, 128, 128, 0, False), # OK
(128, 128, 64, 64, 0, False), # OK (128, 128, 64, 64, 0, False), # OK
(128, 128, 129, 128, 0, True), # tile_height exceeds image_height. (128, 128, 129, 128, 0, False), # tile_height exceeds image_height defaults to 1 tile.
(128, 128, 128, 129, 0, True), # tile_width exceeds image_width. (128, 128, 128, 129, 0, False), # tile_width exceeds image_width defaults to 1 tile.
(128, 128, 64, 128, 64, True), # overlap equals tile_height. (128, 128, 64, 128, 64, True), # overlap equals tile_height.
(128, 128, 128, 64, 64, True), # overlap equals tile_width. (128, 128, 128, 64, 64, True), # overlap equals tile_width.
], ],