diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index bcca3fc8e7..125554fc40 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -511,6 +511,7 @@
"maskBlur": "Blur",
"maskBlurMethod": "Blur Method",
"coherencePassHeader": "Coherence Pass",
+ "coherenceMode": "Mode",
"coherenceSteps": "Steps",
"coherenceStrength": "Strength",
"seamLowThreshold": "Low",
diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addVAEToGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addVAEToGraph.ts
index 34d37e9b17..8e77799293 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addVAEToGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addVAEToGraph.ts
@@ -32,7 +32,7 @@ export const addVAEToGraph = (
graph: NonNullableGraph,
modelLoaderNodeId: string = MAIN_MODEL_LOADER
): void => {
- const { vae } = state.generation;
+ const { vae, canvasCoherenceMode } = state.generation;
const { boundingBoxScaleMethod } = state.canvas;
const { shouldUseSDXLRefiner } = state.sdxl;
@@ -136,16 +136,6 @@ export const addVAEToGraph = (
field: 'vae',
},
},
- {
- source: {
- node_id: isAutoVae ? modelLoaderNodeId : VAE_LOADER,
- field: isAutoVae && isOnnxModel ? 'vae_decoder' : 'vae',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'vae',
- },
- },
{
source: {
node_id: isAutoVae ? modelLoaderNodeId : VAE_LOADER,
@@ -157,6 +147,20 @@ export const addVAEToGraph = (
},
}
);
+
+ // Handle Coherence Mode
+ if (canvasCoherenceMode === 'edge') {
+ graph.edges.push({
+ source: {
+ node_id: isAutoVae ? modelLoaderNodeId : VAE_LOADER,
+ field: isAutoVae && isOnnxModel ? 'vae_decoder' : 'vae',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'vae',
+ },
+ });
+ }
}
if (shouldUseSDXLRefiner) {
diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts
index 1783174079..a87d20a08d 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts
@@ -70,6 +70,7 @@ export const buildCanvasInpaintGraph = (
shouldUseCpuNoise,
maskBlur,
maskBlurMethod,
+ canvasCoherenceMode,
canvasCoherenceSteps,
canvasCoherenceStrength,
clipSkip,
@@ -176,21 +177,6 @@ export const buildCanvasInpaintGraph = (
b: 1,
is_intermediate: true,
},
- [CANVAS_COHERENCE_MASK_EDGE]: {
- type: 'mask_edge',
- id: CANVAS_COHERENCE_MASK_EDGE,
- is_intermediate: true,
- edge_blur: maskBlur,
- edge_size: maskBlur * 2,
- low_threshold: 100,
- high_threshold: 200,
- },
- [CANVAS_COHERENCE_INPAINT_CREATE_MASK]: {
- type: 'create_denoise_mask',
- id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- is_intermediate: true,
- fp32: vaePrecision === 'fp32' ? true : false,
- },
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
type: 'denoise_latents',
id: CANVAS_COHERENCE_DENOISE_LATENTS,
@@ -333,27 +319,6 @@ export const buildCanvasInpaintGraph = (
field: 'denoise_mask',
},
},
- // Create Coherence Mask
- {
- source: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'mask',
- },
- },
- {
- source: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'denoise_mask',
- },
- destination: {
- node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
- field: 'denoise_mask',
- },
- },
// Iterate
{
source: {
@@ -537,26 +502,6 @@ export const buildCanvasInpaintGraph = (
field: 'image',
},
},
- {
- source: {
- node_id: INPAINT_IMAGE_RESIZE_UP,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
- {
- source: {
- node_id: MASK_RESIZE_UP,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- },
// Color Correct The Inpainted Result
{
source: {
@@ -618,16 +563,6 @@ export const buildCanvasInpaintGraph = (
...(graph.nodes[INPAINT_CREATE_MASK] as CreateDenoiseMaskInvocation),
image: canvasInitImage,
};
- graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
- ...(graph.nodes[
- CANVAS_COHERENCE_INPAINT_CREATE_MASK
- ] as CreateDenoiseMaskInvocation),
- image: canvasInitImage,
- };
- graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
- ...(graph.nodes[CANVAS_COHERENCE_MASK_EDGE] as MaskEdgeInvocation),
- image: canvasMaskImage,
- };
graph.edges.push(
// Color Correct The Inpainted Result
@@ -654,6 +589,84 @@ export const buildCanvasInpaintGraph = (
);
}
+ // Handle Coherence Mode
+ if (canvasCoherenceMode === 'edge') {
+ graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
+ type: 'mask_edge',
+ id: CANVAS_COHERENCE_MASK_EDGE,
+ is_intermediate: true,
+ edge_blur: maskBlur,
+ edge_size: maskBlur * 2,
+ low_threshold: 100,
+ high_threshold: 200,
+ };
+ graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
+ type: 'create_denoise_mask',
+ id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ is_intermediate: true,
+ fp32: vaePrecision === 'fp32' ? true : false,
+ };
+
+ if (isUsingScaledDimensions) {
+ graph.edges.push(
+ {
+ source: {
+ node_id: MASK_RESIZE_UP,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ },
+ {
+ source: {
+ node_id: INPAINT_IMAGE_RESIZE_UP,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'image',
+ },
+ }
+ );
+ } else {
+ graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
+ ...(graph.nodes[
+ CANVAS_COHERENCE_INPAINT_CREATE_MASK
+ ] as CreateDenoiseMaskInvocation),
+ image: canvasInitImage,
+ };
+ graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
+ ...(graph.nodes[CANVAS_COHERENCE_MASK_EDGE] as MaskEdgeInvocation),
+ image: canvasMaskImage,
+ };
+ }
+
+ graph.edges.push(
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'mask',
+ },
+ },
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'denoise_mask',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
+ field: 'denoise_mask',
+ },
+ }
+ );
+ }
+
// Handle Seed
if (shouldRandomizeSeed) {
// Random int node to generate the starting seed
diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts
index 20f81611fe..fe2d3f1698 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts
@@ -71,6 +71,7 @@ export const buildCanvasOutpaintGraph = (
shouldUseNoiseSettings,
shouldUseCpuNoise,
maskBlur,
+ canvasCoherenceMode,
canvasCoherenceSteps,
canvasCoherenceStrength,
infillTileSize,
@@ -185,21 +186,6 @@ export const buildCanvasOutpaintGraph = (
b: 1,
is_intermediate: true,
},
- [CANVAS_COHERENCE_MASK_EDGE]: {
- type: 'mask_edge',
- id: CANVAS_COHERENCE_MASK_EDGE,
- is_intermediate: true,
- edge_blur: maskBlur,
- edge_size: maskBlur * 2,
- low_threshold: 100,
- high_threshold: 200,
- },
- [CANVAS_COHERENCE_INPAINT_CREATE_MASK]: {
- type: 'create_denoise_mask',
- id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- is_intermediate: true,
- fp32: vaePrecision === 'fp32' ? true : false,
- },
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
type: 'denoise_latents',
id: CANVAS_COHERENCE_DENOISE_LATENTS,
@@ -363,27 +349,6 @@ export const buildCanvasOutpaintGraph = (
field: 'denoise_mask',
},
},
- // Create Coherence Mask
- {
- source: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'mask',
- },
- },
- {
- source: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'denoise_mask',
- },
- destination: {
- node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
- field: 'denoise_mask',
- },
- },
// Iterate
{
source: {
@@ -476,6 +441,16 @@ export const buildCanvasOutpaintGraph = (
field: 'latents',
},
},
+ {
+ source: {
+ node_id: INPAINT_INFILL,
+ field: 'image',
+ },
+ destination: {
+ node_id: INPAINT_CREATE_MASK,
+ field: 'image',
+ },
+ },
// Decode the result from Inpaint
{
source: {
@@ -588,26 +563,7 @@ export const buildCanvasOutpaintGraph = (
field: 'image',
},
},
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
+
// Take combined mask and resize and then blur
{
source: {
@@ -619,16 +575,7 @@ export const buildCanvasOutpaintGraph = (
field: 'image',
},
},
- {
- source: {
- node_id: MASK_RESIZE_UP,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- },
+
// Resize Results Down
{
source: {
@@ -712,37 +659,6 @@ export const buildCanvasOutpaintGraph = (
};
graph.edges.push(
- // Take combined mask and plug it to blur
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
- {
- source: {
- node_id: MASK_COMBINE,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- },
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
// Color Correct The Inpainted Result
{
source: {
@@ -777,6 +693,82 @@ export const buildCanvasOutpaintGraph = (
);
}
+ // Handle Coherence Mode
+ if (canvasCoherenceMode === 'edge') {
+ graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
+ type: 'mask_edge',
+ id: CANVAS_COHERENCE_MASK_EDGE,
+ is_intermediate: true,
+ edge_blur: maskBlur,
+ edge_size: maskBlur * 2,
+ low_threshold: 100,
+ high_threshold: 200,
+ };
+ graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
+ type: 'create_denoise_mask',
+ id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ is_intermediate: true,
+ fp32: vaePrecision === 'fp32' ? true : false,
+ };
+
+ if (isUsingScaledDimensions) {
+ graph.edges.push({
+ source: {
+ node_id: MASK_RESIZE_UP,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ });
+ } else {
+ graph.edges.push({
+ source: {
+ node_id: MASK_COMBINE,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ });
+ }
+
+ graph.edges.push(
+ {
+ source: {
+ node_id: INPAINT_INFILL,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'image',
+ },
+ },
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'mask',
+ },
+ },
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'denoise_mask',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
+ field: 'denoise_mask',
+ },
+ }
+ );
+ }
+
// Handle Seed
if (shouldRandomizeSeed) {
// Random int node to generate the starting seed
diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts
index ca3f39257e..6b898e1db6 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts
@@ -71,6 +71,7 @@ export const buildCanvasSDXLInpaintGraph = (
shouldUseCpuNoise,
maskBlur,
maskBlurMethod,
+ canvasCoherenceMode,
canvasCoherenceSteps,
canvasCoherenceStrength,
seamlessXAxis,
@@ -182,21 +183,6 @@ export const buildCanvasSDXLInpaintGraph = (
b: 1,
is_intermediate: true,
},
- [CANVAS_COHERENCE_MASK_EDGE]: {
- type: 'mask_edge',
- id: CANVAS_COHERENCE_MASK_EDGE,
- is_intermediate: true,
- edge_blur: maskBlur,
- edge_size: maskBlur * 2,
- low_threshold: 100,
- high_threshold: 200,
- },
- [CANVAS_COHERENCE_INPAINT_CREATE_MASK]: {
- type: 'create_denoise_mask',
- id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- is_intermediate: true,
- fp32: vaePrecision === 'fp32' ? true : false,
- },
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
type: 'denoise_latents',
id: CANVAS_COHERENCE_DENOISE_LATENTS,
@@ -348,27 +334,6 @@ export const buildCanvasSDXLInpaintGraph = (
field: 'denoise_mask',
},
},
- // Create Coherence Mask
- {
- source: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'mask',
- },
- },
- {
- source: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'denoise_mask',
- },
- destination: {
- node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
- field: 'denoise_mask',
- },
- },
// Iterate
{
source: {
@@ -552,26 +517,6 @@ export const buildCanvasSDXLInpaintGraph = (
field: 'image',
},
},
- {
- source: {
- node_id: INPAINT_IMAGE_RESIZE_UP,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
- {
- source: {
- node_id: MASK_RESIZE_UP,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- },
// Color Correct The Inpainted Result
{
source: {
@@ -633,16 +578,6 @@ export const buildCanvasSDXLInpaintGraph = (
...(graph.nodes[INPAINT_CREATE_MASK] as CreateDenoiseMaskInvocation),
image: canvasInitImage,
};
- graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
- ...(graph.nodes[
- CANVAS_COHERENCE_INPAINT_CREATE_MASK
- ] as CreateDenoiseMaskInvocation),
- image: canvasInitImage,
- };
- graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
- ...(graph.nodes[CANVAS_COHERENCE_MASK_EDGE] as MaskEdgeInvocation),
- image: canvasMaskImage,
- };
graph.edges.push(
// Color Correct The Inpainted Result
@@ -669,6 +604,84 @@ export const buildCanvasSDXLInpaintGraph = (
);
}
+ // Handle Coherence Mode
+ if (canvasCoherenceMode === 'edge') {
+ graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
+ type: 'mask_edge',
+ id: CANVAS_COHERENCE_MASK_EDGE,
+ is_intermediate: true,
+ edge_blur: maskBlur,
+ edge_size: maskBlur * 2,
+ low_threshold: 100,
+ high_threshold: 200,
+ };
+ graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
+ type: 'create_denoise_mask',
+ id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ is_intermediate: true,
+ fp32: vaePrecision === 'fp32' ? true : false,
+ };
+
+ if (isUsingScaledDimensions) {
+ graph.edges.push(
+ {
+ source: {
+ node_id: MASK_RESIZE_UP,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ },
+ {
+ source: {
+ node_id: INPAINT_IMAGE_RESIZE_UP,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'image',
+ },
+ }
+ );
+ } else {
+ graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
+ ...(graph.nodes[
+ CANVAS_COHERENCE_INPAINT_CREATE_MASK
+ ] as CreateDenoiseMaskInvocation),
+ image: canvasInitImage,
+ };
+ graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
+ ...(graph.nodes[CANVAS_COHERENCE_MASK_EDGE] as MaskEdgeInvocation),
+ image: canvasMaskImage,
+ };
+ }
+
+ graph.edges.push(
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'mask',
+ },
+ },
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'denoise_mask',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
+ field: 'denoise_mask',
+ },
+ }
+ );
+ }
+
// Handle Seed
if (shouldRandomizeSeed) {
// Random int node to generate the starting seed
diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts
index bd06228beb..c839815f98 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts
@@ -72,9 +72,11 @@ export const buildCanvasSDXLOutpaintGraph = (
shouldUseNoiseSettings,
shouldUseCpuNoise,
maskBlur,
+ canvasCoherenceMode,
canvasCoherenceSteps,
canvasCoherenceStrength,
infillTileSize,
+ infillPatchmatchDownscaleSize,
infillMethod,
seamlessXAxis,
seamlessYAxis,
@@ -190,21 +192,6 @@ export const buildCanvasSDXLOutpaintGraph = (
b: 1,
is_intermediate: true,
},
- [CANVAS_COHERENCE_MASK_EDGE]: {
- type: 'mask_edge',
- id: CANVAS_COHERENCE_MASK_EDGE,
- is_intermediate: true,
- edge_blur: maskBlur,
- edge_size: maskBlur * 2,
- low_threshold: 100,
- high_threshold: 200,
- },
- [CANVAS_COHERENCE_INPAINT_CREATE_MASK]: {
- type: 'create_denoise_mask',
- id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- is_intermediate: true,
- fp32: vaePrecision === 'fp32' ? true : false,
- },
[CANVAS_COHERENCE_DENOISE_LATENTS]: {
type: 'denoise_latents',
id: CANVAS_COHERENCE_DENOISE_LATENTS,
@@ -377,27 +364,6 @@ export const buildCanvasSDXLOutpaintGraph = (
field: 'denoise_mask',
},
},
- // Create Coherence Mask
- {
- source: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'mask',
- },
- },
- {
- source: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'denoise_mask',
- },
- destination: {
- node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
- field: 'denoise_mask',
- },
- },
// Iterate
{
source: {
@@ -490,6 +456,16 @@ export const buildCanvasSDXLOutpaintGraph = (
field: 'latents',
},
},
+ {
+ source: {
+ node_id: INPAINT_INFILL,
+ field: 'image',
+ },
+ destination: {
+ node_id: INPAINT_CREATE_MASK,
+ field: 'image',
+ },
+ },
// Decode inpainted latents to image
{
source: {
@@ -602,26 +578,7 @@ export const buildCanvasSDXLOutpaintGraph = (
field: 'image',
},
},
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
+
// Take combined mask and resize and then blur
{
source: {
@@ -633,16 +590,7 @@ export const buildCanvasSDXLOutpaintGraph = (
field: 'image',
},
},
- {
- source: {
- node_id: MASK_RESIZE_UP,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- },
+
// Resize Results Down
{
source: {
@@ -726,37 +674,6 @@ export const buildCanvasSDXLOutpaintGraph = (
};
graph.edges.push(
- // Take combined mask and plug it to blur
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
- {
- source: {
- node_id: MASK_COMBINE,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_MASK_EDGE,
- field: 'image',
- },
- },
- {
- source: {
- node_id: INPAINT_INFILL,
- field: 'image',
- },
- destination: {
- node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
- field: 'image',
- },
- },
// Color Correct The Inpainted Result
{
source: {
@@ -791,6 +708,82 @@ export const buildCanvasSDXLOutpaintGraph = (
);
}
+ // Handle Coherence Mode
+ if (canvasCoherenceMode === 'edge') {
+ graph.nodes[CANVAS_COHERENCE_MASK_EDGE] = {
+ type: 'mask_edge',
+ id: CANVAS_COHERENCE_MASK_EDGE,
+ is_intermediate: true,
+ edge_blur: maskBlur,
+ edge_size: maskBlur * 2,
+ low_threshold: 100,
+ high_threshold: 200,
+ };
+ graph.nodes[CANVAS_COHERENCE_INPAINT_CREATE_MASK] = {
+ type: 'create_denoise_mask',
+ id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ is_intermediate: true,
+ fp32: vaePrecision === 'fp32' ? true : false,
+ };
+
+ if (isUsingScaledDimensions) {
+ graph.edges.push({
+ source: {
+ node_id: MASK_RESIZE_UP,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ });
+ } else {
+ graph.edges.push({
+ source: {
+ node_id: MASK_COMBINE,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ });
+ }
+
+ graph.edges.push(
+ {
+ source: {
+ node_id: INPAINT_INFILL,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'image',
+ },
+ },
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_MASK_EDGE,
+ field: 'image',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'mask',
+ },
+ },
+ {
+ source: {
+ node_id: CANVAS_COHERENCE_INPAINT_CREATE_MASK,
+ field: 'denoise_mask',
+ },
+ destination: {
+ node_id: CANVAS_COHERENCE_DENOISE_LATENTS,
+ field: 'denoise_mask',
+ },
+ }
+ );
+ }
+
// Handle Seed
if (shouldRandomizeSeed) {
// Random int node to generate the starting seed
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceMode.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceMode.tsx
new file mode 100644
index 0000000000..398a11957c
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/CoherencePass/ParamCanvasCoherenceMode.tsx
@@ -0,0 +1,41 @@
+import type { RootState } from 'app/store/store';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import { IAISelectDataType } from 'common/components/IAIMantineSearchableSelect';
+import IAIMantineSelect from 'common/components/IAIMantineSelect';
+import { setCanvasCoherenceMode } from 'features/parameters/store/generationSlice';
+import { CanvasCoherenceModeParam } from 'features/parameters/types/parameterSchemas';
+
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+
+const coherenceModeSelectData: IAISelectDataType[] = [
+ { label: 'Full', value: 'full' },
+ { label: 'Edge', value: 'edge' },
+];
+
+const ParamCanvasCoherenceMode = () => {
+ const dispatch = useAppDispatch();
+ const canvasCoherenceMode = useAppSelector(
+ (state: RootState) => state.generation.canvasCoherenceMode
+ );
+ const { t } = useTranslation();
+
+ const handleCoherenceModeChange = (v: string | null) => {
+ if (!v) {
+ return;
+ }
+
+ dispatch(setCanvasCoherenceMode(v as CanvasCoherenceModeParam));
+ };
+
+ return (
+
+ );
+};
+
+export default memo(ParamCanvasCoherenceMode);
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx
index c3c978e8a1..e06287c7c7 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/Compositing/ParamCompositingSettingsCollapse.tsx
@@ -3,6 +3,7 @@ import IAICollapse from 'common/components/IAICollapse';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import SubParametersWrapper from '../../SubParametersWrapper';
+import ParamCanvasCoherenceMode from './CoherencePass/ParamCanvasCoherenceMode';
import ParamCanvasCoherenceSteps from './CoherencePass/ParamCanvasCoherenceSteps';
import ParamCanvasCoherenceStrength from './CoherencePass/ParamCanvasCoherenceStrength';
import ParamMaskBlur from './MaskAdjustment/ParamMaskBlur';
@@ -20,6 +21,7 @@ const ParamCompositingSettingsCollapse = () => {
+
diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
index 7bbfc5149d..7703376e43 100644
--- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
+++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
@@ -7,6 +7,7 @@ import { ImageDTO } from 'services/api/types';
import { clipSkipMap } from '../types/constants';
import {
+ CanvasCoherenceModeParam,
CfgScaleParam,
HeightParam,
MainModelParam,
@@ -37,6 +38,7 @@ export interface GenerationState {
scheduler: SchedulerParam;
maskBlur: number;
maskBlurMethod: MaskBlurMethodParam;
+ canvasCoherenceMode: CanvasCoherenceModeParam;
canvasCoherenceSteps: number;
canvasCoherenceStrength: StrengthParam;
seed: SeedParam;
@@ -78,6 +80,7 @@ export const initialGenerationState: GenerationState = {
scheduler: 'euler',
maskBlur: 16,
maskBlurMethod: 'box',
+ canvasCoherenceMode: 'edge',
canvasCoherenceSteps: 20,
canvasCoherenceStrength: 0.3,
seed: 0,
@@ -208,6 +211,12 @@ export const generationSlice = createSlice({
setMaskBlurMethod: (state, action: PayloadAction) => {
state.maskBlurMethod = action.payload;
},
+ setCanvasCoherenceMode: (
+ state,
+ action: PayloadAction
+ ) => {
+ state.canvasCoherenceMode = action.payload;
+ },
setCanvasCoherenceSteps: (state, action: PayloadAction) => {
state.canvasCoherenceSteps = action.payload;
},
@@ -331,6 +340,7 @@ export const {
setScheduler,
setMaskBlur,
setMaskBlurMethod,
+ setCanvasCoherenceMode,
setCanvasCoherenceSteps,
setCanvasCoherenceStrength,
setSeed,
diff --git a/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts b/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts
index e210efc414..e53749582b 100644
--- a/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts
+++ b/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts
@@ -418,6 +418,22 @@ export const isValidMaskBlurMethod = (
val: unknown
): val is MaskBlurMethodParam => zMaskBlurMethod.safeParse(val).success;
+/**
+ * Zod schema for a Canvas Coherence Mode method parameter
+ */
+export const zCanvasCoherenceMode = z.enum(['full', 'edge']);
+/**
+ * Type alias for Canvas Coherence Mode parameter, inferred from its zod schema
+ */
+export type CanvasCoherenceModeParam = z.infer;
+/**
+ * Validates/type-guards a value as a mask blur method parameter
+ */
+export const isValidCoherenceModeParam = (
+ val: unknown
+): val is CanvasCoherenceModeParam =>
+ zCanvasCoherenceMode.safeParse(val).success;
+
// /**
// * Zod schema for BaseModelType
// */