mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
install, nodes, ui: restore ad-hoc upscaling (#3800)
I've opted to leave out any additional upscaling parameters like scale and denoising strength, which, from my review of the ESRGAN code, don't do much: - scale just resizes the image using CV2 after the AI upscaling, so that's not particularly useful - denoising strength is only valid for one class of model, which we are no longer supporting If there is demand, we can implement output size/scale UI and handle it by passing the upscaled image to that a resize/scale node. I also understand we previously had some functionality to blend the upscaled image with the original. If that is desired, we would need to implement that as a node that we can pass the upscaled image to. Demo: https://github.com/invoke-ai/InvokeAI/assets/4822129/32eee615-62a1-40ce-a183-87e7d935fbf1 --- [feat(nodes): add RealESRGAN_x2plus.pth, update upscale nodes](dbc256c5b4
) - add `RealESRGAN_x2plus.pth` model to installer @lstein - add `RealESRGAN_x2plus.pth` to `realesrgan` node - rename `RealESRGAN` to `ESRGAN` in nodes - make `scale_factor` optional in `img_scale` node [feat(ui): restore ad-hoc upscaling](b3fd29e5ad
) - remove face restoration entirely - add dropdown for ESRGAN model select - add ad-hoc upscaling graph and workflow
This commit is contained in:
commit
c89fa4b635
@ -518,8 +518,8 @@ class ImageScaleInvocation(BaseInvocation, PILInvocationConfig):
|
|||||||
type: Literal["img_scale"] = "img_scale"
|
type: Literal["img_scale"] = "img_scale"
|
||||||
|
|
||||||
# Inputs
|
# Inputs
|
||||||
image: Optional[ImageField] = Field(default=None, description="The image to scale")
|
image: Optional[ImageField] = Field(default=None, description="The image to scale")
|
||||||
scale_factor: float = Field(gt=0, description="The factor by which to scale the image")
|
scale_factor: Optional[float] = Field(default=2.0, gt=0, description="The factor by which to scale the image")
|
||||||
resample_mode: PIL_RESAMPLING_MODES = Field(default="bicubic", description="The resampling mode")
|
resample_mode: PIL_RESAMPLING_MODES = Field(default="bicubic", description="The resampling mode")
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654) & the InvokeAI Team
|
# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654) & the InvokeAI Team
|
||||||
from pathlib import Path, PosixPath
|
from pathlib import Path
|
||||||
from typing import Literal, Union, cast
|
from typing import Literal, Union
|
||||||
|
|
||||||
import cv2 as cv
|
import cv2 as cv
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -16,19 +16,20 @@ from .image import ImageOutput
|
|||||||
|
|
||||||
# TODO: Populate this from disk?
|
# TODO: Populate this from disk?
|
||||||
# TODO: Use model manager to load?
|
# TODO: Use model manager to load?
|
||||||
REALESRGAN_MODELS = Literal[
|
ESRGAN_MODELS = Literal[
|
||||||
"RealESRGAN_x4plus.pth",
|
"RealESRGAN_x4plus.pth",
|
||||||
"RealESRGAN_x4plus_anime_6B.pth",
|
"RealESRGAN_x4plus_anime_6B.pth",
|
||||||
"ESRGAN_SRx4_DF2KOST_official-ff704c30.pth",
|
"ESRGAN_SRx4_DF2KOST_official-ff704c30.pth",
|
||||||
|
"RealESRGAN_x2plus.pth",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class RealESRGANInvocation(BaseInvocation):
|
class ESRGANInvocation(BaseInvocation):
|
||||||
"""Upscales an image using RealESRGAN."""
|
"""Upscales an image using RealESRGAN."""
|
||||||
|
|
||||||
type: Literal["realesrgan"] = "realesrgan"
|
type: Literal["esrgan"] = "esrgan"
|
||||||
image: Union[ImageField, None] = Field(default=None, description="The input image")
|
image: Union[ImageField, None] = Field(default=None, description="The input image")
|
||||||
model_name: REALESRGAN_MODELS = Field(
|
model_name: ESRGAN_MODELS = Field(
|
||||||
default="RealESRGAN_x4plus.pth", description="The Real-ESRGAN model to use"
|
default="RealESRGAN_x4plus.pth", description="The Real-ESRGAN model to use"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,19 +74,17 @@ class RealESRGANInvocation(BaseInvocation):
|
|||||||
scale=4,
|
scale=4,
|
||||||
)
|
)
|
||||||
netscale = 4
|
netscale = 4
|
||||||
# TODO: add x2 models handling?
|
elif self.model_name in ["RealESRGAN_x2plus.pth"]:
|
||||||
# elif self.model_name in ["RealESRGAN_x2plus"]:
|
# x2 RRDBNet model
|
||||||
# # x2 RRDBNet model
|
rrdbnet_model = RRDBNet(
|
||||||
# model = RRDBNet(
|
num_in_ch=3,
|
||||||
# num_in_ch=3,
|
num_out_ch=3,
|
||||||
# num_out_ch=3,
|
num_feat=64,
|
||||||
# num_feat=64,
|
num_block=23,
|
||||||
# num_block=23,
|
num_grow_ch=32,
|
||||||
# num_grow_ch=32,
|
scale=2,
|
||||||
# scale=2,
|
)
|
||||||
# )
|
netscale = 2
|
||||||
# model_path = Path()
|
|
||||||
# netscale = 2
|
|
||||||
else:
|
else:
|
||||||
msg = f"Invalid RealESRGAN model: {self.model_name}"
|
msg = f"Invalid RealESRGAN model: {self.model_name}"
|
||||||
context.services.logger.error(msg)
|
context.services.logger.error(msg)
|
||||||
|
@ -222,7 +222,7 @@ def download_conversion_models():
|
|||||||
|
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
def download_realesrgan():
|
def download_realesrgan():
|
||||||
logger.info("Installing RealESRGAN models...")
|
logger.info("Installing ESRGAN Upscaling models...")
|
||||||
URLs = [
|
URLs = [
|
||||||
dict(
|
dict(
|
||||||
url = "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth",
|
url = "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth",
|
||||||
@ -239,6 +239,11 @@ def download_realesrgan():
|
|||||||
dest= "core/upscaling/realesrgan/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth",
|
dest= "core/upscaling/realesrgan/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth",
|
||||||
description = "ESRGAN_SRx4_DF2KOST_official.pth",
|
description = "ESRGAN_SRx4_DF2KOST_official.pth",
|
||||||
),
|
),
|
||||||
|
dict(
|
||||||
|
url= "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth",
|
||||||
|
dest= "core/upscaling/realesrgan/RealESRGAN_x2plus.pth",
|
||||||
|
description = "RealESRGAN_x2plus.pth",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
for model in URLs:
|
for model in URLs:
|
||||||
download_with_progress_bar(model['url'], config.models_path / model['dest'], model['description'])
|
download_with_progress_bar(model['url'], config.models_path / model['dest'], model['description'])
|
||||||
|
@ -59,15 +59,8 @@ export const SCHEDULER_LABEL_MAP: Record<SchedulerParam, string> = {
|
|||||||
|
|
||||||
export type Scheduler = (typeof SCHEDULER_NAMES)[number];
|
export type Scheduler = (typeof SCHEDULER_NAMES)[number];
|
||||||
|
|
||||||
// Valid upscaling levels
|
|
||||||
export const UPSCALING_LEVELS: Array<{ label: string; value: string }> = [
|
|
||||||
{ label: '2x', value: '2' },
|
|
||||||
{ label: '4x', value: '4' },
|
|
||||||
];
|
|
||||||
export const NUMPY_RAND_MIN = 0;
|
export const NUMPY_RAND_MIN = 0;
|
||||||
|
|
||||||
export const NUMPY_RAND_MAX = 2147483647;
|
export const NUMPY_RAND_MAX = 2147483647;
|
||||||
|
|
||||||
export const FACETOOL_TYPES = ['gfpgan', 'codeformer'] as const;
|
|
||||||
|
|
||||||
export const NODE_MIN_WIDTH = 250;
|
export const NODE_MIN_WIDTH = 250;
|
||||||
|
@ -90,6 +90,7 @@ import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
|
|||||||
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
|
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
|
||||||
import { addModelLoadStartedEventListener } from './listeners/socketio/socketModelLoadStarted';
|
import { addModelLoadStartedEventListener } from './listeners/socketio/socketModelLoadStarted';
|
||||||
import { addModelLoadCompletedEventListener } from './listeners/socketio/socketModelLoadCompleted';
|
import { addModelLoadCompletedEventListener } from './listeners/socketio/socketModelLoadCompleted';
|
||||||
|
import { addUpscaleRequestedListener } from './listeners/upscaleRequested';
|
||||||
|
|
||||||
export const listenerMiddleware = createListenerMiddleware();
|
export const listenerMiddleware = createListenerMiddleware();
|
||||||
|
|
||||||
@ -228,3 +229,5 @@ addModelSelectedListener();
|
|||||||
addAppStartedListener();
|
addAppStartedListener();
|
||||||
addModelsLoadedListener();
|
addModelsLoadedListener();
|
||||||
addAppConfigReceivedListener();
|
addAppConfigReceivedListener();
|
||||||
|
|
||||||
|
addUpscaleRequestedListener();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { log } from 'app/logging/useLogger';
|
||||||
import { startAppListening } from '..';
|
|
||||||
import { sessionCreated } from 'services/api/thunks/session';
|
|
||||||
import { serializeError } from 'serialize-error';
|
import { serializeError } from 'serialize-error';
|
||||||
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'session' });
|
const moduleLog = log.child({ namespace: 'session' });
|
||||||
|
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
|
import { buildAdHocUpscaleGraph } from 'features/nodes/util/graphBuilders/buildAdHocUpscaleGraph';
|
||||||
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
|
const moduleLog = log.child({ namespace: 'upscale' });
|
||||||
|
|
||||||
|
export const upscaleRequested = createAction<{ image_name: string }>(
|
||||||
|
`upscale/upscaleRequested`
|
||||||
|
);
|
||||||
|
|
||||||
|
export const addUpscaleRequestedListener = () => {
|
||||||
|
startAppListening({
|
||||||
|
actionCreator: upscaleRequested,
|
||||||
|
effect: async (
|
||||||
|
action,
|
||||||
|
{ dispatch, getState, take, unsubscribe, subscribe }
|
||||||
|
) => {
|
||||||
|
const { image_name } = action.payload;
|
||||||
|
const { esrganModelName } = getState().postprocessing;
|
||||||
|
|
||||||
|
const graph = buildAdHocUpscaleGraph({
|
||||||
|
image_name,
|
||||||
|
esrganModelName,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a session to run the graph & wait til it's ready to invoke
|
||||||
|
dispatch(sessionCreated({ graph }));
|
||||||
|
|
||||||
|
await take(sessionCreated.fulfilled.match);
|
||||||
|
|
||||||
|
dispatch(sessionReadyToInvoke());
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
@ -11,7 +11,7 @@ interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
|||||||
|
|
||||||
const IAIMantineSelectItemWithTooltip = forwardRef<HTMLDivElement, ItemProps>(
|
const IAIMantineSelectItemWithTooltip = forwardRef<HTMLDivElement, ItemProps>(
|
||||||
({ label, tooltip, description, disabled, ...others }: ItemProps, ref) => (
|
({ label, tooltip, description, disabled, ...others }: ItemProps, ref) => (
|
||||||
<Tooltip label={tooltip} placement="top" hasArrow>
|
<Tooltip label={tooltip} placement="top" hasArrow openDelay={500}>
|
||||||
<Box ref={ref} {...others}>
|
<Box ref={ref} {...others}>
|
||||||
<Box>
|
<Box>
|
||||||
<Text>{label}</Text>
|
<Text>{label}</Text>
|
||||||
|
@ -5,34 +5,26 @@ import {
|
|||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Flex,
|
Flex,
|
||||||
FlexProps,
|
FlexProps,
|
||||||
Link,
|
|
||||||
Menu,
|
Menu,
|
||||||
MenuButton,
|
MenuButton,
|
||||||
MenuItem,
|
|
||||||
MenuList,
|
MenuList,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
// import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
// import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
import IAIPopover from 'common/components/IAIPopover';
|
|
||||||
|
|
||||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||||
import { useAppToaster } from 'app/components/Toaster';
|
import { useAppToaster } from 'app/components/Toaster';
|
||||||
|
import { upscaleRequested } from 'app/store/middleware/listenerMiddleware/listeners/upscaleRequested';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
|
||||||
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
|
||||||
import { DeleteImageButton } from 'features/imageDeletion/components/DeleteImageButton';
|
import { DeleteImageButton } from 'features/imageDeletion/components/DeleteImageButton';
|
||||||
import { imageToDeleteSelected } from 'features/imageDeletion/store/imageDeletionSlice';
|
import { imageToDeleteSelected } from 'features/imageDeletion/store/imageDeletionSlice';
|
||||||
import FaceRestoreSettings from 'features/parameters/components/Parameters/FaceRestore/FaceRestoreSettings';
|
import ParamUpscalePopover from 'features/parameters/components/Parameters/Upscale/ParamUpscaleSettings';
|
||||||
import UpscaleSettings from 'features/parameters/components/Parameters/Upscale/UpscaleSettings';
|
|
||||||
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
|
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
|
||||||
import { initialImageSelected } from 'features/parameters/store/actions';
|
import { initialImageSelected } from 'features/parameters/store/actions';
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
import { useCopyImageToClipboard } from 'features/ui/hooks/useCopyImageToClipboard';
|
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
import {
|
import {
|
||||||
setActiveTab,
|
|
||||||
setShouldShowImageDetails,
|
setShouldShowImageDetails,
|
||||||
setShouldShowProgressInViewer,
|
setShouldShowProgressInViewer,
|
||||||
} from 'features/ui/store/uiSlice';
|
} from 'features/ui/store/uiSlice';
|
||||||
@ -42,38 +34,25 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import {
|
import {
|
||||||
FaAsterisk,
|
FaAsterisk,
|
||||||
FaCode,
|
FaCode,
|
||||||
FaCopy,
|
|
||||||
FaDownload,
|
|
||||||
FaExpandArrowsAlt,
|
|
||||||
FaGrinStars,
|
|
||||||
FaHourglassHalf,
|
FaHourglassHalf,
|
||||||
FaQuoteRight,
|
FaQuoteRight,
|
||||||
FaSeedling,
|
FaSeedling,
|
||||||
FaShare,
|
|
||||||
FaShareAlt,
|
FaShareAlt,
|
||||||
} from 'react-icons/fa';
|
} from 'react-icons/fa';
|
||||||
import {
|
import {
|
||||||
useGetImageDTOQuery,
|
useGetImageDTOQuery,
|
||||||
useGetImageMetadataQuery,
|
useGetImageMetadataQuery,
|
||||||
} from 'services/api/endpoints/images';
|
} from 'services/api/endpoints/images';
|
||||||
import { useDebounce } from 'use-debounce';
|
|
||||||
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
|
||||||
import { menuListMotionProps } from 'theme/components/menu';
|
import { menuListMotionProps } from 'theme/components/menu';
|
||||||
|
import { useDebounce } from 'use-debounce';
|
||||||
|
import { sentImageToImg2Img } from '../../store/actions';
|
||||||
import SingleSelectionMenuItems from '../ImageContextMenu/SingleSelectionMenuItems';
|
import SingleSelectionMenuItems from '../ImageContextMenu/SingleSelectionMenuItems';
|
||||||
|
|
||||||
const currentImageButtonsSelector = createSelector(
|
const currentImageButtonsSelector = createSelector(
|
||||||
[stateSelector, activeTabNameSelector],
|
[stateSelector, activeTabNameSelector],
|
||||||
({ gallery, system, postprocessing, ui }, activeTabName) => {
|
({ gallery, system, ui }, activeTabName) => {
|
||||||
const {
|
const { isProcessing, isConnected, shouldConfirmOnDelete, progressImage } =
|
||||||
isProcessing,
|
system;
|
||||||
isConnected,
|
|
||||||
isGFPGANAvailable,
|
|
||||||
isESRGANAvailable,
|
|
||||||
shouldConfirmOnDelete,
|
|
||||||
progressImage,
|
|
||||||
} = system;
|
|
||||||
|
|
||||||
const { upscalingLevel, facetoolStrength } = postprocessing;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
shouldShowImageDetails,
|
shouldShowImageDetails,
|
||||||
@ -88,10 +67,6 @@ const currentImageButtonsSelector = createSelector(
|
|||||||
shouldConfirmOnDelete,
|
shouldConfirmOnDelete,
|
||||||
isProcessing,
|
isProcessing,
|
||||||
isConnected,
|
isConnected,
|
||||||
isGFPGANAvailable,
|
|
||||||
isESRGANAvailable,
|
|
||||||
upscalingLevel,
|
|
||||||
facetoolStrength,
|
|
||||||
shouldDisableToolbarButtons: Boolean(progressImage) || !lastSelectedImage,
|
shouldDisableToolbarButtons: Boolean(progressImage) || !lastSelectedImage,
|
||||||
shouldShowImageDetails,
|
shouldShowImageDetails,
|
||||||
activeTabName,
|
activeTabName,
|
||||||
@ -114,27 +89,17 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
const {
|
const {
|
||||||
isProcessing,
|
isProcessing,
|
||||||
isConnected,
|
isConnected,
|
||||||
isGFPGANAvailable,
|
|
||||||
isESRGANAvailable,
|
|
||||||
upscalingLevel,
|
|
||||||
facetoolStrength,
|
|
||||||
shouldDisableToolbarButtons,
|
shouldDisableToolbarButtons,
|
||||||
shouldShowImageDetails,
|
shouldShowImageDetails,
|
||||||
activeTabName,
|
|
||||||
lastSelectedImage,
|
lastSelectedImage,
|
||||||
shouldShowProgressInViewer,
|
shouldShowProgressInViewer,
|
||||||
} = useAppSelector(currentImageButtonsSelector);
|
} = useAppSelector(currentImageButtonsSelector);
|
||||||
|
|
||||||
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
|
|
||||||
const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled;
|
const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled;
|
||||||
const isFaceRestoreEnabled = useFeatureStatus('faceRestore').isFeatureEnabled;
|
|
||||||
|
|
||||||
const toaster = useAppToaster();
|
const toaster = useAppToaster();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { isClipboardAPIAvailable, copyImageToClipboard } =
|
|
||||||
useCopyImageToClipboard();
|
|
||||||
|
|
||||||
const { recallBothPrompts, recallSeed, recallAllParameters } =
|
const { recallBothPrompts, recallSeed, recallAllParameters } =
|
||||||
useRecallParameters();
|
useRecallParameters();
|
||||||
|
|
||||||
@ -155,42 +120,6 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
|
|
||||||
const metadata = metadataData?.metadata;
|
const metadata = metadataData?.metadata;
|
||||||
|
|
||||||
const handleCopyImageLink = useCallback(() => {
|
|
||||||
const getImageUrl = () => {
|
|
||||||
if (!imageDTO) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imageDTO.image_url.startsWith('http')) {
|
|
||||||
return imageDTO.image_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window.location.toString() + imageDTO.image_url;
|
|
||||||
};
|
|
||||||
|
|
||||||
const url = getImageUrl();
|
|
||||||
|
|
||||||
if (!url) {
|
|
||||||
toaster({
|
|
||||||
title: t('toast.problemCopyingImageLink'),
|
|
||||||
status: 'error',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
navigator.clipboard.writeText(url).then(() => {
|
|
||||||
toaster({
|
|
||||||
title: t('toast.imageLinkCopied'),
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, [toaster, t, imageDTO]);
|
|
||||||
|
|
||||||
const handleClickUseAllParameters = useCallback(() => {
|
const handleClickUseAllParameters = useCallback(() => {
|
||||||
recallAllParameters(metadata);
|
recallAllParameters(metadata);
|
||||||
}, [metadata, recallAllParameters]);
|
}, [metadata, recallAllParameters]);
|
||||||
@ -223,8 +152,11 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
useHotkeys('shift+i', handleSendToImageToImage, [imageDTO]);
|
useHotkeys('shift+i', handleSendToImageToImage, [imageDTO]);
|
||||||
|
|
||||||
const handleClickUpscale = useCallback(() => {
|
const handleClickUpscale = useCallback(() => {
|
||||||
// selectedImage && dispatch(runESRGAN(selectedImage));
|
if (!imageDTO) {
|
||||||
}, []);
|
return;
|
||||||
|
}
|
||||||
|
dispatch(upscaleRequested({ image_name: imageDTO.image_name }));
|
||||||
|
}, [dispatch, imageDTO]);
|
||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
const handleDelete = useCallback(() => {
|
||||||
if (!imageDTO) {
|
if (!imageDTO) {
|
||||||
@ -242,53 +174,17 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
enabled: () =>
|
enabled: () =>
|
||||||
Boolean(
|
Boolean(
|
||||||
isUpscalingEnabled &&
|
isUpscalingEnabled &&
|
||||||
isESRGANAvailable &&
|
|
||||||
!shouldDisableToolbarButtons &&
|
!shouldDisableToolbarButtons &&
|
||||||
isConnected &&
|
isConnected &&
|
||||||
!isProcessing &&
|
!isProcessing
|
||||||
upscalingLevel
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
isUpscalingEnabled,
|
isUpscalingEnabled,
|
||||||
imageDTO,
|
imageDTO,
|
||||||
isESRGANAvailable,
|
|
||||||
shouldDisableToolbarButtons,
|
shouldDisableToolbarButtons,
|
||||||
isConnected,
|
isConnected,
|
||||||
isProcessing,
|
isProcessing,
|
||||||
upscalingLevel,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClickFixFaces = useCallback(() => {
|
|
||||||
// selectedImage && dispatch(runFacetool(selectedImage));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useHotkeys(
|
|
||||||
'Shift+R',
|
|
||||||
() => {
|
|
||||||
handleClickFixFaces();
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enabled: () =>
|
|
||||||
Boolean(
|
|
||||||
isFaceRestoreEnabled &&
|
|
||||||
isGFPGANAvailable &&
|
|
||||||
!shouldDisableToolbarButtons &&
|
|
||||||
isConnected &&
|
|
||||||
!isProcessing &&
|
|
||||||
facetoolStrength
|
|
||||||
),
|
|
||||||
},
|
|
||||||
|
|
||||||
[
|
|
||||||
isFaceRestoreEnabled,
|
|
||||||
imageDTO,
|
|
||||||
isGFPGANAvailable,
|
|
||||||
shouldDisableToolbarButtons,
|
|
||||||
isConnected,
|
|
||||||
isProcessing,
|
|
||||||
facetoolStrength,
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -297,25 +193,6 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
[dispatch, shouldShowImageDetails]
|
[dispatch, shouldShowImageDetails]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSendToCanvas = useCallback(() => {
|
|
||||||
if (!imageDTO) return;
|
|
||||||
dispatch(sentImageToCanvas());
|
|
||||||
|
|
||||||
dispatch(setInitialCanvasImage(imageDTO));
|
|
||||||
dispatch(requestCanvasRescale());
|
|
||||||
|
|
||||||
if (activeTabName !== 'unifiedCanvas') {
|
|
||||||
dispatch(setActiveTab('unifiedCanvas'));
|
|
||||||
}
|
|
||||||
|
|
||||||
toaster({
|
|
||||||
title: t('toast.sentToUnifiedCanvas'),
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
}, [imageDTO, dispatch, activeTabName, toaster, t]);
|
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'i',
|
'i',
|
||||||
() => {
|
() => {
|
||||||
@ -337,13 +214,6 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
dispatch(setShouldShowProgressInViewer(!shouldShowProgressInViewer));
|
dispatch(setShouldShowProgressInViewer(!shouldShowProgressInViewer));
|
||||||
}, [dispatch, shouldShowProgressInViewer]);
|
}, [dispatch, shouldShowProgressInViewer]);
|
||||||
|
|
||||||
const handleCopyImage = useCallback(() => {
|
|
||||||
if (!imageDTO) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
copyImageToClipboard(imageDTO.image_url);
|
|
||||||
}, [copyImageToClipboard, imageDTO]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flex
|
<Flex
|
||||||
@ -396,72 +266,12 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
{(isUpscalingEnabled || isFaceRestoreEnabled) && (
|
{isUpscalingEnabled && (
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
isAttached={true}
|
isAttached={true}
|
||||||
isDisabled={shouldDisableToolbarButtons}
|
isDisabled={shouldDisableToolbarButtons}
|
||||||
>
|
>
|
||||||
{isFaceRestoreEnabled && (
|
{isUpscalingEnabled && <ParamUpscalePopover imageDTO={imageDTO} />}
|
||||||
<IAIPopover
|
|
||||||
triggerComponent={
|
|
||||||
<IAIIconButton
|
|
||||||
icon={<FaGrinStars />}
|
|
||||||
aria-label={t('parameters.restoreFaces')}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
flexDirection: 'column',
|
|
||||||
rowGap: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaceRestoreSettings />
|
|
||||||
<IAIButton
|
|
||||||
isDisabled={
|
|
||||||
!isGFPGANAvailable ||
|
|
||||||
!imageDTO ||
|
|
||||||
!(isConnected && !isProcessing) ||
|
|
||||||
!facetoolStrength
|
|
||||||
}
|
|
||||||
onClick={handleClickFixFaces}
|
|
||||||
>
|
|
||||||
{t('parameters.restoreFaces')}
|
|
||||||
</IAIButton>
|
|
||||||
</Flex>
|
|
||||||
</IAIPopover>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{isUpscalingEnabled && (
|
|
||||||
<IAIPopover
|
|
||||||
triggerComponent={
|
|
||||||
<IAIIconButton
|
|
||||||
icon={<FaExpandArrowsAlt />}
|
|
||||||
aria-label={t('parameters.upscale')}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<UpscaleSettings />
|
|
||||||
<IAIButton
|
|
||||||
isDisabled={
|
|
||||||
!isESRGANAvailable ||
|
|
||||||
!imageDTO ||
|
|
||||||
!(isConnected && !isProcessing) ||
|
|
||||||
!upscalingLevel
|
|
||||||
}
|
|
||||||
onClick={handleClickUpscale}
|
|
||||||
>
|
|
||||||
{t('parameters.upscaleImage')}
|
|
||||||
</IAIButton>
|
|
||||||
</Flex>
|
|
||||||
</IAIPopover>
|
|
||||||
)}
|
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
import { NonNullableGraph } from 'features/nodes/types/types';
|
||||||
|
import { ESRGANModelName } from 'features/parameters/store/postprocessingSlice';
|
||||||
|
import { Graph, ESRGANInvocation } from 'services/api/types';
|
||||||
|
import { REALESRGAN as ESRGAN } from './constants';
|
||||||
|
|
||||||
|
type Arg = {
|
||||||
|
image_name: string;
|
||||||
|
esrganModelName: ESRGANModelName;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildAdHocUpscaleGraph = ({
|
||||||
|
image_name,
|
||||||
|
esrganModelName,
|
||||||
|
}: Arg): Graph => {
|
||||||
|
const realesrganNode: ESRGANInvocation = {
|
||||||
|
id: ESRGAN,
|
||||||
|
type: 'esrgan',
|
||||||
|
image: { image_name },
|
||||||
|
model_name: esrganModelName,
|
||||||
|
is_intermediate: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const graph: NonNullableGraph = {
|
||||||
|
id: `adhoc-esrgan-graph`,
|
||||||
|
nodes: {
|
||||||
|
[ESRGAN]: realesrganNode,
|
||||||
|
},
|
||||||
|
edges: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
};
|
@ -20,6 +20,9 @@ export const DYNAMIC_PROMPT = 'dynamic_prompt';
|
|||||||
export const IMAGE_COLLECTION = 'image_collection';
|
export const IMAGE_COLLECTION = 'image_collection';
|
||||||
export const IMAGE_COLLECTION_ITERATE = 'image_collection_iterate';
|
export const IMAGE_COLLECTION_ITERATE = 'image_collection_iterate';
|
||||||
export const METADATA_ACCUMULATOR = 'metadata_accumulator';
|
export const METADATA_ACCUMULATOR = 'metadata_accumulator';
|
||||||
|
export const REALESRGAN = 'esrgan';
|
||||||
|
export const DIVIDE = 'divide';
|
||||||
|
export const SCALE = 'scale_image';
|
||||||
|
|
||||||
// friendly graph ids
|
// friendly graph ids
|
||||||
export const TEXT_TO_IMAGE_GRAPH = 'text_to_image_graph';
|
export const TEXT_TO_IMAGE_GRAPH = 'text_to_image_graph';
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import type { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISlider from 'common/components/IAISlider';
|
|
||||||
import { setCodeformerFidelity } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export default function CodeformerFidelity() {
|
|
||||||
const isGFPGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isGFPGANAvailable
|
|
||||||
);
|
|
||||||
|
|
||||||
const codeformerFidelity = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.codeformerFidelity
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISlider
|
|
||||||
isDisabled={!isGFPGANAvailable}
|
|
||||||
label={t('parameters.codeformerFidelity')}
|
|
||||||
step={0.05}
|
|
||||||
min={0}
|
|
||||||
max={1}
|
|
||||||
onChange={(v) => dispatch(setCodeformerFidelity(v))}
|
|
||||||
handleReset={() => dispatch(setCodeformerFidelity(1))}
|
|
||||||
value={codeformerFidelity}
|
|
||||||
withReset
|
|
||||||
withSliderMarks
|
|
||||||
withInput
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
import { VStack } from '@chakra-ui/react';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import type { RootState } from 'app/store/store';
|
|
||||||
import FaceRestoreType from './FaceRestoreType';
|
|
||||||
import FaceRestoreStrength from './FaceRestoreStrength';
|
|
||||||
import CodeformerFidelity from './CodeformerFidelity';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays face-fixing/GFPGAN options (strength).
|
|
||||||
*/
|
|
||||||
const FaceRestoreSettings = () => {
|
|
||||||
const facetoolType = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.facetoolType
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<VStack gap={2} alignItems="stretch">
|
|
||||||
<FaceRestoreType />
|
|
||||||
<FaceRestoreStrength />
|
|
||||||
{facetoolType === 'codeformer' && <CodeformerFidelity />}
|
|
||||||
</VStack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FaceRestoreSettings;
|
|
@ -1,34 +0,0 @@
|
|||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISlider from 'common/components/IAISlider';
|
|
||||||
import { setFacetoolStrength } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export default function FaceRestoreStrength() {
|
|
||||||
const isGFPGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isGFPGANAvailable
|
|
||||||
);
|
|
||||||
|
|
||||||
const facetoolStrength = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.facetoolStrength
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISlider
|
|
||||||
isDisabled={!isGFPGANAvailable}
|
|
||||||
label={t('parameters.strength')}
|
|
||||||
step={0.05}
|
|
||||||
min={0}
|
|
||||||
max={1}
|
|
||||||
onChange={(v) => dispatch(setFacetoolStrength(v))}
|
|
||||||
handleReset={() => dispatch(setFacetoolStrength(0.75))}
|
|
||||||
value={facetoolStrength}
|
|
||||||
withReset
|
|
||||||
withSliderMarks
|
|
||||||
withInput
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
|
||||||
import { setShouldRunFacetool } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { ChangeEvent } from 'react';
|
|
||||||
|
|
||||||
export default function FaceRestoreToggle() {
|
|
||||||
const isGFPGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isGFPGANAvailable
|
|
||||||
);
|
|
||||||
|
|
||||||
const shouldRunFacetool = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.shouldRunFacetool
|
|
||||||
);
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const handleChangeShouldRunFacetool = (e: ChangeEvent<HTMLInputElement>) =>
|
|
||||||
dispatch(setShouldRunFacetool(e.target.checked));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISwitch
|
|
||||||
isDisabled={!isGFPGANAvailable}
|
|
||||||
isChecked={shouldRunFacetool}
|
|
||||||
onChange={handleChangeShouldRunFacetool}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
import { FACETOOL_TYPES } from 'app/constants';
|
|
||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
|
||||||
import {
|
|
||||||
FacetoolType,
|
|
||||||
setFacetoolType,
|
|
||||||
} from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export default function FaceRestoreType() {
|
|
||||||
const facetoolType = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.facetoolType
|
|
||||||
);
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleChangeFacetoolType = (v: string) =>
|
|
||||||
dispatch(setFacetoolType(v as FacetoolType));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAIMantineSearchableSelect
|
|
||||||
label={t('parameters.type')}
|
|
||||||
data={FACETOOL_TYPES.concat()}
|
|
||||||
value={facetoolType}
|
|
||||||
onChange={handleChangeFacetoolType}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { stateSelector } from 'app/store/store';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|
||||||
import IAICollapse from 'common/components/IAICollapse';
|
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { ParamHiresStrength } from './ParamHiresStrength';
|
|
||||||
import { ParamHiresToggle } from './ParamHiresToggle';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
|
||||||
stateSelector,
|
|
||||||
(state) => {
|
|
||||||
const activeLabel = state.postprocessing.hiresFix ? 'Enabled' : undefined;
|
|
||||||
|
|
||||||
return { activeLabel };
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
const ParamHiresCollapse = () => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { activeLabel } = useAppSelector(selector);
|
|
||||||
|
|
||||||
const isHiresEnabled = useFeatureStatus('hires').isFeatureEnabled;
|
|
||||||
|
|
||||||
if (!isHiresEnabled) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAICollapse label={t('parameters.hiresOptim')} activeLabel={activeLabel}>
|
|
||||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
|
||||||
<ParamHiresToggle />
|
|
||||||
<ParamHiresStrength />
|
|
||||||
</Flex>
|
|
||||||
</IAICollapse>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(ParamHiresCollapse);
|
|
@ -1,3 +0,0 @@
|
|||||||
// TODO
|
|
||||||
|
|
||||||
export default {};
|
|
@ -1,3 +0,0 @@
|
|||||||
// TODO
|
|
||||||
|
|
||||||
export default {};
|
|
@ -1,51 +0,0 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISlider from 'common/components/IAISlider';
|
|
||||||
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
|
|
||||||
import { setHiresStrength } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { isEqual } from 'lodash-es';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const hiresStrengthSelector = createSelector(
|
|
||||||
[postprocessingSelector],
|
|
||||||
({ hiresFix, hiresStrength }) => ({ hiresFix, hiresStrength }),
|
|
||||||
{
|
|
||||||
memoizeOptions: {
|
|
||||||
resultEqualityCheck: isEqual,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const ParamHiresStrength = () => {
|
|
||||||
const { hiresFix, hiresStrength } = useAppSelector(hiresStrengthSelector);
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleHiresStrength = (v: number) => {
|
|
||||||
dispatch(setHiresStrength(v));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHiResStrengthReset = () => {
|
|
||||||
dispatch(setHiresStrength(0.75));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISlider
|
|
||||||
label={t('parameters.hiresStrength')}
|
|
||||||
step={0.01}
|
|
||||||
min={0.01}
|
|
||||||
max={0.99}
|
|
||||||
onChange={handleHiresStrength}
|
|
||||||
value={hiresStrength}
|
|
||||||
isInteger={false}
|
|
||||||
withInput
|
|
||||||
withSliderMarks
|
|
||||||
// inputWidth={22}
|
|
||||||
withReset
|
|
||||||
handleReset={handleHiResStrengthReset}
|
|
||||||
isDisabled={!hiresFix}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,30 +0,0 @@
|
|||||||
import type { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
|
||||||
import { setHiresFix } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { ChangeEvent } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hires Fix Toggle
|
|
||||||
*/
|
|
||||||
export const ParamHiresToggle = () => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const hiresFix = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.hiresFix
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleChangeHiresFix = (e: ChangeEvent<HTMLInputElement>) =>
|
|
||||||
dispatch(setHiresFix(e.target.checked));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISwitch
|
|
||||||
label={t('parameters.hiresOptim')}
|
|
||||||
isChecked={hiresFix}
|
|
||||||
onChange={handleChangeHiresFix}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
// TODO
|
|
||||||
|
|
||||||
export default {};
|
|
@ -0,0 +1,58 @@
|
|||||||
|
import { SelectItem } from '@mantine/core';
|
||||||
|
import type { RootState } from 'app/store/store';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import IAIMantineSelect from 'common/components/IAIMantineSelect';
|
||||||
|
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||||
|
import {
|
||||||
|
ESRGANModelName,
|
||||||
|
esrganModelNameChanged,
|
||||||
|
} from 'features/parameters/store/postprocessingSlice';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export const ESRGAN_MODEL_NAMES: SelectItem[] = [
|
||||||
|
{
|
||||||
|
label: 'RealESRGAN x2 Plus',
|
||||||
|
value: 'RealESRGAN_x2plus.pth',
|
||||||
|
tooltip: 'Attempts to retain sharpness, low smoothing',
|
||||||
|
group: 'x2 Upscalers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'RealESRGAN x4 Plus',
|
||||||
|
value: 'RealESRGAN_x4plus.pth',
|
||||||
|
tooltip: 'Best for photos and highly detailed images, medium smoothing',
|
||||||
|
group: 'x4 Upscalers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'RealESRGAN x4 Plus (anime 6B)',
|
||||||
|
value: 'RealESRGAN_x4plus_anime_6B.pth',
|
||||||
|
tooltip: 'Best for anime/manga, high smoothing',
|
||||||
|
group: 'x4 Upscalers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ESRGAN SRx4',
|
||||||
|
value: 'ESRGAN_SRx4_DF2KOST_official-ff704c30.pth',
|
||||||
|
tooltip: 'Retains sharpness, low smoothing',
|
||||||
|
group: 'x4 Upscalers',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ParamESRGANModel() {
|
||||||
|
const esrganModelName = useAppSelector(
|
||||||
|
(state: RootState) => state.postprocessing.esrganModelName
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const handleChange = (v: string) =>
|
||||||
|
dispatch(esrganModelNameChanged(v as ESRGANModelName));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAIMantineSelect
|
||||||
|
label="ESRGAN Model"
|
||||||
|
value={esrganModelName}
|
||||||
|
itemComponent={IAIMantineSelectItemWithTooltip}
|
||||||
|
onChange={handleChange}
|
||||||
|
data={ESRGAN_MODEL_NAMES}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||||
|
import { upscaleRequested } from 'app/store/middleware/listenerMiddleware/listeners/upscaleRequested';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import IAIButton from 'common/components/IAIButton';
|
||||||
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
|
import IAIPopover from 'common/components/IAIPopover';
|
||||||
|
import { selectIsBusy } from 'features/system/store/systemSelectors';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { FaExpandArrowsAlt } from 'react-icons/fa';
|
||||||
|
import { ImageDTO } from 'services/api/types';
|
||||||
|
import ParamESRGANModel from './ParamRealESRGANModel';
|
||||||
|
|
||||||
|
type Props = { imageDTO?: ImageDTO };
|
||||||
|
|
||||||
|
const ParamUpscalePopover = (props: Props) => {
|
||||||
|
const { imageDTO } = props;
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const isBusy = useAppSelector(selectIsBusy);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
|
||||||
|
const handleClickUpscale = useCallback(() => {
|
||||||
|
onClose();
|
||||||
|
if (!imageDTO) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(upscaleRequested({ image_name: imageDTO.image_name }));
|
||||||
|
}, [dispatch, imageDTO, onClose]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IAIPopover
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
triggerComponent={
|
||||||
|
<IAIIconButton
|
||||||
|
onClick={onOpen}
|
||||||
|
icon={<FaExpandArrowsAlt />}
|
||||||
|
aria-label={t('parameters.upscale')}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ParamESRGANModel />
|
||||||
|
<IAIButton
|
||||||
|
size="sm"
|
||||||
|
isDisabled={!imageDTO || isBusy}
|
||||||
|
onClick={handleClickUpscale}
|
||||||
|
>
|
||||||
|
{t('parameters.upscaleImage')}
|
||||||
|
</IAIButton>
|
||||||
|
</Flex>
|
||||||
|
</IAIPopover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ParamUpscalePopover;
|
@ -1,36 +0,0 @@
|
|||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISlider from 'common/components/IAISlider';
|
|
||||||
import { setUpscalingDenoising } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export default function UpscaleDenoisingStrength() {
|
|
||||||
const isESRGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isESRGANAvailable
|
|
||||||
);
|
|
||||||
|
|
||||||
const upscalingDenoising = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.upscalingDenoising
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISlider
|
|
||||||
label={t('parameters.denoisingStrength')}
|
|
||||||
value={upscalingDenoising}
|
|
||||||
min={0}
|
|
||||||
max={1}
|
|
||||||
step={0.01}
|
|
||||||
onChange={(v) => {
|
|
||||||
dispatch(setUpscalingDenoising(v));
|
|
||||||
}}
|
|
||||||
handleReset={() => dispatch(setUpscalingDenoising(0.75))}
|
|
||||||
withSliderMarks
|
|
||||||
withInput
|
|
||||||
withReset
|
|
||||||
isDisabled={!isESRGANAvailable}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
import { UPSCALING_LEVELS } from 'app/constants';
|
|
||||||
import type { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
|
||||||
import {
|
|
||||||
UpscalingLevel,
|
|
||||||
setUpscalingLevel,
|
|
||||||
} from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export default function UpscaleScale() {
|
|
||||||
const isESRGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isESRGANAvailable
|
|
||||||
);
|
|
||||||
|
|
||||||
const upscalingLevel = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.upscalingLevel
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const handleChangeLevel = (v: string) =>
|
|
||||||
dispatch(setUpscalingLevel(Number(v) as UpscalingLevel));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAIMantineSearchableSelect
|
|
||||||
disabled={!isESRGANAvailable}
|
|
||||||
label={t('parameters.scale')}
|
|
||||||
value={String(upscalingLevel)}
|
|
||||||
onChange={handleChangeLevel}
|
|
||||||
data={UPSCALING_LEVELS}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import { VStack } from '@chakra-ui/react';
|
|
||||||
import UpscaleDenoisingStrength from './UpscaleDenoisingStrength';
|
|
||||||
import UpscaleStrength from './UpscaleStrength';
|
|
||||||
import UpscaleScale from './UpscaleScale';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays upscaling/ESRGAN options (level and strength).
|
|
||||||
*/
|
|
||||||
const UpscaleSettings = () => {
|
|
||||||
return (
|
|
||||||
<VStack gap={2} alignItems="stretch">
|
|
||||||
<UpscaleScale />
|
|
||||||
<UpscaleDenoisingStrength />
|
|
||||||
<UpscaleStrength />
|
|
||||||
</VStack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UpscaleSettings;
|
|
@ -1,33 +0,0 @@
|
|||||||
import type { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISlider from 'common/components/IAISlider';
|
|
||||||
import { setUpscalingStrength } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export default function UpscaleStrength() {
|
|
||||||
const isESRGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isESRGANAvailable
|
|
||||||
);
|
|
||||||
const upscalingStrength = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.upscalingStrength
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IAISlider
|
|
||||||
label={`${t('parameters.upscale')} ${t('parameters.strength')}`}
|
|
||||||
value={upscalingStrength}
|
|
||||||
min={0}
|
|
||||||
max={1}
|
|
||||||
step={0.05}
|
|
||||||
onChange={(v) => dispatch(setUpscalingStrength(v))}
|
|
||||||
handleReset={() => dispatch(setUpscalingStrength(0.75))}
|
|
||||||
withSliderMarks
|
|
||||||
withInput
|
|
||||||
withReset
|
|
||||||
isDisabled={!isESRGANAvailable}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
|
||||||
import { setShouldRunESRGAN } from 'features/parameters/store/postprocessingSlice';
|
|
||||||
import { ChangeEvent } from 'react';
|
|
||||||
|
|
||||||
export default function UpscaleToggle() {
|
|
||||||
const isESRGANAvailable = useAppSelector(
|
|
||||||
(state: RootState) => state.system.isESRGANAvailable
|
|
||||||
);
|
|
||||||
|
|
||||||
const shouldRunESRGAN = useAppSelector(
|
|
||||||
(state: RootState) => state.postprocessing.shouldRunESRGAN
|
|
||||||
);
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const handleChangeShouldRunESRGAN = (e: ChangeEvent<HTMLInputElement>) =>
|
|
||||||
dispatch(setShouldRunESRGAN(e.target.checked));
|
|
||||||
return (
|
|
||||||
<IAISwitch
|
|
||||||
isDisabled={!isESRGANAvailable}
|
|
||||||
isChecked={shouldRunESRGAN}
|
|
||||||
onChange={handleChangeShouldRunESRGAN}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,98 +1,27 @@
|
|||||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import { FACETOOL_TYPES } from 'app/constants';
|
import { ESRGANInvocation } from 'services/api/types';
|
||||||
|
|
||||||
export type UpscalingLevel = 2 | 4;
|
export type ESRGANModelName = NonNullable<ESRGANInvocation['model_name']>;
|
||||||
|
|
||||||
export type FacetoolType = (typeof FACETOOL_TYPES)[number];
|
|
||||||
|
|
||||||
export interface PostprocessingState {
|
export interface PostprocessingState {
|
||||||
codeformerFidelity: number;
|
esrganModelName: ESRGANModelName;
|
||||||
facetoolStrength: number;
|
|
||||||
facetoolType: FacetoolType;
|
|
||||||
hiresFix: boolean;
|
|
||||||
hiresStrength: number;
|
|
||||||
shouldLoopback: boolean;
|
|
||||||
shouldRunESRGAN: boolean;
|
|
||||||
shouldRunFacetool: boolean;
|
|
||||||
upscalingLevel: UpscalingLevel;
|
|
||||||
upscalingDenoising: number;
|
|
||||||
upscalingStrength: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialPostprocessingState: PostprocessingState = {
|
export const initialPostprocessingState: PostprocessingState = {
|
||||||
codeformerFidelity: 0.75,
|
esrganModelName: 'RealESRGAN_x4plus.pth',
|
||||||
facetoolStrength: 0.75,
|
|
||||||
facetoolType: 'gfpgan',
|
|
||||||
hiresFix: false,
|
|
||||||
hiresStrength: 0.75,
|
|
||||||
shouldLoopback: false,
|
|
||||||
shouldRunESRGAN: false,
|
|
||||||
shouldRunFacetool: false,
|
|
||||||
upscalingLevel: 4,
|
|
||||||
upscalingDenoising: 0.75,
|
|
||||||
upscalingStrength: 0.75,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const postprocessingSlice = createSlice({
|
export const postprocessingSlice = createSlice({
|
||||||
name: 'postprocessing',
|
name: 'postprocessing',
|
||||||
initialState: initialPostprocessingState,
|
initialState: initialPostprocessingState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setFacetoolStrength: (state, action: PayloadAction<number>) => {
|
esrganModelNameChanged: (state, action: PayloadAction<ESRGANModelName>) => {
|
||||||
state.facetoolStrength = action.payload;
|
state.esrganModelName = action.payload;
|
||||||
},
|
|
||||||
setCodeformerFidelity: (state, action: PayloadAction<number>) => {
|
|
||||||
state.codeformerFidelity = action.payload;
|
|
||||||
},
|
|
||||||
setUpscalingLevel: (state, action: PayloadAction<UpscalingLevel>) => {
|
|
||||||
state.upscalingLevel = action.payload;
|
|
||||||
},
|
|
||||||
setUpscalingDenoising: (state, action: PayloadAction<number>) => {
|
|
||||||
state.upscalingDenoising = action.payload;
|
|
||||||
},
|
|
||||||
setUpscalingStrength: (state, action: PayloadAction<number>) => {
|
|
||||||
state.upscalingStrength = action.payload;
|
|
||||||
},
|
|
||||||
setHiresFix: (state, action: PayloadAction<boolean>) => {
|
|
||||||
state.hiresFix = action.payload;
|
|
||||||
},
|
|
||||||
setHiresStrength: (state, action: PayloadAction<number>) => {
|
|
||||||
state.hiresStrength = action.payload;
|
|
||||||
},
|
|
||||||
resetPostprocessingState: (state) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
...initialPostprocessingState,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
setShouldRunFacetool: (state, action: PayloadAction<boolean>) => {
|
|
||||||
state.shouldRunFacetool = action.payload;
|
|
||||||
},
|
|
||||||
setFacetoolType: (state, action: PayloadAction<FacetoolType>) => {
|
|
||||||
state.facetoolType = action.payload;
|
|
||||||
},
|
|
||||||
setShouldRunESRGAN: (state, action: PayloadAction<boolean>) => {
|
|
||||||
state.shouldRunESRGAN = action.payload;
|
|
||||||
},
|
|
||||||
setShouldLoopback: (state, action: PayloadAction<boolean>) => {
|
|
||||||
state.shouldLoopback = action.payload;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const { esrganModelNameChanged } = postprocessingSlice.actions;
|
||||||
resetPostprocessingState,
|
|
||||||
setCodeformerFidelity,
|
|
||||||
setFacetoolStrength,
|
|
||||||
setFacetoolType,
|
|
||||||
setHiresFix,
|
|
||||||
setHiresStrength,
|
|
||||||
setShouldLoopback,
|
|
||||||
setShouldRunESRGAN,
|
|
||||||
setShouldRunFacetool,
|
|
||||||
setUpscalingLevel,
|
|
||||||
setUpscalingDenoising,
|
|
||||||
setUpscalingStrength,
|
|
||||||
} = postprocessingSlice.actions;
|
|
||||||
|
|
||||||
export default postprocessingSlice.reducer;
|
export default postprocessingSlice.reducer;
|
||||||
|
@ -4,7 +4,6 @@ import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Adv
|
|||||||
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse';
|
||||||
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
|
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
|
||||||
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
|
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
|
||||||
import ParamHiresCollapse from 'features/parameters/components/Parameters/Hires/ParamHiresCollapse';
|
|
||||||
import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse';
|
import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse';
|
||||||
import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse';
|
import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse';
|
||||||
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
|
||||||
@ -26,7 +25,6 @@ const TextToImageTabParameters = () => {
|
|||||||
<ParamVariationCollapse />
|
<ParamVariationCollapse />
|
||||||
<ParamNoiseCollapse />
|
<ParamNoiseCollapse />
|
||||||
<ParamSymmetryCollapse />
|
<ParamSymmetryCollapse />
|
||||||
<ParamHiresCollapse />
|
|
||||||
<ParamSeamlessCollapse />
|
<ParamSeamlessCollapse />
|
||||||
<ParamAdvancedCollapse />
|
<ParamAdvancedCollapse />
|
||||||
</>
|
</>
|
||||||
|
@ -1105,6 +1105,41 @@ export type components = {
|
|||||||
*/
|
*/
|
||||||
combinatorial?: boolean;
|
combinatorial?: boolean;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* ESRGANInvocation
|
||||||
|
* @description Upscales an image using RealESRGAN.
|
||||||
|
*/
|
||||||
|
ESRGANInvocation: {
|
||||||
|
/**
|
||||||
|
* Id
|
||||||
|
* @description The id of this node. Must be unique among all nodes.
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* Is Intermediate
|
||||||
|
* @description Whether or not this node is an intermediate node.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
is_intermediate?: boolean;
|
||||||
|
/**
|
||||||
|
* Type
|
||||||
|
* @default esrgan
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
type?: "esrgan";
|
||||||
|
/**
|
||||||
|
* Image
|
||||||
|
* @description The input image
|
||||||
|
*/
|
||||||
|
image?: components["schemas"]["ImageField"];
|
||||||
|
/**
|
||||||
|
* Model Name
|
||||||
|
* @description The Real-ESRGAN model to use
|
||||||
|
* @default RealESRGAN_x4plus.pth
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
model_name?: "RealESRGAN_x4plus.pth" | "RealESRGAN_x4plus_anime_6B.pth" | "ESRGAN_SRx4_DF2KOST_official-ff704c30.pth" | "RealESRGAN_x2plus.pth";
|
||||||
|
};
|
||||||
/** Edge */
|
/** Edge */
|
||||||
Edge: {
|
Edge: {
|
||||||
/**
|
/**
|
||||||
@ -1219,7 +1254,7 @@ export type components = {
|
|||||||
* @description The nodes in this graph
|
* @description The nodes in this graph
|
||||||
*/
|
*/
|
||||||
nodes?: {
|
nodes?: {
|
||||||
[key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["RealESRGANInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined;
|
[key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Edges
|
* Edges
|
||||||
@ -1262,7 +1297,7 @@ export type components = {
|
|||||||
* @description The results of node executions
|
* @description The results of node executions
|
||||||
*/
|
*/
|
||||||
results: {
|
results: {
|
||||||
[key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["MetadataAccumulatorOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined;
|
[key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["MetadataAccumulatorOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Errors
|
* Errors
|
||||||
@ -2012,8 +2047,9 @@ export type components = {
|
|||||||
/**
|
/**
|
||||||
* Scale Factor
|
* Scale Factor
|
||||||
* @description The factor by which to scale the image
|
* @description The factor by which to scale the image
|
||||||
|
* @default 2
|
||||||
*/
|
*/
|
||||||
scale_factor: number;
|
scale_factor?: number;
|
||||||
/**
|
/**
|
||||||
* Resample Mode
|
* Resample Mode
|
||||||
* @description The resampling mode
|
* @description The resampling mode
|
||||||
@ -3988,41 +4024,6 @@ export type components = {
|
|||||||
*/
|
*/
|
||||||
step?: number;
|
step?: number;
|
||||||
};
|
};
|
||||||
/**
|
|
||||||
* RealESRGANInvocation
|
|
||||||
* @description Upscales an image using RealESRGAN.
|
|
||||||
*/
|
|
||||||
RealESRGANInvocation: {
|
|
||||||
/**
|
|
||||||
* Id
|
|
||||||
* @description The id of this node. Must be unique among all nodes.
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
/**
|
|
||||||
* Is Intermediate
|
|
||||||
* @description Whether or not this node is an intermediate node.
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
is_intermediate?: boolean;
|
|
||||||
/**
|
|
||||||
* Type
|
|
||||||
* @default realesrgan
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
type?: "realesrgan";
|
|
||||||
/**
|
|
||||||
* Image
|
|
||||||
* @description The input image
|
|
||||||
*/
|
|
||||||
image?: components["schemas"]["ImageField"];
|
|
||||||
/**
|
|
||||||
* Model Name
|
|
||||||
* @description The Real-ESRGAN model to use
|
|
||||||
* @default RealESRGAN_x4plus.pth
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
model_name?: "RealESRGAN_x4plus.pth" | "RealESRGAN_x4plus_anime_6B.pth" | "ESRGAN_SRx4_DF2KOST_official-ff704c30.pth";
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* ResizeLatentsInvocation
|
* ResizeLatentsInvocation
|
||||||
* @description Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.
|
* @description Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.
|
||||||
@ -4300,7 +4301,7 @@ export type components = {
|
|||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* SDXLRawPromptInvocation
|
* SDXLRawPromptInvocation
|
||||||
* @description Parse prompt using compel package to conditioning.
|
* @description Pass unmodified prompt to conditioning without compel processing.
|
||||||
*/
|
*/
|
||||||
SDXLRawPromptInvocation: {
|
SDXLRawPromptInvocation: {
|
||||||
/**
|
/**
|
||||||
@ -5379,7 +5380,7 @@ export type operations = {
|
|||||||
};
|
};
|
||||||
requestBody: {
|
requestBody: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["RealESRGANInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
responses: {
|
responses: {
|
||||||
@ -5416,7 +5417,7 @@ export type operations = {
|
|||||||
};
|
};
|
||||||
requestBody: {
|
requestBody: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["RealESRGANInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
"application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
responses: {
|
responses: {
|
||||||
|
@ -90,6 +90,9 @@ export type InpaintInvocation = TypeReq<
|
|||||||
export type ImageResizeInvocation = TypeReq<
|
export type ImageResizeInvocation = TypeReq<
|
||||||
components['schemas']['ImageResizeInvocation']
|
components['schemas']['ImageResizeInvocation']
|
||||||
>;
|
>;
|
||||||
|
export type ImageScaleInvocation = TypeReq<
|
||||||
|
components['schemas']['ImageScaleInvocation']
|
||||||
|
>;
|
||||||
export type RandomIntInvocation = TypeReq<
|
export type RandomIntInvocation = TypeReq<
|
||||||
components['schemas']['RandomIntInvocation']
|
components['schemas']['RandomIntInvocation']
|
||||||
>;
|
>;
|
||||||
@ -124,6 +127,12 @@ export type LoraLoaderInvocation = TypeReq<
|
|||||||
export type MetadataAccumulatorInvocation = TypeReq<
|
export type MetadataAccumulatorInvocation = TypeReq<
|
||||||
components['schemas']['MetadataAccumulatorInvocation']
|
components['schemas']['MetadataAccumulatorInvocation']
|
||||||
>;
|
>;
|
||||||
|
export type ESRGANInvocation = TypeReq<
|
||||||
|
components['schemas']['ESRGANInvocation']
|
||||||
|
>;
|
||||||
|
export type DivideInvocation = TypeReq<
|
||||||
|
components['schemas']['DivideInvocation']
|
||||||
|
>;
|
||||||
|
|
||||||
// ControlNet Nodes
|
// ControlNet Nodes
|
||||||
export type ControlNetInvocation = TypeReq<
|
export type ControlNetInvocation = TypeReq<
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from .test_nodes import ImageToImageTestInvocation, TextToImageTestInvocation, ListPassThroughInvocation, PromptTestInvocation
|
from .test_nodes import ImageToImageTestInvocation, TextToImageTestInvocation, ListPassThroughInvocation, PromptTestInvocation
|
||||||
from invokeai.app.services.graph import Edge, Graph, GraphInvocation, InvalidEdgeError, NodeAlreadyInGraphError, NodeNotFoundError, are_connections_compatible, EdgeConnection, CollectInvocation, IterateInvocation
|
from invokeai.app.services.graph import Edge, Graph, GraphInvocation, InvalidEdgeError, NodeAlreadyInGraphError, NodeNotFoundError, are_connections_compatible, EdgeConnection, CollectInvocation, IterateInvocation
|
||||||
from invokeai.app.invocations.upscale import RealESRGANInvocation
|
from invokeai.app.invocations.upscale import ESRGANInvocation
|
||||||
from invokeai.app.invocations.image import *
|
from invokeai.app.invocations.image import *
|
||||||
from invokeai.app.invocations.math import AddInvocation, SubtractInvocation
|
from invokeai.app.invocations.math import AddInvocation, SubtractInvocation
|
||||||
from invokeai.app.invocations.params import ParamIntInvocation
|
from invokeai.app.invocations.params import ParamIntInvocation
|
||||||
@ -19,7 +19,7 @@ def create_edge(from_id: str, from_field: str, to_id: str, to_field: str) -> Edg
|
|||||||
def test_connections_are_compatible():
|
def test_connections_are_compatible():
|
||||||
from_node = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
from_node = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
from_field = "image"
|
from_field = "image"
|
||||||
to_node = RealESRGANInvocation(id = "2")
|
to_node = ESRGANInvocation(id = "2")
|
||||||
to_field = "image"
|
to_field = "image"
|
||||||
|
|
||||||
result = are_connections_compatible(from_node, from_field, to_node, to_field)
|
result = are_connections_compatible(from_node, from_field, to_node, to_field)
|
||||||
@ -29,7 +29,7 @@ def test_connections_are_compatible():
|
|||||||
def test_connections_are_incompatible():
|
def test_connections_are_incompatible():
|
||||||
from_node = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
from_node = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
from_field = "image"
|
from_field = "image"
|
||||||
to_node = RealESRGANInvocation(id = "2")
|
to_node = ESRGANInvocation(id = "2")
|
||||||
to_field = "strength"
|
to_field = "strength"
|
||||||
|
|
||||||
result = are_connections_compatible(from_node, from_field, to_node, to_field)
|
result = are_connections_compatible(from_node, from_field, to_node, to_field)
|
||||||
@ -39,7 +39,7 @@ def test_connections_are_incompatible():
|
|||||||
def test_connections_incompatible_with_invalid_fields():
|
def test_connections_incompatible_with_invalid_fields():
|
||||||
from_node = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
from_node = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
from_field = "invalid_field"
|
from_field = "invalid_field"
|
||||||
to_node = RealESRGANInvocation(id = "2")
|
to_node = ESRGANInvocation(id = "2")
|
||||||
to_field = "image"
|
to_field = "image"
|
||||||
|
|
||||||
# From field is invalid
|
# From field is invalid
|
||||||
@ -86,10 +86,10 @@ def test_graph_fails_to_update_node_if_type_changes():
|
|||||||
g = Graph()
|
g = Graph()
|
||||||
n = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
g.add_node(n)
|
g.add_node(n)
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
|
|
||||||
nu = RealESRGANInvocation(id = "1")
|
nu = ESRGANInvocation(id = "1")
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
g.update_node("1", nu)
|
g.update_node("1", nu)
|
||||||
@ -98,7 +98,7 @@ def test_graph_allows_non_conflicting_id_change():
|
|||||||
g = Graph()
|
g = Graph()
|
||||||
n = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
g.add_node(n)
|
g.add_node(n)
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e1 = create_edge(n.id,"image",n2.id,"image")
|
e1 = create_edge(n.id,"image",n2.id,"image")
|
||||||
g.add_edge(e1)
|
g.add_edge(e1)
|
||||||
@ -128,7 +128,7 @@ def test_graph_fails_to_update_node_id_if_conflict():
|
|||||||
def test_graph_adds_edge():
|
def test_graph_adds_edge():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e = create_edge(n1.id,"image",n2.id,"image")
|
e = create_edge(n1.id,"image",n2.id,"image")
|
||||||
@ -139,7 +139,7 @@ def test_graph_adds_edge():
|
|||||||
|
|
||||||
def test_graph_fails_to_add_edge_with_cycle():
|
def test_graph_fails_to_add_edge_with_cycle():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = RealESRGANInvocation(id = "1")
|
n1 = ESRGANInvocation(id = "1")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
e = create_edge(n1.id,"image",n1.id,"image")
|
e = create_edge(n1.id,"image",n1.id,"image")
|
||||||
with pytest.raises(InvalidEdgeError):
|
with pytest.raises(InvalidEdgeError):
|
||||||
@ -148,8 +148,8 @@ def test_graph_fails_to_add_edge_with_cycle():
|
|||||||
def test_graph_fails_to_add_edge_with_long_cycle():
|
def test_graph_fails_to_add_edge_with_long_cycle():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
n3 = RealESRGANInvocation(id = "3")
|
n3 = ESRGANInvocation(id = "3")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
g.add_node(n3)
|
g.add_node(n3)
|
||||||
@ -164,7 +164,7 @@ def test_graph_fails_to_add_edge_with_long_cycle():
|
|||||||
def test_graph_fails_to_add_edge_with_missing_node_id():
|
def test_graph_fails_to_add_edge_with_missing_node_id():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e1 = create_edge("1","image","3","image")
|
e1 = create_edge("1","image","3","image")
|
||||||
@ -177,8 +177,8 @@ def test_graph_fails_to_add_edge_with_missing_node_id():
|
|||||||
def test_graph_fails_to_add_edge_when_destination_exists():
|
def test_graph_fails_to_add_edge_when_destination_exists():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
n3 = RealESRGANInvocation(id = "3")
|
n3 = ESRGANInvocation(id = "3")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
g.add_node(n3)
|
g.add_node(n3)
|
||||||
@ -194,7 +194,7 @@ def test_graph_fails_to_add_edge_when_destination_exists():
|
|||||||
def test_graph_fails_to_add_edge_with_mismatched_types():
|
def test_graph_fails_to_add_edge_with_mismatched_types():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e1 = create_edge("1","image","2","strength")
|
e1 = create_edge("1","image","2","strength")
|
||||||
@ -344,7 +344,7 @@ def test_graph_iterator_invalid_if_output_and_input_types_different():
|
|||||||
def test_graph_validates():
|
def test_graph_validates():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e1 = create_edge("1","image","2","image")
|
e1 = create_edge("1","image","2","image")
|
||||||
@ -377,8 +377,8 @@ def test_graph_invalid_if_subgraph_invalid():
|
|||||||
|
|
||||||
def test_graph_invalid_if_has_cycle():
|
def test_graph_invalid_if_has_cycle():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = RealESRGANInvocation(id = "1")
|
n1 = ESRGANInvocation(id = "1")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.nodes[n1.id] = n1
|
g.nodes[n1.id] = n1
|
||||||
g.nodes[n2.id] = n2
|
g.nodes[n2.id] = n2
|
||||||
e1 = create_edge("1","image","2","image")
|
e1 = create_edge("1","image","2","image")
|
||||||
@ -391,7 +391,7 @@ def test_graph_invalid_if_has_cycle():
|
|||||||
def test_graph_invalid_with_invalid_connection():
|
def test_graph_invalid_with_invalid_connection():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.nodes[n1.id] = n1
|
g.nodes[n1.id] = n1
|
||||||
g.nodes[n2.id] = n2
|
g.nodes[n2.id] = n2
|
||||||
e1 = create_edge("1","image","2","strength")
|
e1 = create_edge("1","image","2","strength")
|
||||||
@ -503,7 +503,7 @@ def test_graph_fails_to_enumerate_non_subgraph_node():
|
|||||||
|
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
|
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
|
|
||||||
with pytest.raises(NodeNotFoundError):
|
with pytest.raises(NodeNotFoundError):
|
||||||
@ -512,7 +512,7 @@ def test_graph_fails_to_enumerate_non_subgraph_node():
|
|||||||
def test_graph_gets_networkx_graph():
|
def test_graph_gets_networkx_graph():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e = create_edge(n1.id,"image",n2.id,"image")
|
e = create_edge(n1.id,"image",n2.id,"image")
|
||||||
@ -529,7 +529,7 @@ def test_graph_gets_networkx_graph():
|
|||||||
def test_graph_can_serialize():
|
def test_graph_can_serialize():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e = create_edge(n1.id,"image",n2.id,"image")
|
e = create_edge(n1.id,"image",n2.id,"image")
|
||||||
@ -541,7 +541,7 @@ def test_graph_can_serialize():
|
|||||||
def test_graph_can_deserialize():
|
def test_graph_can_deserialize():
|
||||||
g = Graph()
|
g = Graph()
|
||||||
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
n1 = TextToImageTestInvocation(id = "1", prompt = "Banana sushi")
|
||||||
n2 = RealESRGANInvocation(id = "2")
|
n2 = ESRGANInvocation(id = "2")
|
||||||
g.add_node(n1)
|
g.add_node(n1)
|
||||||
g.add_node(n2)
|
g.add_node(n2)
|
||||||
e = create_edge(n1.id,"image",n2.id,"image")
|
e = create_edge(n1.id,"image",n2.id,"image")
|
||||||
|
Loading…
Reference in New Issue
Block a user