mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Compare commits
2 Commits
v3.5.0rc2
...
release/ad
Author | SHA1 | Date | |
---|---|---|---|
8c6a8d072d | |||
ec52f15f4b |
6
.github/workflows/lint-frontend.yml
vendored
6
.github/workflows/lint-frontend.yml
vendored
@ -21,16 +21,16 @@ jobs:
|
|||||||
if: github.event.pull_request.draft == false
|
if: github.event.pull_request.draft == false
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Setup Node 18
|
- name: Setup Node 20
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '20'
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v2
|
uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
version: '8.12.1'
|
version: 8
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: 'pnpm install --prefer-frozen-lockfile'
|
run: 'pnpm install --prefer-frozen-lockfile'
|
||||||
- name: Typescript
|
- name: Typescript
|
||||||
|
38
.github/workflows/pypi-release.yml
vendored
38
.github/workflows/pypi-release.yml
vendored
@ -1,15 +1,13 @@
|
|||||||
name: PyPI Release
|
name: PyPI Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'invokeai/version/invokeai_version.py'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
|
||||||
publish_package:
|
|
||||||
description: 'Publish build on PyPi? [true/false]'
|
|
||||||
required: true
|
|
||||||
default: 'false'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-release:
|
release:
|
||||||
if: github.repository == 'invoke-ai/InvokeAI'
|
if: github.repository == 'invoke-ai/InvokeAI'
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
@ -17,39 +15,33 @@ jobs:
|
|||||||
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
TWINE_NON_INTERACTIVE: 1
|
TWINE_NON_INTERACTIVE: 1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node 18
|
- name: Setup Node 20
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '20'
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v2
|
uses: pnpm/action-setup@v2
|
||||||
with:
|
with:
|
||||||
version: '8.12.1'
|
version: 8
|
||||||
|
|
||||||
- name: Install frontend dependencies
|
- name: Install pnpm dependencies
|
||||||
run: pnpm install --prefer-frozen-lockfile
|
|
||||||
working-directory: invokeai/frontend/web
|
working-directory: invokeai/frontend/web
|
||||||
|
run: 'pnpm install --prefer-frozen-lockfile'
|
||||||
|
|
||||||
- name: Build frontend
|
- name: Build frontend
|
||||||
run: pnpm run build
|
|
||||||
working-directory: invokeai/frontend/web
|
working-directory: invokeai/frontend/web
|
||||||
|
run: 'pnpm build'
|
||||||
|
|
||||||
- name: Install python dependencies
|
- name: Install python deps
|
||||||
run: pip install --upgrade build twine
|
run: pip install --upgrade build twine
|
||||||
|
|
||||||
- name: Build python package
|
- name: Build wheel package
|
||||||
run: python3 -m build
|
run: python3 -m build
|
||||||
|
|
||||||
- name: Upload build as workflow artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: dist
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
- name: Check distribution
|
- name: Check distribution
|
||||||
run: twine check dist/*
|
run: twine check dist/*
|
||||||
|
|
||||||
@ -62,6 +54,6 @@ jobs:
|
|||||||
EXISTS=scripts.pypi_helper.local_on_pypi(); \
|
EXISTS=scripts.pypi_helper.local_on_pypi(); \
|
||||||
print(f'PACKAGE_EXISTS={EXISTS}')" >> $GITHUB_ENV
|
print(f'PACKAGE_EXISTS={EXISTS}')" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Publish build on PyPi
|
- name: Upload package
|
||||||
if: env.PACKAGE_EXISTS == 'False' && env.TWINE_PASSWORD != '' && github.event.inputs.publish_package == 'true'
|
if: env.PACKAGE_EXISTS == 'False' && env.TWINE_PASSWORD != ''
|
||||||
run: twine upload dist/*
|
run: twine upload dist/*
|
||||||
|
@ -23,7 +23,7 @@ This is done via Docker Desktop preferences
|
|||||||
1. Make a copy of `env.sample` and name it `.env` (`cp env.sample .env` (Mac/Linux) or `copy example.env .env` (Windows)). Make changes as necessary. Set `INVOKEAI_ROOT` to an absolute path to:
|
1. Make a copy of `env.sample` and name it `.env` (`cp env.sample .env` (Mac/Linux) or `copy example.env .env` (Windows)). Make changes as necessary. Set `INVOKEAI_ROOT` to an absolute path to:
|
||||||
a. the desired location of the InvokeAI runtime directory, or
|
a. the desired location of the InvokeAI runtime directory, or
|
||||||
b. an existing, v3.0.0 compatible runtime directory.
|
b. an existing, v3.0.0 compatible runtime directory.
|
||||||
1. Execute `run.sh`
|
1. `docker compose up`
|
||||||
|
|
||||||
The image will be built automatically if needed.
|
The image will be built automatically if needed.
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ The Docker daemon on the system must be already set up to use the GPU. In case o
|
|||||||
|
|
||||||
## Customize
|
## Customize
|
||||||
|
|
||||||
Check the `.env.sample` file. It contains some environment variables for running in Docker. Copy it, name it `.env`, and fill it in with your own values. Next time you run `run.sh`, your custom values will be used.
|
Check the `.env.sample` file. It contains some environment variables for running in Docker. Copy it, name it `.env`, and fill it in with your own values. Next time you run `docker compose up`, your custom values will be used.
|
||||||
|
|
||||||
You can also set these values in `docker-compose.yml` directly, but `.env` will help avoid conflicts when code is updated.
|
You can also set these values in `docker-compose.yml` directly, but `.env` will help avoid conflicts when code is updated.
|
||||||
|
|
||||||
|
11
docker/build.sh
Executable file
11
docker/build.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
build_args=""
|
||||||
|
|
||||||
|
[[ -f ".env" ]] && build_args=$(awk '$1 ~ /\=[^$]/ {print "--build-arg " $0 " "}' .env)
|
||||||
|
|
||||||
|
echo "docker compose build args:"
|
||||||
|
echo $build_args
|
||||||
|
|
||||||
|
docker compose build $build_args
|
@ -2,8 +2,23 @@
|
|||||||
|
|
||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
x-invokeai: &invokeai
|
services:
|
||||||
|
invokeai:
|
||||||
image: "local/invokeai:latest"
|
image: "local/invokeai:latest"
|
||||||
|
# edit below to run on a container runtime other than nvidia-container-runtime.
|
||||||
|
# not yet tested with rocm/AMD GPUs
|
||||||
|
# Comment out the "deploy" section to run on CPU only
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
reservations:
|
||||||
|
devices:
|
||||||
|
- driver: nvidia
|
||||||
|
count: 1
|
||||||
|
capabilities: [gpu]
|
||||||
|
# For AMD support, comment out the deploy section above and uncomment the devices section below:
|
||||||
|
#devices:
|
||||||
|
# - /dev/kfd:/dev/kfd
|
||||||
|
# - /dev/dri:/dev/dri
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: docker/Dockerfile
|
dockerfile: docker/Dockerfile
|
||||||
@ -35,27 +50,3 @@ x-invokeai: &invokeai
|
|||||||
# - |
|
# - |
|
||||||
# invokeai-model-install --yes --default-only --config_file ${INVOKEAI_ROOT}/config_custom.yaml
|
# invokeai-model-install --yes --default-only --config_file ${INVOKEAI_ROOT}/config_custom.yaml
|
||||||
# invokeai-nodes-web --host 0.0.0.0
|
# invokeai-nodes-web --host 0.0.0.0
|
||||||
|
|
||||||
services:
|
|
||||||
invokeai-nvidia:
|
|
||||||
<<: *invokeai
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: 1
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
invokeai-cpu:
|
|
||||||
<<: *invokeai
|
|
||||||
profiles:
|
|
||||||
- cpu
|
|
||||||
|
|
||||||
invokeai-rocm:
|
|
||||||
<<: *invokeai
|
|
||||||
devices:
|
|
||||||
- /dev/kfd:/dev/kfd
|
|
||||||
- /dev/dri:/dev/dri
|
|
||||||
profiles:
|
|
||||||
- rocm
|
|
||||||
|
@ -1,28 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
run() {
|
# This script is provided for backwards compatibility with the old docker setup.
|
||||||
local scriptdir=$(dirname "${BASH_SOURCE[0]}")
|
# it doesn't do much aside from wrapping the usual docker compose CLI.
|
||||||
cd "$scriptdir" || exit 1
|
|
||||||
|
|
||||||
local build_args=""
|
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||||
local profile=""
|
cd "$SCRIPTDIR" || exit 1
|
||||||
|
|
||||||
[[ -f ".env" ]] &&
|
docker compose up -d
|
||||||
build_args=$(awk '$1 ~ /=[^$]/ && $0 !~ /^#/ {print "--build-arg " $0 " "}' .env) &&
|
docker compose logs -f
|
||||||
profile="$(awk -F '=' '/GPU_DRIVER/ {print $2}' .env)"
|
|
||||||
|
|
||||||
local service_name="invokeai-$profile"
|
|
||||||
|
|
||||||
printf "%s\n" "docker compose build args:"
|
|
||||||
printf "%s\n" "$build_args"
|
|
||||||
|
|
||||||
docker compose build $build_args
|
|
||||||
unset build_args
|
|
||||||
|
|
||||||
printf "%s\n" "starting service $service_name"
|
|
||||||
docker compose --profile "$profile" up -d "$service_name"
|
|
||||||
docker compose logs -f
|
|
||||||
}
|
|
||||||
|
|
||||||
run
|
|
||||||
|
@ -91,11 +91,9 @@ rm -rf InvokeAI-Installer
|
|||||||
|
|
||||||
# copy content
|
# copy content
|
||||||
mkdir InvokeAI-Installer
|
mkdir InvokeAI-Installer
|
||||||
for f in templates *.txt *.reg; do
|
for f in templates lib *.txt *.reg; do
|
||||||
cp -r ${f} InvokeAI-Installer/
|
cp -r ${f} InvokeAI-Installer/
|
||||||
done
|
done
|
||||||
mkdir InvokeAI-Installer/lib
|
|
||||||
cp lib/*.py InvokeAI-Installer/lib
|
|
||||||
|
|
||||||
# Move the wheel
|
# Move the wheel
|
||||||
mv dist/*.whl InvokeAI-Installer/lib/
|
mv dist/*.whl InvokeAI-Installer/lib/
|
||||||
@ -113,6 +111,6 @@ cp WinLongPathsEnabled.reg InvokeAI-Installer/
|
|||||||
zip -r InvokeAI-installer-$VERSION.zip InvokeAI-Installer
|
zip -r InvokeAI-installer-$VERSION.zip InvokeAI-Installer
|
||||||
|
|
||||||
# clean up
|
# clean up
|
||||||
rm -rf InvokeAI-Installer tmp dist ../invokeai/frontend/web/dist/
|
rm -rf InvokeAI-Installer tmp dist
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -77,7 +77,7 @@ class CalculateImageTilesInvocation(BaseInvocation):
|
|||||||
title="Calculate Image Tiles Even Split",
|
title="Calculate Image Tiles Even Split",
|
||||||
tags=["tiles"],
|
tags=["tiles"],
|
||||||
category="tiles",
|
category="tiles",
|
||||||
version="1.1.0",
|
version="1.0.0",
|
||||||
classification=Classification.Beta,
|
classification=Classification.Beta,
|
||||||
)
|
)
|
||||||
class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
|
class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
|
||||||
@ -97,11 +97,11 @@ 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: int = InputField(
|
overlap_fraction: float = InputField(
|
||||||
default=128,
|
default=0.25,
|
||||||
ge=0,
|
ge=0,
|
||||||
multiple_of=8,
|
lt=1,
|
||||||
description="The overlap, in pixels, between adjacent tiles.",
|
description="Overlap between adjacent tiles as a fraction of the tile's dimensions (0-1)",
|
||||||
)
|
)
|
||||||
|
|
||||||
def invoke(self, context: InvocationContext) -> CalculateImageTilesOutput:
|
def invoke(self, context: InvocationContext) -> CalculateImageTilesOutput:
|
||||||
@ -110,7 +110,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)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ def lora_token_vector_length(checkpoint: dict) -> int:
|
|||||||
:param checkpoint: The checkpoint
|
:param checkpoint: The checkpoint
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _get_shape_1(key: str, tensor, checkpoint) -> int:
|
def _get_shape_1(key, tensor, checkpoint):
|
||||||
lora_token_vector_length = None
|
lora_token_vector_length = None
|
||||||
|
|
||||||
if "." not in key:
|
if "." not in key:
|
||||||
@ -57,10 +57,6 @@ def lora_token_vector_length(checkpoint: dict) -> int:
|
|||||||
for key, tensor in checkpoint.items():
|
for key, tensor in checkpoint.items():
|
||||||
if key.startswith("lora_unet_") and ("_attn2_to_k." in key or "_attn2_to_v." in key):
|
if key.startswith("lora_unet_") and ("_attn2_to_k." in key or "_attn2_to_v." in key):
|
||||||
lora_token_vector_length = _get_shape_1(key, tensor, checkpoint)
|
lora_token_vector_length = _get_shape_1(key, tensor, checkpoint)
|
||||||
elif key.startswith("lora_unet_") and (
|
|
||||||
"time_emb_proj.lora_down" in key
|
|
||||||
): # recognizes format at https://civitai.com/models/224641
|
|
||||||
lora_token_vector_length = _get_shape_1(key, tensor, checkpoint)
|
|
||||||
elif key.startswith("lora_te") and "_self_attn_" in key:
|
elif key.startswith("lora_te") and "_self_attn_" in key:
|
||||||
tmp_length = _get_shape_1(key, tensor, checkpoint)
|
tmp_length = _get_shape_1(key, tensor, checkpoint)
|
||||||
if key.startswith("lora_te_"):
|
if key.startswith("lora_te_"):
|
||||||
|
@ -400,8 +400,6 @@ class LoRACheckpointProbe(CheckpointProbeBase):
|
|||||||
return BaseModelType.StableDiffusion1
|
return BaseModelType.StableDiffusion1
|
||||||
elif token_vector_length == 1024:
|
elif token_vector_length == 1024:
|
||||||
return BaseModelType.StableDiffusion2
|
return BaseModelType.StableDiffusion2
|
||||||
elif token_vector_length == 1280:
|
|
||||||
return BaseModelType.StableDiffusionXL # recognizes format at https://civitai.com/models/224641
|
|
||||||
elif token_vector_length == 2048:
|
elif token_vector_length == 2048:
|
||||||
return BaseModelType.StableDiffusionXL
|
return BaseModelType.StableDiffusionXL
|
||||||
else:
|
else:
|
||||||
|
@ -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: int = 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,35 +111,31 @@ 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 (int, optional): The overlap between adjacent tiles in pixels. 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.
|
||||||
"""
|
"""
|
||||||
# Ensure the image is divisible by LATENT_SCALE_FACTOR
|
|
||||||
|
# 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 {LATENT_SCALE_FACTOR}")
|
raise ValueError(f"image size (({image_width}, {image_height})) must be divisible by {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 overlap size based on the percentage and adjust it to be divisible by 8 (rounding up)
|
||||||
if num_tiles_x > 1:
|
overlap_x = LATENT_SCALE_FACTOR * math.ceil(
|
||||||
# ensure the overlap is not more than the maximum overlap if we only have 1 tile then we dont care about overlap
|
int((image_width / num_tiles_x) * overlap_fraction) / LATENT_SCALE_FACTOR
|
||||||
assert overlap <= image_width - (LATENT_SCALE_FACTOR * (num_tiles_x - 1))
|
)
|
||||||
tile_size_x = LATENT_SCALE_FACTOR * math.floor(
|
overlap_y = LATENT_SCALE_FACTOR * math.ceil(
|
||||||
((image_width + overlap * (num_tiles_x - 1)) // num_tiles_x) / LATENT_SCALE_FACTOR
|
int((image_height / num_tiles_y) * overlap_fraction) / LATENT_SCALE_FACTOR
|
||||||
)
|
)
|
||||||
assert overlap < tile_size_x
|
|
||||||
else:
|
|
||||||
tile_size_x = image_width
|
|
||||||
|
|
||||||
if num_tiles_y > 1:
|
# Calculate the tile size based on the number of tiles and overlap, and ensure it's divisible by 8 (rounding down)
|
||||||
# ensure the overlap is not more than the maximum overlap if we only have 1 tile then we dont care about overlap
|
tile_size_x = LATENT_SCALE_FACTOR * math.floor(
|
||||||
assert overlap <= image_height - (LATENT_SCALE_FACTOR * (num_tiles_y - 1))
|
((image_width + overlap_x * (num_tiles_x - 1)) // num_tiles_x) / LATENT_SCALE_FACTOR
|
||||||
tile_size_y = LATENT_SCALE_FACTOR * math.floor(
|
)
|
||||||
((image_height + overlap * (num_tiles_y - 1)) // num_tiles_y) / LATENT_SCALE_FACTOR
|
tile_size_y = LATENT_SCALE_FACTOR * math.floor(
|
||||||
)
|
((image_height + overlap_y * (num_tiles_y - 1)) // num_tiles_y) / LATENT_SCALE_FACTOR
|
||||||
assert overlap < tile_size_y
|
)
|
||||||
else:
|
|
||||||
tile_size_y = image_height
|
|
||||||
|
|
||||||
# tiles[y * num_tiles_x + x] is the tile for the y'th row, x'th column.
|
# tiles[y * num_tiles_x + x] is the tile for the y'th row, x'th column.
|
||||||
tiles: list[Tile] = []
|
tiles: list[Tile] = []
|
||||||
@ -147,7 +143,7 @@ def calc_tiles_even_split(
|
|||||||
# 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):
|
||||||
# Calculate the top and bottom of the row
|
# Calculate the top and bottom of the row
|
||||||
top = tile_idx_y * (tile_size_y - overlap)
|
top = tile_idx_y * (tile_size_y - overlap_y)
|
||||||
bottom = min(top + tile_size_y, image_height)
|
bottom = min(top + tile_size_y, image_height)
|
||||||
# For the last row adjust bottom to be the height of the image
|
# For the last row adjust bottom to be the height of the image
|
||||||
if tile_idx_y == num_tiles_y - 1:
|
if tile_idx_y == num_tiles_y - 1:
|
||||||
@ -155,7 +151,7 @@ def calc_tiles_even_split(
|
|||||||
|
|
||||||
for tile_idx_x in range(num_tiles_x):
|
for tile_idx_x in range(num_tiles_x):
|
||||||
# Calculate the left & right coordinate of each tile
|
# Calculate the left & right coordinate of each tile
|
||||||
left = tile_idx_x * (tile_size_x - overlap)
|
left = tile_idx_x * (tile_size_x - overlap_x)
|
||||||
right = min(left + tile_size_x, image_width)
|
right = min(left + tile_size_x, image_width)
|
||||||
# For the last tile in the row adjust right to be the width of the image
|
# For the last tile in the row adjust right to be the width of the image
|
||||||
if tile_idx_x == num_tiles_x - 1:
|
if tile_idx_x == num_tiles_x - 1:
|
||||||
|
@ -727,6 +727,9 @@
|
|||||||
"showMinimapnodes": "Mostrar el minimapa",
|
"showMinimapnodes": "Mostrar el minimapa",
|
||||||
"reloadNodeTemplates": "Recargar las plantillas de nodos",
|
"reloadNodeTemplates": "Recargar las plantillas de nodos",
|
||||||
"loadWorkflow": "Cargar el flujo de trabajo",
|
"loadWorkflow": "Cargar el flujo de trabajo",
|
||||||
|
"resetWorkflow": "Reiniciar e flujo de trabajo",
|
||||||
|
"resetWorkflowDesc": "¿Está seguro de que deseas restablecer este flujo de trabajo?",
|
||||||
|
"resetWorkflowDesc2": "Al reiniciar el flujo de trabajo se borrarán todos los nodos, aristas y detalles del flujo de trabajo.",
|
||||||
"downloadWorkflow": "Descargar el flujo de trabajo en un archivo JSON"
|
"downloadWorkflow": "Descargar el flujo de trabajo en un archivo JSON"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,8 +898,11 @@
|
|||||||
"zoomInNodes": "Ingrandire",
|
"zoomInNodes": "Ingrandire",
|
||||||
"fitViewportNodes": "Adatta vista",
|
"fitViewportNodes": "Adatta vista",
|
||||||
"showGraphNodes": "Mostra sovrapposizione grafico",
|
"showGraphNodes": "Mostra sovrapposizione grafico",
|
||||||
|
"resetWorkflowDesc2": "Il ripristino dell'editor del flusso di lavoro cancellerà tutti i nodi, le connessioni e i dettagli del flusso di lavoro. I flussi di lavoro salvati non saranno interessati.",
|
||||||
"reloadNodeTemplates": "Ricarica i modelli di nodo",
|
"reloadNodeTemplates": "Ricarica i modelli di nodo",
|
||||||
"loadWorkflow": "Importa flusso di lavoro JSON",
|
"loadWorkflow": "Importa flusso di lavoro JSON",
|
||||||
|
"resetWorkflow": "Reimposta l'editor del flusso di lavoro",
|
||||||
|
"resetWorkflowDesc": "Sei sicuro di voler reimpostare l'editor del flusso di lavoro?",
|
||||||
"downloadWorkflow": "Esporta flusso di lavoro JSON",
|
"downloadWorkflow": "Esporta flusso di lavoro JSON",
|
||||||
"scheduler": "Campionatore",
|
"scheduler": "Campionatore",
|
||||||
"addNode": "Aggiungi nodo",
|
"addNode": "Aggiungi nodo",
|
||||||
@ -1616,6 +1619,7 @@
|
|||||||
"saveWorkflow": "Salva flusso di lavoro",
|
"saveWorkflow": "Salva flusso di lavoro",
|
||||||
"openWorkflow": "Apri flusso di lavoro",
|
"openWorkflow": "Apri flusso di lavoro",
|
||||||
"clearWorkflowSearchFilter": "Cancella il filtro di ricerca del flusso di lavoro",
|
"clearWorkflowSearchFilter": "Cancella il filtro di ricerca del flusso di lavoro",
|
||||||
|
"workflowEditorReset": "Reimpostazione dell'editor del flusso di lavoro",
|
||||||
"workflowLibrary": "Libreria",
|
"workflowLibrary": "Libreria",
|
||||||
"noRecentWorkflows": "Nessun flusso di lavoro recente",
|
"noRecentWorkflows": "Nessun flusso di lavoro recente",
|
||||||
"workflowSaved": "Flusso di lavoro salvato",
|
"workflowSaved": "Flusso di lavoro salvato",
|
||||||
|
@ -844,6 +844,9 @@
|
|||||||
"hideLegendNodes": "Typelegende veld verbergen",
|
"hideLegendNodes": "Typelegende veld verbergen",
|
||||||
"reloadNodeTemplates": "Herlaad knooppuntsjablonen",
|
"reloadNodeTemplates": "Herlaad knooppuntsjablonen",
|
||||||
"loadWorkflow": "Laad werkstroom",
|
"loadWorkflow": "Laad werkstroom",
|
||||||
|
"resetWorkflow": "Herstel werkstroom",
|
||||||
|
"resetWorkflowDesc": "Weet je zeker dat je deze werkstroom wilt herstellen?",
|
||||||
|
"resetWorkflowDesc2": "Herstel van een werkstroom haalt alle knooppunten, randen en werkstroomdetails weg.",
|
||||||
"downloadWorkflow": "Download JSON van werkstroom",
|
"downloadWorkflow": "Download JSON van werkstroom",
|
||||||
"booleanPolymorphicDescription": "Een verzameling Booleanse waarden.",
|
"booleanPolymorphicDescription": "Een verzameling Booleanse waarden.",
|
||||||
"scheduler": "Planner",
|
"scheduler": "Planner",
|
||||||
|
@ -909,6 +909,9 @@
|
|||||||
"hideLegendNodes": "Скрыть тип поля",
|
"hideLegendNodes": "Скрыть тип поля",
|
||||||
"showMinimapnodes": "Показать миникарту",
|
"showMinimapnodes": "Показать миникарту",
|
||||||
"loadWorkflow": "Загрузить рабочий процесс",
|
"loadWorkflow": "Загрузить рабочий процесс",
|
||||||
|
"resetWorkflowDesc2": "Сброс рабочего процесса очистит все узлы, ребра и детали рабочего процесса.",
|
||||||
|
"resetWorkflow": "Сбросить рабочий процесс",
|
||||||
|
"resetWorkflowDesc": "Вы уверены, что хотите сбросить этот рабочий процесс?",
|
||||||
"reloadNodeTemplates": "Перезагрузить шаблоны узлов",
|
"reloadNodeTemplates": "Перезагрузить шаблоны узлов",
|
||||||
"downloadWorkflow": "Скачать JSON рабочего процесса",
|
"downloadWorkflow": "Скачать JSON рабочего процесса",
|
||||||
"booleanPolymorphicDescription": "Коллекция логических значений.",
|
"booleanPolymorphicDescription": "Коллекция логических значений.",
|
||||||
@ -1596,6 +1599,7 @@
|
|||||||
"saveWorkflow": "Сохранить рабочий процесс",
|
"saveWorkflow": "Сохранить рабочий процесс",
|
||||||
"openWorkflow": "Открытый рабочий процесс",
|
"openWorkflow": "Открытый рабочий процесс",
|
||||||
"clearWorkflowSearchFilter": "Очистить фильтр поиска рабочих процессов",
|
"clearWorkflowSearchFilter": "Очистить фильтр поиска рабочих процессов",
|
||||||
|
"workflowEditorReset": "Сброс редактора рабочих процессов",
|
||||||
"workflowLibrary": "Библиотека",
|
"workflowLibrary": "Библиотека",
|
||||||
"downloadWorkflow": "Скачать рабочий процесс",
|
"downloadWorkflow": "Скачать рабочий процесс",
|
||||||
"noRecentWorkflows": "Нет недавних рабочих процессов",
|
"noRecentWorkflows": "Нет недавних рабочих процессов",
|
||||||
|
@ -892,8 +892,11 @@
|
|||||||
},
|
},
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"zoomInNodes": "放大",
|
"zoomInNodes": "放大",
|
||||||
|
"resetWorkflowDesc": "是否确定要重置工作流编辑器?",
|
||||||
|
"resetWorkflow": "重置工作流编辑器",
|
||||||
"loadWorkflow": "加载工作流",
|
"loadWorkflow": "加载工作流",
|
||||||
"zoomOutNodes": "缩小",
|
"zoomOutNodes": "缩小",
|
||||||
|
"resetWorkflowDesc2": "重置工作流编辑器将清除所有节点、边际和节点图详情。不影响已保存的工作流。",
|
||||||
"reloadNodeTemplates": "重载节点模板",
|
"reloadNodeTemplates": "重载节点模板",
|
||||||
"hideGraphNodes": "隐藏节点图信息",
|
"hideGraphNodes": "隐藏节点图信息",
|
||||||
"fitViewportNodes": "自适应视图",
|
"fitViewportNodes": "自适应视图",
|
||||||
@ -1634,6 +1637,7 @@
|
|||||||
"saveWorkflow": "保存工作流",
|
"saveWorkflow": "保存工作流",
|
||||||
"openWorkflow": "打开工作流",
|
"openWorkflow": "打开工作流",
|
||||||
"clearWorkflowSearchFilter": "清除工作流检索过滤器",
|
"clearWorkflowSearchFilter": "清除工作流检索过滤器",
|
||||||
|
"workflowEditorReset": "工作流编辑器重置",
|
||||||
"workflowLibrary": "工作流库",
|
"workflowLibrary": "工作流库",
|
||||||
"downloadWorkflow": "下载工作流",
|
"downloadWorkflow": "下载工作流",
|
||||||
"noRecentWorkflows": "无最近工作流",
|
"noRecentWorkflows": "无最近工作流",
|
||||||
|
@ -144,7 +144,6 @@ export const buildCanvasImageToImageGraph = (
|
|||||||
type: 'l2i',
|
type: 'l2i',
|
||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
@ -256,7 +255,6 @@ export const buildCanvasImageToImageGraph = (
|
|||||||
is_intermediate,
|
is_intermediate,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graph.edges.push(
|
graph.edges.push(
|
||||||
@ -297,7 +295,6 @@ export const buildCanvasImageToImageGraph = (
|
|||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
fp32,
|
fp32,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(graph.nodes[IMAGE_TO_LATENTS] as ImageToLatentsInvocation).image =
|
(graph.nodes[IMAGE_TO_LATENTS] as ImageToLatentsInvocation).image =
|
||||||
|
@ -191,7 +191,6 @@ export const buildCanvasInpaintGraph = (
|
|||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
reference: canvasInitImage,
|
reference: canvasInitImage,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -199,7 +199,6 @@ export const buildCanvasOutpaintGraph = (
|
|||||||
type: 'color_correct',
|
type: 'color_correct',
|
||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -266,7 +266,6 @@ export const buildCanvasSDXLImageToImageGraph = (
|
|||||||
is_intermediate,
|
is_intermediate,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graph.edges.push(
|
graph.edges.push(
|
||||||
@ -307,7 +306,6 @@ export const buildCanvasSDXLImageToImageGraph = (
|
|||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
fp32,
|
fp32,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(graph.nodes[IMAGE_TO_LATENTS] as ImageToLatentsInvocation).image =
|
(graph.nodes[IMAGE_TO_LATENTS] as ImageToLatentsInvocation).image =
|
||||||
|
@ -196,7 +196,6 @@ export const buildCanvasSDXLInpaintGraph = (
|
|||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
reference: canvasInitImage,
|
reference: canvasInitImage,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -204,7 +204,6 @@ export const buildCanvasSDXLOutpaintGraph = (
|
|||||||
type: 'color_correct',
|
type: 'color_correct',
|
||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -258,7 +258,6 @@ export const buildCanvasSDXLTextToImageGraph = (
|
|||||||
is_intermediate,
|
is_intermediate,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graph.edges.push(
|
graph.edges.push(
|
||||||
@ -289,7 +288,6 @@ export const buildCanvasSDXLTextToImageGraph = (
|
|||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
fp32,
|
fp32,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graph.edges.push({
|
graph.edges.push({
|
||||||
|
@ -246,7 +246,6 @@ export const buildCanvasTextToImageGraph = (
|
|||||||
is_intermediate,
|
is_intermediate,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graph.edges.push(
|
graph.edges.push(
|
||||||
@ -277,7 +276,6 @@ export const buildCanvasTextToImageGraph = (
|
|||||||
id: CANVAS_OUTPUT,
|
id: CANVAS_OUTPUT,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
fp32,
|
fp32,
|
||||||
use_cache: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graph.edges.push({
|
graph.edges.push({
|
||||||
|
@ -143,7 +143,6 @@ export const buildLinearImageToImageGraph = (
|
|||||||
// },
|
// },
|
||||||
fp32,
|
fp32,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -154,7 +154,6 @@ export const buildLinearSDXLImageToImageGraph = (
|
|||||||
// },
|
// },
|
||||||
fp32,
|
fp32,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -127,7 +127,6 @@ export const buildLinearSDXLTextToImageGraph = (
|
|||||||
id: LATENTS_TO_IMAGE,
|
id: LATENTS_TO_IMAGE,
|
||||||
fp32,
|
fp32,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -146,7 +146,6 @@ export const buildLinearTextToImageGraph = (
|
|||||||
id: LATENTS_TO_IMAGE,
|
id: LATENTS_TO_IMAGE,
|
||||||
fp32,
|
fp32,
|
||||||
is_intermediate,
|
is_intermediate,
|
||||||
use_cache: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
edges: [
|
edges: [
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "3.5.0rc2"
|
__version__ = "3.4.0post2"
|
||||||
|
@ -305,7 +305,9 @@ def test_calc_tiles_min_overlap_input_validation(
|
|||||||
|
|
||||||
def test_calc_tiles_even_split_single_tile():
|
def test_calc_tiles_even_split_single_tile():
|
||||||
"""Test calc_tiles_even_split() behavior when a single tile covers the image."""
|
"""Test calc_tiles_even_split() behavior when a single tile covers the image."""
|
||||||
tiles = calc_tiles_even_split(image_height=512, image_width=1024, num_tiles_x=1, num_tiles_y=1, overlap=64)
|
tiles = calc_tiles_even_split(
|
||||||
|
image_height=512, image_width=1024, num_tiles_x=1, num_tiles_y=1, overlap_fraction=0.25
|
||||||
|
)
|
||||||
|
|
||||||
expected_tiles = [
|
expected_tiles = [
|
||||||
Tile(
|
Tile(
|
||||||
@ -320,34 +322,36 @@ def test_calc_tiles_even_split_single_tile():
|
|||||||
def test_calc_tiles_even_split_evenly_divisible():
|
def test_calc_tiles_even_split_evenly_divisible():
|
||||||
"""Test calc_tiles_even_split() behavior when the image is evenly covered by multiple tiles."""
|
"""Test calc_tiles_even_split() behavior when the image is evenly covered by multiple tiles."""
|
||||||
# Parameters mimic roughly the same output as the original tile generations of the same test name
|
# Parameters mimic roughly the same output as the original tile generations of the same test name
|
||||||
tiles = calc_tiles_even_split(image_height=576, image_width=1600, num_tiles_x=3, num_tiles_y=2, overlap=64)
|
tiles = calc_tiles_even_split(
|
||||||
|
image_height=576, image_width=1600, num_tiles_x=3, num_tiles_y=2, overlap_fraction=0.25
|
||||||
|
)
|
||||||
|
|
||||||
expected_tiles = [
|
expected_tiles = [
|
||||||
# Row 0
|
# Row 0
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=320, left=0, right=576),
|
coords=TBLR(top=0, bottom=320, left=0, right=624),
|
||||||
overlap=TBLR(top=0, bottom=64, left=0, right=64),
|
overlap=TBLR(top=0, bottom=72, left=0, right=136),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=320, left=512, right=1088),
|
coords=TBLR(top=0, bottom=320, left=488, right=1112),
|
||||||
overlap=TBLR(top=0, bottom=64, left=64, right=64),
|
overlap=TBLR(top=0, bottom=72, left=136, right=136),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=320, left=1024, right=1600),
|
coords=TBLR(top=0, bottom=320, left=976, right=1600),
|
||||||
overlap=TBLR(top=0, bottom=64, left=64, right=0),
|
overlap=TBLR(top=0, bottom=72, left=136, right=0),
|
||||||
),
|
),
|
||||||
# Row 1
|
# Row 1
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=256, bottom=576, left=0, right=576),
|
coords=TBLR(top=248, bottom=576, left=0, right=624),
|
||||||
overlap=TBLR(top=64, bottom=0, left=0, right=64),
|
overlap=TBLR(top=72, bottom=0, left=0, right=136),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=256, bottom=576, left=512, right=1088),
|
coords=TBLR(top=248, bottom=576, left=488, right=1112),
|
||||||
overlap=TBLR(top=64, bottom=0, left=64, right=64),
|
overlap=TBLR(top=72, bottom=0, left=136, right=136),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=256, bottom=576, left=1024, right=1600),
|
coords=TBLR(top=248, bottom=576, left=976, right=1600),
|
||||||
overlap=TBLR(top=64, bottom=0, left=64, right=0),
|
overlap=TBLR(top=72, bottom=0, left=136, right=0),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
assert tiles == expected_tiles
|
assert tiles == expected_tiles
|
||||||
@ -356,34 +360,36 @@ def test_calc_tiles_even_split_evenly_divisible():
|
|||||||
def test_calc_tiles_even_split_not_evenly_divisible():
|
def test_calc_tiles_even_split_not_evenly_divisible():
|
||||||
"""Test calc_tiles_even_split() behavior when the image requires 'uneven' overlaps to achieve proper coverage."""
|
"""Test calc_tiles_even_split() behavior when the image requires 'uneven' overlaps to achieve proper coverage."""
|
||||||
# Parameters mimic roughly the same output as the original tile generations of the same test name
|
# Parameters mimic roughly the same output as the original tile generations of the same test name
|
||||||
tiles = calc_tiles_even_split(image_height=400, image_width=1200, num_tiles_x=3, num_tiles_y=2, overlap=64)
|
tiles = calc_tiles_even_split(
|
||||||
|
image_height=400, image_width=1200, num_tiles_x=3, num_tiles_y=2, overlap_fraction=0.25
|
||||||
|
)
|
||||||
|
|
||||||
expected_tiles = [
|
expected_tiles = [
|
||||||
# Row 0
|
# Row 0
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=232, left=0, right=440),
|
coords=TBLR(top=0, bottom=224, left=0, right=464),
|
||||||
overlap=TBLR(top=0, bottom=64, left=0, right=64),
|
overlap=TBLR(top=0, bottom=56, left=0, right=104),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=232, left=376, right=816),
|
coords=TBLR(top=0, bottom=224, left=360, right=824),
|
||||||
overlap=TBLR(top=0, bottom=64, left=64, right=64),
|
overlap=TBLR(top=0, bottom=56, left=104, right=104),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=232, left=752, right=1200),
|
coords=TBLR(top=0, bottom=224, left=720, right=1200),
|
||||||
overlap=TBLR(top=0, bottom=64, left=64, right=0),
|
overlap=TBLR(top=0, bottom=56, left=104, right=0),
|
||||||
),
|
),
|
||||||
# Row 1
|
# Row 1
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=168, bottom=400, left=0, right=440),
|
coords=TBLR(top=168, bottom=400, left=0, right=464),
|
||||||
overlap=TBLR(top=64, bottom=0, left=0, right=64),
|
overlap=TBLR(top=56, bottom=0, left=0, right=104),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=168, bottom=400, left=376, right=816),
|
coords=TBLR(top=168, bottom=400, left=360, right=824),
|
||||||
overlap=TBLR(top=64, bottom=0, left=64, right=64),
|
overlap=TBLR(top=56, bottom=0, left=104, right=104),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=168, bottom=400, left=752, right=1200),
|
coords=TBLR(top=168, bottom=400, left=720, right=1200),
|
||||||
overlap=TBLR(top=64, bottom=0, left=64, right=0),
|
overlap=TBLR(top=56, bottom=0, left=104, right=0),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -393,26 +399,28 @@ def test_calc_tiles_even_split_not_evenly_divisible():
|
|||||||
def test_calc_tiles_even_split_difficult_size():
|
def test_calc_tiles_even_split_difficult_size():
|
||||||
"""Test calc_tiles_even_split() behavior when the image is a difficult size to spilt evenly and keep div8."""
|
"""Test calc_tiles_even_split() behavior when the image is a difficult size to spilt evenly and keep div8."""
|
||||||
# Parameters are a difficult size for other tile gen routines to calculate
|
# Parameters are a difficult size for other tile gen routines to calculate
|
||||||
tiles = calc_tiles_even_split(image_height=1000, image_width=1000, num_tiles_x=2, num_tiles_y=2, overlap=64)
|
tiles = calc_tiles_even_split(
|
||||||
|
image_height=1000, image_width=1000, num_tiles_x=2, num_tiles_y=2, overlap_fraction=0.25
|
||||||
|
)
|
||||||
|
|
||||||
expected_tiles = [
|
expected_tiles = [
|
||||||
# Row 0
|
# Row 0
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=528, left=0, right=528),
|
coords=TBLR(top=0, bottom=560, left=0, right=560),
|
||||||
overlap=TBLR(top=0, bottom=64, left=0, right=64),
|
overlap=TBLR(top=0, bottom=128, left=0, right=128),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=0, bottom=528, left=464, right=1000),
|
coords=TBLR(top=0, bottom=560, left=432, right=1000),
|
||||||
overlap=TBLR(top=0, bottom=64, left=64, right=0),
|
overlap=TBLR(top=0, bottom=128, left=128, right=0),
|
||||||
),
|
),
|
||||||
# Row 1
|
# Row 1
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=464, bottom=1000, left=0, right=528),
|
coords=TBLR(top=432, bottom=1000, left=0, right=560),
|
||||||
overlap=TBLR(top=64, bottom=0, left=0, right=64),
|
overlap=TBLR(top=128, bottom=0, left=0, right=128),
|
||||||
),
|
),
|
||||||
Tile(
|
Tile(
|
||||||
coords=TBLR(top=464, bottom=1000, left=464, right=1000),
|
coords=TBLR(top=432, bottom=1000, left=432, right=1000),
|
||||||
overlap=TBLR(top=64, bottom=0, left=64, right=0),
|
overlap=TBLR(top=128, bottom=0, left=128, right=0),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -420,13 +428,11 @@ def test_calc_tiles_even_split_difficult_size():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
["image_height", "image_width", "num_tiles_x", "num_tiles_y", "overlap", "raises"],
|
["image_height", "image_width", "num_tiles_x", "num_tiles_y", "overlap_fraction", "raises"],
|
||||||
[
|
[
|
||||||
(128, 128, 1, 1, 127, False), # OK
|
(128, 128, 1, 1, 0.25, False), # OK
|
||||||
(128, 128, 1, 1, 0, False), # OK
|
(128, 128, 1, 1, 0, False), # OK
|
||||||
(128, 128, 2, 2, 0, False), # OK
|
(128, 128, 2, 1, 0, False), # OK
|
||||||
(128, 128, 2, 1, 120, True), # overlap equals tile_height.
|
|
||||||
(128, 128, 1, 2, 120, True), # overlap equals tile_width.
|
|
||||||
(127, 127, 1, 1, 0, True), # image size must be dividable by 8
|
(127, 127, 1, 1, 0, True), # image size must be dividable by 8
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -435,15 +441,15 @@ def test_calc_tiles_even_split_input_validation(
|
|||||||
image_width: int,
|
image_width: int,
|
||||||
num_tiles_x: int,
|
num_tiles_x: int,
|
||||||
num_tiles_y: int,
|
num_tiles_y: int,
|
||||||
overlap: int,
|
overlap_fraction: float,
|
||||||
raises: bool,
|
raises: bool,
|
||||||
):
|
):
|
||||||
"""Test that calc_tiles_even_split() raises an exception if the inputs are invalid."""
|
"""Test that calc_tiles_even_split() raises an exception if the inputs are invalid."""
|
||||||
if raises:
|
if raises:
|
||||||
with pytest.raises((AssertionError, ValueError)):
|
with pytest.raises(ValueError):
|
||||||
calc_tiles_even_split(image_height, image_width, num_tiles_x, num_tiles_y, overlap)
|
calc_tiles_even_split(image_height, image_width, num_tiles_x, num_tiles_y, overlap_fraction)
|
||||||
else:
|
else:
|
||||||
calc_tiles_even_split(image_height, image_width, num_tiles_x, num_tiles_y, overlap)
|
calc_tiles_even_split(image_height, image_width, num_tiles_x, num_tiles_y, overlap_fraction)
|
||||||
|
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
|
Reference in New Issue
Block a user