稳定扩散(Stable Diffusion) 是一种 AI 模型,用于根据文本提示生成图像。 使用 ONNX 运行时,可以快速开始使用你喜欢的 .NET 技术(如 C# 和 Visual Studio)在本地生成 AI 图像!
推荐:用 NSDT设计器 快速搭建可编程3D场景。
1、什么是 ONNX 运行时?
开放神经网络交换 (ONNX) 是一种表示 AI 模型的开源格式。 ONNX 运行时 (ORT) 是 ONNX 模型的运行时,它提供了一个接口,用于加速机器学习模型的消费/推理,与特定于硬件的库集成,以及跨编程语言和框架(如 PyTorch、Tensorflow/Keras、scikit)共享模型 -learn、ML.NET 等。
这意味着你可以:
- 在众多支持 ONNX 转换的流行机器学习框架之一中训练模型。
- 将你的模型转换为 ONNX 格式。
- 使用不同于最初训练模型的框架或语言(如 C#)加载和使用 ONNX 模型。
2、什么是Stable Diffusion?
Stable Diffusion 是一种 AI 模型,可以根据文本提示生成图像。
3、Stable Diffusion工作原理
尽管稳定扩散背后的理论和创新可能很复杂,但它由相对较少的组件组成。
Stable Diffusion 的主要组成部分是:
- 文本编码器——将文本编码为嵌入。 本文中引用的示例结合使用了 OpenAI 的对比语言-图像预训练 (CLIP) 和 ONNX 模型的 ONNX 运行时扩展实现。
- 变分自编码器 (VAE) – 将图像编码和解码为嵌入。
- U-Net——通常用于图像分割任务的神经网络架构。
- Scheduler——计算去噪图像嵌入。 本文中引用的示例使用线性多步 (LMS) 离散调度程序的 C# 实现。
有关稳定扩散的更多详细信息,请参阅原始论文 High-Resolution Image Synthesis with Latent Diffusion Models。
在高层次上,使用稳定扩散生成图像的过程包括 3 个步骤:
- 将文本提示和随机噪声编码为文本和图像嵌入。
- 使用 U-Net 神经网络和调度程序来减少图像中的噪声(降噪)。
- 解码去噪图像。
4、生成文本和图像嵌入
使用 Stable Diffusion 生成 AI 图像的第一步是:
- 生成带有随机噪声的图像样本和嵌入。
- 使用 ONNX 运行时扩展 CLIP 文本标记器和 CLIP 嵌入 ONNX 模型将用户提示转换为文本嵌入。
嵌入是文本、图像、音频等信息的数字表示。这种数字表示包含语义。 在稳定扩散的情况下,文本和图像被编码到一个嵌入空间中,作为去噪过程的一部分,U-Net 神经网络可以理解该嵌入空间。
OpenAI 的 CLIP 文本分词器是用 Python 编写的。 ONNX Runtime 没有使用 C# 重新实现它,而是使用 ONNX Runtime Extensions 创建了一个跨平台实现。 ONNX Runtime Extensions 是一个库,它通过为视觉、文本和 NLP 模型提供通用的预处理和后处理运算符来扩展 ONNX 模型的功能并使用 ONNX Runtime 进行推理。
请注意,对于训练,你还需要使用 VAE 对训练期间使用的图像进行编码。 本文中引用的示例仅用于推理,因此不需要使用 VAE。
此代码示例显示了对输入文本提示进行标记化和编码的一般过程。 为简洁起见,省略了一些代码。
var prompt = "a fireplace in an old cabin in the woods";
//...
var textTokenized = TextProcessing.TokenizeText(prompt);
var textPromptEmbeddings = TextProcessing.TextEncoder(textTokenized).ToArray();
5、去噪图像循环
图像和文本嵌入是 U-Net 模型的初始输入。 U-Net 模型然后使用文本提示作为条件来降低图像中的噪声(去噪)。
然后使用调度程序算法,使用 U-Net 模型的输出来计算新的图像嵌入。 然后将这些新图像嵌入用作 U-Net 模型的新输入。
这个去噪过程重复 N 步。
此代码示例显示了当文本和图像嵌入通过 U-Net 运行并由调度程序去噪时发生的一般过程。 为简洁起见,省略了一些代码。
//...
var scheduler = new LMSDiscreteScheduler();
//...
var timesteps = scheduler.SetTimesteps(numInferenceSteps);
//...
var seed = new Random().Next();
var latents = GenerateLatentSample(batchSize, height, width, seed, scheduler.InitNoiseSigma);
//...
var unetSession = new InferenceSession(modelPath, options);
var input = new List<NamedOnnxValue>();
//...
for (int t = 0; t < timesteps.Length; t++)
{
//...
var latentModelInput = TensorHelper.Duplicate(latents.ToArray(), new[] { 2, 4, height / 8, width / 8 });
//...
latentModelInput = scheduler.ScaleInput(latentModelInput, timesteps[t]);
//...
input = CreateUnetModelInput(textEmbeddings, latentModelInput, timesteps[t]);
var output = unetSession.Run(input);
//...
noisePred = performGuidance(noisePred, noisePredText, guidanceScale);
//...
latents = scheduler.Step(noisePred, timesteps[t], latents);
}
6、解码去噪图像
在图像去噪循环完成后,VAE 用于将最终图像嵌入解码回图像。
此代码示例显示了使用 VAE 将最终去噪输出解码为图像的一般过程。 为简洁起见,省略了一些代码。
var decoderInput = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("latent_sample", latents) };
var imageResultTensor = VaeDecoder.Decoder(decoderInput);
var image = VaeDecoder.ConvertToImage(imageResultTensor);
7、结束语
现在你已经大致了解了 Stable Diffusion 的工作原理,是时候发挥你的创造力了!
要开始使用 AI 在你的 .NET 应用程序中生成自己的图像,请查看使用 C# 和 ONNX 运行时的推理稳定扩散教程和相应的 GitHub 存储库。
原文链接:http://www.bimant.com/blog/stable-diffusion-app-dev-with-csharp/