Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
247fbfbc21 | ||
|
|
9b24eddd9c | ||
|
|
505314294f | ||
|
|
f5cd56ce86 | ||
|
|
cbcacbe3c9 | ||
|
|
7c020bab28 | ||
|
|
9e751a242f | ||
|
|
0e311cf2c6 | ||
|
|
889f08c08b | ||
|
|
5d661b2509 | ||
|
|
be162a2047 | ||
|
|
4ea26ed8de | ||
|
|
c237737420 | ||
|
|
232cf8966c | ||
|
|
96a0618c59 | ||
|
|
d143e83dba | ||
|
|
3dfe98c795 | ||
|
|
c0cc5572d8 |
@@ -27,15 +27,15 @@ jobs:
|
||||
steps:
|
||||
- name: ♻️ Checking out the repository
|
||||
uses: actions/checkout@v3
|
||||
- name: "🐍 Setting up Python"
|
||||
- name: '🐍 Setting up Python'
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10.9"
|
||||
python-version: '3.10.9'
|
||||
|
||||
- name: 📦 Building and Bundling wheels
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip wheel --no-cache-dir --no-deps -r requirements-wheels.txt -w ./wheels 2>&1 | tee build.log
|
||||
python -m pip wheel --no-cache-dir -r reqs.txt -w ./wheels 2>&1 | tee build.log
|
||||
|
||||
# find source wheels
|
||||
packages=$(cat build.log | awk -F 'Building wheels for collected packages: ' '{print $2}')
|
||||
@@ -43,6 +43,13 @@ jobs:
|
||||
|
||||
IFS=', ' read -r -a package_array <<< "$packages"
|
||||
|
||||
# Save reversed package_array to wheel_order.txt
|
||||
reversed_array=()
|
||||
for ((idx=${#package_array[@]}-1; idx>=0; idx--)); do
|
||||
reversed_array+=("${package_array[idx]}")
|
||||
done
|
||||
printf '%s\n' "${reversed_array[@]}" > ./wheels/wheel_order.txt
|
||||
|
||||
printf "Autodetect this source package: \e[32m%s\e[0m\n" "${package_array[@]}"
|
||||
|
||||
# Iterate through the wheel files and remove those that are not source built
|
||||
|
||||
@@ -39,14 +39,20 @@ jobs:
|
||||
- name: 🗑️ Remove files and directories listed in .release_ignore
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f "${{ env.repo_name }}/.release_ignore" ]; then
|
||||
while IFS= read -r entry; do
|
||||
if [ -f "${{ env.repo_name }}/$entry" ]; then
|
||||
rm "${{ env.repo_name }}/$entry"
|
||||
elif [ -d "${{ env.repo_name }}/$entry" ]; then
|
||||
rm -r "${{ env.repo_name }}/$entry"
|
||||
release_ignore="${{ env.repo_name }}/.release_ignore"
|
||||
if [ -f "$release_ignore" ]; then
|
||||
while IFS= read -r entry || [ -n "$entry" ]; do
|
||||
target="${{ env.repo_name }}/$entry"
|
||||
if [ -e "$target" ]; then
|
||||
if [ -f "$target" ]; then
|
||||
rm "$target"
|
||||
elif [ -d "$target" ]; then
|
||||
rm -r "$target"
|
||||
fi
|
||||
else
|
||||
echo "Warning: $entry does not exist in the repository. Skipping removal."
|
||||
fi
|
||||
done < "${{ env.repo_name }}/.release_ignore"
|
||||
done < "$release_ignore"
|
||||
else
|
||||
echo "No .release_ignore file found. Skipping removal of files and directories."
|
||||
fi
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
extern/frame_interpolation/moment.gif
|
||||
extern/frame_interpolation/photos
|
||||
extern/GFPGAN/inputs
|
||||
extern/GFPGAN/inputs
|
||||
.git
|
||||
+2
-2
@@ -49,7 +49,7 @@ python scripts/download_models.py
|
||||
1. 确保您处于用于 ComfyUI 的 Python 环境中。
|
||||
2. 运行以下命令安装所需的依赖项:
|
||||
```bash
|
||||
pip install -r comfy_mtb/requirements.txt
|
||||
pip install -r comfy_mtb/reqs.txt
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -77,7 +77,7 @@ python scripts/download_models.py
|
||||
!python custom_nodes/comfy_mtb/scripts/download_models.py -y
|
||||
|
||||
# install the dependencies
|
||||
!pip install -r custom_nodes/comfy_mtb/requirements.txt -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
|
||||
!pip install -r custom_nodes/comfy_mtb/reqs.txt -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
|
||||
```
|
||||
|
||||
如果运行后 colab 抱怨需要重新启动运行时,请重新启动,然后不要重新运行之前的单元格,只运行运行本地隧道的单元格。(可能需要先添加一个包含 `%cd ComfyUI` 的单元格)
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ python scripts/download_models.py
|
||||
1. ComfyUIで使用しているPython環境であることを確認してください。
|
||||
2. 以下のコマンドを実行して、必要な依存関係をインストールします:
|
||||
```bash
|
||||
pip install -r comfy_mtb/requirements.txt
|
||||
pip install -r comfy_mtb/reqs.txt
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -78,7 +78,7 @@ ComfyUI with localtunnel (Recommended Way)**ヘッダーのすぐ後(コード
|
||||
!python custom_nodes/comfy_mtb/scripts/download_models.py -y
|
||||
|
||||
# install the dependencies
|
||||
!pip install -r custom_nodes/comfy_mtb/requirements.txt -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
|
||||
!pip install -r custom_nodes/comfy_mtb/reqs.txt -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
|
||||
```
|
||||
これを実行した後、colabがランタイムを再起動する必要があると文句を言ったら、それを実行し、それ以前のセルは再実行せず、localtunnelを実行するセルだけを再実行してください。(最初に`%cd ComfyUI`のセルを追加する必要があるかもしれません...)
|
||||
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ On first run the script [tries to symlink](https://github.com/melMass/comfy_mtb/
|
||||
1. Make sure you are in the Python environment you use for ComfyUI.
|
||||
2. Install the required dependencies by running the following command:
|
||||
```bash
|
||||
pip install -r comfy_mtb/requirements.txt
|
||||
pip install -r comfy_mtb/reqs.txt
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -76,7 +76,7 @@ Add a new code cell just after the **Run ComfyUI with localtunnel (Recommended W
|
||||
!python custom_nodes/comfy_mtb/scripts/download_models.py -y
|
||||
|
||||
# install the dependencies
|
||||
!pip install -r custom_nodes/comfy_mtb/requirements.txt -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
|
||||
!pip install -r custom_nodes/comfy_mtb/reqs.txt -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
|
||||
```
|
||||
If after running this, colab complains about needing to restart runtime, do it, and then do not rerun earlier cells, just the one to run the localtunnel. (you might have to add a cell with `%cd ComfyUI` first...)
|
||||
|
||||
|
||||
+14
-17
@@ -1,13 +1,13 @@
|
||||
## MTB Nodes
|
||||
# MTB Nodes
|
||||
|
||||
<a href="https://www.buymeacoffee.com/melmass" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 32px !important;width: 140px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
|
||||
|
||||
[** 安装指南**](./INSTALL-CN.md) | [** 示例**](https://github.com/melMass/comfy_mtb/wiki/Examples)
|
||||
|
||||
欢迎使用 MTB Nodes 项目!这个代码库是开放的,您可以自由地探索和利用。它的主要目的是构建用于 [MLOPs](https://github.com/Bismuth-Consultancy-BV/MLOPs) 中的概念验证(POCs)。该项目中的许多节点都是受到现有社区贡献或内置功能的启发而创建的。
|
||||
|
||||
在继续之前,请注意与此项目中使用的某些库相关的许可证。例如,`deepbump` 库采用 [GPLv3](https://github.com/HugoTini/DeepBump/blob/master/LICENSE) 许可证。
|
||||
|
||||
- [MTB Nodes](#mtb-nodes)
|
||||
- [安装](#安装)
|
||||
- [节点列表](#节点列表)
|
||||
- [bbox](#bbox)
|
||||
- [colors](#colors)
|
||||
@@ -20,27 +20,24 @@
|
||||
- [Comfy 资源](#comfy-资源)
|
||||
|
||||
|
||||
## 安装
|
||||
|
||||
- 移至 [INSTALL-CN.md](./INSTALL-CN.md)
|
||||
|
||||
|
||||
## 节点列表
|
||||
# 节点列表
|
||||
|
||||
### bbox
|
||||
## bbox
|
||||
- `Bounding Box`: BBox 构造函数(自定义类型)
|
||||
- `BBox From Mask`: 从遮罩中提取边界框
|
||||
- `Crop`: 根据边界框裁剪图像
|
||||
- `Uncrop`: 根据边界框还原图像
|
||||
|
||||
### colors
|
||||
## colors
|
||||
- `Colored Image`: 给定尺寸的纯色图像
|
||||
- `RGB to HSV`: -
|
||||
- `HSV to RGB`: -
|
||||
- `Color Correct`: 基本颜色校正工具
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/7c20ac83-31ff-40ea-a1a0-06c2acefb2ef" width=345/>
|
||||
|
||||
### 人脸检测/交换
|
||||
## 人脸检测/交换
|
||||
- `Face Swap`: 使用 deepinsight/insightface 模型进行人脸交换(该节点在早期版本中称为 `Roop`,功能相同,`Roop` 只是使用这些模型的应用程序)
|
||||
> **注意**
|
||||
> 人脸索引允许您选择要替换的人脸,如下所示:
|
||||
@@ -48,13 +45,13 @@
|
||||
- `Load Face Swap Model`: 加载 insightface 模型用于人脸交换
|
||||
- `Restore Face`: 使用 [GFPGan](https://github.com/TencentARC/GFPGAN) 还原人脸,与 `Face Swap` 配合使用效果很好,并支持 `bg_upscaler` 的 Comfy 原生放大器
|
||||
|
||||
### 图像插值(动画)
|
||||
## 图像插值(动画)
|
||||
- `Load Film Model`: 加载 [FILM](https://github.com/google-research/frame-interpolation) 模型
|
||||
- `Film Interpolation`: 使用 [FILM](https://github.com/google-research/frame-interpolation) 处理输入帧
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/3afd1647-6634-4b92-a34b-51432e6a9834" width=400/>
|
||||
- `Export to Prores (experimental)`: 将输入帧导出为 ProRes 4444 mov 文件。这使用 ffmpeg stdin 发送原始的 NumPy 数组,与 `Film Interpolation` 一起使用,目前很简单,但可以进一步扩展。
|
||||
|
||||
### 图像操作
|
||||
## 图像操作
|
||||
- `Blur`: 使用高斯滤波器对图像进行模糊处理。
|
||||
- `Deglaze Image`: 从 [FN16](https://github.com/Fannovel16/FN16-ComfyUI-nodes/blob/main/DeglazeImage.py) 中提取
|
||||
- `Denoise`: 对输入图像进行降噪处理
|
||||
@@ -66,11 +63,11 @@
|
||||
- `Mask To Image`: 将遮罩(Alpha)转换为带有颜色和背景的 RGB 图像
|
||||
- `Save Image Grid`: 将输入批次中的所有图像保存为图像网格。
|
||||
|
||||
### 潜在变量工具
|
||||
## 潜在变量工具
|
||||
- `Latent Lerp`: 两个潜在变量之间的线性插值(混合)
|
||||
|
||||
|
||||
### 其他工具
|
||||
## 其他工具
|
||||
- `Concat Images`: 接受两个图像流,并将它们合并为其他 Comfy 管道支持的图像批次。
|
||||
- `Image Resize Factor`: **已弃用**,因为我后来发现了内
|
||||
|
||||
@@ -84,11 +81,11 @@
|
||||
- `Int to Number`: 用于 WASSuite 数字节点的补充
|
||||
- `Smart Step`: 使用百分比来控制 `KAdvancedSampler` 的步骤(开始/停止)
|
||||
|
||||
### 纹理
|
||||
## 纹理
|
||||
|
||||
- `DeepBump`: 从单张图片生成法线图和高度图
|
||||
|
||||
## Comfy 资源
|
||||
# Comfy 资源
|
||||
|
||||
**指南**:
|
||||
- [官方示例(英文)](https://comfyanonymous.github.io/ComfyUI_examples/)
|
||||
@@ -99,4 +96,4 @@
|
||||
**扩展和自定义节点**:
|
||||
- @WASasquatch 的[Comfy 列表插件(英文)](https://github.com/WASasquatch/comfyui-plugins)
|
||||
|
||||
- [CivitAI 上的 ComfyUI 标签(英文)](https://civitai.com/tag/comfyui)
|
||||
- [CivitAI 上的 ComfyUI 标签(英文)](https://civitai.com/tag/comfyui)
|
||||
|
||||
+14
-19
@@ -1,13 +1,13 @@
|
||||
## MTB Nodes
|
||||
# MTB Nodes
|
||||
|
||||
<a href="https://www.buymeacoffee.com/melmass" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 32px !important;width: 140px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
|
||||
|
||||
[**インストールガイド**](./INSTALL-JP.md) | [**サンプル**](https://github.com/melMass/comfy_mtb/wiki/Examples)
|
||||
|
||||
MTB Nodesプロジェクトへようこそ!このコードベースは、自由に探索し、利用することができます。主な目的は、[MLOPs](https://github.com/Bismuth-Consultancy-BV/MLOPs)の実装のための概念実証(POC)を構築することです。このプロジェクトの多くのノードは、既存のコミュニティの貢献や組み込みの機能に触発されています。
|
||||
|
||||
続行する前に、このプロジェクトで使用されている特定のライブラリに関連するライセンスに注意してください。たとえば、「deepbump」ライブラリは、[GPLv3](https://github.com/HugoTini/DeepBump/blob/master/LICENSE)の下でライセンスされています。
|
||||
|
||||
- [MTB Nodes](#mtb-nodes)
|
||||
- [インストール](#インストール)
|
||||
- [ノードリスト](#ノードリスト)
|
||||
- [bbox](#bbox)
|
||||
- [colors](#colors)
|
||||
@@ -20,27 +20,22 @@ MTB Nodesプロジェクトへようこそ!このコードベースは、自
|
||||
- [Comfyリソース](#comfyリソース)
|
||||
|
||||
|
||||
## インストール
|
||||
# ノードリスト
|
||||
|
||||
- [INSTALL-JP.md](./INSTALL-JP.md)に移動しました。
|
||||
|
||||
|
||||
## ノードリスト
|
||||
|
||||
### bbox
|
||||
## bbox
|
||||
- `Bounding Box`: BBoxコンストラクタ(カスタムタイプ)
|
||||
- `BBox From Mask`: マスクからバウンディングボックスを抽出
|
||||
- `Crop`: BBoxから画像を切り抜く
|
||||
- `Uncrop`: BBoxから画像を元に戻す
|
||||
|
||||
### colors
|
||||
## colors
|
||||
- `Colored Image`: 指定されたサイズの一定の色の画像
|
||||
- `RGB to HSV`: -
|
||||
- `HSV to RGB`: -
|
||||
- `Color Correct`: 基本的なカラーコレクションツール
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/7c20ac83-31ff-40ea-a1a0-06c2acefb2ef" width=345/>
|
||||
|
||||
### 顔検出 / スワッピング
|
||||
## 顔検出 / スワッピング
|
||||
- `Face Swap`: deepinsight/insightfaceモデルを使用した顔の入れ替え(このノードは初期バージョンでは「Roop」と呼ばれていましたが、同じ機能を提供します。Roopは単にこれらのモデルを使用するアプリです)
|
||||
> **注意**
|
||||
> 顔のインデックスを使用して置き換える顔を選択できます。以下を参照してください:
|
||||
@@ -48,13 +43,13 @@ MTB Nodesプロジェクトへようこそ!このコードベースは、自
|
||||
- `Load Face Swap Model`: 顔の交換のためのinsightfaceモデルを読み込む
|
||||
- `Restore Face`: [GFPGan](https://github.com/TencentARC/GFPGAN)を使用して顔を復元し、`Face Swap`と組み合わせて使用すると非常に効果的であり、`bg_upscaler`のComfyネイティブアップスケーラーもサポートしています。
|
||||
|
||||
### 画像補間(アニメーション)
|
||||
## 画像補間(アニメーション)
|
||||
- `Load Film Model`: [FILM](https://github.com/google-research/frame-interpolation)モデルを読み込む
|
||||
- `Film Interpolation`: [FILM](https://github.com/google-research/frame-interpolation)を使用して入力フレームを処理する
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/3afd1647-6634-4b92-a34b-51432e6a9834" width=400/>
|
||||
- `Export to Prores (experimental)`: 入力フレームをProRes 4444 movファイルにエクスポートします。これは現在は単純なものですが、`Film Interpolation`と組み合わせて使用するためのffmpegのstdinを使用して生のNumPy配列を送信するもので、拡張することもできます。
|
||||
|
||||
### 画像操作
|
||||
## 画像操作
|
||||
- `Blur`: ガウスフィルタを使用して画像をぼかす
|
||||
- `Deglaze Image`: [FN16](https://github.com/Fannovel16/FN16-ComfyUI-nodes/blob/main/DeglazeImage.py)から取得
|
||||
- `Denoise`: 入力画像のノイズを除去する
|
||||
@@ -68,10 +63,10 @@ MTB Nodesプロジェクトへようこそ!このコードベースは、自
|
||||
- `Mask To Image`: マスク(アルファ)をカラーと背景を持つRGBイメージに変換します。
|
||||
- `Save Image Grid`: 入力バッチのすべての画像を画像グリッドとして保存します。
|
||||
|
||||
### 潜在的なユーティリティ
|
||||
## 潜在的なユーティリティ
|
||||
- `Latent Lerp`: 2つの潜在的なベクトルの間の線形補間(ブレンド)
|
||||
|
||||
### その他のユーティリティ
|
||||
## その他のユーティリティ
|
||||
- `Concat Images`: 2つの画像ストリームを取り、他のComfyパイプラインでサポートされている画像のバッチとしてマージします。
|
||||
- `Image Resize Factor`: **非推奨**。組み込みの画像リサイズ機能を発見したため、削除される予定です。
|
||||
- `Text To Image`: フォントを使用してテキストを画像に変換するためのユーティリティ
|
||||
@@ -83,11 +78,11 @@ MTB Nodesプロジェクトへようこそ!このコードベースは、自
|
||||
- `Int to Number`: WASSuiteの数値ノードの補完
|
||||
- `Smart Step`: `KAdvancedSampler`のステップ(開始/停止)を制御するための非常に基本的なツールで、パーセンテージを使用します。
|
||||
|
||||
### テクスチャ
|
||||
## テクスチャ
|
||||
|
||||
- `DeepBump`: 1枚の画像から法線マップと高さマップを生成します。
|
||||
|
||||
## Comfyリソース
|
||||
# Comfyリソース
|
||||
|
||||
**ガイド**:
|
||||
- [公式の例(英語)](https://comfyanonymous.github.io/ComfyUI_examples/)
|
||||
@@ -98,4 +93,4 @@ MTB Nodesプロジェクトへようこそ!このコードベースは、自
|
||||
**拡張機能とカスタムノード**:
|
||||
- @WASasquatchによる[Comfyリスト用のプラグイン(英語)](https://github.com/WASasquatch/comfyui-plugins)
|
||||
|
||||
- [CivitAIのComfyUIタグ(英語)](https://civitai.com/tag/comfyui)
|
||||
- [CivitAIのComfyUIタグ(英語)](https://civitai.com/tag/comfyui)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
## MTB Nodes
|
||||
# MTB Nodes
|
||||
<!-- omit in toc -->
|
||||
|
||||
**Translated Readme (using DeepTranslate, PRs are welcome)**:
|
||||

|
||||
@@ -8,12 +9,12 @@
|
||||
|
||||
<a href="https://www.buymeacoffee.com/melmass" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 32px !important;width: 140px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
|
||||
|
||||
[**Install Guide**](./INSTALL.md) | [**Examples**](https://github.com/melMass/comfy_mtb/wiki/Examples)
|
||||
|
||||
Welcome to the MTB Nodes project! This codebase is open for you to explore and utilize as you wish. Its primary purpose is to build proof-of-concepts (POCs) for implementation in [MLOPs](https://github.com/Bismuth-Consultancy-BV/MLOPs). Many nodes in this project are inspired by existing community contributions or built-in functionalities.
|
||||
|
||||
Before proceeding, please be aware of the licenses associated with certain libraries used in this project. For example, the `deepbump` library is licensed under [GPLv3](https://github.com/HugoTini/DeepBump/blob/master/LICENSE).
|
||||
|
||||
- [MTB Nodes](#mtb-nodes)
|
||||
- [Installation](#installation)
|
||||
- [Node List](#node-list)
|
||||
- [bbox](#bbox)
|
||||
- [colors](#colors)
|
||||
@@ -26,27 +27,22 @@ Before proceeding, please be aware of the licenses associated with certain libra
|
||||
- [Comfy Resources](#comfy-resources)
|
||||
|
||||
|
||||
## Installation
|
||||
# Node List
|
||||
|
||||
- Moved to [INSTALL.md](./INSTALL.md)
|
||||
|
||||
|
||||
## Node List
|
||||
|
||||
### bbox
|
||||
## bbox
|
||||
- `Bounding Box`: BBox constructor (custom type),
|
||||
- `BBox From Mask`: From a mask extract the bounding box
|
||||
- `Crop`: Crop image from BBox
|
||||
- `Uncrop`: Uncrop image from BBox
|
||||
|
||||
### colors
|
||||
## colors
|
||||
- `Colored Image`: Constant color image of given size
|
||||
- `RGB to HSV`: -,
|
||||
- `HSV to RGB`: -,
|
||||
- `Color Correct`: Basic color correction tools
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/7c20ac83-31ff-40ea-a1a0-06c2acefb2ef" width=345/>
|
||||
|
||||
### face detection / swapping
|
||||
## face detection / swapping
|
||||
- `Face Swap`: Face swap using deepinsight/insightface models (this node used to be called `Roop` in early versions, it does the same, roop is *just* an app that uses those model)
|
||||
> **Note**
|
||||
> The face index allow you to choose which face to replace as you can see here:
|
||||
@@ -54,13 +50,13 @@ Before proceeding, please be aware of the licenses associated with certain libra
|
||||
- `Load Face Swap Model`: Load an insightface model for face swapping
|
||||
- `Restore Face`: Using [GFPGan](https://github.com/TencentARC/GFPGAN) to restore faces, works great in conjunction with `Face Swap` and supports Comfy native upscalers for the `bg_upscaler`
|
||||
|
||||
### image interpolation (animation)
|
||||
## image interpolation (animation)
|
||||
- `Load Film Model`: Loads a [FILM](https://github.com/google-research/frame-interpolation) model
|
||||
- `Film Interpolation`: Process input frames using [FILM](https://github.com/google-research/frame-interpolation)
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/3afd1647-6634-4b92-a34b-51432e6a9834" width=400/>
|
||||
- `Export to Prores (experimental)`: Exports the input frames to a ProRes 4444 mov file. This is using ffmpeg stdin to send raw numpy arrays, used with `Film Interpolation` and very simple for now but could be expanded upon.
|
||||
|
||||
### image ops
|
||||
## image ops
|
||||
- `Blur`: Blur an image using a Gaussian filter.
|
||||
- `Deglaze Image`: taken from [FN16](https://github.com/Fannovel16/FN16-ComfyUI-nodes/blob/main/DeglazeImage.py),
|
||||
- `Denoise`: Denoise the input image,
|
||||
@@ -72,11 +68,11 @@ Before proceeding, please be aware of the licenses associated with certain libra
|
||||
- `Mask To Image`: Converts a mask (alpha) to an RGB image with a color and background
|
||||
- `Save Image Grid`: Save all the images in the input batch as a grid of images.
|
||||
|
||||
### latent utils
|
||||
## latent utils
|
||||
- `Latent Lerp`: Linear interpolation (blend) between two latent
|
||||
|
||||
|
||||
### misc utils
|
||||
## misc utils
|
||||
- `Concat Images`: Takes two image stream and merge them as a batch of images supported by other Comfy pipelines.
|
||||
- `Image Resize Factor`: **Deprecated**, I since discovered the builtin image resize.
|
||||
- `Text To Image`: Utils to convert text to image using a font
|
||||
@@ -88,11 +84,11 @@ Before proceeding, please be aware of the licenses associated with certain libra
|
||||
- `Int to Number`: Supplement for WASSuite number nodes
|
||||
- `Smart Step`: A very basic tool to control the steps (start/stop) of the `KAdvancedSampler` using percentage
|
||||
|
||||
### textures
|
||||
## textures
|
||||
|
||||
- `DeepBump`: Normal & height maps generation from single pictures
|
||||
|
||||
## Comfy Resources
|
||||
# Comfy Resources
|
||||
|
||||
**Guides**:
|
||||
- [Official Examples (eng)](https://comfyanonymous.github.io/ComfyUI_examples/)
|
||||
|
||||
+111
-103
@@ -5,11 +5,13 @@
|
||||
# Project: comfy_mtb
|
||||
# Author: Mel Massadian
|
||||
# Copyright (c) 2023 Mel Massadian
|
||||
#
|
||||
#
|
||||
###
|
||||
import os
|
||||
|
||||
# todo: don't override this if the user has that setup already
|
||||
os.environ["TF_FORCE_GPU_ALLOW_GROWTH"] = "true"
|
||||
os.environ["TF_GPU_ALLOCATOR"] = "cuda_malloc_async"
|
||||
|
||||
import traceback
|
||||
from .log import log, blue_text, cyan_text, get_summary, get_label
|
||||
@@ -24,7 +26,7 @@ NODE_CLASS_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
NODE_CLASS_MAPPINGS_DEBUG = {}
|
||||
|
||||
__version__ = "0.1.1"
|
||||
__version__ = "0.1.2"
|
||||
|
||||
|
||||
def extract_nodes_from_source(filename):
|
||||
@@ -112,8 +114,16 @@ if web_mtb.exists():
|
||||
|
||||
elif web_extensions_root.exists():
|
||||
web_tgt = here / "web"
|
||||
src = web_tgt.as_posix()
|
||||
dst = web_mtb.as_posix()
|
||||
try:
|
||||
os.symlink(web_tgt.as_posix(), web_mtb.as_posix())
|
||||
if os.name == "nt":
|
||||
import _winapi
|
||||
|
||||
_winapi.CreateJunction(src, dst)
|
||||
else:
|
||||
os.symlink(web_tgt.as_posix(), web_mtb.as_posix())
|
||||
|
||||
except OSError:
|
||||
log.warn(f"Failed to create symlink to {web_mtb}, trying to copy it")
|
||||
try:
|
||||
@@ -174,123 +184,121 @@ from importlib import reload
|
||||
import logging
|
||||
from .endpoint import endlog
|
||||
|
||||
if hasattr(PromptServer, "instance"):
|
||||
|
||||
@PromptServer.instance.routes.get("/mtb/status")
|
||||
async def get_full_library(request):
|
||||
from . import endpoint
|
||||
@PromptServer.instance.routes.get("/mtb/status")
|
||||
async def get_full_library(request):
|
||||
from . import endpoint
|
||||
|
||||
reload(endpoint)
|
||||
reload(endpoint)
|
||||
|
||||
endlog.debug("Getting node registration status")
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = endpoint.render_table(
|
||||
NODE_CLASS_MAPPINGS_DEBUG, title="Registered"
|
||||
)
|
||||
html_response += endpoint.render_table(
|
||||
{k: "-" for k in failed}, title="Failed to load"
|
||||
endlog.debug("Getting node registration status")
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = endpoint.render_table(
|
||||
NODE_CLASS_MAPPINGS_DEBUG, title="Registered"
|
||||
)
|
||||
html_response += endpoint.render_table(
|
||||
{k: "-" for k in failed}, title="Failed to load"
|
||||
)
|
||||
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("MTB", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
|
||||
return web.json_response(
|
||||
{
|
||||
"registered": NODE_CLASS_MAPPINGS_DEBUG,
|
||||
"failed": failed,
|
||||
}
|
||||
)
|
||||
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("MTB", html_response),
|
||||
content_type="text/html",
|
||||
@PromptServer.instance.routes.post("/mtb/debug")
|
||||
async def set_debug(request):
|
||||
json_data = await request.json()
|
||||
enabled = json_data.get("enabled")
|
||||
if enabled:
|
||||
os.environ["MTB_DEBUG"] = "true"
|
||||
log.setLevel(logging.DEBUG)
|
||||
log.debug("Debug mode set from API (/mtb/debug POST route)")
|
||||
|
||||
else:
|
||||
if "MTB_DEBUG" in os.environ:
|
||||
# del os.environ["MTB_DEBUG"]
|
||||
os.environ.pop("MTB_DEBUG")
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
return web.json_response(
|
||||
{"message": f"Debug mode {'set' if enabled else 'unset'}"}
|
||||
)
|
||||
|
||||
return web.json_response(
|
||||
{
|
||||
"registered": NODE_CLASS_MAPPINGS_DEBUG,
|
||||
"failed": failed,
|
||||
}
|
||||
)
|
||||
@PromptServer.instance.routes.get("/mtb")
|
||||
async def get_home(request):
|
||||
from . import endpoint
|
||||
|
||||
reload(endpoint)
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = f"""
|
||||
<div class="flex-container menu">
|
||||
<a href="/mtb/debug">debug</a>
|
||||
<a href="/mtb/status">status</a>
|
||||
</div>
|
||||
"""
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("MTB", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
|
||||
@PromptServer.instance.routes.post("/mtb/debug")
|
||||
async def set_debug(request):
|
||||
json_data = await request.json()
|
||||
enabled = json_data.get("enabled")
|
||||
if enabled:
|
||||
os.environ["MTB_DEBUG"] = "true"
|
||||
log.setLevel(logging.DEBUG)
|
||||
log.debug("Debug mode set from API (/mtb/debug POST route)")
|
||||
# Return JSON for other requests
|
||||
return web.json_response({"message": "Welcome to MTB!"})
|
||||
|
||||
else:
|
||||
@PromptServer.instance.routes.get("/mtb/debug")
|
||||
async def get_debug(request):
|
||||
from . import endpoint
|
||||
|
||||
reload(endpoint)
|
||||
enabled = False
|
||||
if "MTB_DEBUG" in os.environ:
|
||||
# del os.environ["MTB_DEBUG"]
|
||||
os.environ.pop("MTB_DEBUG")
|
||||
log.setLevel(logging.INFO)
|
||||
enabled = True
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = f"""
|
||||
<h1>MTB Debug Status: {'Enabled' if enabled else 'Disabled'}</h1>
|
||||
"""
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("Debug", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
|
||||
return web.json_response({"message": f"Debug mode {'set' if enabled else 'unset'}"})
|
||||
# Return JSON for other requests
|
||||
return web.json_response({"enabled": enabled})
|
||||
|
||||
@PromptServer.instance.routes.get("/mtb/actions")
|
||||
async def no_route(request):
|
||||
from . import endpoint
|
||||
|
||||
@PromptServer.instance.routes.get("/mtb")
|
||||
async def get_home(request):
|
||||
from . import endpoint
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
html_response = f"""
|
||||
<h1>Actions has no get for now...</h1>
|
||||
"""
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("Actions", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
return web.json_response({"message": "actions has no get for now"})
|
||||
|
||||
reload(endpoint)
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = f"""
|
||||
<div class="flex-container menu">
|
||||
<a href="/mtb/debug">debug</a>
|
||||
<a href="/mtb/status">status</a>
|
||||
</div>
|
||||
"""
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("MTB", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
@PromptServer.instance.routes.post("/mtb/actions")
|
||||
async def do_action(request):
|
||||
from . import endpoint
|
||||
|
||||
# Return JSON for other requests
|
||||
return web.json_response({"message": "Welcome to MTB!"})
|
||||
reload(endpoint)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/mtb/debug")
|
||||
async def get_debug(request):
|
||||
from . import endpoint
|
||||
|
||||
reload(endpoint)
|
||||
enabled = False
|
||||
if "MTB_DEBUG" in os.environ:
|
||||
enabled = True
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = f"""
|
||||
<h1>MTB Debug Status: {'Enabled' if enabled else 'Disabled'}</h1>
|
||||
"""
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("Debug", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
|
||||
# Return JSON for other requests
|
||||
return web.json_response({"enabled": enabled})
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/mtb/actions")
|
||||
async def no_route(request):
|
||||
from . import endpoint
|
||||
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
html_response = f"""
|
||||
<h1>Actions has no get for now...</h1>
|
||||
"""
|
||||
return web.Response(
|
||||
text=endpoint.render_base_template("Actions", html_response),
|
||||
content_type="text/html",
|
||||
)
|
||||
return web.json_response({"message": "actions has no get for now"})
|
||||
|
||||
|
||||
@PromptServer.instance.routes.post("/mtb/actions")
|
||||
async def do_action(request):
|
||||
from . import endpoint
|
||||
|
||||
reload(endpoint)
|
||||
|
||||
return await endpoint.do_action(request)
|
||||
return await endpoint.do_action(request)
|
||||
|
||||
|
||||
# - WAS Dictionary
|
||||
|
||||
+274
-237
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"last_node_id": 76,
|
||||
"last_link_id": 161,
|
||||
"last_node_id": 86,
|
||||
"last_link_id": 178,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 59,
|
||||
@@ -14,7 +14,7 @@
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -50,7 +50,7 @@
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -85,7 +85,7 @@
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -121,7 +121,7 @@
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -167,7 +167,7 @@
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 87,
|
||||
"link": 164,
|
||||
"widget": {
|
||||
"name": "text",
|
||||
"config": [
|
||||
@@ -242,7 +242,7 @@
|
||||
164.31304931640625
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -316,6 +316,114 @@
|
||||
"revAnimated_v122.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
2338.9229387812507,
|
||||
-632.8275743593749
|
||||
],
|
||||
"size": [
|
||||
726.28564453125,
|
||||
475.3432312011719
|
||||
],
|
||||
"flags": {},
|
||||
"order": 20,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 150
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 75,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1573.5946044921875,
|
||||
-629.80322265625
|
||||
],
|
||||
"size": [
|
||||
691.7459716796875,
|
||||
479.6098327636719
|
||||
],
|
||||
"flags": {},
|
||||
"order": 19,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 169
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 73,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
760,
|
||||
-630
|
||||
],
|
||||
"size": [
|
||||
671.1859741210938,
|
||||
483.1548156738281
|
||||
],
|
||||
"flags": {},
|
||||
"order": 16,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 153
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 79,
|
||||
"type": "Text box",
|
||||
"pos": [
|
||||
-1400,
|
||||
276
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
200
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
164
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"title": "❌Mel Negatives (general) (Negative)",
|
||||
"properties": {
|
||||
"Node name for S&R": "Text box"
|
||||
},
|
||||
"widgets_values": [
|
||||
"embedding:EasyNegative, embedding:EasyNegativeV2, watermark, text, deformed, disfigured, blurry"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "KSampler",
|
||||
@@ -328,7 +436,7 @@
|
||||
474
|
||||
],
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"order": 14,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -366,7 +474,7 @@
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
542821171532982,
|
||||
542821171533322,
|
||||
"fixed",
|
||||
45,
|
||||
8,
|
||||
@@ -389,7 +497,7 @@
|
||||
"flags": {
|
||||
"collapsed": false
|
||||
},
|
||||
"order": 14,
|
||||
"order": 15,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -410,7 +518,7 @@
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
153,
|
||||
161
|
||||
167
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
@@ -421,74 +529,24 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "PreviewImage",
|
||||
"id": 70,
|
||||
"type": "Restore Face (mtb)",
|
||||
"pos": [
|
||||
2338.9229387812507,
|
||||
-632.8275743593749
|
||||
2320,
|
||||
-50
|
||||
],
|
||||
"size": [
|
||||
726.28564453125,
|
||||
475.3432312011719
|
||||
],
|
||||
"flags": {},
|
||||
"order": 19,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 150
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 75,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1573.5946044921875,
|
||||
-629.80322265625
|
||||
],
|
||||
"size": [
|
||||
691.7459716796875,
|
||||
479.6098327636719
|
||||
315,
|
||||
186
|
||||
],
|
||||
"flags": {},
|
||||
"order": 18,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 156
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 70,
|
||||
"type": "Restore Face (mtb)",
|
||||
"pos": [
|
||||
1899,
|
||||
-51
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
150
|
||||
],
|
||||
"flags": {},
|
||||
"order": 17,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 149
|
||||
"link": 168
|
||||
},
|
||||
{
|
||||
"name": "model",
|
||||
@@ -512,78 +570,56 @@
|
||||
"Node name for S&R": "Restore Face (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
"false",
|
||||
"false",
|
||||
false,
|
||||
false,
|
||||
0.5,
|
||||
"true"
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 67,
|
||||
"type": "Face Swap (mtb)",
|
||||
"id": 72,
|
||||
"type": "UpscaleModelLoader",
|
||||
"pos": [
|
||||
1127,
|
||||
-26
|
||||
1715,
|
||||
52
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
122
|
||||
260.3902351585391,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 16,
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 161
|
||||
},
|
||||
{
|
||||
"name": "reference",
|
||||
"type": "IMAGE",
|
||||
"link": 160,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "faceswap_model",
|
||||
"type": "FACESWAP_MODEL",
|
||||
"link": 147,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"name": "UPSCALE_MODEL",
|
||||
"type": "UPSCALE_MODEL",
|
||||
"links": [
|
||||
149,
|
||||
156
|
||||
152
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Face Swap (mtb)"
|
||||
"Node name for S&R": "UpscaleModelLoader"
|
||||
},
|
||||
"widgets_values": [
|
||||
"0",
|
||||
"false"
|
||||
"4x-UltraSharp.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 71,
|
||||
"type": "Load Face Enhance Model (mtb)",
|
||||
"pos": [
|
||||
1476,
|
||||
240
|
||||
2005,
|
||||
40
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
265.97600515853924,
|
||||
87.31192548828142
|
||||
],
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
@@ -611,82 +647,26 @@
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 72,
|
||||
"type": "UpscaleModelLoader",
|
||||
"pos": [
|
||||
1110,
|
||||
241
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "UPSCALE_MODEL",
|
||||
"type": "UPSCALE_MODEL",
|
||||
"links": [
|
||||
152
|
||||
],
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "UpscaleModelLoader"
|
||||
},
|
||||
"widgets_values": [
|
||||
"4x-UltraSharp.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 73,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
760,
|
||||
-630
|
||||
],
|
||||
"size": [
|
||||
671.1859741210938,
|
||||
483.1548156738281
|
||||
],
|
||||
"flags": {},
|
||||
"order": 15,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 153
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 76,
|
||||
"type": "Load Image From Url (mtb)",
|
||||
"pos": [
|
||||
161,
|
||||
231
|
||||
624,
|
||||
39
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
160
|
||||
166
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
@@ -703,22 +683,22 @@
|
||||
"id": 69,
|
||||
"type": "Load Face Swap Model (mtb)",
|
||||
"pos": [
|
||||
172,
|
||||
503
|
||||
621,
|
||||
252
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "FACESWAP_MODEL",
|
||||
"type": "FACESWAP_MODEL",
|
||||
"links": [
|
||||
147
|
||||
165
|
||||
],
|
||||
"shape": 3
|
||||
}
|
||||
@@ -731,43 +711,92 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"type": "Styles Loader (mtb)",
|
||||
"id": 81,
|
||||
"type": "Load Face Analysis Model (mtb)",
|
||||
"pos": [
|
||||
-1341,
|
||||
276
|
||||
624,
|
||||
144
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
78
|
||||
58
|
||||
],
|
||||
"flags": {
|
||||
"collapsed": false
|
||||
},
|
||||
"order": 5,
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "STRING",
|
||||
"links": [],
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "STRING",
|
||||
"name": "FACE_ANALYSIS_MODEL",
|
||||
"type": "FACE_ANALYSIS_MODEL",
|
||||
"links": [
|
||||
87
|
||||
170
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Styles Loader (mtb)"
|
||||
"Node name for S&R": "Load Face Analysis Model (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
"❌Low Token"
|
||||
"buffalo_l"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 80,
|
||||
"type": "Face Swap (mtb)",
|
||||
"pos": [
|
||||
1255,
|
||||
-32
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
154
|
||||
],
|
||||
"flags": {},
|
||||
"order": 17,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 167
|
||||
},
|
||||
{
|
||||
"name": "reference",
|
||||
"type": "IMAGE",
|
||||
"link": 166
|
||||
},
|
||||
{
|
||||
"name": "faceanalysis_model",
|
||||
"type": "FACE_ANALYSIS_MODEL",
|
||||
"link": 170,
|
||||
"slot_index": 2
|
||||
},
|
||||
{
|
||||
"name": "faceswap_model",
|
||||
"type": "FACESWAP_MODEL",
|
||||
"link": 165,
|
||||
"slot_index": 3
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
168,
|
||||
169
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Face Swap (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
"0",
|
||||
false
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -796,14 +825,6 @@
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
87,
|
||||
20,
|
||||
1,
|
||||
7,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
117,
|
||||
16,
|
||||
@@ -876,22 +897,6 @@
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
147,
|
||||
69,
|
||||
0,
|
||||
67,
|
||||
2,
|
||||
"FACESWAP_MODEL"
|
||||
],
|
||||
[
|
||||
149,
|
||||
67,
|
||||
0,
|
||||
70,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
150,
|
||||
70,
|
||||
@@ -925,28 +930,60 @@
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
156,
|
||||
67,
|
||||
164,
|
||||
79,
|
||||
0,
|
||||
7,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
165,
|
||||
69,
|
||||
0,
|
||||
80,
|
||||
3,
|
||||
"FACESWAP_MODEL"
|
||||
],
|
||||
[
|
||||
166,
|
||||
76,
|
||||
0,
|
||||
80,
|
||||
1,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
167,
|
||||
66,
|
||||
0,
|
||||
80,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
168,
|
||||
80,
|
||||
0,
|
||||
70,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
169,
|
||||
80,
|
||||
0,
|
||||
75,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
160,
|
||||
76,
|
||||
170,
|
||||
81,
|
||||
0,
|
||||
67,
|
||||
1,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
161,
|
||||
66,
|
||||
0,
|
||||
67,
|
||||
0,
|
||||
"IMAGE"
|
||||
80,
|
||||
2,
|
||||
"FACE_ANALYSIS_MODEL"
|
||||
]
|
||||
],
|
||||
"groups": [
|
||||
|
||||
+436
-412
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"last_node_id": 39,
|
||||
"last_node_id": 42,
|
||||
"last_link_id": 69,
|
||||
"nodes": [
|
||||
{
|
||||
@@ -93,7 +93,7 @@
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
36.36605696244669
|
||||
36.366058349609375
|
||||
],
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
@@ -347,7 +347,7 @@
|
||||
114
|
||||
],
|
||||
"size": [
|
||||
301.23302978515596,
|
||||
301.2330322265625,
|
||||
98
|
||||
],
|
||||
"flags": {},
|
||||
@@ -469,7 +469,7 @@
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
"A blonde doll with a pink dress sleeping, draping, wrinkles"
|
||||
"A plastic Barbie doll with a pink dress sleeping, draping, wrinkles, shiny"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -481,7 +481,7 @@
|
||||
],
|
||||
"size": [
|
||||
294,
|
||||
95.12843764123829
|
||||
95.1284408569336
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
@@ -502,7 +502,7 @@
|
||||
"Node name for S&R": "Text box"
|
||||
},
|
||||
"widgets_values": [
|
||||
"embedding:EasyNegative, embedding:EasyNegativeV2, watermark, text, deformed"
|
||||
"embedding:EasyNegative, embedding:EasyNegativeV2, watermark, text, deformed, NSFW, Cleavage, Pubic Hair, Nudity, Naked, censored"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -690,8 +690,8 @@
|
||||
259
|
||||
],
|
||||
"size": [
|
||||
330.11123461913985,
|
||||
378.1239961059566
|
||||
330.1112365722656,
|
||||
378.1239929199219
|
||||
],
|
||||
"flags": {},
|
||||
"order": 19,
|
||||
@@ -716,8 +716,8 @@
|
||||
1256
|
||||
],
|
||||
"size": [
|
||||
356.17758847656205,
|
||||
471.87858076171824
|
||||
356.1775817871094,
|
||||
471.8785705566406
|
||||
],
|
||||
"flags": {},
|
||||
"order": 14,
|
||||
@@ -735,8 +735,7 @@
|
||||
"widgets_values": [
|
||||
12,
|
||||
1,
|
||||
true,
|
||||
"/view?filename=7964e7cc8b.gif&subfolder=&type=output"
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -833,7 +832,7 @@
|
||||
882
|
||||
],
|
||||
"size": [
|
||||
232.28509687500036,
|
||||
232.28509521484375,
|
||||
166
|
||||
],
|
||||
"flags": {},
|
||||
@@ -873,12 +872,12 @@
|
||||
"id": 17,
|
||||
"type": "Animation Builder (mtb)",
|
||||
"pos": [
|
||||
-1309,
|
||||
-1310,
|
||||
883
|
||||
],
|
||||
"size": [
|
||||
211.60000610351562,
|
||||
294
|
||||
318
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
@@ -1175,8 +1174,8 @@
|
||||
{
|
||||
"title": "START THE QUEUE BY CLICKLING HERE 👆",
|
||||
"bounding": [
|
||||
-1611,
|
||||
1196,
|
||||
-1612,
|
||||
1219,
|
||||
521,
|
||||
80
|
||||
],
|
||||
|
||||
@@ -1,932 +0,0 @@
|
||||
{
|
||||
"last_node_id": 24,
|
||||
"last_link_id": 30,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 11,
|
||||
"type": "Get Batch From History (mtb)",
|
||||
"pos": [
|
||||
-828,
|
||||
522
|
||||
],
|
||||
"size": [
|
||||
235.1999969482422,
|
||||
118
|
||||
],
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "passthrough_image",
|
||||
"type": "IMAGE",
|
||||
"link": 10
|
||||
},
|
||||
{
|
||||
"name": "enable",
|
||||
"type": "BOOL",
|
||||
"link": 9,
|
||||
"widget": {
|
||||
"name": "enable",
|
||||
"config": [
|
||||
"BOOL",
|
||||
{
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "i",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
26
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Get Batch From History (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
false,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"color": "#223",
|
||||
"bgcolor": "#335"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"type": "Note",
|
||||
"pos": [
|
||||
-827,
|
||||
406
|
||||
],
|
||||
"size": [
|
||||
229.35427033319013,
|
||||
69.73426380916959
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"text": ""
|
||||
},
|
||||
"widgets_values": [
|
||||
"On first frame we get the init image, on all subsequent ones the feedback from the previous queue item"
|
||||
],
|
||||
"color": "#223",
|
||||
"bgcolor": "#335",
|
||||
"shape": 1
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
-1388,
|
||||
321
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
314
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
10
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"example.png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
-1679,
|
||||
817
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "INT",
|
||||
"type": "INT",
|
||||
"links": [
|
||||
8
|
||||
],
|
||||
"widget": {
|
||||
"name": "int",
|
||||
"config": [
|
||||
"INT",
|
||||
{
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"title": "int",
|
||||
"properties": {},
|
||||
"widgets_values": [
|
||||
0,
|
||||
"increment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"type": "Int To Bool (mtb)",
|
||||
"pos": [
|
||||
-1290,
|
||||
818
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
42.2801628112793
|
||||
],
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "int",
|
||||
"type": "INT",
|
||||
"link": 8,
|
||||
"widget": {
|
||||
"name": "int",
|
||||
"config": [
|
||||
"INT",
|
||||
{
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "BOOL",
|
||||
"type": "BOOL",
|
||||
"links": [
|
||||
9
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Int To Bool (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"type": "Transform Image (mtb)",
|
||||
"pos": [
|
||||
-54,
|
||||
515
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
154
|
||||
],
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 26
|
||||
},
|
||||
{
|
||||
"name": "angle",
|
||||
"type": "FLOAT",
|
||||
"link": 30,
|
||||
"widget": {
|
||||
"name": "angle",
|
||||
"config": [
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
24
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Transform Image (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
0,
|
||||
5,
|
||||
1.02,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"type": "Export To Prores (mtb)",
|
||||
"pos": [
|
||||
394,
|
||||
1803
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 17
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "VIDEO",
|
||||
"type": "VIDEO",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Export To Prores (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
12,
|
||||
"export"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"type": "Save Gif (mtb)",
|
||||
"pos": [
|
||||
392,
|
||||
1321
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
336
|
||||
],
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 18
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Save Gif (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
12,
|
||||
1,
|
||||
true,
|
||||
"/view?filename=8b62123f3c.gif&subfolder=&type=output"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"type": "Styles Loader (mtb)",
|
||||
"pos": [
|
||||
72,
|
||||
213
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
78
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
15
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Styles Loader (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
"❌Low Token"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "CheckpointLoaderSimple",
|
||||
"pos": [
|
||||
64,
|
||||
68
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
98
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
4
|
||||
],
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": [
|
||||
5
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "VAE",
|
||||
"type": "VAE",
|
||||
"links": [
|
||||
6
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CheckpointLoaderSimple"
|
||||
},
|
||||
"widgets_values": [
|
||||
"revAnimated_v122.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"type": "Fit Number (mtb)",
|
||||
"pos": [
|
||||
39,
|
||||
842
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
166
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "FLOAT",
|
||||
"link": 27
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "FLOAT",
|
||||
"type": "FLOAT",
|
||||
"links": [
|
||||
28
|
||||
],
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Fit Number (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
true,
|
||||
0,
|
||||
1,
|
||||
0.9,
|
||||
0.2
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"type": "Fit Number (mtb)",
|
||||
"pos": [
|
||||
-342,
|
||||
621
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
166
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "FLOAT",
|
||||
"link": 29
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "FLOAT",
|
||||
"type": "FLOAT",
|
||||
"links": [
|
||||
30
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Fit Number (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
true,
|
||||
0.7,
|
||||
1,
|
||||
0,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "## i2i [cac944]",
|
||||
"pos": [
|
||||
567,
|
||||
65
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
230
|
||||
],
|
||||
"flags": {},
|
||||
"order": 14,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 4,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 5
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 6
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 24
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "STRING",
|
||||
"link": 15,
|
||||
"widget": {
|
||||
"name": "negative",
|
||||
"config": [
|
||||
"STRING",
|
||||
{
|
||||
"multiline": true,
|
||||
"placeholder": "negative",
|
||||
"default": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"slot_index": 4
|
||||
},
|
||||
{
|
||||
"name": "denoise",
|
||||
"type": "FLOAT",
|
||||
"link": 28,
|
||||
"widget": {
|
||||
"name": "denoise",
|
||||
"config": [
|
||||
"FLOAT",
|
||||
{
|
||||
"default": 0.6,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"step": 0.01
|
||||
}
|
||||
]
|
||||
},
|
||||
"slot_index": 5
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
25
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"title": "## i2i",
|
||||
"properties": {
|
||||
"Node name for S&R": "## i2i [cac944]"
|
||||
},
|
||||
"widgets_values": [
|
||||
"A blond girl in a pink dress, clear sky, 1958",
|
||||
"",
|
||||
0.2599999999999997
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"type": "SaveImage",
|
||||
"pos": [
|
||||
1054,
|
||||
67
|
||||
],
|
||||
"size": [
|
||||
1110.1168110198978,
|
||||
630.0240418701173
|
||||
],
|
||||
"flags": {},
|
||||
"order": 15,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 25
|
||||
}
|
||||
],
|
||||
"properties": {},
|
||||
"widgets_values": [
|
||||
"ComfyUI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"type": "Animation Builder (mtb)",
|
||||
"pos": [
|
||||
-1032,
|
||||
1274
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
306
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "frame",
|
||||
"type": "INT",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "0-1 (scaled)",
|
||||
"type": "FLOAT",
|
||||
"links": [
|
||||
27,
|
||||
29
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "count",
|
||||
"type": "INT",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "loop_ended",
|
||||
"type": "BOOL",
|
||||
"links": [
|
||||
16
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Animation Builder (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
30,
|
||||
1,
|
||||
1,
|
||||
90,
|
||||
1,
|
||||
"raw: 90\nframe: 0",
|
||||
"Done 😎!",
|
||||
"reset",
|
||||
"queue"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"type": "Get Batch From History (mtb)",
|
||||
"pos": [
|
||||
-369,
|
||||
1511
|
||||
],
|
||||
"size": [
|
||||
235.1999969482422,
|
||||
118
|
||||
],
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "passthrough_image",
|
||||
"type": "IMAGE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "enable",
|
||||
"type": "BOOL",
|
||||
"link": 16,
|
||||
"widget": {
|
||||
"name": "enable",
|
||||
"config": [
|
||||
"BOOL",
|
||||
{
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "i",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
17,
|
||||
18
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Get Batch From History (mtb)"
|
||||
},
|
||||
"widgets_values": [
|
||||
false,
|
||||
30,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
4,
|
||||
9,
|
||||
0,
|
||||
8,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
5,
|
||||
9,
|
||||
1,
|
||||
8,
|
||||
1,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
6,
|
||||
9,
|
||||
2,
|
||||
8,
|
||||
2,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
8,
|
||||
13,
|
||||
0,
|
||||
12,
|
||||
0,
|
||||
"INT"
|
||||
],
|
||||
[
|
||||
9,
|
||||
12,
|
||||
0,
|
||||
11,
|
||||
1,
|
||||
"BOOL"
|
||||
],
|
||||
[
|
||||
10,
|
||||
10,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
15,
|
||||
16,
|
||||
1,
|
||||
8,
|
||||
4,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
16,
|
||||
17,
|
||||
3,
|
||||
18,
|
||||
1,
|
||||
"BOOL"
|
||||
],
|
||||
[
|
||||
17,
|
||||
18,
|
||||
0,
|
||||
20,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
18,
|
||||
18,
|
||||
0,
|
||||
19,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
24,
|
||||
14,
|
||||
0,
|
||||
8,
|
||||
3,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
25,
|
||||
8,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
26,
|
||||
11,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
27,
|
||||
17,
|
||||
1,
|
||||
22,
|
||||
0,
|
||||
"FLOAT"
|
||||
],
|
||||
[
|
||||
28,
|
||||
22,
|
||||
0,
|
||||
8,
|
||||
5,
|
||||
"FLOAT"
|
||||
],
|
||||
[
|
||||
29,
|
||||
17,
|
||||
1,
|
||||
23,
|
||||
0,
|
||||
"FLOAT"
|
||||
],
|
||||
[
|
||||
30,
|
||||
23,
|
||||
0,
|
||||
14,
|
||||
1,
|
||||
"FLOAT"
|
||||
]
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"title": "Init Image",
|
||||
"bounding": [
|
||||
-1730,
|
||||
215,
|
||||
716,
|
||||
713
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"title": "Video Output",
|
||||
"bounding": [
|
||||
-426,
|
||||
1176,
|
||||
1223,
|
||||
787
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"title": "Animation",
|
||||
"bounding": [
|
||||
-473,
|
||||
363,
|
||||
900,
|
||||
718
|
||||
],
|
||||
"color": "#3f789e",
|
||||
"locked": false
|
||||
}
|
||||
],
|
||||
"config": {},
|
||||
"extra": {},
|
||||
"version": 0.4
|
||||
}
|
||||
+27
-13
@@ -258,23 +258,16 @@ def import_or_install(requirement, dry=False):
|
||||
|
||||
# Install dependencies from requirements.txt
|
||||
def install_dependencies(dry=False):
|
||||
parsed_requirements = get_requirements(here / "requirements.txt")
|
||||
parsed_requirements = get_requirements(here / "reqs.txt")
|
||||
if not parsed_requirements:
|
||||
return
|
||||
print_formatted(
|
||||
"Installing dependencies from requirements.txt...", "italic", color="yellow"
|
||||
"Installing dependencies from reqs.txt...", "italic", color="yellow"
|
||||
)
|
||||
|
||||
for requirement in parsed_requirements:
|
||||
import_or_install(requirement, dry=dry)
|
||||
|
||||
if mode == "venv":
|
||||
parsed_requirements = get_requirements(here / "requirements-wheels.txt")
|
||||
if not parsed_requirements:
|
||||
return
|
||||
for requirement in parsed_requirements:
|
||||
import_or_install(requirement, dry=dry)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
full = False
|
||||
@@ -328,7 +321,6 @@ if __name__ == "__main__":
|
||||
|
||||
# Install dependencies from requirements.txt
|
||||
# if args.requirements or mode == "venv":
|
||||
install_dependencies(dry=args.dry)
|
||||
|
||||
if (not args.wheels and mode not in ["colab", "embeded"]) and not full:
|
||||
print_formatted(
|
||||
@@ -336,6 +328,8 @@ if __name__ == "__main__":
|
||||
"italic",
|
||||
color="yellow",
|
||||
)
|
||||
|
||||
install_dependencies(dry=args.dry)
|
||||
sys.exit()
|
||||
|
||||
if mode in ["colab", "embeded"]:
|
||||
@@ -349,7 +343,7 @@ if __name__ == "__main__":
|
||||
|
||||
# - Check the env before proceeding.
|
||||
missing_wheels = False
|
||||
parsed_requirements = get_requirements(here / "requirements-wheels.txt")
|
||||
parsed_requirements = get_requirements(here / "reqs.txt")
|
||||
if parsed_requirements:
|
||||
for requirement in parsed_requirements:
|
||||
installed, pip_name, import_name = try_import(requirement)
|
||||
@@ -359,7 +353,7 @@ if __name__ == "__main__":
|
||||
|
||||
if not missing_wheels:
|
||||
print_formatted(
|
||||
f"All required wheels are already installed.", "italic", color="green"
|
||||
f"All requirements are already installed.", "italic", color="green"
|
||||
)
|
||||
sys.exit()
|
||||
|
||||
@@ -408,7 +402,7 @@ if __name__ == "__main__":
|
||||
)
|
||||
|
||||
wheels_directory.mkdir(exist_ok=True)
|
||||
|
||||
# - Install the wheels
|
||||
for asset in matching_assets:
|
||||
asset_name = asset["name"]
|
||||
asset_download_url = asset["browser_download_url"]
|
||||
@@ -418,6 +412,7 @@ if __name__ == "__main__":
|
||||
|
||||
# - Unzip to wheels dir
|
||||
whl_files = []
|
||||
whl_order = None
|
||||
with zipfile.ZipFile(asset_dest, "r") as zip_ref:
|
||||
for item in tqdm(zip_ref.namelist(), desc="Extracting", unit="file"):
|
||||
if item.endswith(".whl"):
|
||||
@@ -428,6 +423,14 @@ if __name__ == "__main__":
|
||||
) as target:
|
||||
whl_files.append(target_path)
|
||||
shutil.copyfileobj(source, target)
|
||||
elif item.endswith("order.txt"):
|
||||
item_basename = os.path.basename(item)
|
||||
target_path = wheels_directory / item_basename
|
||||
with zip_ref.open(item) as source, open(
|
||||
target_path, "wb"
|
||||
) as target:
|
||||
whl_order = target_path
|
||||
shutil.copyfileobj(source, target)
|
||||
|
||||
print_formatted(
|
||||
f"Wheels extracted for {current_platform} to the '{wheels_directory}' directory.",
|
||||
@@ -436,6 +439,14 @@ if __name__ == "__main__":
|
||||
)
|
||||
|
||||
if whl_files:
|
||||
if whl_order:
|
||||
with open(whl_order, "r") as order:
|
||||
wheel_order_lines = [line.strip() for line in order]
|
||||
whl_files = sorted(
|
||||
whl_files,
|
||||
key=lambda x: wheel_order_lines.index(x.split("-")[0]),
|
||||
)
|
||||
|
||||
for whl_file in tqdm(whl_files, desc="Installing", unit="package"):
|
||||
whl_path = wheels_directory / whl_file
|
||||
|
||||
@@ -470,3 +481,6 @@ if __name__ == "__main__":
|
||||
print_formatted("Wheels installation completed.", color="green")
|
||||
else:
|
||||
print_formatted("No .whl files found. Nothing to install.", color="yellow")
|
||||
|
||||
# - Install all remainings
|
||||
install_dependencies(dry=args.dry)
|
||||
|
||||
@@ -28,6 +28,10 @@ class LoadFaceEnhanceModel:
|
||||
@classmethod
|
||||
def get_models(cls):
|
||||
models_path = cls.get_models_root()
|
||||
|
||||
if not models_path.exists():
|
||||
log.warning(f"No models found at {models_path}")
|
||||
return []
|
||||
|
||||
return [
|
||||
x
|
||||
|
||||
+46
-14
@@ -22,6 +22,37 @@ import comfy.model_management as model_management
|
||||
|
||||
log = mklog(__name__)
|
||||
|
||||
class LoadFaceAnalysisModel:
|
||||
"""Loads a face analysis model"""
|
||||
|
||||
models = []
|
||||
@staticmethod
|
||||
def get_models() -> List[str]:
|
||||
models_path = os.path.join(folder_paths.models_dir, "insightface/*")
|
||||
models = glob.glob(models_path)
|
||||
models = [Path(x).name for x in models if x.endswith(".onnx") or x.endswith(".pth")]
|
||||
return models
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"faceswap_model": (
|
||||
["antelopev2", "buffalo_l", "buffalo_m", "buffalo_sc"],
|
||||
{"default": "buffalo_l"},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FACE_ANALYSIS_MODEL",)
|
||||
FUNCTION = "load_model"
|
||||
CATEGORY = "mtb/facetools"
|
||||
|
||||
def load_model(self, faceswap_model: str):
|
||||
face_analyser = insightface.app.FaceAnalysis(
|
||||
name=faceswap_model, root=os.path.join(folder_paths.models_dir, "insightface")
|
||||
)
|
||||
return (face_analyser,)
|
||||
|
||||
class LoadFaceSwapModel:
|
||||
"""Loads a faceswap model"""
|
||||
@@ -81,6 +112,7 @@ class FaceSwap:
|
||||
"image": ("IMAGE",),
|
||||
"reference": ("IMAGE",),
|
||||
"faces_index": ("STRING", {"default": "0"}),
|
||||
"faceanalysis_model": ("FACE_ANALYSIS_MODEL", {"default": "None"}),
|
||||
"faceswap_model": ("FACESWAP_MODEL", {"default": "None"}),
|
||||
"debug": ("BOOL", {"default": False}),
|
||||
},
|
||||
@@ -96,6 +128,7 @@ class FaceSwap:
|
||||
image: torch.Tensor,
|
||||
reference: torch.Tensor,
|
||||
faces_index: str,
|
||||
faceanalysis_model,
|
||||
faceswap_model,
|
||||
debug=False,
|
||||
):
|
||||
@@ -107,7 +140,7 @@ class FaceSwap:
|
||||
int(x) for x in faces_index.strip(",").split(",") if x.isnumeric()
|
||||
}
|
||||
sys.stdout = NullWriter()
|
||||
swapped = swap_face(ref, img, faceswap_model, face_ids)
|
||||
swapped = swap_face(faceanalysis_model,ref, img, faceswap_model, face_ids)
|
||||
sys.stdout = sys.__stdout__
|
||||
return pil2tensor(swapped)
|
||||
|
||||
@@ -121,8 +154,8 @@ class FaceSwap:
|
||||
image = do_swap(image)
|
||||
|
||||
else:
|
||||
image = [do_swap(image[i]) for i in range(batch_count)]
|
||||
image = torch.cat(image, dim=0)
|
||||
image_batch = [do_swap(image[i]) for i in range(batch_count)]
|
||||
image = torch.cat(image_batch, dim=0)
|
||||
|
||||
return (image,)
|
||||
|
||||
@@ -131,17 +164,15 @@ class FaceSwap:
|
||||
|
||||
|
||||
# region face swap utils
|
||||
def get_face_single(img_data: np.ndarray, face_index=0, det_size=(640, 640)):
|
||||
face_analyser = insightface.app.FaceAnalysis(
|
||||
name="buffalo_l", root=os.path.join(folder_paths.models_dir, "insightface")
|
||||
)
|
||||
def get_face_single(face_analyser,img_data: np.ndarray, face_index=0, det_size=(640, 640)):
|
||||
|
||||
face_analyser.prepare(ctx_id=0, det_size=det_size)
|
||||
face = face_analyser.get(img_data)
|
||||
|
||||
if len(face) == 0 and det_size[0] > 320 and det_size[1] > 320:
|
||||
log.debug("No face ed, trying again with smaller image")
|
||||
det_size_half = (det_size[0] // 2, det_size[1] // 2)
|
||||
return get_face_single(img_data, face_index=face_index, det_size=det_size_half)
|
||||
return get_face_single(face_analyser,img_data, face_index=face_index, det_size=det_size_half)
|
||||
|
||||
try:
|
||||
return sorted(face, key=lambda x: x.bbox[0])[face_index]
|
||||
@@ -150,6 +181,7 @@ def get_face_single(img_data: np.ndarray, face_index=0, det_size=(640, 640)):
|
||||
|
||||
|
||||
def swap_face(
|
||||
face_analyser,
|
||||
source_img: Union[Image.Image, List[Image.Image]],
|
||||
target_img: Union[Image.Image, List[Image.Image]],
|
||||
face_swapper_model,
|
||||
@@ -161,14 +193,14 @@ def swap_face(
|
||||
result_image = target_img
|
||||
|
||||
if face_swapper_model is not None:
|
||||
source_img = cv2.cvtColor(np.array(source_img), cv2.COLOR_RGB2BGR)
|
||||
target_img = cv2.cvtColor(np.array(target_img), cv2.COLOR_RGB2BGR)
|
||||
source_face = get_face_single(source_img, face_index=0)
|
||||
cv_source_img = cv2.cvtColor(np.array(source_img), cv2.COLOR_RGB2BGR)
|
||||
cv_target_img = cv2.cvtColor(np.array(target_img), cv2.COLOR_RGB2BGR)
|
||||
source_face = get_face_single(face_analyser,cv_source_img, face_index=0)
|
||||
if source_face is not None:
|
||||
result = target_img
|
||||
result = cv_target_img
|
||||
|
||||
for face_num in faces_index:
|
||||
target_face = get_face_single(target_img, face_index=face_num)
|
||||
target_face = get_face_single(face_analyser,cv_target_img, face_index=face_num)
|
||||
if target_face is not None:
|
||||
sys.stdout = NullWriter()
|
||||
result = face_swapper_model.get(result, target_face, source_face)
|
||||
@@ -187,4 +219,4 @@ def swap_face(
|
||||
# endregion face swap utils
|
||||
|
||||
|
||||
__nodes__ = [FaceSwap, LoadFaceSwapModel]
|
||||
__nodes__ = [FaceSwap, LoadFaceSwapModel, LoadFaceAnalysisModel]
|
||||
|
||||
+1
-1
@@ -13,6 +13,6 @@
|
||||
"reportMissingImports": true,
|
||||
"reportMissingTypeStubs": false,
|
||||
"pythonVersion": "3.10",
|
||||
"pythonPlatform": "Windows",
|
||||
"pythonPlatform": "All",
|
||||
"reportOptionalMemberAccess": "none"
|
||||
}
|
||||
@@ -8,7 +8,10 @@ tensorflow<2.11.0; platform_system == "Windows"
|
||||
tb-nightly==2.12.0a20230126; platform_system == "Windows"
|
||||
tensorflow; platform_system != "Windows"
|
||||
# the old tf version on windows comes with a breaking protobuf version
|
||||
protobuf==3.19.6
|
||||
protobuf==3.20.2; platform_system == "Windows"
|
||||
gdown @ git+https://github.com/melMass/gdown@main
|
||||
mmdet==3.0.0
|
||||
facexlib==0.3.0
|
||||
insightface==0.7.3
|
||||
mmcv==2.0.0
|
||||
basicsr==1.4.2
|
||||
@@ -1,3 +0,0 @@
|
||||
insightface==0.7.3
|
||||
mmcv==2.0.0
|
||||
basicsr==1.4.2
|
||||
@@ -0,0 +1,32 @@
|
||||
## Core
|
||||
These 3 scripts cannot be used independently and must all be present to work, they are mostly enhancing the frontend of python nodes
|
||||
- `comfy_shared`: library of methods used in `mtb_widgets` and `debug`
|
||||
|
||||
**mtb_widgets** define ui callbacks, and various widgets like the `COLOR` type:
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/5dbcb714-e1e2-4be7-b0e2-68a6c38c83de" width=400/>
|
||||
|
||||
or the `BOOL` type:
|
||||
<img src="https://github.com/melMass/comfy_mtb/assets/7041726/7601366d-601c-4f4d-b735-1a4b076770b0" width=400/>
|
||||
|
||||
There is also `Debug` which is a node that should be able to display any data input, it handle a few cases and fallback to the string representation of the
|
||||
data otherwise:
|
||||

|
||||
|
||||
|
||||
|
||||
## Standalone
|
||||
These scripts can be taken and placed independently of `comfy_mtb` or any other files, mimicking what pythongosss did for their
|
||||
|
||||
- **imageFeed**: a fork of @pythongosssss ' s [image feed](https://github.com/pythongosssss/ComfyUI-Custom-Scripts/tree/main/js), it adds support for: a lightbox to see images bigger, a way to load the current session history (in case of a web page reload), and different icons, most of the work come from the original script.
|
||||
|
||||
|
||||
> **NOTE**
|
||||
>
|
||||
> The original imagefeed got updated since and offer more options, ideally I would clean my lightbox thing and PR it to pythongoss later but in the meantime the script will detect if you already use the original one and not load this fork
|
||||
|
||||
|
||||
- 
|
||||
|
||||
|
||||
- **notify**: a basic toast notification system that I use in some places accross mtb, it can be used by simply calling `window.MTB.notify("Hello world!")`
|
||||

|
||||
+26
-6
@@ -34,7 +34,7 @@ const styles = {
|
||||
zIndex: 9999999,
|
||||
fontSize: '30px',
|
||||
cursor: 'pointer',
|
||||
pointerEvents: 'bounding-box',
|
||||
pointerEvents: 'auto',
|
||||
...extra,
|
||||
}),
|
||||
img_list: {
|
||||
@@ -53,10 +53,21 @@ let currentImageIndex = 0
|
||||
const imageUrls = []
|
||||
|
||||
let image_menu = null
|
||||
let activated = true
|
||||
|
||||
app.registerExtension({
|
||||
name: 'mtb.ImageFeed',
|
||||
setup: async () => {
|
||||
init: async () => {
|
||||
const pythongossFeed = app.extensions.find(
|
||||
(e) => e.name == 'pysssss.ImageFeed'
|
||||
)
|
||||
if (pythongossFeed) {
|
||||
console.warn(
|
||||
"[mtb] - Aborting the loading of mtb's imageFeed in favor of pysssss.ImageFeed"
|
||||
)
|
||||
activated = false // just in case other methods are added later on
|
||||
return
|
||||
}
|
||||
// - HTML & CSS
|
||||
//- lightbox
|
||||
const lightboxContainer = document.createElement('div')
|
||||
@@ -209,11 +220,14 @@ app.registerExtension({
|
||||
Object.assign(but.style, {
|
||||
height: '120px',
|
||||
width: '120px',
|
||||
border: 'none',
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
})
|
||||
Object.assign(img.style, {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'scale-down',
|
||||
objectFit: 'cover',
|
||||
})
|
||||
|
||||
img.src = `/view?filename=${encodeURIComponent(src.filename)}&type=${
|
||||
@@ -224,6 +238,10 @@ app.registerExtension({
|
||||
|
||||
console.debug(img.src)
|
||||
|
||||
img.onload = () => {
|
||||
but.style.width = `${120 * (img.naturalWidth / img.naturalHeight)}px`
|
||||
}
|
||||
|
||||
but.onclick = () => {
|
||||
lightboxContainer.style.display = 'flex'
|
||||
// add the same image to the lightbox
|
||||
@@ -270,9 +288,11 @@ app.registerExtension({
|
||||
if (history.outputs) {
|
||||
for (const key of Object.keys(history.outputs)) {
|
||||
console.debug(key)
|
||||
for (const im of history.outputs[key].images) {
|
||||
console.debug(im)
|
||||
createImageBtn(im)
|
||||
if (history.outputs[key].images) {
|
||||
for (const im of history.outputs[key].images) {
|
||||
console.debug(im)
|
||||
createImageBtn(im)
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (const src of outputs.outputs.images) {
|
||||
|
||||
+47
-10
@@ -688,7 +688,34 @@ const mtb_widgets = {
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Save Gif (mtb)': {
|
||||
//TODO: remove this non sense
|
||||
case 'Get Batch From History (mtb)': {
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated
|
||||
? onNodeCreated.apply(this, arguments)
|
||||
: undefined
|
||||
const internal_count = this.widgets.find(
|
||||
(w) => w.name === 'internal_count'
|
||||
)
|
||||
shared.hideWidgetForGood(this, internal_count)
|
||||
internal_count.afterQueued = function () {
|
||||
this.value++
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
const onExecuted = nodeType.prototype.onExecuted
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
const r = onExecuted ? onExecuted.apply(this, message) : undefined
|
||||
return r
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
case 'Save Gif (mtb)':
|
||||
case 'Save Animated Image (mtb)': {
|
||||
const onExecuted = nodeType.prototype.onExecuted
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
const prefix = 'anything_'
|
||||
@@ -704,15 +731,25 @@ const mtb_widgets = {
|
||||
}
|
||||
|
||||
let imgURLs = []
|
||||
if (message && message.gif) {
|
||||
imgURLs = imgURLs.concat(
|
||||
message.gif.map((params) => {
|
||||
return api.apiURL(
|
||||
'/view?' + new URLSearchParams(params).toString()
|
||||
)
|
||||
})
|
||||
)
|
||||
|
||||
if (message) {
|
||||
if (message.gif) {
|
||||
imgURLs = imgURLs.concat(
|
||||
message.gif.map((params) => {
|
||||
return api.apiURL(
|
||||
'/view?' + new URLSearchParams(params).toString()
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
if (message.apng) {
|
||||
imgURLs = imgURLs.concat(
|
||||
message.apng.map((params) => {
|
||||
return api.apiURL(
|
||||
'/view?' + new URLSearchParams(params).toString()
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
let i = 0
|
||||
for (const img of imgURLs) {
|
||||
const w = this.addCustomWidget(
|
||||
|
||||
Reference in New Issue
Block a user