背景
本文次要介绍 AI
绘图开源工具 Stable Diffusion WebUI
的 API
开启和根本调用办法,通过本文的浏览,你将理解到 stable-diffusion-webui
的根本介绍、装置及 API
环境配置;文生图、图生图、部分重绘、前期解决等 API
接口调用;图像处理开发中罕用到一些办法如 Base64
、PNG
、Canvas
及 URL
互相转换、Canvas
色彩转换等。
AI
绘图工具目前市面上比拟宽泛应用的次要有两款,一个是 Midjourney
,它提供面向用户有好的操作界面,文生图、图生图等性能十分弱小,然而它是一款免费软件;另一个就是开源工具 Stable Diffusion
, 同样具备弱小的 AI 绘图和图片再发明能力,然而学习老本和上手难度绝对较大,不过因为它是开源的,当初有十分多的用户和开发者,咱们能够找到丰盛的训练模型和学习资源。本文介绍的 Stable Diffusion WebUI
就是基于 Stable Diffusion
的具备比较完善的可视化操作界面的 AI
绘图开源工具,它的 github
拜访地址是 https://github.com/AUTOMATIC1111/stable-diffusion-webui。
顺便一提,本文上方的
Banner
图就是应用Stable Diffusion
生成的😎
应用体验
在正式开发之前,咱们能够先体验一下 Stable Diffusion WebUI
以及两个接口封装和操作界面比拟优良的 AI
绘图网站,理解 文生图 、 图生图 、 前期解决 等根本操作步骤。
🔗
https://stablediffusionweb.com/WebUI🔗
https://d.design🔗
https://www.liblibai.com
环境配置
装置 Stable Diffusion WebUI
咱们首先须要先在本地或者服务器装置部署 Stable Diffusion WebUI
,能够从 Github 克隆仓库,而后按阐明文档进行装置,对前端开发来说装置流程非常简单,具体装置流程大家能够自行搜寻,当初网上曾经有很多保姆级的教程,本文不再赘述。
装置实现后,在 Windows
操作系统中进入 stable-diffusion-webui
根目录,而后双击 webui-user.bat
文件即可开启本地运行服务,在浏览器中输出 http://localhost:7860
加载如下所示的界面。在 txt2img
输入框中输出须要生图图像的的正向关键词和反向关键词,点击 Generate
按钮即可生成图像。
实现根本装置后,还能够装置界面汉化插件、关键字中文翻译插件、本人喜爱的格调模型等,都能够依照教程非常容易实现。
开启 API 性能
在 stable-diffusion-webui
根目录下找到文件 webui-user.bat
,应用编辑器关上这个文件,而后在 COMMANDLINE_ARGS
配置项前面增加 --api
。
set COMMANDLINE_ARGS= --lowvram --precision full --api --listen
而后双击 webui-user.bat
重启服务,此时在浏览器中输出地址 https://localhost:7860/doc
,就能看到如下所示的所有接口文档了,咱们能够从文档中找到须要接入的接口及具体参数。
💡
咱们还能够配置如上所示的 –listen 参数,这样就能够通过局域网拜访 stable-diffusion-webui 的接口了。
实现
文生图
文生图接口,能够通过向 stable-diffusion-webui
服务发送正向关键字、反向关键字、图片尺寸、采样步数等参数来调用 AI 能力生成图片。咱们先来看看它有哪些可配置的 payload
参数选项。(临时只用到前面写了正文的参数,基本上能够满足大部分文生图参数配置)
{
"enable_hr": false, // 开启高清 hr
"denoising_strength": 0, // 降噪强度
"hr_scale": 2, // 高清级别
"hr_upscaler": "string",
"hr_second_pass_steps": 0,
"hr_resize_x": 0,
"hr_resize_y": 0,
"hr_sampler_name": "string",
"hr_prompt": "","hr_negative_prompt":"",
"prompt": "", // 正向关键字"styles": ["string"],"seed": -1, // 随机种子"subseed": -1, // 子级种子"subseed_strength": 0, // 子级种子影响力度"seed_resize_from_h": -1,"seed_resize_from_w": -1,"sampler_name":"string","batch_size": 1, // 每次生成的张数"n_iter": 1, // 生成批次"steps": 50, // 生成步数"cfg_scale": 7, // 关键词相关性"width": 512, // 生成图像宽度"height": 512, // 生成图像高度"restore_faces": false, // 面部修复"tiling": false, // 平铺"do_not_save_samples": false,"do_not_save_grid": false,"negative_prompt":"string", // 反向关键字"eta": 0, // 等待时间"s_min_uncond": 0,"s_churn": 0,"s_tmax": 0,"s_tmin": 0,"s_noise": 1,"override_settings": {}, // 覆盖性配置"override_settings_restore_afterwards": true,"script_args": [], // lora 模型参数配置"sampler_index":"Euler", // 采样办法"script_name":"string","send_images": true, // 是否发送图像"save_images": false, // 是否在服务端保留生成的图像"alwayson_scripts": {} // alwayson 配置}
依据须要的参数,在页面逻辑中,咱们能够像上面这样实现,此时服务端会依据接口参数,一次生成 4 张对应的图。接口返回胜利之后,咱们会接管到一个蕴含所有图片数据名为 images
的数组,数组项是格局为 base64
的图片,咱们能够向上面这样转化为页面上可间接显示的图片。
const response = await txt2img({id_task: `task(${taskId})`,
// 正向关键词
prompt: 'xxxx',
// 反向关键词
negative_prompt: 'xxxx',
// 随机种子
seed: 'xxxx',
// 生成步数
steps: 7,
// 关键词相关性
cfg_scale: 20,
width: 1024,
height: 1024,
// 每次生成的张数
batch_size: 4,
// 生成批次
n_iter: 1,
// 采样办法
sampler_index: 'xxxx',
// 采纳的模型哈希值
sd_model_hash: 'xxxx',
override_settings: {
sd_model_checkpoint: sdModelCheckpoint,
eta_noise_seed_delta: 0.0,
CLIP_stop_at_last_layers: 1.0,
},
})
if (response.status === 200 && response.data) {
try {
const images = response.data.images;
if (images.length === 0) return;
data.imageUrls = images.map(item => `data:image/png;base64,${item}`);
} catch (err) {}}
生成成果就是本文 Banner
图中的粉色长头发的 3D
卡通格调小姐姐 ✨
,正向关键字 大抵是 girl, long hair, pink
,模型采纳的是 3dAnimationDiffusion_v10
,其余参数可自行调节。本文后续实例的 图生图 、 图优化 都将采纳这张图作为 参考图 进行演示。
图生图
图生图接口 ,stable-diffusion-webui
将依据咱们从接口传送的参考图,生成内容和格调相似的图片,就像最近抖音上很火的 瞬息全宇宙 特效一样,也能够将同一张图片通过抉择不同模型转化为另一种画风。上面是 图生图 接口的具体 payload
参数,能够察看到基本上和 文生图 是一样的,多了一些与 参考图片 相干的配置,如 init_images
。
{
"init_images": ["string"],
"resize_mode": 0,
"denoising_strength": 0.75,
"image_cfg_scale": 0,
"mask": "string",
"mask_blur": 0,
"mask_blur_x": 4,
"mask_blur_y": 4,
"inpainting_fill": 0,
"inpaint_full_res": true,
"inpaint_full_res_padding": 0,
"inpainting_mask_invert": 0,
"initial_noise_multiplier": 0,
"prompt": "","styles": ["string"],"seed": -1,"subseed": -1,"subseed_strength": 0,"seed_resize_from_h": -1,"seed_resize_from_w": -1,"sampler_name":"string","batch_size": 1,"n_iter": 1,"steps": 50,"cfg_scale": 7,"width": 512,"height": 512,"restore_faces": false,"tiling": false,"do_not_save_samples": false,"do_not_save_grid": false,"negative_prompt":"string","eta": 0,"s_min_uncond": 0,"s_churn": 0,"s_tmax": 0,"s_tmin": 0,"s_noise": 1,"override_settings": {},"override_settings_restore_afterwards": true,"script_args": [],"sampler_index":"Euler","include_init_images": false,"script_name":"string","send_images": true,"save_images": false,"alwayson_scripts": {}}
在页面接口逻辑中,咱们能够通过以下办法实现,其余参数和文生图都是一样的,咱们只须要把参考图以 base64
格局增加到 init_images
数组即可。
const response = await img2img({
// 正向关键词
prompt: prompt,
// 反向关键词
negative_prompt: negativePrompt,
// 初始图像
init_images: [sourceImage.value],
// 尺寸缩放
resize_mode: 0,
// ...
});
咱们将 文生图 示例中的图片作为 参考图 ,而后将大模型切换为 墨幽人造人_v1030
,就能失去如下图所示的 真人写实格调 的图片。
部分重绘
图生图 API
还能够实现图片 部分重绘、涂鸦、重绘蒙版、高清放大、图像裁减 等成果。本文中,咱们简略解说以下如何实现部分重绘性能。
要实现 部分重绘 性能,首先咱们须要应用 Canvas
创立一个画布,而后通过鼠标挪动在画布上 涂抹 出须要重绘的门路,在理论开发时咱们能够实现一个如下图所示的图片重绘编辑器,右侧图片黄色区域 🟨
是通过画笔涂抹须要重绘批改的区域。涂抹性能能够通过以下代码简略实现,像 擦除 、 画笔大小色彩抉择 、 撤销重做 等扩大性能可自行搜寻如何实现。
<div>
<canvas id="canvas"></canvas>
<img src="your_image.jpg" id="image">
<button onclick="clearMask()"> 革除遮罩 </button>
</div>
<script>
var canvas = document.getElementById('canvas');
var image = document.getElementById('image');
// 设置 canvas 宽高与图像尺寸雷同
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
var isDrawing = false; // 是否正在绘制
var lastX = 0;
var lastY = 0;
// 鼠标按下事件处理程序
canvas.addEventListener('mousedown', function(e) {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
// 鼠标挪动事件处理程序
canvas.addEventListener('mousemove', function(e) {if (!isDrawing) return;
drawMask(e.offsetX, e.offsetY);
});
// 鼠标开释事件处理程序
canvas.addEventListener('mouseup', function() {isDrawing = false;});
// 绘制遮罩函数
function drawMask(x, y) {ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.strokeStyle = 'rgba(0, 0, 0, 1)'; // 设置遮罩色彩(彩色)ctx.lineWidth = 20; // 设置遮罩宽度
ctx.lineCap = 'round'; // 设置线条末端形态为圆形
ctx.stroke();
[lastX, lastY] = [x, y];
}
// 革除遮罩函数
function clearMask() {ctx.clearRect(0, 0, canvas.width, canvas.height);
}
</script>
涂抹实现后,咱们右键保留图片,能够失去如下图左侧所示的图片。然而 stable-diffusion-webui
须要的 Mask 遮罩图是涂改区域为纯白色,非批改区域为彩色,且大小须要和原图统一,如右侧图片所示。此时就须要将失去的左侧通明遮罩层转换为右侧须要的遮罩层图片。
Canvas
遮罩层转换方法能够通过如下形式实现,绘制 Mask
图片,Canvas
应用鼠标绘制彩色图案,导出图片时须要把空白局部变为彩色,绘制线条的局部变为红色,并且须要转换成和原图雷同的尺寸。其中两个参数 _canvas
是须要转换的画布,_image
是涂抹的原图。其中用于获取图像原始尺寸的办法 getImageOriginSize
能够在本文开端办法汇总中查看
export const drawMask = async (_canvas, _image) => {return new Promise(async(resolve) => {
const canvas = _canvas;
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.clientWidth, canvas.clientHeight);
const imageDataContent = imageData.data;
// 批改图像数据中的像素色彩
for (let i = 0; i < imageDataContent.length; i += 4) {
// 判断透明度是否小于阈值
if (imageDataContent[i + 3] < 128) {
// 将通明局部设置为彩色
imageDataContent[i] = 0;
imageDataContent[i + 1] = 0;
imageDataContent[i + 2] = 0;
imageDataContent[i + 3] = 255;
} else {
// 将线条局部设置为红色
imageDataContent[i] = 255;
imageDataContent[i + 1] = 255;
imageDataContent[i + 2] = 255;
imageDataContent[i + 3] = 255;
}
}
// 将批改后的图像数据导出为图片格式
const exportCanvas = document.createElement('canvas');
exportCanvas.width = canvas.clientWidth;
exportCanvas.height = canvas.clientHeight;
const exportCtx = exportCanvas.getContext('2d');
exportCtx.putImageData(imageData, 0, 0);
// mask 放大到和原图统一
const size = await getImageOriginSize(_image);
const finalMask = await scaleImage(exportCanvas.toDataURL(), size.width, size.height);
resolve(finalMask);
});
}
而后咱们将转换后的遮罩图以 base64
的模式作为 mask
参数增加到接口参数中,增加一些正向关键字等参数进行图生图接口申请,返回后果和上述 API
都是一样的,最终就能够失去上面所示的图像,能够察看到被涂抹区域的花朵隐没了 🌺
。
const response = await img2img({init_images: [sourceImage.value],
mask: data.mask,
// ...
});
💡
本文实现中将用到十分多对于图像转换的办法,,比方 PNG 转 Base64、URL 转 Base64、Canvas 转 Base64 等,这些办法的具体实现将放在文章开端的汇总中。
前期解决
前期解决接口 ,能够实现图片 高清放大、裁切、裁减 等性能,有批量和单图调整两种接口,如下所示是单图调整接口。咱们先来看看单图优化 API
能够接管的参数有哪些:
{
"resize_mode": 0,
"show_extras_results": true,
"gfpgan_visibility": 0,
"codeformer_visibility": 0,
"codeformer_weight": 0,
"upscaling_resize": 2,
"upscaling_resize_w": 512,
"upscaling_resize_h": 512,
"upscaling_crop": true,
"upscaler_1": "None",
"upscaler_2": "None",
"extras_upscaler_2_visibility": 0,
"upscale_first": false,
"image": "" // 原图
}
其余
更多接口
stable-diffusion-webui
还有许多实用的 API
能够调用,比方能够通过 进度查问 接口实时获取到生成图片的进度、剩余时间、排队状态等、能够通过 配置查问 接口获取到配置信息、已装置的模型列表等;反向推理 接口能够通过已生成的图片反推出图像信息、形容关键字等。具体接口应用办法和参数都能够在 API
文档中查问。
实用办法
在做 Web
图片解决利用时须要用到很多图片相干的实用办法,以下是一些简略汇总。
① Canvas 转 Base64/PNG
要将 Canvas
转换为 Base64
格局图像数据,能够应用 Canvas
的 toDataURL()
办法。该办法将返回一个蕴含图像数据的字符串,其中包含图像的类型,如 image/png
和 Base64
编码的图像数据。
// 获取 Canvas 元素
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// 将 Canvas 转换为 Base64 格局的图像数据
var dataURL = canvas.toDataURL();
② 图片 URL 转 Base64
export const convertUrlToBase64 = src => {
return new Promise(resolve => {const img = new Image()
img.crossOrigin = ''
img.src = src
img.onload = function () {const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
const ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase();
const dataURL = canvas.toDataURL('image/' + ext);
resolve(dataURL);
}
});
};
③ Base64 转 PNG
export const convertBase64ToImage = src => {return new Promise((resolve) => {const arr = src.split(',');
const byteString = atob(arr[1]);
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < byteString.length; i++) {ia[i] = byteString.charCodeAt(i);
}
const file = new File([ab], generateRandomId(), { type: 'image/png'});
resolve(file);
});
}
④ 获取图像原始尺寸
export const getImageOriginSize = (src) => {return new Promise((resolve) => {const image = new Image();
image.src = src;
image.onload = () => {
resolve({
width: image.naturalWidth,
height: image.naturalHeight
});
};
});
}
⑤ 等比缩放 Base64
export const scaleImage = (src, width, height) => {return new Promise((resolve) => {const image = new Image();
image.src = src;
image.onload = () => {const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, width, height);
resolve(canvas.toDataURL());
};
})
};
还有上述文章中提到的将通明黑白 Canvas
转化为 stable-diffusion-webui
部分重绘所需的 黑底红色图案 办法等。
总结
本文次要蕴含的知识点包含:
stable-diffusion-webui
的根本介绍stable-diffusion-webui
装置及API
环境配置- 文生图、图生图、部分重绘、前期解决等
API
接口调用 - 图像处理开发中罕用到一些办法如
Base64
、PNG
、Canvas
及URL
互相转换、Canvas
色彩转换等
想理解其余前端常识或其余未在本文中详细描述的 AI 相干 开发技术相干常识,可浏览我往期的文章。如果有疑难能够在评论中 留言 ,如果感觉文章对你有帮忙,不要忘了 一键三连哦 👍。
附录
- [1]. 🌴 Three.js 打造缤纷夏日 3D 梦中情岛
- [2]. 🔥 Three.js 实现炫酷的赛博朋克格调 3D 数字地球大屏
- [3]. 🐼 Three.js 实现 2022 冬奥主题 3D 趣味页面,含冰墩墩
- [4]. 🦊 Three.js 实现 3D 凋谢世界小游戏:阿狸的多元宇宙
- [5]. 🏡 Three.js 进阶之旅:全景漫游 - 高阶版在线看房
...
- 【Three.js 进阶之旅】系列专栏拜访 👈
- 【前端玩转 AIGC】专栏拜访 👈
参考
- [1]. Stable Diffusion WebUI
- [2]. stable-diffusion-webui github
- [3]. stable diffusion 远端跑图—— Api 基础知识把握
- [4]. 哩布哩布 AI