目录
说明
效果
项目
代码
下载
C# StableDiffusion StableDiffusionSharp 脱离python臃肿的环境
说明
Stable Diffusion in pure C/C++
github地址:https://github.com/leejet/stable-diffusion.cpp
C# Wrapper for StableDiffusion.cpp
github地址:https://github.com/DarthAffe/StableDiffusion.NET
效果
项目
电脑配置
AMD Ryzen 7 7735H with Radeon Graphics 3.19GHz
NVIDIA GeForce RTX 4060 Laptop GPU
cuda12.1+cudnn 8.8.1
代码
using NLog;
using OpenCvSharp;
using StableDiffusionSharp.Enums;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
namespace StableDiffusionSharp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
NLog.Windows.Forms.RichTextBoxTarget.ReInitializeAllTextboxes(this);
}
StableDiffusionModel sd;
ModelParameter mp;
StableDiffusionParameter sdp;
string modelpath = "C:\\MyStudy\\v1-5-pruned-emaonly.safetensors";
string prompt = "";
int progress = 0;
private static Logger _log = NLog.LogManager.GetCurrentClassLogger();
private void button1_Click(object sender, System.EventArgs e)
{
prompt = txtPrompt.Text;
if (string.IsNullOrEmpty(prompt))
{
MessageBox.Show("请输入提示词!");
txtPrompt.Focus();
return;
}
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
pictureBox1.Image = null;
button1.Enabled = false;
progress = 0;
//各种参数设置 TODO:从UI界面取值
sdp.SampleSteps = 25;
sdp.Width = 512;
sdp.Height = 512;
sdp.CfgScale = 7.5f;
sdp.SampleMethod = Sampler.Euler_A;
sdp.NegativePrompt = string.Empty;
sdp.Seed = -1;
sdp.Strength = 0.7f;
sdp.ClipSkip = -1;
sdp.ControlNet.Image = null;
sdp.ControlNet.Strength = 0.9f;
sdp.ControlNet.CannyPreprocess = false;
sdp.ControlNet.CannyHighThreshold = 0.08f;
sdp.ControlNet.CannyLowThreshold = 0.08f;
sdp.ControlNet.CannyWeak = 0.8f;
sdp.ControlNet.CannyStrong = 1.0f;
sdp.ControlNet.CannyInverse = false;
sdp.PhotoMaker.InputIdImageDirectory = string.Empty;
sdp.PhotoMaker.StyleRatio = 20f;
sdp.PhotoMaker.NormalizeInput = false;
backgroundWorker1.RunWorkerAsync();
}
private void Form1_Load(object sender, System.EventArgs e)
{
//检查文件是否存在
if (!File.Exists(modelpath))
{
MessageBox.Show("文件不存在,请检查!");
return;
}
timer1.Enabled = true;
timer1.Interval = 100;
StableDiffusionModel.Log += StableDiffusionModel_Log;
StableDiffusionModel.Progress += StableDiffusionModel_Progress;
}
private void timer1_Tick(object sender, System.EventArgs e)
{
mp = new ModelParameter();
sdp = new StableDiffusionParameter();
sd = new StableDiffusionModel(modelpath, mp);
button1.Enabled = true;
timer1.Enabled = false;
}
private void StableDiffusionModel_Progress(object sender, EventArgs.StableDiffusionProgressEventArgs e)
{
_log.Info($"{e.Step}|{e.Steps} taking {e.Time}s");
progress = (int)(e.Progress * 100);
backgroundWorker1.ReportProgress(progress);
}
private void StableDiffusionModel_Log(object sender, EventArgs.StableDiffusionLogEventArgs e)
{
_log.Info($"{e.Text.Replace("\n", "")}");
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
StableDiffusionImage sdimage = sd.TextToImage(prompt, sdp);
Mat image = new Mat(sdimage.Height, sdimage.Width, MatType.CV_8UC3, sdimage.Data);
Cv2.CvtColor(image, image, ColorConversionCodes.BGR2RGB);
//Cv2.ImShow("output", image);
pictureBox1.Image = new Bitmap(image.ToMemoryStream());
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Enabled = true;
//progressBar1.Value = 0;
}
private void button2_Click(object sender, System.EventArgs e)
{
if (pictureBox1.Image == null)
{
return;
}
Bitmap output = new Bitmap(pictureBox1.Image);
SaveFileDialog sdf = new SaveFileDialog();
sdf.Title = "保存";
sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp|Images (*.emf)|*.emf|Images (*.exif)|*.exif|Images (*.gif)|*.gif|Images (*.ico)|*.ico|Images (*.tiff)|*.tiff|Images (*.wmf)|*.wmf";
if (sdf.ShowDialog() == DialogResult.OK)
{
switch (sdf.FilterIndex)
{
case 1:
{
output.Save(sdf.FileName, ImageFormat.Jpeg);
break;
}
case 2:
{
output.Save(sdf.FileName, ImageFormat.Png);
break;
}
case 3:
{
output.Save(sdf.FileName, ImageFormat.Bmp);
break;
}
case 4:
{
output.Save(sdf.FileName, ImageFormat.Emf);
break;
}
case 5:
{
output.Save(sdf.FileName, ImageFormat.Exif);
break;
}
case 6:
{
output.Save(sdf.FileName, ImageFormat.Gif);
break;
}
case 7:
{
output.Save(sdf.FileName, ImageFormat.Icon);
break;
}
case 8:
{
output.Save(sdf.FileName, ImageFormat.Tiff);
break;
}
case 9:
{
output.Save(sdf.FileName, ImageFormat.Wmf);
break;
}
}
MessageBox.Show("保存成功,位置:" + sdf.FileName);
}
}
}
}
using NLog;
using OpenCvSharp;
using StableDiffusionSharp.Enums;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;namespace StableDiffusionSharp
{public partial class Form1 : Form{public Form1(){InitializeComponent();NLog.Windows.Forms.RichTextBoxTarget.ReInitializeAllTextboxes(this);}StableDiffusionModel sd;ModelParameter mp;StableDiffusionParameter sdp;string modelpath = "C:\\MyStudy\\v1-5-pruned-emaonly.safetensors";string prompt = "";int progress = 0;private static Logger _log = NLog.LogManager.GetCurrentClassLogger();private void button1_Click(object sender, System.EventArgs e){prompt = txtPrompt.Text;if (string.IsNullOrEmpty(prompt)){MessageBox.Show("请输入提示词!");txtPrompt.Focus();return;}if (pictureBox1.Image != null){pictureBox1.Image.Dispose();}pictureBox1.Image = null;button1.Enabled = false;progress = 0;//各种参数设置 TODO:从UI界面取值sdp.SampleSteps = 25;sdp.Width = 512;sdp.Height = 512;sdp.CfgScale = 7.5f;sdp.SampleMethod = Sampler.Euler_A;sdp.NegativePrompt = string.Empty;sdp.Seed = -1;sdp.Strength = 0.7f;sdp.ClipSkip = -1;sdp.ControlNet.Image = null;sdp.ControlNet.Strength = 0.9f;sdp.ControlNet.CannyPreprocess = false;sdp.ControlNet.CannyHighThreshold = 0.08f;sdp.ControlNet.CannyLowThreshold = 0.08f;sdp.ControlNet.CannyWeak = 0.8f;sdp.ControlNet.CannyStrong = 1.0f;sdp.ControlNet.CannyInverse = false;sdp.PhotoMaker.InputIdImageDirectory = string.Empty;sdp.PhotoMaker.StyleRatio = 20f;sdp.PhotoMaker.NormalizeInput = false;backgroundWorker1.RunWorkerAsync();}private void Form1_Load(object sender, System.EventArgs e){//检查文件是否存在if (!File.Exists(modelpath)){MessageBox.Show("文件不存在,请检查!");return;}timer1.Enabled = true;timer1.Interval = 100;StableDiffusionModel.Log += StableDiffusionModel_Log;StableDiffusionModel.Progress += StableDiffusionModel_Progress;}private void timer1_Tick(object sender, System.EventArgs e){mp = new ModelParameter();sdp = new StableDiffusionParameter();sd = new StableDiffusionModel(modelpath, mp);button1.Enabled = true;timer1.Enabled = false;}private void StableDiffusionModel_Progress(object sender, EventArgs.StableDiffusionProgressEventArgs e){_log.Info($"{e.Step}|{e.Steps} taking {e.Time}s");progress = (int)(e.Progress * 100);backgroundWorker1.ReportProgress(progress);}private void StableDiffusionModel_Log(object sender, EventArgs.StableDiffusionLogEventArgs e){_log.Info($"{e.Text.Replace("\n", "")}");}private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e){StableDiffusionImage sdimage = sd.TextToImage(prompt, sdp);Mat image = new Mat(sdimage.Height, sdimage.Width, MatType.CV_8UC3, sdimage.Data);Cv2.CvtColor(image, image, ColorConversionCodes.BGR2RGB);//Cv2.ImShow("output", image);pictureBox1.Image = new Bitmap(image.ToMemoryStream());}private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e){progressBar1.Value = e.ProgressPercentage;}private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){button1.Enabled = true;//progressBar1.Value = 0;}private void button2_Click(object sender, System.EventArgs e){if (pictureBox1.Image == null){return;}Bitmap output = new Bitmap(pictureBox1.Image);SaveFileDialog sdf = new SaveFileDialog();sdf.Title = "保存";sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp|Images (*.emf)|*.emf|Images (*.exif)|*.exif|Images (*.gif)|*.gif|Images (*.ico)|*.ico|Images (*.tiff)|*.tiff|Images (*.wmf)|*.wmf";if (sdf.ShowDialog() == DialogResult.OK){switch (sdf.FilterIndex){case 1:{output.Save(sdf.FileName, ImageFormat.Jpeg);break;}case 2:{output.Save(sdf.FileName, ImageFormat.Png);break;}case 3:{output.Save(sdf.FileName, ImageFormat.Bmp);break;}case 4:{output.Save(sdf.FileName, ImageFormat.Emf);break;}case 5:{output.Save(sdf.FileName, ImageFormat.Exif);break;}case 6:{output.Save(sdf.FileName, ImageFormat.Gif);break;}case 7:{output.Save(sdf.FileName, ImageFormat.Icon);break;}case 8:{output.Save(sdf.FileName, ImageFormat.Tiff);break;}case 9:{output.Save(sdf.FileName, ImageFormat.Wmf);break;}}MessageBox.Show("保存成功,位置:" + sdf.FileName);}}}
}
下载
源码下载(模型太大,需要单独下载)
模型下载
Stable Diffusion v1.4 https://huggingface.co/CompVis/stable-diffusion-v-1-4-original
Stable Diffusion v1.5 https://huggingface.co/runwayml/stable-diffusion-v1-5
Stable Diffuison v2.1 https://huggingface.co/stabilityai/stable-diffusion-2-1