stable-diffusion 生成同一人物不同动作的尝试(基础动作

原文:stable-diffusion 生成同一人物不同动作的尝试(基础动作融合) - 知乎

目录

开发游戏中,美术资源是一大块成本。而游戏中包含很多角色,每个角色需要表现出不同的动作,因此一直在研究的一个课题“是如何用AI去生成同一个角色的多种动作”,此前也尝试过不少方法,研究之路继续进行,以下是一些以前的研究连接。

罗培羽:AI做游戏,扩散模型生成角色行走图76 赞同 · 18 评论文章正在上传…重新上传取消

罗培羽:stable-diffusion 生成同一人物不同动作的尝试(多姿势图)98 赞同 · 9 评论文章正在上传…重新上传取消

本次是尝试修改stable-diffusion的生成过程,使得模型可以记录一部分角色信息,从而为后续生成同个角色的其他动作的图像提供可能性。

效果展示

如下图所示,左图是用sd模型+controlnet生成的一张角色图(图中的“特征图”),而如果不采用任何新方法,使用同样参数+另外的controlnet姿态,会生成下图(图中”动作A未融合“)的样式,角色样貌与“特征图”会有一些差异,例如人物衣服的颜色有较大的不同。使用新方法生成的图片如左上图所示(图中”动作A特征融合“),可见角色形态与”特征图“更为接近。

下图是另一个例子,使用新方法后,人物的衣服和裙子样式、头上的发饰都更接近原始的”特征图“,更像是同一个角色的不同动作。

原理说明

要做到”同一角色“,就需要把角色的信息传递给生成模型,目前会有比较多的想法,待一步步尝试。而本文所使用的方法,因实现较为简单,因此先做个实验。如下图所示,展示了diffusion+controlnet的生成过程,在每一个去噪步骤中,都会输入噪声、prompt和openpose姿势图。

有一个简单办法可以保留部分”特征图“的信息,如下图所示,在前几个生成步骤中,使用同特征图的参数,而在后几个步骤中,再改变姿态图。从中可以预想,前几步的生成过程中”特征图“与”新图像“遵循着同样的步骤和参数,相当于”特征图“的一部分生成过程信息传递到”新图像“中。

代码实现

为了实现这个过程,简单修改了stable-diffusion-webui中controlnet插件的代码(插件代码地址:https://github.com/Mikubill/sd-webui-controlnet),在下方新增identity_reserve_step、is_save_identity、is_load_identity三个选项。在生成特征图时,勾选is_save_identity,那么程序会记录生成过程中一些信息;在生成新图像时,勾选is_load_identity,以读取之前保存的信息;identity_reserve_step是一个控制项,指定在前多少个去噪步骤中使用保存的信息。

出于实验性质的考虑,我们此处并不考虑代码质量,仅仅关注实现功能。若后续得到很好的实验结果,再做代码改进。本次主要改动controlnet插件script/hook.py中的代码,因为它包含对unet改动的相关内容。

先是定义两个全局变量,一个用于计数,一个用于保存信息。注意,此处过多考虑代码质量,仅做实验展示。

#identity
identity_count=0
identity_dict = {}

然后修改cfg_based_adder方法,原始unet和controlnet结果相加部分会在这里,两处”##### identity start #####“和”##### identity end #####“中间的内容为插入的代码,具体作用是保存生成信息以及恢复。代码中写死了17、20等数值,它们代表每一次去噪中unet与controlnet结果相加的次数,以及20次去噪步骤。

    def hook(self, model):
        ……
        def cfg_based_adder(base, x, require_autocast, is_adapter=False):

            ##### identity start #####
            global identity_count
            global identity_dict

            param = self.control_params[0]
            
            per_step_length  = 17 #没有反向词17,有反向词34(不完全准确)
            identity_index = identity_count % (20*per_step_length) #20个step

            
            if identity_index == 0:
                print("param.identity_reserve_step",param.identity_reserve_step)
                print("param.is_save_identity",param.is_save_identity)
                print("param.is_load_identity",param.is_load_identity)

            identity_count = identity_count+1
            ##### identity end #####

            (……原始内容……)

            ##### identity start #####
            if  param.is_save_identity == True:
                print("save identity_index " + str(identity_index),identity_count)
                identity_dict[identity_index] = base + x


            if  param.is_load_identity == True and identity_index < per_step_length*param.identity_reserve_step:
                print("read identity_index " + str(identity_index),identity_count)
                return identity_dict[identity_index]
            ##### identity end #####

            return base + x

为了在界面上增加三个参数,修改controlnet.py,增加三个UI控件。

class Script(scripts.Script):
    ……
    def uigroup(self, tabname, is_img2img):
        ……
        with gr.Row():
            identity_reserve_step = gr.Slider(label="identity_reserve_step", value=default_unit.identity_reserve_step, minimum=0.0, maximum=20, interactive=True)
            is_save_identity = gr.Checkbox(label='is_save_identity', value=default_unit.is_save_identity)
            is_load_identity = gr.Checkbox(label='is_load_identity', value=default_unit.is_load_identity)

而相关参数传递涉及较多处代码,这里仿照其他参数的写法,修改了相应的文件,修改内容如下。

更多效果

下图展示更多的生成效果,图中展示两个动作,可见用新方法得到的图像与第一张图更加接近,长袖、长裙、卷发这些元素得到体现。

下图是另一个实例,可见的裙子样式和颜色与原图更加接近。

不足之处

该方法也有一些不足之处,如下所示,当动作变化较大时,一个正面一个侧面,虽说也更像同一个角色,但拟合效果就打了折扣。

后续也将继续实验,用另外的方法将特征图的信息传递到生成图像。

PS:如果你想从事游戏开发,就不得不提到笔者编写的《Unity3D网络游戏实战》这本书,它是一本非常实用的书籍,看完就可以自己做一款网络游戏出来,注意了注意了,是当今游戏公司都在做的网络游戏哦,而不是较为简单的单机游戏。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值