我们设计了一种新的架构,可以在条件文本到图像生成中支持 10 多种控件类型,并且可以生成在视觉上可与中途相媲美的高分辨率图像。该网络基于原始的 ControlNet 架构,我们提出了两个新模块: 1 扩展原始 ControlNet 以使用相同的网络参数支持不同的图像条件。 2 支持多种条件输入而不增加计算卸载,这对于想要详细编辑图像的设计者来说尤其重要,不同的条件使用相同的条件编码器,而不需要添加额外的计算或参数。我们对SDXL进行了充分的实验,无论是控制能力还是美观评分都取得了优异的表现。我们将方法和模型发布到开源社区,让每个人都能享受到。
如果您觉得有用,请给我一个star,非常感谢!!
SDXL ProMax版本已经发布啦!!!,尽情享受吧!!!
很抱歉,由于项目的收支难以平衡,GPU资源被分配给其他更可能盈利的项目,SD3训练停止,直到找到足够的GPU支持,我会尽力找到 GPU 继续训练。如果这给您带来不便,我深表歉意。我要感谢所有喜欢这个项目的人,你们的支持是我前进的动力
注意:我们将带有 promax 后缀的 promax 模型放在同一个 Huggingface 模型仓库中,稍后将添加详细说明。
以下示例显示从 1M 分辨率 --> 9M 分辨率
使用像novelai一样的桶训练,可以生成任何长宽比的高分辨率图像
使用大量高质量数据(超过1000万张图像),数据集涵盖多种情况
使用像DALLE.3一样的重新字幕提示,使用CogVLM生成详细描述,良好的提示跟随能力
在训练期间使用许多有用的技巧。包括但不限于日期增强、多重损失、多分辨率
使用与原始ControlNet几乎相同的参数。网络参数或计算量没有明显增加。
支持10+控制条件,与独立训练相比,任何单一条件下性能均无明显下降
支持多条件生成,在训练过程中学习条件融合。无需设置超参数或设计提示。
与其他开源 SDXL 模型兼容,例如 BluePencilXL、CounterfeitXL。与其他 Lora 型号兼容。
https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0
https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0
https://huggingface.co/xinsir/controlnet-tile-sdxl-1.0
https://huggingface.co/xinsir/controlnet-canny-sdxl-1.0
[07/06/2024] 发布ControlNet++
和预训练模型。
[07/06/2024] 发布推理代码(单条件和多条件)。
[07/13/2024] 发布具有高级编辑功能的ProMax ControlNet++
。
用于渐变的 ControlNet++
Comfyui 的 ControlNet++
发布培训规范和培训指南。
发布 arxiv 论文。
最重要的controlnet模型之一,我们在训练这个模型时使用了很多技巧,与https://huggingface.co/xinsir/controlnet-openpose-sdxl-1.0一样好,在姿态控制方面表现SOTA。为了让openpose模型达到最佳性能,需要替换controlnet_aux包中的draw_pose函数(comfyui有自己的controlnet_aux包),具体参考Inference Scripts 。
最重要的controlnet模型之一,canny是与线稿、动漫线稿、mlsd混合训练。处理任何细线的稳健性能,模型是降低畸形率的关键,建议使用细线重画手/脚。
作为最重要的控制网模型之一,涂鸦模型可以支持任何线宽和任何线型。和https://huggingface.co/xinsir/controlnet-scribble-sdxl-1.0一样,让每个人都成为灵魂画家。
注意:使用姿势骨架控制人体姿势,使用细线绘制手/脚细节以避免变形
注意:深度图包含细节信息,建议背景使用深度,前景使用姿势骨架
注意:Scribble是一个强线条模型,如果你想画一些轮廓不严格的东西,可以使用它。 Openpose + Scribble 让您可以更自由地生成初始图像,然后您可以使用细线编辑细节。
我们收集了大量的高质量图像。图片经过严格的过滤和标注,图片题材广泛,包括摄影、动漫、自然、旅途等。
我们在 ControlNet++ 中提出了两个新模块,分别称为条件转换器和控制编码器。我们稍微修改了一个旧模块以增强其表示能力。此外,我们提出了一种统一的训练策略,以实现单阶段和多阶段控制。
对于每个条件,我们为其分配一个控制类型id,例如openpose--(1, 0, 0, 0, 0, 0),深度--(0, 1, 0, 0, 0, 0),多重条件类似于 (openpose, depth) --(1, 1, 0, 0, 0, 0)。在控制编码器中,控制类型 id 将转换为控制类型嵌入(使用正弦位置嵌入),然后我们使用单个线性层来投影控制类型嵌入,使其与时间嵌入具有相同的暗度。将控制类型特征添加到时间嵌入中以指示不同的控制类型,这个简单的设置可以帮助ControlNet区分不同的控制类型,因为时间嵌入往往对整个网络产生全局影响。无论是单条件还是多条件,都有一个唯一的控件类型id与之对应。
我们扩展 ControlNet 以使用同一网络同时支持多个控制输入。条件转换器用于组合不同的图像条件特征。我们的方法有两个主要创新,首先,不同的条件共享相同的条件编码器,这使得网络更加简单和轻量。这与 T2I 或 UniControlNet 等其他主流方法不同。其次,我们添加一个 Transformer 层来交换原始图像和条件图像的信息,而不是直接使用 Transformer 的输出,而是用它来预测原始条件特征的条件偏差。这有点像ResNet,我们通过实验发现这个设置可以明显提高网络的性能。
ControlNet 的原始条件编码器是卷积层和 Silu 激活的堆栈。我们不改变编码器架构,只是增加转换通道以获得“胖”编码器。这可以明显提高网络的性能。原因是我们对所有图像条件共享相同的编码器,因此要求编码器具有更高的表示能力。原始设置适用于单一条件,但不适用于 10 个以上条件。请注意,使用原始设置也可以,只是牺牲了一些图像生成质量。
使用单一条件进行训练可能会受到数据多样性的限制。例如,openpose 要求您使用人物图像进行训练,mlsd 要求您使用线条图像进行训练,因此在生成看不见的物体时可能会影响性能。此外,不同条件的训练难度不同,让所有条件同时收敛并达到每个单一条件的最佳性能是很棘手的。最后,我们会倾向于同时使用两个或多个条件,多条件训练将使不同条件的融合更加平滑,增加网络的鲁棒性(因为单个条件学习的知识有限)。我们提出了一个统一的训练阶段来同时实现单条件优化收敛和多条件融合。
ControlNet++ 需要将控制类型 ID 传递给网络。我们将10+个控件合并为6种控件类型,每种类型的含义如下:
0——开放姿势
1——深度
2 -- 粗线(scribble/hed/softedge/ted-512)
3 -- 细线(canny/mlsd/ Lineart/animelinert/ted-1280)
4——正常
5——段
我们推荐Python版本>=3.8,您可以使用以下命令设置虚拟环境:
conda create -n controlplus python=3.8 conda 激活 controlplus pip install -r 要求.txt
您可以在 https://huggingface.co/xinsir/controlnet-union-sdxl-1.0 中下载模型权重。任何新型号发布都会发布在huggingface上,您可以关注https://huggingface.co/xinsir获取最新型号信息。
我们为每个控制条件提供了推理脚本。请参阅它以了解更多详细信息。
存在一些预处理差异,为了获得最佳的openpose-control性能,请执行以下操作:找到controlnet_aux包中的util.py,将draw_bodypose函数替换为以下代码
def draw_bodypose(canvas: np.ndarray, keypoints: List[Keypoint]) -> np.ndarray: """ 在给定画布上绘制代表身体姿势的关键点和肢体。参数:canvas (np.ndarray): 3D numpy 数组表示要在其上绘制身体关键点的画布(图像) (List[Keypoint]):表示要绘制的身体关键点的关键点对象列表。 np.ndarray:一个 3D numpy 数组,表示具有绘制的身体姿势的修改后的画布。 注意:该函数期望关键点的 x 和 y 坐标在 0 和 1 之间标准化。 """ H、W、C = 画布。形状 如果 max(W, H) < 500:比率 = 1.0 elif max(W, H) >= 500 且 max(W, H) < 1000:比率 = 2.0 elif max(W, H) >= 1000 且 max(W , H) < 2000: 比率 = 3.0 elif max(W, H) >= 2000 且 max(W, H) < 3000:比率 = 4.0 elif max(W, H) >= 3000 且 max(W, H) < 4000:比率 = 5.0 elif max(W, H) >= 4000 且 max(W, H) < 5000:比率 = 6.0 否则:比率 = 7.0 棍宽 = 4 肢体序列 = [ [2, 3], [2, 6], [3, 4], [4, 5], [6, 7], [7, 8], [2, 9], [9, 10], [10, 11], [2, 12], [12, 13], [13, 14], [2, 1], [1, 15], [15, 17], [1, 16], [16, 18], ] 颜色 = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0 ], [0, 255, 0], [0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85 , 0, 255], [170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85]] for (k1_index, k2_index), zip(limbSeq, Colors)中的颜色:keypoint1 =关键点[k1_index - 1] keypoint2 = 关键点[k2_index - 1] 如果关键点1为 None 或 keypoint2 为 None: continue Y = np.array([keypoint1.x, keypoint2.x]) * float(W) X = np.array([keypoint1.y, keypoint2.y]) * float(H) mX = np.mean(X) mY = np.mean(Y) 长度 = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) * * 0.5 角度 = math. Degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) 多边形 = cv2.ellipse2Poly((int(mY), int(mX)), (int(长度 / 2), int(棒宽 * 比例)), int(角度), 0, 360, 1) cv2.fillConvexPoly(canvas,多边形,[int(float(c) * 0.6) for c in color]) for keypoint, color in zip(keypoints, Colors): if keypoint is None: continue x, y = keypoint.x, keypoint.y x = int( x * W) y = int(y * H) cv2.circle(canvas, (int(x), int(y)), int(4 * 比例), 颜色, 厚度=-1) return 帆布
对于单条件推理,您应该给出提示和控制图像,更改python文件中的相应行。
python controlnet_union_test_openpose.py
对于多条件推理,应确保输入的 image_list 与 control_type 兼容,例如,如果要使用 openpose 和深度控制, image_list --> [controlnet_img_pose, controlnet_img_depth, 0, 0, 0, 0], control_type -- > [1, 1, 0, 0, 0, 0]。有关更多详细信息,请参阅 controlnet_union_test_multi_control.py。
理论上,你不需要为不同的条件设置条件尺度,网络被设计和训练来自然地融合不同的条件。每个条件输入的默认设置为1.0,与多条件训练相同。但是,如果您想增加某些特定输入条件的影响,您可以在条件转换器模块中调整条件比例。在该模块中,输入条件将与偏差预测一起添加到源图像特征中。乘以一定的比例会产生很大的影响(但可能会导致一些未知的结果)。
python controlnet_union_test_multi_control.py