diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index 63380a19fa..fbae5b4a30 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -503,6 +503,9 @@
"hiresStrength": "High Res Strength",
"imageFit": "Fit Initial Image To Output Size",
"codeformerFidelity": "Fidelity",
+ "maskAdjustmentsHeader": "Mask Adjustments",
+ "maskBlur": "Mask Blur",
+ "maskBlurMethod": "Mask Blur Method",
"seamSize": "Seam Size",
"seamBlur": "Seam Blur",
"seamStrength": "Seam Strength",
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 892cdc2d7c..817e8d5176 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts
@@ -13,12 +13,15 @@ import { addVAEToGraph } from './addVAEToGraph';
import { addWatermarkerToGraph } from './addWatermarkerToGraph';
import {
CLIP_SKIP,
+ COLOR_CORRECT,
INPAINT,
+ INPAINT_FINAL_IMAGE,
INPAINT_GRAPH,
INPAINT_IMAGE,
ITERATE,
LATENTS_TO_IMAGE,
MAIN_MODEL_LOADER,
+ MASK_BLUR,
NEGATIVE_CONDITIONING,
NOISE,
POSITIVE_CONDITIONING,
@@ -50,10 +53,8 @@ export const buildCanvasInpaintGraph = (
vaePrecision,
shouldUseNoiseSettings,
shouldUseCpuNoise,
- seamSize,
- seamBlur,
- seamSteps,
- seamStrength,
+ maskBlur,
+ maskBlurMethod,
tileSize,
infillMethod,
clipSkip,
@@ -90,7 +91,6 @@ export const buildCanvasInpaintGraph = (
scheduler: scheduler,
denoising_start: 1 - strength,
denoising_end: 1,
- mask: canvasMaskImage,
},
[INPAINT_IMAGE]: {
type: 'i2l',
@@ -137,7 +137,27 @@ export const buildCanvasInpaintGraph = (
is_intermediate: true,
skipped_layers: clipSkip,
},
-
+ [COLOR_CORRECT]: {
+ type: 'color_correct',
+ id: COLOR_CORRECT,
+ is_intermediate: true,
+ reference: canvasInitImage,
+ mask: canvasMaskImage,
+ },
+ [MASK_BLUR]: {
+ type: 'img_blur',
+ id: MASK_BLUR,
+ is_intermediate: true,
+ image: canvasMaskImage,
+ radius: maskBlur,
+ blur_type: maskBlurMethod,
+ },
+ [INPAINT_FINAL_IMAGE]: {
+ type: 'img_paste',
+ id: INPAINT_FINAL_IMAGE,
+ is_intermediate: true,
+ base_image: canvasInitImage,
+ },
[RANGE_OF_SIZE]: {
type: 'range_of_size',
id: RANGE_OF_SIZE,
@@ -234,6 +254,16 @@ export const buildCanvasInpaintGraph = (
field: 'latents',
},
},
+ {
+ source: {
+ node_id: MASK_BLUR,
+ field: 'image',
+ },
+ destination: {
+ node_id: INPAINT,
+ field: 'mask',
+ },
+ },
{
source: {
node_id: RANGE_OF_SIZE,
@@ -264,6 +294,36 @@ export const buildCanvasInpaintGraph = (
field: 'latents',
},
},
+ {
+ source: {
+ node_id: LATENTS_TO_IMAGE,
+ field: 'image',
+ },
+ destination: {
+ node_id: COLOR_CORRECT,
+ field: 'image',
+ },
+ },
+ {
+ source: {
+ node_id: MASK_BLUR,
+ field: 'image',
+ },
+ destination: {
+ node_id: INPAINT_FINAL_IMAGE,
+ field: 'mask',
+ },
+ },
+ {
+ source: {
+ node_id: COLOR_CORRECT,
+ field: 'image',
+ },
+ destination: {
+ node_id: INPAINT_FINAL_IMAGE,
+ field: 'image',
+ },
+ },
],
};
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse.tsx
new file mode 100644
index 0000000000..9ca6503d3d
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse.tsx
@@ -0,0 +1,21 @@
+import { Flex } from '@chakra-ui/react';
+import IAICollapse from 'common/components/IAICollapse';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+import ParamMaskBlur from './ParamMaskBlur';
+import ParamMaskBlurMethod from './ParamMaskBlurMethod';
+
+const ParamMaskAdjustmentCollapse = () => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default memo(ParamMaskAdjustmentCollapse);
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamBlur.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlur.tsx
similarity index 62%
rename from invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamBlur.tsx
rename to invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlur.tsx
index 5c20ba7a13..82b82228e2 100644
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamBlur.tsx
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlur.tsx
@@ -1,31 +1,31 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
-import { setSeamBlur } from 'features/parameters/store/generationSlice';
+import { setMaskBlur } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
-export default function ParamSeamBlur() {
+export default function ParamMaskBlur() {
const dispatch = useAppDispatch();
- const seamBlur = useAppSelector(
- (state: RootState) => state.generation.seamBlur
+ const maskBlur = useAppSelector(
+ (state: RootState) => state.generation.maskBlur
);
const { t } = useTranslation();
return (
{
- dispatch(setSeamBlur(v));
+ dispatch(setMaskBlur(v));
}}
withInput
withSliderMarks
withReset
handleReset={() => {
- dispatch(setSeamBlur(16));
+ dispatch(setMaskBlur(16));
}}
/>
);
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod.tsx
new file mode 100644
index 0000000000..b45dc8b884
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod.tsx
@@ -0,0 +1,36 @@
+import { SelectItem } from '@mantine/core';
+import { RootState } from 'app/store/store';
+
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIMantineSelect from 'common/components/IAIMantineSelect';
+import { setMaskBlurMethod } from 'features/parameters/store/generationSlice';
+import { useTranslation } from 'react-i18next';
+
+export type MaskBlurMethods = 'box' | 'gaussian';
+
+const maskBlurMethods: SelectItem[] = [
+ { label: 'Box Blur', value: 'box' },
+ { label: 'Gaussian Blur', value: 'gaussian' },
+];
+
+export default function ParamMaskBlurMethod() {
+ const maskBlurMethod = useAppSelector(
+ (state: RootState) => state.generation.maskBlurMethod
+ );
+ const dispatch = useAppDispatch();
+ const { t } = useTranslation();
+
+ const handleMaskBlurMethodChange = (v: string | null) => {
+ if (!v) return;
+ dispatch(setMaskBlurMethod(v as MaskBlurMethods));
+ };
+
+ return (
+
+ );
+}
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse.tsx
deleted file mode 100644
index 88d839fa15..0000000000
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import IAICollapse from 'common/components/IAICollapse';
-import { memo } from 'react';
-import { useTranslation } from 'react-i18next';
-import ParamSeamBlur from './ParamSeamBlur';
-import ParamSeamSize from './ParamSeamSize';
-import ParamSeamSteps from './ParamSeamSteps';
-import ParamSeamStrength from './ParamSeamStrength';
-
-const ParamSeamCorrectionCollapse = () => {
- const { t } = useTranslation();
-
- return (
-
-
-
-
-
-
- );
-};
-
-export default memo(ParamSeamCorrectionCollapse);
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSize.tsx
deleted file mode 100644
index 8e56cded7b..0000000000
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSize.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { RootState } from 'app/store/store';
-import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
-import IAISlider from 'common/components/IAISlider';
-import { setSeamSize } from 'features/parameters/store/generationSlice';
-import { useTranslation } from 'react-i18next';
-
-export default function ParamSeamSize() {
- const dispatch = useAppDispatch();
- const { t } = useTranslation();
-
- const seamSize = useAppSelector(
- (state: RootState) => state.generation.seamSize
- );
-
- return (
- {
- dispatch(setSeamSize(v));
- }}
- withInput
- withSliderMarks
- withReset
- handleReset={() => dispatch(setSeamSize(96))}
- />
- );
-}
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSteps.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSteps.tsx
deleted file mode 100644
index 8ca5226621..0000000000
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSteps.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import type { RootState } from 'app/store/store';
-import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
-import IAISlider from 'common/components/IAISlider';
-import { setSeamSteps } from 'features/parameters/store/generationSlice';
-import { useTranslation } from 'react-i18next';
-
-export default function ParamSeamSteps() {
- const { t } = useTranslation();
- const seamSteps = useAppSelector(
- (state: RootState) => state.generation.seamSteps
- );
- const dispatch = useAppDispatch();
-
- return (
- {
- dispatch(setSeamSteps(v));
- }}
- withInput
- withSliderMarks
- withReset
- handleReset={() => {
- dispatch(setSeamSteps(30));
- }}
- />
- );
-}
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamStrength.tsx
deleted file mode 100644
index de74156cd3..0000000000
--- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamStrength.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { RootState } from 'app/store/store';
-import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
-import IAISlider from 'common/components/IAISlider';
-import { setSeamStrength } from 'features/parameters/store/generationSlice';
-import { useTranslation } from 'react-i18next';
-
-export default function ParamSeamStrength() {
- const dispatch = useAppDispatch();
- const { t } = useTranslation();
- const seamStrength = useAppSelector(
- (state: RootState) => state.generation.seamStrength
- );
-
- return (
- {
- dispatch(setSeamStrength(v));
- }}
- withInput
- withSliderMarks
- withReset
- handleReset={() => {
- dispatch(setSeamStrength(0.7));
- }}
- />
- );
-}
diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
index 12f2c3eabf..33a76da4e6 100644
--- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
+++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
@@ -4,6 +4,7 @@ import { roundToMultiple } from 'common/util/roundDownToMultiple';
import { configChanged } from 'features/system/store/configSlice';
import { clamp } from 'lodash-es';
import { ImageDTO } from 'services/api/types';
+import { MaskBlurMethods } from '../components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod';
import { clipSkipMap } from '../types/constants';
import {
CfgScaleParam,
@@ -33,10 +34,8 @@ export interface GenerationState {
positivePrompt: PositivePromptParam;
negativePrompt: NegativePromptParam;
scheduler: SchedulerParam;
- seamBlur: number;
- seamSize: number;
- seamSteps: number;
- seamStrength: number;
+ maskBlur: number;
+ maskBlurMethod: MaskBlurMethods;
seed: SeedParam;
seedWeights: string;
shouldFitToWidthHeight: boolean;
@@ -72,10 +71,8 @@ export const initialGenerationState: GenerationState = {
positivePrompt: '',
negativePrompt: '',
scheduler: 'euler',
- seamBlur: 16,
- seamSize: 96,
- seamSteps: 30,
- seamStrength: 0.7,
+ maskBlur: 16,
+ maskBlurMethod: 'box',
seed: 0,
seedWeights: '',
shouldFitToWidthHeight: true,
@@ -196,17 +193,11 @@ export const generationSlice = createSlice({
clearInitialImage: (state) => {
state.initialImage = undefined;
},
- setSeamSize: (state, action: PayloadAction) => {
- state.seamSize = action.payload;
+ setMaskBlur: (state, action: PayloadAction) => {
+ state.maskBlur = action.payload;
},
- setSeamBlur: (state, action: PayloadAction) => {
- state.seamBlur = action.payload;
- },
- setSeamStrength: (state, action: PayloadAction) => {
- state.seamStrength = action.payload;
- },
- setSeamSteps: (state, action: PayloadAction) => {
- state.seamSteps = action.payload;
+ setMaskBlurMethod: (state, action: PayloadAction) => {
+ state.maskBlurMethod = action.payload;
},
setTileSize: (state, action: PayloadAction) => {
state.tileSize = action.payload;
@@ -312,10 +303,8 @@ export const {
setPositivePrompt,
setNegativePrompt,
setScheduler,
- setSeamBlur,
- setSeamSize,
- setSeamSteps,
- setSeamStrength,
+ setMaskBlur,
+ setMaskBlurMethod,
setSeed,
setSeedWeights,
setShouldFitToWidthHeight,
diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx
index de7ce3b084..fcfffee48b 100644
--- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx
@@ -2,10 +2,10 @@ import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/Para
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse';
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
-import ParamSeamCorrectionCollapse from 'features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse';
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
// import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse';
+import ParamMaskAdjustmentCollapse from 'features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse';
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters';
@@ -21,7 +21,7 @@ const UnifiedCanvasParameters = () => {
{/* */}
-
+
>