使用Unity 接入 Stable-Diffusion-WebUI 文生图生成图像
文章目录
一、前言
在无聊的时候,想瞅一下sd生图遂做了一下
注意:我采用了异步处理,每点击一次发送一次请求,不需要等待生成完再点击。后面生成的画面会覆盖掉之前的。
二、具体步骤
1、启动SD的api设置
注意,运行后的api相关功能可以在:http://127.0.0.1:7860/docs 查看
比如这一次我们要的生图的地址就是/sdapi/v1/txt2img 是POST
所以可以通过requests 向 "http://127.0.0.1:7860/sdapi/v1/txt2img"发送POST请求并拿到数据
注意: “http://127.0.0.1:7860/sdapi/v1/txt2img” ,里面的地址和端口在unity中改成你设置的,如果没有改就不动
到这里sd的前期准备就OK了
2、unity 创建生图脚本
新建C#脚本,imgsd
注意:
- “http://127.0.0.1:7860/sdapi/v1/txt2img” 里面的ip和端口与sd中设置的一致
- sd_model_name = “animePastelDream_softBakedVae” 模型用你自己的模型,如果删掉则用默认你第一个模型。模型文件如:majicmixRealistic_v7.safetensors 则模型名为majicmixRealistic_v7
- 要用某个魔,需要在sd的web中能看到这个模型,你才能使用api调用。你需要下载模型后放在models文件夹在,参考地址如:sd-webui-aki-v4\models\Stable-diffusion
其他的保持不动即可
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Text;
using System;
using System.Collections;
using Unity.VisualScripting;
using UnityEditor.PackageManager.Requests;
public class imgsd : MonoBehaviour
{
public InputField promptInputField; // 在Inspector中设置
public InputField negativePromptInputField; // 在Inspector中设置
public RawImage outputImage; // 在Inspector中设置
private string txt2imgUrl = "http://127.0.0.1:7860/sdapi/v1/txt2img";
// 调用这个方法来开始生成图像的过程
public void GenerateImage()
{
string prompt = promptInputField.text;
string negativePrompt = negativePromptInputField.text;
StartCoroutine(PostRequest(txt2imgUrl, prompt, negativePrompt));
}
[Serializable]
public class YourResponseType
{
public string[] images;
// 添加其他需要的字段
}
IEnumerator PostRequest(string url, string prompt1, string negativePrompt)
{
//1、上行数据准备
var data = new
{
prompt = prompt1,
negative_prompt = negativePrompt,
steps= 50,
width= 512,
height= 512,
sd_model_name = "animePastelDream_softBakedVae"
};
// 将data序列化成一个json数据
string jsonData = JsonUtility.ToJson(data);
//2、api请求
using (UnityWebRequest www = UnityWebRequest.Post(url, UnityWebRequest.kHttpVerbPOST))
{
// 将Json字符串转换为byte[]
byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);
// 添加请求头
www.SetRequestHeader("Content-Type", "application/json");
// 实例上传处理器 并将postData 设置为上传的数据
www.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
// 实例化下载处理器存储数据s
www.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
// 显式定义所有Handler以便后续释放
www.disposeUploadHandlerOnDispose = true;
www.disposeDownloadHandlerOnDispose = true;
www.disposeCertificateHandlerOnDispose = true;
// 发起 Http请求
yield return www.SendWebRequest();
// 3、异常处理
if (www.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"请求失败: {www.error}");
}
else
{
try
{
Debug.Log("请求成功");
// 解析响应
string jsonResponse = www.downloadHandler.text;
YourResponseType response = JsonUtility.FromJson<YourResponseType>(jsonResponse);
// 假设YourResponseType是你定义的类,用来匹配JSON响应的结构
// 显示图像
DisplayImage(response.images[0]); // 假设images[0]包含了Base64编码的图像
}
finally{
//强制释放底层Native数组
www.downloadHandler.Dispose();
}
}
}
}
private void DisplayImage(string base64String)
{
// 1. 将Base64字符串转换为字节数组
byte[] bytes = Convert.FromBase64String(base64String);
// 2. 创建临时纹理(初始尺寸占位)
Texture2D texture = new Texture2D(2, 2);
// 3. 加载图像数据到纹理
if (texture.LoadImage(bytes)) // 自动识别PNG/JPG格式并调整纹理尺寸
{
// 销毁旧纹理
if (outputImage.texture != null)
{
Destroy(outputImage.texture);
outputImage.texture = null;
}
// 4. 将纹理应用到UI组件
outputImage.texture = texture;
}
else
{
Debug.LogError("图像加载失败");
}
}
}
3、Unity 生图交互配置
要通过点击事件触发GenerateImage
方法,你可以使用Unity的UI系统中的按钮(Button)组件。这里有一个简单的步骤说明如何做到这一点:
步骤 1: 创建sdControl
- 在Unity编辑器中,右键点击Hierarchy面板中的空白区域。
- 创建一个空对象
Create Empty
,并改名为sdcontrol。 - 将上一步创建的imgsd脚本拖拽到sdcontrol
步骤2:生成后图片画布
- 在Unity编辑器中,右键点击Hierarchy面板中的空白区域。
- UI
->
Raw Image ``
步骤3:创建两个输入框
- 在Unity编辑器中,右键点击Hierarchy面板中的空白区域。
- UI
->
Legacy -> input fileld `` - UI
->
Legacy -> input fileld ``
执行两次,创建两个输入框
注:UI ->如果没有Legacy 那就UI -> input fileld
步骤4:sdcontrol赋值
步骤 5: 创建按钮并绑定点击事件
-
在Unity编辑器中,右键点击Hierarchy面板中的空白区域。
-
选择
UI
->Button
。这将自动创建一个Canvas
(如果尚未存在),button的text改为生成 -
选中你刚刚创建的按钮对象。
-
在Inspector面板中找到
Button (Script)
组件。 -
拖拽包含
imgsd
脚本的sdcontrol
对象(即你将该脚本附加到的对象)到Button (Script)
组件下方的OnClick()
列表中。 -
点击
OnClick()
列表旁边的加号(+)来添加一个新的条目。 -
然后点击旁边的下拉菜单,选择
imgsd
->GenerateImage
。
三、测试
- 进入Play模式,输入prompt 点击按钮,这应该会触发
GenerateImage
方法,从而开始图像生成的过程。
注:如果发现生成了画面,但与实际的不符,请尝试输入另外一个框,再试着点击一次。因为两个框依次代表,prompt 和native prompt如果输错了框会导致生成效果不理想。