stable diffusionを使って画像生成する簡単なc#プログラム④(img2img+Embedding)複数
前回とあまり変更がありませんが複数種類のイメージをバッチ処理するコードを掲載します。
メモリ周りはWebUIの方が優れていますが短いコードでいろんな処理ができるのでc#で組むのはありかなと思います。
Nuget情報
概要
Filename配列に指定した画像ファイルを順番にimg2img処理をしていきます。
※「TESTDATA」というユーザー環境変数で指定した場所に入力画像があり、また出力画像を出力する前提です。
例題のコードでは1つのファイルに対してランダムのシードで変化を加えた画像を5枚出力します。
その時の名前は、Fname.pngに対してFname_1.png、Fname_2.png、、Fname_3.pngというファイルを出力します。
元画像に忠実にするため、CfgsSale=7、Strength=0.2にしています。それぞれの値を大きくすることで元画像と乖離したものが生成されますが、よりリアルによりモデルデータに忠実になります。
メモリエラーで落ちる場合は元画像の解像度を下げてみてください(RTX3090 24GBで768X1280、960X960が限界っぽい、1280X1280も実行できるが画像が汚い)
using HPPH;
using HPPH.System.Drawing;
using StableDiffusion.NET;
namespace StableDiffusion.Test
{
public class Program
{
static void Main(string[] args)
{
Task task = MainAsync();
task.Wait();
}
private static string ModelPath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"jiaowobaba02\stable-diffusion-v2-1-GGUF\beautifulRealistic_v7.safetensors";
private static string VaePath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"jiaowobaba02\stable-diffusion-v2-1-GGUF\vae-ft-mse-840000-ema-pruned.safetensors";
private static string UpscalePath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"jiaowobaba02\stable-diffusion-v2-1-GGUF\RealESRGAN_x4plus.pth";
private static string EmbedPath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"jiaowobaba02\stable-diffusion-v2-1-GGUF\negative_hand-neg.pt";
public static async Task MainAsync()
{
int intWidth = 0;
int intHeight = 0;
IImage<ColorRGB> objImage;
IImage<ColorRGB> objUpscale;
IImage<ColorRGB> Image2ImageSource;
try
{
//Load Model
StableDiffusionModel sdModel = await Task.Run(() => new StableDiffusionModel(ModelPath, new ModelParameter { VaePath = VaePath, Schedule = Schedule.Karras, EmbeddingsDirectory = EmbedPath }));
string strPrompt = "((best quality, masterpiece, absurbres, super-resolution)), (photorealistic,realistic:1.4), (20 years old cute actress), (beautiful fingers)";
string strAntiPrompt = "(worst quality:2) , (low quality:2) , (normal quality:2) , lowres, ugly face, unclear eyes, bad mouth, bad tooth, bad anatomy, extra legs, (bad fingers, bad hands, missing fingers), embedding";
//ここに処理したい画像ファイル名を書きます
string[] Filename = { "nt13-0030.png", "nt13-0060-2.png", "nt13-0080.png" };
for (int j = 0; j < Filename.Length; j++)
{
Console.WriteLine($"** AI Convert Start ** =>{Filename[j]}");
string ImagePath = Environment.GetEnvironmentVariable("TESTDATA", System.EnvironmentVariableTarget.User) + Filename[j];
Image2ImageSource = ImageHelper.LoadImage(ImagePath).ConvertTo<ColorRGB>();
intHeight = Image2ImageSource.Height;
intWidth = Image2ImageSource.Width;
long lngSeed = -1;
string[] Fname = Filename[j].Split('.');
for (int i = 0; i < 5; i++)
{
//Seed Random
Random rSeed = new Random();
lngSeed = rSeed.Next(0, int.MaxValue);
objImage = await Task.Run(() => sdModel?.ImageToImage(strPrompt, Image2ImageSource, new StableDiffusionParameter
{
NegativePrompt = strAntiPrompt,
Width = intWidth,
Height = intHeight,
CfgScale = 7f,
SampleSteps = 100,
Seed = lngSeed,
SampleMethod = Sampler.DPMPP2Mv2,
Strength = 0.2f,
}));
string savePath = Environment.GetEnvironmentVariable("TESTDATA", System.EnvironmentVariableTarget.User) + $"{Fname[0]}_{i+1}.{Fname[1]}";
File.WriteAllBytes(savePath, objImage.ToPng());
Console.WriteLine($" AI Convert ** =>{Fname[0]}_{i+1}.{Fname[1]}");
}
Console.WriteLine($"** AI Convert E.n.d ** =>{Filename[j]}\n");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
処理した画像(ノア☆エスカレーションからヒロインの乃亜)
人間っぽくはなりましたが、なんだか目が離れてあまりいい出来ではないですね^^;
【元画像】
img2img (CfgScale = 7,Strength = 0.2)