Merge pull request #48 from DarthAffe/Inpainting

Fixed Image2Image and added Inpainting support
This commit is contained in:
DarthAffe 2025-01-05 15:06:27 +01:00 committed by GitHub
commit d42883540f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 72 additions and 3 deletions

View File

@ -202,17 +202,75 @@ public sealed unsafe class DiffusionModel : IDisposable
ObjectDisposedException.ThrowIf(_disposed, this); ObjectDisposedException.ThrowIf(_disposed, this);
ArgumentNullException.ThrowIfNull(prompt); ArgumentNullException.ThrowIfNull(prompt);
ArgumentNullException.ThrowIfNull(image);
parameter.Validate(); parameter.Validate();
if (image is not IImage<ColorRGB> refImage) if (image is not IImage<ColorRGB> refImage)
refImage = image.ConvertTo<ColorRGB>(); refImage = image.ConvertTo<ColorRGB>();
fixed (byte* imagePtr = refImage.AsRefImage()) // DarthAffe 10.08.2024: Mask needs to be a 1 channel all max value image when it's not used - I really don't like this concept as it adds unnecessary allocations, but that's how it is :(
return ImageToImage(prompt, refImage.ToSdImage(imagePtr), parameter); Span<byte> maskBuffer = new byte[image.Width * image.Height];
maskBuffer.Fill(byte.MaxValue);
fixed (byte* maskPtr = maskBuffer)
{
Native.sd_image_t maskImage = new()
{
width = (uint)image.Width,
height = (uint)image.Height,
channel = 1,
data = maskPtr
};
fixed (byte* imagePtr = refImage.AsRefImage())
return ImageToImage(prompt, refImage.ToSdImage(imagePtr), maskImage, parameter);
}
} }
private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, DiffusionParameter parameter) public IImage<ColorRGB> Inpaint(string prompt, IImage image, IImage mask, DiffusionParameter? parameter = null)
{
parameter ??= GetDefaultParameter();
ObjectDisposedException.ThrowIf(_disposed, this);
ArgumentNullException.ThrowIfNull(prompt);
ArgumentNullException.ThrowIfNull(image);
ArgumentNullException.ThrowIfNull(mask);
if (image.Width != mask.Width) throw new ArgumentException("The mask needs to have the same with as the image.", nameof(mask));
if (image.Height != mask.Height) throw new ArgumentException("The mask needs to have the same height as the image.", nameof(mask));
parameter.Validate();
if (image is not IImage<ColorRGB> refImage)
refImage = image.ConvertTo<ColorRGB>();
// DarthAffe 10.08.2024: HPPH does currently not support monochrome images, that's why we need to convert it here. We're going for the simple conversion as the source image is supposed to be monochrome anyway.
Span<byte> maskBuffer = new byte[image.Width * image.Height];
for (int y = 0; y < image.Height; y++)
for (int x = 0; x < image.Width; x++)
{
IColor color = mask[x, y];
maskBuffer[(image.Width * y) + x] = (byte)Math.Round((color.R + color.G + color.B) / 3.0);
}
fixed (byte* maskPtr = maskBuffer)
{
Native.sd_image_t maskImage = new()
{
width = (uint)image.Width,
height = (uint)image.Height,
channel = 1,
data = maskPtr
};
fixed (byte* imagePtr = refImage.AsRefImage())
return ImageToImage(prompt, refImage.ToSdImage(imagePtr), maskImage, parameter);
}
}
private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, Native.sd_image_t mask, DiffusionParameter parameter)
{ {
ObjectDisposedException.ThrowIf(_disposed, this); ObjectDisposedException.ThrowIf(_disposed, this);
ArgumentNullException.ThrowIfNull(prompt); ArgumentNullException.ThrowIfNull(prompt);
@ -246,6 +304,7 @@ public sealed unsafe class DiffusionModel : IDisposable
result = Native.img2img(_ctx, result = Native.img2img(_ctx,
image, image,
mask,
prompt, prompt,
parameter.NegativePrompt, parameter.NegativePrompt,
parameter.ClipSkip, parameter.ClipSkip,
@ -283,6 +342,7 @@ public sealed unsafe class DiffusionModel : IDisposable
result = Native.img2img(_ctx, result = Native.img2img(_ctx,
image, image,
mask,
prompt, prompt,
parameter.NegativePrompt, parameter.NegativePrompt,
parameter.ClipSkip, parameter.ClipSkip,
@ -312,6 +372,7 @@ public sealed unsafe class DiffusionModel : IDisposable
{ {
result = Native.img2img(_ctx, result = Native.img2img(_ctx,
image, image,
mask,
prompt, prompt,
parameter.NegativePrompt, parameter.NegativePrompt,
parameter.ClipSkip, parameter.ClipSkip,

View File

@ -64,6 +64,13 @@ public static class DiffusionParameterExtension
return parameter; return parameter;
} }
public static DiffusionParameter WithStrength(this DiffusionParameter parameter, float strength)
{
parameter.Strength = strength;
return parameter;
}
public static DiffusionParameter WithSlgScale(this DiffusionParameter parameter, float slgScale) public static DiffusionParameter WithSlgScale(this DiffusionParameter parameter, float slgScale)
{ {
parameter.SlgScale = slgScale; parameter.SlgScale = slgScale;

View File

@ -102,6 +102,7 @@ internal unsafe partial class Native
[LibraryImport(LIB_NAME, EntryPoint = "img2img")] [LibraryImport(LIB_NAME, EntryPoint = "img2img")]
internal static partial sd_image_t* img2img(sd_ctx_t* sd_ctx, internal static partial sd_image_t* img2img(sd_ctx_t* sd_ctx,
sd_image_t init_image, sd_image_t init_image,
sd_image_t mask_image,
[MarshalAs(UnmanagedType.LPStr)] string prompt, [MarshalAs(UnmanagedType.LPStr)] string prompt,
[MarshalAs(UnmanagedType.LPStr)] string negative_prompt, [MarshalAs(UnmanagedType.LPStr)] string negative_prompt,
int clip_skip, int clip_skip,