Skip to content

Commit 157290b

Browse files
dunkeronipsychedelicious
authored andcommitted
add: size option for image noise node and filter
1 parent b7389da commit 157290b

File tree

6 files changed

+49
-9
lines changed

6 files changed

+49
-9
lines changed

invokeai/app/invocations/image.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ def invoke(self, context: InvocationContext) -> ImageOutput:
10971097
title="Add Image Noise",
10981098
tags=["image", "noise"],
10991099
category="image",
1100-
version="1.0.0",
1100+
version="1.0.1",
11011101
)
11021102
class ImageNoiseInvocation(BaseInvocation, WithMetadata, WithBoard):
11031103
"""Add noise to an image"""
@@ -1115,6 +1115,7 @@ class ImageNoiseInvocation(BaseInvocation, WithMetadata, WithBoard):
11151115
)
11161116
amount: float = InputField(default=0.1, ge=0, le=1, description="The amount of noise to add")
11171117
noise_color: bool = InputField(default=True, description="Whether to add colored noise")
1118+
size: int = InputField(default=1, ge=1, description="The size of the noise points")
11181119

11191120
def invoke(self, context: InvocationContext) -> ImageOutput:
11201121
image = context.images.get_pil(self.image.image_name, mode="RGBA")
@@ -1127,18 +1128,18 @@ def invoke(self, context: InvocationContext) -> ImageOutput:
11271128

