mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): add optimized denoising toggle to linear UI for FLUX image to image and inpainting
This commit is contained in:
@@ -40,6 +40,7 @@ export type ParamsState = {
|
||||
cfgRescaleMultiplier: ParameterCFGRescaleMultiplier;
|
||||
guidance: ParameterGuidance;
|
||||
img2imgStrength: ParameterStrength;
|
||||
optimizedDenoisingEnabled: boolean;
|
||||
iterations: number;
|
||||
scheduler: ParameterScheduler;
|
||||
seed: ParameterSeed;
|
||||
@@ -83,6 +84,7 @@ const initialState: ParamsState = {
|
||||
cfgRescaleMultiplier: 0,
|
||||
guidance: 4,
|
||||
img2imgStrength: 0.75,
|
||||
optimizedDenoisingEnabled: true,
|
||||
iterations: 1,
|
||||
scheduler: 'euler',
|
||||
seed: 0,
|
||||
@@ -141,6 +143,9 @@ export const paramsSlice = createSlice({
|
||||
setImg2imgStrength: (state, action: PayloadAction<number>) => {
|
||||
state.img2imgStrength = action.payload;
|
||||
},
|
||||
setOptimizedDenoisingEnabled: (state, action: PayloadAction<boolean>) => {
|
||||
state.optimizedDenoisingEnabled = action.payload;
|
||||
},
|
||||
setSeamlessXAxis: (state, action: PayloadAction<boolean>) => {
|
||||
state.seamlessXAxis = action.payload;
|
||||
},
|
||||
@@ -273,6 +278,7 @@ export const {
|
||||
setScheduler,
|
||||
setSeed,
|
||||
setImg2imgStrength,
|
||||
setOptimizedDenoisingEnabled,
|
||||
setSeamlessXAxis,
|
||||
setSeamlessYAxis,
|
||||
setShouldRandomizeSeed,
|
||||
@@ -341,6 +347,7 @@ export const selectInfillPatchmatchDownscaleSize = createParamsSelector(
|
||||
);
|
||||
export const selectInfillColorValue = createParamsSelector((params) => params.infillColorValue);
|
||||
export const selectImg2imgStrength = createParamsSelector((params) => params.img2imgStrength);
|
||||
export const selectOptimizedDenoisingEnabled = createParamsSelector((params) => params.optimizedDenoisingEnabled);
|
||||
export const selectPositivePrompt = createParamsSelector((params) => params.positivePrompt);
|
||||
export const selectNegativePrompt = createParamsSelector((params) => params.negativePrompt);
|
||||
export const selectPositivePrompt2 = createParamsSelector((params) => params.positivePrompt2);
|
||||
|
||||
@@ -37,7 +37,17 @@ export const buildFLUXGraph = async (
|
||||
|
||||
const { originalSize, scaledSize } = getSizes(bbox);
|
||||
|
||||
const { model, guidance, seed, steps, fluxVAE, t5EncoderModel, clipEmbedModel, img2imgStrength } = params;
|
||||
const {
|
||||
model,
|
||||
guidance,
|
||||
seed,
|
||||
steps,
|
||||
fluxVAE,
|
||||
t5EncoderModel,
|
||||
clipEmbedModel,
|
||||
img2imgStrength,
|
||||
optimizedDenoisingEnabled,
|
||||
} = params;
|
||||
|
||||
assert(model, 'No model found in state');
|
||||
assert(t5EncoderModel, 'No T5 Encoder model found in state');
|
||||
@@ -68,7 +78,8 @@ export const buildFLUXGraph = async (
|
||||
guidance,
|
||||
num_steps: steps,
|
||||
seed,
|
||||
denoising_start: 0, // denoising_start should be 0 when latents are not provided
|
||||
trajectory_guidance_strength: 0,
|
||||
denoising_start: 0,
|
||||
denoising_end: 1,
|
||||
width: scaledSize.width,
|
||||
height: scaledSize.height,
|
||||
@@ -113,6 +124,8 @@ export const buildFLUXGraph = async (
|
||||
clip_embed_model: clipEmbedModel,
|
||||
});
|
||||
|
||||
const denoisingStart = 1 - img2imgStrength;
|
||||
|
||||
if (generationMode === 'txt2img') {
|
||||
canvasOutput = addTextToImage(g, l2i, originalSize, scaledSize);
|
||||
} else if (generationMode === 'img2img') {
|
||||
@@ -125,9 +138,15 @@ export const buildFLUXGraph = async (
|
||||
originalSize,
|
||||
scaledSize,
|
||||
bbox,
|
||||
1 - img2imgStrength,
|
||||
denoisingStart,
|
||||
false
|
||||
);
|
||||
if (optimizedDenoisingEnabled) {
|
||||
g.updateNode(noise, {
|
||||
denoising_start: 0,
|
||||
trajectory_guidance_strength: img2imgStrength,
|
||||
});
|
||||
}
|
||||
} else if (generationMode === 'inpaint') {
|
||||
canvasOutput = await addInpaint(
|
||||
state,
|
||||
@@ -139,9 +158,15 @@ export const buildFLUXGraph = async (
|
||||
modelLoader,
|
||||
originalSize,
|
||||
scaledSize,
|
||||
1 - img2imgStrength,
|
||||
denoisingStart,
|
||||
false
|
||||
);
|
||||
if (optimizedDenoisingEnabled) {
|
||||
g.updateNode(noise, {
|
||||
denoising_start: 0,
|
||||
trajectory_guidance_strength: img2imgStrength,
|
||||
});
|
||||
}
|
||||
} else if (generationMode === 'outpaint') {
|
||||
canvasOutput = await addOutpaint(
|
||||
state,
|
||||
@@ -153,9 +178,15 @@ export const buildFLUXGraph = async (
|
||||
modelLoader,
|
||||
originalSize,
|
||||
scaledSize,
|
||||
1 - img2imgStrength,
|
||||
denoisingStart,
|
||||
false
|
||||
);
|
||||
if (optimizedDenoisingEnabled) {
|
||||
g.updateNode(noise, {
|
||||
denoising_start: 0,
|
||||
trajectory_guidance_strength: img2imgStrength,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (state.system.shouldUseNSFWChecker) {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||
import {
|
||||
selectOptimizedDenoisingEnabled,
|
||||
setOptimizedDenoisingEnabled,
|
||||
} from 'features/controlLayers/store/paramsSlice';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ParamOptimizedDenoisingToggle = memo(() => {
|
||||
const optimizedDenoisingEnabled = useAppSelector(selectOptimizedDenoisingEnabled);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const onChange = useCallback(
|
||||
(event: ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(setOptimizedDenoisingEnabled(event.target.checked));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<FormControl w="min-content">
|
||||
<InformationalPopover feature="optimizedDenoising">
|
||||
<FormLabel m={0}>{t('parameters.optimizedDenoising')}</FormLabel>
|
||||
</InformationalPopover>
|
||||
<Switch isChecked={optimizedDenoisingEnabled} onChange={onChange} />
|
||||
</FormControl>
|
||||
);
|
||||
});
|
||||
|
||||
ParamOptimizedDenoisingToggle.displayName = 'ParamOptimizedDenoisingToggle';
|
||||
@@ -3,8 +3,9 @@ import { Expander, Flex, FormControlGroup, StandaloneAccordion } from '@invoke-a
|
||||
import { EMPTY_ARRAY } from 'app/store/constants';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectParamsSlice } from 'features/controlLayers/store/paramsSlice';
|
||||
import { selectIsFLUX, selectParamsSlice } from 'features/controlLayers/store/paramsSlice';
|
||||
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
|
||||
import { ParamOptimizedDenoisingToggle } from 'features/parameters/components/Advanced/ParamOptimizedDenoisingToggle';
|
||||
import BboxScaledHeight from 'features/parameters/components/Bbox/BboxScaledHeight';
|
||||
import BboxScaledWidth from 'features/parameters/components/Bbox/BboxScaledWidth';
|
||||
import BboxScaleMethod from 'features/parameters/components/Bbox/BboxScaleMethod';
|
||||
@@ -58,6 +59,7 @@ export const ImageSettingsAccordion = memo(() => {
|
||||
id: 'image-settings-advanced',
|
||||
defaultIsOpen: false,
|
||||
});
|
||||
const isFLUX = useAppSelector(selectIsFLUX);
|
||||
|
||||
return (
|
||||
<StandaloneAccordion
|
||||
@@ -76,6 +78,7 @@ export const ImageSettingsAccordion = memo(() => {
|
||||
<ParamDenoisingStrength />
|
||||
<Expander label={t('accordions.advanced.options')} isOpen={isOpenExpander} onToggle={onToggleExpander}>
|
||||
<Flex gap={4} pb={4} flexDir="column">
|
||||
{isFLUX && <ParamOptimizedDenoisingToggle />}
|
||||
<BboxScaleMethod />
|
||||
<FormControlGroup formLabelProps={scalingLabelProps}>
|
||||
<BboxScaledWidth />
|
||||
|
||||
Reference in New Issue
Block a user