1
0
Fork 0

feat: add fill color control to inpaint

This commit is contained in:
Sean Sube 2023-01-18 08:41:02 -06:00
parent 08dbc0c738
commit 3679735d86
7 changed files with 41 additions and 26 deletions

View File

@ -14,7 +14,7 @@ def get_pixel_index(x: int, y: int, width: int) -> int:
return (y * width) + x return (y * width) + x
def mask_filter_none(mask_image: Image, dims: Point, origin: Point, fill='white') -> Image: def mask_filter_none(mask_image: Image, dims: Point, origin: Point, fill='white', **kw) -> Image:
width, height = dims width, height = dims
noise = Image.new('RGB', (width, height), fill) noise = Image.new('RGB', (width, height), fill)
@ -23,7 +23,7 @@ def mask_filter_none(mask_image: Image, dims: Point, origin: Point, fill='white'
return noise return noise
def mask_filter_gaussian_multiply(mask_image: Image, dims: Point, origin: Point, rounds=3) -> Image: def mask_filter_gaussian_multiply(mask_image: Image, dims: Point, origin: Point, rounds=3, **kw) -> Image:
''' '''
Gaussian blur with multiply, source image centered on white canvas. Gaussian blur with multiply, source image centered on white canvas.
''' '''
@ -36,7 +36,7 @@ def mask_filter_gaussian_multiply(mask_image: Image, dims: Point, origin: Point,
return noise return noise
def mask_filter_gaussian_screen(mask_image: Image, dims: Point, origin: Point, rounds=3) -> Image: def mask_filter_gaussian_screen(mask_image: Image, dims: Point, origin: Point, rounds=3, **kw) -> Image:
''' '''
Gaussian blur, source image centered on white canvas. Gaussian blur, source image centered on white canvas.
''' '''
@ -49,7 +49,7 @@ def mask_filter_gaussian_screen(mask_image: Image, dims: Point, origin: Point, r
return noise return noise
def noise_source_fill_edge(source_image: Image, dims: Point, origin: Point, fill='white') -> Image: def noise_source_fill_edge(source_image: Image, dims: Point, origin: Point, fill='white', **kw) -> Image:
''' '''
Identity transform, source image centered on white canvas. Identity transform, source image centered on white canvas.
''' '''
@ -61,7 +61,7 @@ def noise_source_fill_edge(source_image: Image, dims: Point, origin: Point, fill
return noise return noise
def noise_source_fill_mask(source_image: Image, dims: Point, origin: Point, fill='white') -> Image: def noise_source_fill_mask(source_image: Image, dims: Point, origin: Point, fill='white', **kw) -> Image:
''' '''
Fill the whole canvas, no source or noise. Fill the whole canvas, no source or noise.
''' '''
@ -72,7 +72,7 @@ def noise_source_fill_mask(source_image: Image, dims: Point, origin: Point, fill
return noise return noise
def noise_source_gaussian(source_image: Image, dims: Point, origin: Point, rounds=3) -> Image: def noise_source_gaussian(source_image: Image, dims: Point, origin: Point, rounds=3, **kw) -> Image:
''' '''
Gaussian blur, source image centered on white canvas. Gaussian blur, source image centered on white canvas.
''' '''
@ -85,7 +85,7 @@ def noise_source_gaussian(source_image: Image, dims: Point, origin: Point, round
return noise return noise
def noise_source_uniform(source_image: Image, dims: Point, origin: Point) -> Image: def noise_source_uniform(source_image: Image, dims: Point, origin: Point, **kw) -> Image:
width, height = dims width, height = dims
size = width * height size = width * height
@ -107,7 +107,7 @@ def noise_source_uniform(source_image: Image, dims: Point, origin: Point) -> Ima
return noise return noise
def noise_source_normal(source_image: Image, dims: Point, origin: Point) -> Image: def noise_source_normal(source_image: Image, dims: Point, origin: Point, **kw) -> Image:
width, height = dims width, height = dims
size = width * height size = width * height
@ -129,7 +129,7 @@ def noise_source_normal(source_image: Image, dims: Point, origin: Point) -> Imag
return noise return noise
def noise_source_histogram(source_image: Image, dims: Point, origin: Point) -> Image: def noise_source_histogram(source_image: Image, dims: Point, origin: Point, **kw) -> Image:
r, g, b = source_image.split() r, g, b = source_image.split()
width, height = dims width, height = dims
size = width * height size = width * height
@ -177,8 +177,8 @@ def expand_image(
full_source = Image.new('RGB', dims, fill) full_source = Image.new('RGB', dims, fill)
full_source.paste(source_image, origin) full_source.paste(source_image, origin)
full_mask = mask_filter(mask_image, dims, origin) full_mask = mask_filter(mask_image, dims, origin, fill=fill)
full_noise = noise_source(source_image, dims, origin) full_noise = noise_source(source_image, dims, origin, fill=fill)
full_noise = ImageChops.multiply(full_noise, full_mask) full_noise = ImageChops.multiply(full_noise, full_mask)
full_source = Image.composite(full_noise, full_source, full_mask.convert('L')) full_source = Image.composite(full_noise, full_source, full_mask.convert('L'))

View File

@ -150,6 +150,7 @@ def run_inpaint_pipeline(
noise_source: Any, noise_source: Any,
mask_filter: Any, mask_filter: Any,
strength: float, strength: float,
fill_color: str,
): ):
pipe = load_pipeline(OnnxStableDiffusionInpaintPipeline, pipe = load_pipeline(OnnxStableDiffusionInpaintPipeline,
params.model, params.provider, params.scheduler) params.model, params.provider, params.scheduler)
@ -162,6 +163,7 @@ def run_inpaint_pipeline(
source_image, source_image,
mask_image, mask_image,
expand, expand,
fill=fill_color,
noise_source=noise_source, noise_source=noise_source,
mask_filter=mask_filter) mask_filter=mask_filter)

View File

@ -390,6 +390,7 @@ def inpaint():
expand = border_from_request() expand = border_from_request()
upscale = upscale_from_request() upscale = upscale_from_request()
fill_color = request.args.get('fillColor', 'white')
mask_filter = get_from_map(request.args, 'filter', mask_filters, 'none') mask_filter = get_from_map(request.args, 'filter', mask_filters, 'none')
noise_source = get_from_map( noise_source = get_from_map(
request.args, 'noise', noise_sources, 'histogram') request.args, 'noise', noise_sources, 'histogram')
@ -411,6 +412,7 @@ def inpaint():
mask_filter.__name__, mask_filter.__name__,
noise_source.__name__, noise_source.__name__,
strength, strength,
fill_color,
) )
) )
print("inpaint output: %s" % output) print("inpaint output: %s" % output)
@ -430,7 +432,8 @@ def inpaint():
expand, expand,
noise_source, noise_source,
mask_filter, mask_filter,
strength) strength,
fill_color)
return jsonify({ return jsonify({
'output': output, 'output': output,

View File

@ -48,6 +48,7 @@ export interface InpaintParams extends BaseImgParams {
filter: string; filter: string;
noise: string; noise: string;
strength: number; strength: number;
fillColor: string;
} }
export interface OutpaintPixels { export interface OutpaintPixels {

View File

@ -44,7 +44,6 @@ export function ImageInput(props: ImageInputProps) {
const { files } = event.target; const { files } = event.target;
if (doesExist(files) && files.length > 0) { if (doesExist(files) && files.length > 0) {
const file = mustExist(files[0]); const file = mustExist(files[0]);
props.onChange(file); props.onChange(file);
} }
}} }}

View File

@ -53,6 +53,7 @@ export function Inpaint() {
} }
const state = mustExist(useContext(StateContext)); const state = mustExist(useContext(StateContext));
const fillColor = useStore(state, (s) => s.inpaint.fillColor);
const filter = useStore(state, (s) => s.inpaint.filter); const filter = useStore(state, (s) => s.inpaint.filter);
const noise = useStore(state, (s) => s.inpaint.noise); const noise = useStore(state, (s) => s.inpaint.noise);
const mask = useStore(state, (s) => s.inpaint.mask); const mask = useStore(state, (s) => s.inpaint.mask);
@ -109,19 +110,6 @@ export function Inpaint() {
}} }}
/> />
<Stack direction='row' spacing={2}> <Stack direction='row' spacing={2}>
<NumericField
label='Strength'
min={params.strength.min}
max={params.strength.max}
step={params.strength.step}
value={strength}
onChange={(value) => {
setInpaint({
strength: value,
});
}}
/>
{/* TODO: numeric input for blend strength */}
<QueryList <QueryList
id='masks' id='masks'
labels={MASK_LABELS} labels={MASK_LABELS}
@ -150,6 +138,26 @@ export function Inpaint() {
}); });
}} }}
/> />
<NumericField
label='Strength'
min={params.strength.min}
max={params.strength.max}
step={params.strength.step}
value={strength}
onChange={(value) => {
setInpaint({
strength: value,
});
}}
/>
<Stack direction='row' spacing={2}>
<input name='fill-color' type='color' value={fillColor} onChange={(event) => {
setInpaint({
fillColor: event.target.value,
});
}} />
<label htmlFor='fill-color'>Fill Color</label>
</Stack>
</Stack> </Stack>
<OutpaintControl /> <OutpaintControl />
<UpscaleControl /> <UpscaleControl />

View File

@ -153,6 +153,7 @@ export function createStateSlices(base: ServerParams) {
const createInpaintSlice: StateCreator<OnnxState, [], [], InpaintSlice> = (set) => ({ const createInpaintSlice: StateCreator<OnnxState, [], [], InpaintSlice> = (set) => ({
inpaint: { inpaint: {
...defaults, ...defaults,
fillColor: '',
filter: 'none', filter: 'none',
mask: null, mask: null,
noise: 'histogram', noise: 'histogram',
@ -171,6 +172,7 @@ export function createStateSlices(base: ServerParams) {
set({ set({
inpaint: { inpaint: {
...defaults, ...defaults,
fillColor: '',
filter: 'none', filter: 'none',
mask: null, mask: null,
noise: 'histogram', noise: 'histogram',