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
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Setup Node 18
|
||||
- name: Setup Node 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
node-version: '20'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: '8.12.1'
|
||||
version: 8
|
||||
- name: Install dependencies
|
||||
run: 'pnpm install --prefer-frozen-lockfile'
|
||||
- name: Typescript
|
||||
|
38
.github/workflows/pypi-release.yml
vendored
38
.github/workflows/pypi-release.yml
vendored
@ -1,15 +1,13 @@
|
||||
name: PyPI Release
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'invokeai/version/invokeai_version.py'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
publish_package:
|
||||
description: 'Publish build on PyPi? [true/false]'
|
||||
required: true
|
||||
default: 'false'
|
||||
|
||||
jobs:
|
||||
build-and-release:
|
||||
release:
|
||||
if: github.repository == 'invoke-ai/InvokeAI'
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
@ -17,39 +15,33 @@ jobs:
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
||||
TWINE_NON_INTERACTIVE: 1
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node 18
|
||||
- name: Setup Node 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: '8.12.1'
|
||||
version: 8
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: pnpm install --prefer-frozen-lockfile
|
||||
- name: Install pnpm dependencies
|
||||
working-directory: invokeai/frontend/web
|
||||
run: 'pnpm install --prefer-frozen-lockfile'
|
||||
|
||||
- name: Build frontend
|
||||
run: pnpm run build
|
||||
working-directory: invokeai/frontend/web
|
||||
run: 'pnpm build'
|
||||
|
||||
- name: Install python dependencies
|
||||
- name: Install python deps
|
||||
run: pip install --upgrade build twine
|
||||
|
||||
- name: Build python package
|
||||
- name: Build wheel package
|
||||
run: python3 -m build
|
||||
|
||||
- name: Upload build as workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
|
||||
- name: Check distribution
|
||||
run: twine check dist/*
|
||||
|
||||
@ -62,6 +54,6 @@ jobs:
|
||||
EXISTS=scripts.pypi_helper.local_on_pypi(); \
|
||||
print(f'PACKAGE_EXISTS={EXISTS}')" >> $GITHUB_ENV
|
||||
|
||||
- name: Publish build on PyPi
|
||||
if: env.PACKAGE_EXISTS == 'False' && env.TWINE_PASSWORD != '' && github.event.inputs.publish_package == 'true'
|
||||
- name: Upload package
|
||||
if: env.PACKAGE_EXISTS == 'False' && env.TWINE_PASSWORD != ''
|
||||
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:
|
||||
a. the desired location of the InvokeAI runtime directory, or
|
||||
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.
|
||||
|
||||
@ -39,7 +39,7 @@ The Docker daemon on the system must be already set up to use the GPU. In case o
|
||||
|
||||
## 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.
|
||||
|
||||
|
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'
|
||||
|
||||
x-invokeai: &invokeai
|
||||
services:
|
||||
invokeai:
|
||||
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:
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile
|
||||
@ -35,27 +50,3 @@ x-invokeai: &invokeai
|
||||
# - |
|
||||
# invokeai-model-install --yes --default-only --config_file ${INVOKEAI_ROOT}/config_custom.yaml
|
||||
# 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
|
||||
set -e
|
||||
|
||||
run() {
|
||||
local scriptdir=$(dirname "${BASH_SOURCE[0]}")
|
||||
cd "$scriptdir" || exit 1
|
||||
# This script is provided for backwards compatibility with the old docker setup.
|
||||
# it doesn't do much aside from wrapping the usual docker compose CLI.
|
||||
|
||||
local build_args=""
|
||||
local profile=""
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
cd "$SCRIPTDIR" || exit 1
|
||||
|
||||
[[ -f ".env" ]] &&
|
||||
build_args=$(awk '$1 ~ /=[^$]/ && $0 !~ /^#/ {print "--build-arg " $0 " "}' .env) &&
|
||||
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
|
||||
docker compose up -d
|
||||
docker compose logs -f
|
||||
|
@ -91,11 +91,9 @@ rm -rf InvokeAI-Installer
|
||||
|
||||
# copy content
|
||||
mkdir InvokeAI-Installer
|
||||
for f in templates *.txt *.reg; do
|
||||
for f in templates lib *.txt *.reg; do
|
||||
cp -r ${f} InvokeAI-Installer/
|
||||
done
|
||||
mkdir InvokeAI-Installer/lib
|
||||
cp lib/*.py InvokeAI-Installer/lib
|
||||
|
||||
# Move the wheel
|
||||
mv dist/*.whl InvokeAI-Installer/lib/
|
||||
@ -113,6 +111,6 @@ cp WinLongPathsEnabled.reg InvokeAI-Installer/
|
||||
zip -r InvokeAI-installer-$VERSION.zip InvokeAI-Installer
|
||||
|
||||
# clean up
|
||||
rm -rf InvokeAI-Installer tmp dist ../invokeai/frontend/web/dist/
|
||||
rm -rf InvokeAI-Installer tmp dist
|
||||
|
||||
exit 0
|
||||
|
@ -77,7 +77,7 @@ class CalculateImageTilesInvocation(BaseInvocation):
|
||||
title="Calculate Image Tiles Even Split",
|
||||
tags=["tiles"],
|
||||
category="tiles",
|
||||
version="1.1.0",
|
||||
version="1.0.0",
|
||||
classification=Classification.Beta,
|
||||
)
|
||||
class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
|
||||
@ -97,11 +97,11 @@ class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
|
||||
ge=1,
|
||||
description="Number of tiles to divide image into on the y axis",
|
||||
)
|
||||
overlap: int = InputField(
|
||||
default=128,
|
||||
overlap_fraction: float = InputField(
|
||||
default=0.25,
|
||||
ge=0,
|
||||
multiple_of=8,
|
||||
description="The overlap, in pixels, between adjacent tiles.",
|
||||
lt=1,
|
||||
description="Overlap between adjacent tiles as a fraction of the tile's dimensions (0-1)",
|
||||
)
|
||||
|
||||
def invoke(self, context: InvocationContext) -> CalculateImageTilesOutput:
|
||||
@ -110,7 +110,7 @@ class CalculateImageTilesEvenSplitInvocation(BaseInvocation):
|
||||
image_width=self.image_width,
|
||||
num_tiles_x=self.num_tiles_x,
|
||||
num_tiles_y=self.num_tiles_y,
|
||||
overlap=self.overlap,
|
||||
overlap_fraction=self.overlap_fraction,
|
||||
)
|
||||
return CalculateImageTilesOutput(tiles=tiles)
|
||||
|
||||
|
@ -9,7 +9,7 @@ def lora_token_vector_length(checkpoint: dict) -> int:
|
||||
: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
|
||||
|
||||
if "." not in key:
|
||||
@ -57,10 +57,6 @@ def lora_token_vector_length(checkpoint: dict) -> int:
|
||||
for key, tensor in checkpoint.items():
|
||||
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)
|
||||
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:
|
||||
tmp_length = _get_shape_1(key, tensor, checkpoint)
|
||||
if key.startswith("lora_te_"):
|
||||
|
@ -400,8 +400,6 @@ class LoRACheckpointProbe(CheckpointProbeBase):
|
||||
return BaseModelType.StableDiffusion1
|
||||
elif token_vector_length == 1024:
|
||||
return BaseModelType.StableDiffusion2
|
||||
elif token_vector_length == 1280:
|
||||
return BaseModelType.StableDiffusionXL # recognizes format at https://civitai.com/models/224641
|
||||
elif token_vector_length == 2048:
|
||||
return BaseModelType.StableDiffusionXL
|
||||
else:
|
||||
|
@ -102,7 +102,7 @@ def calc_tiles_with_overlap(
|
||||
|
||||
|
||||
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]:
|
||||
"""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.
|
||||
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.
|
||||
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:
|
||||
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:
|
||||
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)
|
||||
if num_tiles_x > 1:
|
||||
# ensure the overlap is not more than the maximum overlap if we only have 1 tile then we dont care about overlap
|
||||
assert overlap <= image_width - (LATENT_SCALE_FACTOR * (num_tiles_x - 1))
|
||||
tile_size_x = LATENT_SCALE_FACTOR * math.floor(
|
||||
((image_width + overlap * (num_tiles_x - 1)) // num_tiles_x) / LATENT_SCALE_FACTOR
|
||||
)
|
||||
assert overlap < tile_size_x
|
||||
else:
|
||||
tile_size_x = image_width
|
||||
# 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_fraction) / LATENT_SCALE_FACTOR
|
||||
)
|
||||
overlap_y = LATENT_SCALE_FACTOR * math.ceil(
|
||||
int((image_height / num_tiles_y) * overlap_fraction) / LATENT_SCALE_FACTOR
|
||||
)
|
||||
|
||||
if num_tiles_y > 1:
|
||||
# ensure the overlap is not more than the maximum overlap if we only have 1 tile then we dont care about overlap
|
||||
assert overlap <= image_height - (LATENT_SCALE_FACTOR * (num_tiles_y - 1))
|
||||
tile_size_y = LATENT_SCALE_FACTOR * math.floor(
|
||||
((image_height + overlap * (num_tiles_y - 1)) // num_tiles_y) / LATENT_SCALE_FACTOR
|
||||
)
|
||||
assert overlap < tile_size_y
|
||||
else:
|
||||
tile_size_y = image_height
|
||||
# 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(
|
||||
((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_y * (num_tiles_y - 1)) // num_tiles_y) / LATENT_SCALE_FACTOR
|
||||
)
|
||||
|
||||
# tiles[y * num_tiles_x + x] is the tile for the y'th row, x'th column.
|
||||
tiles: list[Tile] = []
|
||||
@ -147,7 +143,7 @@ def calc_tiles_even_split(
|
||||
# Calculate tile coordinates. (Ignore overlap values for now.)
|
||||
for tile_idx_y in range(num_tiles_y):
|
||||
# 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)
|
||||
# For the last row adjust bottom to be the height of the image
|
||||
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):
|
||||
# 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)
|
||||
# For the last tile in the row adjust right to be the width of the image
|
||||
if tile_idx_x == num_tiles_x - 1:
|
||||
|
@ -727,6 +727,9 @@
|
||||
"showMinimapnodes": "Mostrar el minimapa",
|
||||
"reloadNodeTemplates": "Recargar las plantillas de nodos",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
@ -898,8 +898,11 @@
|
||||
"zoomInNodes": "Ingrandire",
|
||||
"fitViewportNodes": "Adatta vista",
|
||||
"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",
|
||||
"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",
|
||||
"scheduler": "Campionatore",
|
||||
"addNode": "Aggiungi nodo",
|
||||
@ -1616,6 +1619,7 @@
|
||||
"saveWorkflow": "Salva flusso di lavoro",
|
||||
"openWorkflow": "Apri flusso di lavoro",
|
||||
"clearWorkflowSearchFilter": "Cancella il filtro di ricerca del flusso di lavoro",
|
||||
"workflowEditorReset": "Reimpostazione dell'editor del flusso di lavoro",
|
||||
"workflowLibrary": "Libreria",
|
||||
"noRecentWorkflows": "Nessun flusso di lavoro recente",
|
||||
"workflowSaved": "Flusso di lavoro salvato",
|
||||
|
@ -844,6 +844,9 @@
|
||||
"hideLegendNodes": "Typelegende veld verbergen",
|
||||
"reloadNodeTemplates": "Herlaad knooppuntsjablonen",
|
||||
"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",
|
||||
"booleanPolymorphicDescription": "Een verzameling Booleanse waarden.",
|
||||
"scheduler": "Planner",
|
||||
|
@ -909,6 +909,9 @@
|
||||
"hideLegendNodes": "Скрыть тип поля",
|
||||
"showMinimapnodes": "Показать миникарту",
|
||||
"loadWorkflow": "Загрузить рабочий процесс",
|
||||
"resetWorkflowDesc2": "Сброс рабочего процесса очистит все узлы, ребра и детали рабочего процесса.",
|
||||
"resetWorkflow": "Сбросить рабочий процесс",
|
||||
"resetWorkflowDesc": "Вы уверены, что хотите сбросить этот рабочий процесс?",
|
||||
"reloadNodeTemplates": "Перезагрузить шаблоны узлов",
|
||||
"downloadWorkflow": "Скачать JSON рабочего процесса",
|
||||
"booleanPolymorphicDescription": "Коллекция логических значений.",
|
||||
@ -1596,6 +1599,7 @@
|
||||
"saveWorkflow": "Сохранить рабочий процесс",
|
||||
"openWorkflow": "Открытый рабочий процесс",
|
||||
"clearWorkflowSearchFilter": "Очистить фильтр поиска рабочих процессов",
|
||||
"workflowEditorReset": "Сброс редактора рабочих процессов",
|
||||
"workflowLibrary": "Библиотека",
|
||||
"downloadWorkflow": "Скачать рабочий процесс",
|
||||
"noRecentWorkflows": "Нет недавних рабочих процессов",
|
||||
|
@ -892,8 +892,11 @@
|
||||
},
|
||||
"nodes": {
|
||||
"zoomInNodes": "放大",
|
||||
"resetWorkflowDesc": "是否确定要重置工作流编辑器?",
|
||||
"resetWorkflow": "重置工作流编辑器",
|
||||
"loadWorkflow": "加载工作流",
|
||||
"zoomOutNodes": "缩小",
|
||||
"resetWorkflowDesc2": "重置工作流编辑器将清除所有节点、边际和节点图详情。不影响已保存的工作流。",
|
||||
"reloadNodeTemplates": "重载节点模板",
|
||||
"hideGraphNodes": "隐藏节点图信息",
|
||||
"fitViewportNodes": "自适应视图",
|
||||
@ -1634,6 +1637,7 @@
|
||||
"saveWorkflow": "保存工作流",
|
||||
"openWorkflow": "打开工作流",
|
||||
"clearWorkflowSearchFilter": "清除工作流检索过滤器",
|
||||
"workflowEditorReset": "工作流编辑器重置",
|
||||
"workflowLibrary": "工作流库",
|
||||
"downloadWorkflow": "下载工作流",
|
||||
"noRecentWorkflows": "无最近工作流",
|
||||
|
@ -144,7 +144,6 @@ export const buildCanvasImageToImageGraph = (
|
||||
type: 'l2i',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
@ -256,7 +255,6 @@ export const buildCanvasImageToImageGraph = (
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.edges.push(
|
||||
@ -297,7 +295,6 @@ export const buildCanvasImageToImageGraph = (
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
(graph.nodes[IMAGE_TO_LATENTS] as ImageToLatentsInvocation).image =
|
||||
|
@ -191,7 +191,6 @@ export const buildCanvasInpaintGraph = (
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
reference: canvasInitImage,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -199,7 +199,6 @@ export const buildCanvasOutpaintGraph = (
|
||||
type: 'color_correct',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -266,7 +266,6 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.edges.push(
|
||||
@ -307,7 +306,6 @@ export const buildCanvasSDXLImageToImageGraph = (
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
(graph.nodes[IMAGE_TO_LATENTS] as ImageToLatentsInvocation).image =
|
||||
|
@ -196,7 +196,6 @@ export const buildCanvasSDXLInpaintGraph = (
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
reference: canvasInitImage,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -204,7 +204,6 @@ export const buildCanvasSDXLOutpaintGraph = (
|
||||
type: 'color_correct',
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -258,7 +258,6 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.edges.push(
|
||||
@ -289,7 +288,6 @@ export const buildCanvasSDXLTextToImageGraph = (
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.edges.push({
|
||||
|
@ -246,7 +246,6 @@ export const buildCanvasTextToImageGraph = (
|
||||
is_intermediate,
|
||||
width: width,
|
||||
height: height,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.edges.push(
|
||||
@ -277,7 +276,6 @@ export const buildCanvasTextToImageGraph = (
|
||||
id: CANVAS_OUTPUT,
|
||||
is_intermediate,
|
||||
fp32,
|
||||
use_cache: false,
|
||||
};
|
||||
|
||||
graph.edges.push({
|
||||
|
@ -143,7 +143,6 @@ export const buildLinearImageToImageGraph = (
|
||||
// },
|
||||
fp32,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -154,7 +154,6 @@ export const buildLinearSDXLImageToImageGraph = (
|
||||
// },
|
||||
fp32,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -127,7 +127,6 @@ export const buildLinearSDXLTextToImageGraph = (
|
||||
id: LATENTS_TO_IMAGE,
|
||||
fp32,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
edges: [
|
||||
|
@ -146,7 +146,6 @@ export const buildLinearTextToImageGraph = (
|
||||
id: LATENTS_TO_IMAGE,
|
||||
fp32,
|
||||
is_intermediate,
|
||||
use_cache: false,
|
||||
},
|
||||
},
|
||||
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():
|
||||
"""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 = [
|
||||
Tile(
|
||||
@ -320,34 +322,36 @@ def test_calc_tiles_even_split_single_tile():
|
||||
def test_calc_tiles_even_split_evenly_divisible():
|
||||
"""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
|
||||
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 = [
|
||||
# Row 0
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=320, left=0, right=576),
|
||||
overlap=TBLR(top=0, bottom=64, left=0, right=64),
|
||||
coords=TBLR(top=0, bottom=320, left=0, right=624),
|
||||
overlap=TBLR(top=0, bottom=72, left=0, right=136),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=320, left=512, right=1088),
|
||||
overlap=TBLR(top=0, bottom=64, left=64, right=64),
|
||||
coords=TBLR(top=0, bottom=320, left=488, right=1112),
|
||||
overlap=TBLR(top=0, bottom=72, left=136, right=136),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=320, left=1024, right=1600),
|
||||
overlap=TBLR(top=0, bottom=64, left=64, right=0),
|
||||
coords=TBLR(top=0, bottom=320, left=976, right=1600),
|
||||
overlap=TBLR(top=0, bottom=72, left=136, right=0),
|
||||
),
|
||||
# Row 1
|
||||
Tile(
|
||||
coords=TBLR(top=256, bottom=576, left=0, right=576),
|
||||
overlap=TBLR(top=64, bottom=0, left=0, right=64),
|
||||
coords=TBLR(top=248, bottom=576, left=0, right=624),
|
||||
overlap=TBLR(top=72, bottom=0, left=0, right=136),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=256, bottom=576, left=512, right=1088),
|
||||
overlap=TBLR(top=64, bottom=0, left=64, right=64),
|
||||
coords=TBLR(top=248, bottom=576, left=488, right=1112),
|
||||
overlap=TBLR(top=72, bottom=0, left=136, right=136),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=256, bottom=576, left=1024, right=1600),
|
||||
overlap=TBLR(top=64, bottom=0, left=64, right=0),
|
||||
coords=TBLR(top=248, bottom=576, left=976, right=1600),
|
||||
overlap=TBLR(top=72, bottom=0, left=136, right=0),
|
||||
),
|
||||
]
|
||||
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():
|
||||
"""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
|
||||
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 = [
|
||||
# Row 0
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=232, left=0, right=440),
|
||||
overlap=TBLR(top=0, bottom=64, left=0, right=64),
|
||||
coords=TBLR(top=0, bottom=224, left=0, right=464),
|
||||
overlap=TBLR(top=0, bottom=56, left=0, right=104),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=232, left=376, right=816),
|
||||
overlap=TBLR(top=0, bottom=64, left=64, right=64),
|
||||
coords=TBLR(top=0, bottom=224, left=360, right=824),
|
||||
overlap=TBLR(top=0, bottom=56, left=104, right=104),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=232, left=752, right=1200),
|
||||
overlap=TBLR(top=0, bottom=64, left=64, right=0),
|
||||
coords=TBLR(top=0, bottom=224, left=720, right=1200),
|
||||
overlap=TBLR(top=0, bottom=56, left=104, right=0),
|
||||
),
|
||||
# Row 1
|
||||
Tile(
|
||||
coords=TBLR(top=168, bottom=400, left=0, right=440),
|
||||
overlap=TBLR(top=64, bottom=0, left=0, right=64),
|
||||
coords=TBLR(top=168, bottom=400, left=0, right=464),
|
||||
overlap=TBLR(top=56, bottom=0, left=0, right=104),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=168, bottom=400, left=376, right=816),
|
||||
overlap=TBLR(top=64, bottom=0, left=64, right=64),
|
||||
coords=TBLR(top=168, bottom=400, left=360, right=824),
|
||||
overlap=TBLR(top=56, bottom=0, left=104, right=104),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=168, bottom=400, left=752, right=1200),
|
||||
overlap=TBLR(top=64, bottom=0, left=64, right=0),
|
||||
coords=TBLR(top=168, bottom=400, left=720, right=1200),
|
||||
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():
|
||||
"""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
|
||||
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 = [
|
||||
# Row 0
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=528, left=0, right=528),
|
||||
overlap=TBLR(top=0, bottom=64, left=0, right=64),
|
||||
coords=TBLR(top=0, bottom=560, left=0, right=560),
|
||||
overlap=TBLR(top=0, bottom=128, left=0, right=128),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=0, bottom=528, left=464, right=1000),
|
||||
overlap=TBLR(top=0, bottom=64, left=64, right=0),
|
||||
coords=TBLR(top=0, bottom=560, left=432, right=1000),
|
||||
overlap=TBLR(top=0, bottom=128, left=128, right=0),
|
||||
),
|
||||
# Row 1
|
||||
Tile(
|
||||
coords=TBLR(top=464, bottom=1000, left=0, right=528),
|
||||
overlap=TBLR(top=64, bottom=0, left=0, right=64),
|
||||
coords=TBLR(top=432, bottom=1000, left=0, right=560),
|
||||
overlap=TBLR(top=128, bottom=0, left=0, right=128),
|
||||
),
|
||||
Tile(
|
||||
coords=TBLR(top=464, bottom=1000, left=464, right=1000),
|
||||
overlap=TBLR(top=64, bottom=0, left=64, right=0),
|
||||
coords=TBLR(top=432, bottom=1000, left=432, right=1000),
|
||||
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(
|
||||
["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, 2, 2, 0, False), # OK
|
||||
(128, 128, 2, 1, 120, True), # overlap equals tile_height.
|
||||
(128, 128, 1, 2, 120, True), # overlap equals tile_width.
|
||||
(128, 128, 2, 1, 0, False), # OK
|
||||
(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,
|
||||
num_tiles_x: int,
|
||||
num_tiles_y: int,
|
||||
overlap: int,
|
||||
overlap_fraction: float,
|
||||
raises: bool,
|
||||
):
|
||||
"""Test that calc_tiles_even_split() raises an exception if the inputs are invalid."""
|
||||
if raises:
|
||||
with pytest.raises((AssertionError, ValueError)):
|
||||
calc_tiles_even_split(image_height, image_width, num_tiles_x, num_tiles_y, overlap)
|
||||
with pytest.raises(ValueError):
|
||||
calc_tiles_even_split(image_height, image_width, num_tiles_x, num_tiles_y, overlap_fraction)
|
||||
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