feat(ui): add optimized denoising toggle to linear UI for FLUX image to image and inpainting

This commit is contained in:
Mary Hipp
2024-09-20 14:29:40 -04:00
parent 2f82171dff
commit d3d1b49ff2
7 changed files with 99 additions and 9 deletions

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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';

View File

@@ -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 />