mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat: Add Seam Painting Options
This commit is contained in:
parent
611e241ca7
commit
e98d7a52d4
@ -506,10 +506,14 @@
|
|||||||
"maskAdjustmentsHeader": "Mask Adjustments",
|
"maskAdjustmentsHeader": "Mask Adjustments",
|
||||||
"maskBlur": "Mask Blur",
|
"maskBlur": "Mask Blur",
|
||||||
"maskBlurMethod": "Mask Blur Method",
|
"maskBlurMethod": "Mask Blur Method",
|
||||||
|
"seamPaintingHeader": "Seam Painting",
|
||||||
"seamSize": "Seam Size",
|
"seamSize": "Seam Size",
|
||||||
"seamBlur": "Seam Blur",
|
"seamBlur": "Seam Blur",
|
||||||
"seamStrength": "Seam Strength",
|
|
||||||
"seamSteps": "Seam Steps",
|
"seamSteps": "Seam Steps",
|
||||||
|
"seamStrength": "Seam Strength",
|
||||||
|
"seamThreshold": "Seam Threshold",
|
||||||
|
"seamLowThreshold": "Low",
|
||||||
|
"seamHighThreshold": "High",
|
||||||
"scaleBeforeProcessing": "Scale Before Processing",
|
"scaleBeforeProcessing": "Scale Before Processing",
|
||||||
"scaledWidth": "Scaled W",
|
"scaledWidth": "Scaled W",
|
||||||
"scaledHeight": "Scaled H",
|
"scaledHeight": "Scaled H",
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
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 { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const ParamSeamBlur = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const seamBlur = useAppSelector(
|
||||||
|
(state: RootState) => state.generation.seamBlur
|
||||||
|
);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
label={t('parameters.seamBlur')}
|
||||||
|
min={0}
|
||||||
|
max={64}
|
||||||
|
step={8}
|
||||||
|
sliderNumberInputProps={{ max: 512 }}
|
||||||
|
value={seamBlur}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamBlur(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamBlur(8));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ParamSeamBlur);
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Flex } from '@chakra-ui/react';
|
||||||
|
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';
|
||||||
|
import ParamSeamThreshold from './ParamSeamThreshold';
|
||||||
|
|
||||||
|
const ParamSeamPaintingCollapse = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAICollapse label={t('parameters.seamPaintingHeader')}>
|
||||||
|
<Flex sx={{ flexDirection: 'column', gap: 2, paddingBottom: 2 }}>
|
||||||
|
<ParamSeamSize />
|
||||||
|
<ParamSeamBlur />
|
||||||
|
<ParamSeamSteps />
|
||||||
|
<ParamSeamStrength />
|
||||||
|
<ParamSeamThreshold />
|
||||||
|
</Flex>
|
||||||
|
</IAICollapse>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ParamSeamPaintingCollapse);
|
@ -0,0 +1,36 @@
|
|||||||
|
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 { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const ParamSeamSize = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const seamSize = useAppSelector(
|
||||||
|
(state: RootState) => state.generation.seamSize
|
||||||
|
);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
label={t('parameters.seamSize')}
|
||||||
|
min={0}
|
||||||
|
max={128}
|
||||||
|
step={8}
|
||||||
|
sliderNumberInputProps={{ max: 512 }}
|
||||||
|
value={seamSize}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamSize(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamSize(16));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ParamSeamSize);
|
@ -0,0 +1,36 @@
|
|||||||
|
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 { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const ParamSeamSteps = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const seamSteps = useAppSelector(
|
||||||
|
(state: RootState) => state.generation.seamSteps
|
||||||
|
);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
label={t('parameters.seamSteps')}
|
||||||
|
min={0}
|
||||||
|
max={100}
|
||||||
|
step={1}
|
||||||
|
sliderNumberInputProps={{ max: 999 }}
|
||||||
|
value={seamSteps}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamSteps(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamSteps(20));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ParamSeamSteps);
|
@ -0,0 +1,36 @@
|
|||||||
|
import type { 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 { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const ParamSeamStrength = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const seamStrength = useAppSelector(
|
||||||
|
(state: RootState) => state.generation.seamStrength
|
||||||
|
);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAISlider
|
||||||
|
label={t('parameters.seamStrength')}
|
||||||
|
min={0}
|
||||||
|
max={1}
|
||||||
|
step={0.01}
|
||||||
|
sliderNumberInputProps={{ max: 999 }}
|
||||||
|
value={seamStrength}
|
||||||
|
onChange={(v) => {
|
||||||
|
dispatch(setSeamStrength(v));
|
||||||
|
}}
|
||||||
|
withInput
|
||||||
|
withSliderMarks
|
||||||
|
withReset
|
||||||
|
handleReset={() => {
|
||||||
|
dispatch(setSeamStrength(0.7));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ParamSeamStrength);
|
@ -0,0 +1,121 @@
|
|||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
HStack,
|
||||||
|
RangeSlider,
|
||||||
|
RangeSliderFilledTrack,
|
||||||
|
RangeSliderMark,
|
||||||
|
RangeSliderThumb,
|
||||||
|
RangeSliderTrack,
|
||||||
|
Tooltip,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import type { RootState } from 'app/store/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
|
import {
|
||||||
|
setSeamHighThreshold,
|
||||||
|
setSeamLowThreshold,
|
||||||
|
} from 'features/parameters/store/generationSlice';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BiReset } from 'react-icons/bi';
|
||||||
|
|
||||||
|
const ParamSeamThreshold = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const seamLowThreshold = useAppSelector(
|
||||||
|
(state: RootState) => state.generation.seamLowThreshold
|
||||||
|
);
|
||||||
|
|
||||||
|
const seamHighThreshold = useAppSelector(
|
||||||
|
(state: RootState) => state.generation.seamHighThreshold
|
||||||
|
);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const handleSeamThresholdChange = useCallback(
|
||||||
|
(v: number[]) => {
|
||||||
|
dispatch(setSeamLowThreshold(v[0] as number));
|
||||||
|
dispatch(setSeamHighThreshold(v[1] as number));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSeamThresholdReset = () => {
|
||||||
|
dispatch(setSeamLowThreshold(100));
|
||||||
|
dispatch(setSeamHighThreshold(200));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('parameters.seamThreshold')}</FormLabel>
|
||||||
|
<HStack w="100%" gap={4} mt={-2}>
|
||||||
|
<RangeSlider
|
||||||
|
aria-label={[
|
||||||
|
t('parameters.seamLowThreshold'),
|
||||||
|
t('parameters.seamHighThreshold'),
|
||||||
|
]}
|
||||||
|
value={[seamLowThreshold, seamHighThreshold]}
|
||||||
|
min={0}
|
||||||
|
max={255}
|
||||||
|
step={1}
|
||||||
|
minStepsBetweenThumbs={1}
|
||||||
|
onChange={handleSeamThresholdChange}
|
||||||
|
>
|
||||||
|
<RangeSliderTrack>
|
||||||
|
<RangeSliderFilledTrack />
|
||||||
|
</RangeSliderTrack>
|
||||||
|
<Tooltip label={seamLowThreshold} placement="top" hasArrow>
|
||||||
|
<RangeSliderThumb index={0} />
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip label={seamHighThreshold} placement="top" hasArrow>
|
||||||
|
<RangeSliderThumb index={1} />
|
||||||
|
</Tooltip>
|
||||||
|
<RangeSliderMark
|
||||||
|
value={0}
|
||||||
|
sx={{
|
||||||
|
insetInlineStart: '0 !important',
|
||||||
|
insetInlineEnd: 'unset !important',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
0
|
||||||
|
</RangeSliderMark>
|
||||||
|
<RangeSliderMark
|
||||||
|
value={0.392}
|
||||||
|
sx={{
|
||||||
|
insetInlineStart: '38.4% !important',
|
||||||
|
transform: 'translateX(-38.4%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
100
|
||||||
|
</RangeSliderMark>
|
||||||
|
<RangeSliderMark
|
||||||
|
value={0.784}
|
||||||
|
sx={{
|
||||||
|
insetInlineStart: '79.8% !important',
|
||||||
|
transform: 'translateX(-79.8%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
200
|
||||||
|
</RangeSliderMark>
|
||||||
|
<RangeSliderMark
|
||||||
|
value={1}
|
||||||
|
sx={{
|
||||||
|
insetInlineStart: 'unset !important',
|
||||||
|
insetInlineEnd: '0 !important',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
255
|
||||||
|
</RangeSliderMark>
|
||||||
|
</RangeSlider>
|
||||||
|
<IAIIconButton
|
||||||
|
size="sm"
|
||||||
|
aria-label={t('accessibility.reset')}
|
||||||
|
tooltip={t('accessibility.reset')}
|
||||||
|
icon={<BiReset />}
|
||||||
|
onClick={handleSeamThresholdReset}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ParamSeamThreshold);
|
@ -37,6 +37,12 @@ export interface GenerationState {
|
|||||||
scheduler: SchedulerParam;
|
scheduler: SchedulerParam;
|
||||||
maskBlur: number;
|
maskBlur: number;
|
||||||
maskBlurMethod: MaskBlurMethodParam;
|
maskBlurMethod: MaskBlurMethodParam;
|
||||||
|
seamSize: number;
|
||||||
|
seamBlur: number;
|
||||||
|
seamSteps: number;
|
||||||
|
seamStrength: StrengthParam;
|
||||||
|
seamLowThreshold: number;
|
||||||
|
seamHighThreshold: number;
|
||||||
seed: SeedParam;
|
seed: SeedParam;
|
||||||
seedWeights: string;
|
seedWeights: string;
|
||||||
shouldFitToWidthHeight: boolean;
|
shouldFitToWidthHeight: boolean;
|
||||||
@ -74,6 +80,12 @@ export const initialGenerationState: GenerationState = {
|
|||||||
scheduler: 'euler',
|
scheduler: 'euler',
|
||||||
maskBlur: 16,
|
maskBlur: 16,
|
||||||
maskBlurMethod: 'box',
|
maskBlurMethod: 'box',
|
||||||
|
seamSize: 16,
|
||||||
|
seamBlur: 8,
|
||||||
|
seamSteps: 20,
|
||||||
|
seamStrength: 0.7,
|
||||||
|
seamLowThreshold: 100,
|
||||||
|
seamHighThreshold: 200,
|
||||||
seed: 0,
|
seed: 0,
|
||||||
seedWeights: '',
|
seedWeights: '',
|
||||||
shouldFitToWidthHeight: true,
|
shouldFitToWidthHeight: true,
|
||||||
@ -200,6 +212,24 @@ export const generationSlice = createSlice({
|
|||||||
setMaskBlurMethod: (state, action: PayloadAction<MaskBlurMethodParam>) => {
|
setMaskBlurMethod: (state, action: PayloadAction<MaskBlurMethodParam>) => {
|
||||||
state.maskBlurMethod = action.payload;
|
state.maskBlurMethod = action.payload;
|
||||||
},
|
},
|
||||||
|
setSeamSize: (state, action: PayloadAction<number>) => {
|
||||||
|
state.seamSize = action.payload;
|
||||||
|
},
|
||||||
|
setSeamBlur: (state, action: PayloadAction<number>) => {
|
||||||
|
state.seamBlur = action.payload;
|
||||||
|
},
|
||||||
|
setSeamSteps: (state, action: PayloadAction<number>) => {
|
||||||
|
state.seamSteps = action.payload;
|
||||||
|
},
|
||||||
|
setSeamStrength: (state, action: PayloadAction<number>) => {
|
||||||
|
state.seamStrength = action.payload;
|
||||||
|
},
|
||||||
|
setSeamLowThreshold: (state, action: PayloadAction<number>) => {
|
||||||
|
state.seamLowThreshold = action.payload;
|
||||||
|
},
|
||||||
|
setSeamHighThreshold: (state, action: PayloadAction<number>) => {
|
||||||
|
state.seamHighThreshold = action.payload;
|
||||||
|
},
|
||||||
setTileSize: (state, action: PayloadAction<number>) => {
|
setTileSize: (state, action: PayloadAction<number>) => {
|
||||||
state.tileSize = action.payload;
|
state.tileSize = action.payload;
|
||||||
},
|
},
|
||||||
@ -306,6 +336,12 @@ export const {
|
|||||||
setScheduler,
|
setScheduler,
|
||||||
setMaskBlur,
|
setMaskBlur,
|
||||||
setMaskBlurMethod,
|
setMaskBlurMethod,
|
||||||
|
setSeamSize,
|
||||||
|
setSeamBlur,
|
||||||
|
setSeamSteps,
|
||||||
|
setSeamStrength,
|
||||||
|
setSeamLowThreshold,
|
||||||
|
setSeamHighThreshold,
|
||||||
setSeed,
|
setSeed,
|
||||||
setSeedWeights,
|
setSeedWeights,
|
||||||
setShouldFitToWidthHeight,
|
setShouldFitToWidthHeight,
|
||||||
|
@ -2,6 +2,7 @@ import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/Para
|
|||||||
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse';
|
||||||
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
|
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
|
||||||
import ParamMaskAdjustmentCollapse from 'features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse';
|
import ParamMaskAdjustmentCollapse from 'features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse';
|
||||||
|
import ParamSeamPaintingCollapse from 'features/parameters/components/Parameters/Canvas/SeamPainting/ParamSeamPaintingCollapse';
|
||||||
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
||||||
import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse';
|
import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse';
|
||||||
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
|
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
|
||||||
@ -22,6 +23,7 @@ export default function SDXLUnifiedCanvasTabParameters() {
|
|||||||
<ParamNoiseCollapse />
|
<ParamNoiseCollapse />
|
||||||
<ParamMaskAdjustmentCollapse />
|
<ParamMaskAdjustmentCollapse />
|
||||||
<ParamInfillAndScalingCollapse />
|
<ParamInfillAndScalingCollapse />
|
||||||
|
<ParamSeamPaintingCollapse />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import ParamControlNetCollapse from 'features/parameters/components/Parameters/C
|
|||||||
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
||||||
// import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse';
|
// import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse';
|
||||||
import ParamMaskAdjustmentCollapse from 'features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse';
|
import ParamMaskAdjustmentCollapse from 'features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse';
|
||||||
|
import ParamSeamPaintingCollapse from 'features/parameters/components/Parameters/Canvas/SeamPainting/ParamSeamPaintingCollapse';
|
||||||
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
|
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
|
||||||
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
|
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
|
||||||
import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters';
|
import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters';
|
||||||
@ -23,6 +24,7 @@ const UnifiedCanvasParameters = () => {
|
|||||||
<ParamSymmetryCollapse />
|
<ParamSymmetryCollapse />
|
||||||
<ParamMaskAdjustmentCollapse />
|
<ParamMaskAdjustmentCollapse />
|
||||||
<ParamInfillAndScalingCollapse />
|
<ParamInfillAndScalingCollapse />
|
||||||
|
<ParamSeamPaintingCollapse />
|
||||||
<ParamAdvancedCollapse />
|
<ParamAdvancedCollapse />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user