mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat: Add Paste / Mask Blur / Color Correction to Inpainting
Seam options are now removed. They are replaced by two options --Mask Blur and Mask Blur Method .. which control the softness of the mask that is being painted.
This commit is contained in:
parent
69a9dc7b36
commit
1affb7f647
@ -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",
|
||||
|
@ -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',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -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 (
|
||||
<IAICollapse label={t('parameters.maskAdjustmentsHeader')}>
|
||||
<Flex sx={{ flexDirection: 'column', gap: 2 }}>
|
||||
<ParamMaskBlur />
|
||||
<ParamMaskBlurMethod />
|
||||
</Flex>
|
||||
</IAICollapse>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ParamMaskAdjustmentCollapse);
|
@ -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 (
|
||||
<IAISlider
|
||||
label={t('parameters.seamBlur')}
|
||||
label={t('parameters.maskBlur')}
|
||||
min={0}
|
||||
max={64}
|
||||
sliderNumberInputProps={{ max: 512 }}
|
||||
value={seamBlur}
|
||||
value={maskBlur}
|
||||
onChange={(v) => {
|
||||
dispatch(setSeamBlur(v));
|
||||
dispatch(setMaskBlur(v));
|
||||
}}
|
||||
withInput
|
||||
withSliderMarks
|
||||
withReset
|
||||
handleReset={() => {
|
||||
dispatch(setSeamBlur(16));
|
||||
dispatch(setMaskBlur(16));
|
||||
}}
|
||||
/>
|
||||
);
|
@ -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 (
|
||||
<IAIMantineSelect
|
||||
value={maskBlurMethod}
|
||||
onChange={handleMaskBlurMethodChange}
|
||||
label={t('parameters.maskBlurMethod')}
|
||||
data={maskBlurMethods}
|
||||
/>
|
||||
);
|
||||
}
|
@ -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 (
|
||||
<IAICollapse label={t('parameters.seamCorrectionHeader')}>
|
||||
<ParamSeamSize />
|
||||
<ParamSeamBlur />
|
||||
<ParamSeamStrength />
|
||||
<ParamSeamSteps />
|
||||
</IAICollapse>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ParamSeamCorrectionCollapse);
|
@ -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 (
|
||||
<IAISlider
|
||||
label={t('parameters.seamSize')}
|
||||
min={1}
|
||||
max={256}
|
||||
sliderNumberInputProps={{ max: 512 }}
|
||||
value={seamSize}
|
||||
onChange={(v) => {
|
||||
dispatch(setSeamSize(v));
|
||||
}}
|
||||
withInput
|
||||
withSliderMarks
|
||||
withReset
|
||||
handleReset={() => dispatch(setSeamSize(96))}
|
||||
/>
|
||||
);
|
||||
}
|
@ -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 (
|
||||
<IAISlider
|
||||
label={t('parameters.seamSteps')}
|
||||
min={1}
|
||||
max={100}
|
||||
sliderNumberInputProps={{ max: 999 }}
|
||||
value={seamSteps}
|
||||
onChange={(v) => {
|
||||
dispatch(setSeamSteps(v));
|
||||
}}
|
||||
withInput
|
||||
withSliderMarks
|
||||
withReset
|
||||
handleReset={() => {
|
||||
dispatch(setSeamSteps(30));
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
@ -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 (
|
||||
<IAISlider
|
||||
label={t('parameters.seamStrength')}
|
||||
min={0.01}
|
||||
max={0.99}
|
||||
step={0.01}
|
||||
value={seamStrength}
|
||||
onChange={(v) => {
|
||||
dispatch(setSeamStrength(v));
|
||||
}}
|
||||
withInput
|
||||
withSliderMarks
|
||||
withReset
|
||||
handleReset={() => {
|
||||
dispatch(setSeamStrength(0.7));
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
@ -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<number>) => {
|
||||
state.seamSize = action.payload;
|
||||
setMaskBlur: (state, action: PayloadAction<number>) => {
|
||||
state.maskBlur = action.payload;
|
||||
},
|
||||
setSeamBlur: (state, action: PayloadAction<number>) => {
|
||||
state.seamBlur = action.payload;
|
||||
},
|
||||
setSeamStrength: (state, action: PayloadAction<number>) => {
|
||||
state.seamStrength = action.payload;
|
||||
},
|
||||
setSeamSteps: (state, action: PayloadAction<number>) => {
|
||||
state.seamSteps = action.payload;
|
||||
setMaskBlurMethod: (state, action: PayloadAction<MaskBlurMethods>) => {
|
||||
state.maskBlurMethod = action.payload;
|
||||
},
|
||||
setTileSize: (state, action: PayloadAction<number>) => {
|
||||
state.tileSize = action.payload;
|
||||
@ -312,10 +303,8 @@ export const {
|
||||
setPositivePrompt,
|
||||
setNegativePrompt,
|
||||
setScheduler,
|
||||
setSeamBlur,
|
||||
setSeamSize,
|
||||
setSeamSteps,
|
||||
setSeamStrength,
|
||||
setMaskBlur,
|
||||
setMaskBlurMethod,
|
||||
setSeed,
|
||||
setSeedWeights,
|
||||
setShouldFitToWidthHeight,
|
||||
|
@ -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 = () => {
|
||||
<ParamDynamicPromptsCollapse />
|
||||
{/* <ParamVariationCollapse /> */}
|
||||
<ParamSymmetryCollapse />
|
||||
<ParamSeamCorrectionCollapse />
|
||||
<ParamMaskAdjustmentCollapse />
|
||||
<ParamInfillAndScalingCollapse />
|
||||
<ParamAdvancedCollapse />
|
||||
</>
|
||||
|
Loading…
Reference in New Issue
Block a user