11281129
if self.noise_type == "gaussian":
11291130
if self.noise_color:
1130-
noise = rs.normal(0, 1, (image.height, image.width, 3)) * 255
1131+
noise = rs.normal(0, 1, (image.height // self.size, image.width // self.size, 3)) * 255
11311132
else:
1132-
noise = rs.normal(0, 1, (image.height, image.width)) * 255
1133+
noise = rs.normal(0, 1, (image.height // self.size, image.width // self.size)) * 255
11331134
noise = numpy.stack([noise] * 3, axis=-1)
11341135
elif self.noise_type == "salt_and_pepper":
11351136
if self.noise_color:
1136-
noise = rs.choice([0, 255], (image.height, image.width, 3), p=[1 - self.amount, self.amount])
1137+
noise = rs.choice([0, 255], (image.height // self.size, image.width // self.size, 3), p=[1 - self.amount, self.amount])
11371138
else:
1138-
noise = rs.choice([0, 255], (image.height, image.width), p=[1 - self.amount, self.amount])
1139+
noise = rs.choice([0, 255], (image.height // self.size, image.width // self.size), p=[1 - self.amount, self.amount])
11391140
noise = numpy.stack([noise] * 3, axis=-1)
11401141

1141-
noise = Image.fromarray(noise.astype(numpy.uint8), mode="RGB")
1142+
noise = Image.fromarray(noise.astype(numpy.uint8), mode="RGB").resize((image.width, image.height), Image.Resampling.NEAREST)
11421143
noisy_image = Image.blend(image.convert("RGB"), noise, self.amount).convert("RGBA")
11431144

11441145
# Paste back the alpha channel

invokeai/frontend/web/public/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1948,7 +1948,8 @@
19481948
"noise_amount": "Amount",
19491949
"gaussian_type": "Gaussian",
19501950
"salt_and_pepper_type": "Salt and Pepper",
1951-
"noise_color": "Colored Noise"
1951+
"noise_color": "Colored Noise",
1952+
"size": "Noise Size"
19521953
}
19531954
},
19541955
"transform": {

invokeai/frontend/web/src/features/controlLayers/components/Filters/FilterNoise.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ export const FilterNoise = memo(({ onChange, config }: Props) => {
3737
[config, onChange]
3838
);
3939

40+
const handleSizeChange = useCallback(
41+
(v: number) => {
42+
onChange({ ...config, size: v });
43+
},
44+
[config, onChange]
45+
);
46+
4047
const options: { label: string; value: NoiseTypes }[] = useMemo(
4148
() => [
4249
{ label: t('controlLayers.filter.img_noise.gaussian_type'), value: 'gaussian' },
@@ -73,6 +80,26 @@ export const FilterNoise = memo(({ onChange, config }: Props) => {
7380
step={0.01}
7481
/>
7582
</FormControl>
83+
<FormControl>
84+
<FormLabel m={0}>{t('controlLayers.filter.img_noise.size')}</FormLabel>
85+
<CompositeSlider
86+
value={config.size}
87+
defaultValue={DEFAULTS.size}
88+
onChange={handleSizeChange}
89+
min={1}
90+
max={16}
91+
step={1}
92+
marks
93+
/>
94+
<CompositeNumberInput
95+
value={config.size}
96+
defaultValue={DEFAULTS.size}
97+
onChange={handleSizeChange}
98+
min={1}
99+
max={256}
100+
step={1}
101+
/>
102+
</FormControl>
76103
<FormControl w="max-content">
77104
<FormLabel m={0}>{t('controlLayers.filter.img_noise.noise_color')}</FormLabel>
78105
<Switch defaultChecked={DEFAULTS.noise_color} isChecked={config.noise_color} onChange={handleColorChange} />

invokeai/frontend/web/src/features/controlLayers/store/filters.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ const zNoiseFilterConfig = z.object({
113113
noise_type: zNoiseTypes,
114114
amount: z.number().gte(0).lte(1),
115115
noise_color: z.boolean(),
116+
size: z.number().int().gte(1),
116117
});
117118
export type NoiseFilterConfig = z.infer<typeof zNoiseFilterConfig>;
118119

@@ -483,8 +484,9 @@ export const IMAGE_FILTERS: { [key in FilterConfig['type']]: ImageFilterData<key
483484
noise_type: 'gaussian',
484485
amount: 0.3,
485486
noise_color: true,
487+
size: 1,
486488
}),
487-
buildGraph: ({ image_name }, { noise_type, amount, noise_color }) => {
489+
buildGraph: ({ image_name }, { noise_type, amount, noise_color, size }) => {
488490
const graph = new Graph(getPrefixedId('img_noise'));
489491
const node = graph.addNode({
490492
id: getPrefixedId('img_noise'),
@@ -493,6 +495,7 @@ export const IMAGE_FILTERS: { [key in FilterConfig['type']]: ImageFilterData<key
493495
noise_type: noise_type,
494496
amount: amount,
495497
noise_color: noise_color,
498+
size: size,
496499
});
497500
const rand = graph.addNode({
498501
id: getPrefixedId('rand_int'),

invokeai/frontend/web/src/features/controlLayers/store/types.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ describe('Control Adapter Types', () => {
7474
type _MLSDDetectionFilterConfig = Required<
7575
Pick<Invocation<'mlsd_detection'>, 'type' | 'score_threshold' | 'distance_threshold'>
7676
>;
77-
type _NoiseFilterConfig = Required<Pick<Invocation<'img_noise'>, 'type' | 'noise_type' | 'amount' | 'noise_color'>>;
77+
type _NoiseFilterConfig = Required<
78+
Pick<Invocation<'img_noise'>, 'type' | 'noise_type' | 'amount' | 'noise_color' | 'size'>
79+
>;
7880
type _NormalMapFilterConfig = Required<Pick<Invocation<'normal_map'>, 'type'>>;
7981
type _DWOpenposeDetectionFilterConfig = Required<
8082
Pick<Invocation<'dw_openpose_detection'>, 'type' | 'draw_body' | 'draw_face' | 'draw_hands'>

invokeai/frontend/web/src/services/api/schema.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8494,6 +8494,12 @@ export type components = {
84948494
* @default true
84958495
*/
84968496
noise_color?: boolean;
8497+
/**
8498+
* Size
8499+
* @description The size of the noise
8500+
* @default 1
8501+
*/
8502+
size?: number;
84978503
/**
84988504
* type
84998505
* @default img_noise

0 commit comments

Comments
 (0)