AI大模型教程
一起来学习

《PanFusion:Taming Stable Diffusion for Text to 360 Panorama Image Generation》学习——双分支全景图像扩散生成

一、论文概述

        生成模型(如Stable Diffusion)已能从文本提示生成逼真图像,但生成360度全景图像仍面临挑战,主要因为缺乏配对的文本-全景数据和全景图像与透视图像之间的域差异。本文提出了PanFusion,一个双分支扩散模型,利用Stable Diffusion模型的自然图像生成知识,并将其与全景分支注册,以生成360度图像。通过独特的跨注意力机制(EPPA),最小化在协作去噪过程中的失真。实验验证了PanFusion在生成质量和一致性上超越现有方法,并能通过全景分支集成额外的约束(如房间布局)以定制全景输出。

二、方法框架

        1.双分支扩散模型

        PanFusion包含两个分支,一个全景分支(Panorama Branch)和一个透视分支(Perspective Branch),两者都基于Stable Diffusion(SD)的UNet结构。全景分支:负责创建一个连贯的全景“画布”,并注册透视信息以得到无需拼接的全景输出。透视分支:利用SD在透视图像生成方面的能力,提供指导以减轻透视投影下的失真。

        2.EPPA机制

        Equirectangular-Perspective Projection Attention (EPPA) 机制:在两个分支之间传递信息,增强全景和透视视图之间的协同作用。布局生成条件:PanFusion还可以根据给定的房间布局生成全景图像,这对于全景新视角合成和室内3D场景生成非常有用。

        3.输入与输出

        输入:文本提示:用户输入的描述性文本,用于指导全景图像的生成。输出:360度全景图像:根据输入的文本提示生成的全景图像,具有360度水平视场和180度垂直视场。

三、具体步骤

1.文本编码

        输入:用户输入的文本提示,例如:“A living room with a ceiling fan.”

        编码过程:文本提示首先被编码为模型可以理解的形式。这通常涉及到使用一个预训练的语言模型(如BERT或其变体)来将文本转换为高维向量表示,这个向量捕捉了文本的语义信息。在PanFusion中,这一步骤可能涉及到使用BLIP 2模型(一种视觉-语言预训练模型)来生成每个图像的短描述,作为文本提示的编码。

2. 双分支初始化

        全景分支(Panorama Branch):初始化全景潜在映射TzT 作为高斯噪声。

        透视分支(Perspective Branch):将全景潜在映射TzT 投影到多个透视视图中,初始化透视潜在映射TziT​。这里使用最近邻插值进行投影,以减少插值过程中的失真。

3. 迭代去噪

        去噪过程:PanFusion模型使用一个迭代去噪过程来逐步从噪声中恢复出清晰的图像。这个过程涉及到在潜在空间中应用一个UNet模型,该模型被训练来预测在每个时间步 t 的噪声 ϵ 和条件ξ(y) 下的潜在映射 zt​。

        训练目标:训练目标是最小化真实噪声ϵ 和模型预测噪声ϵϕ(zt​,t,ξ(y)) 之间的差异。

4. Equirectangular-Perspective Projection Attention (EPPA) 模块

        EPPA模块:EPPA模块在全景分支和透视分支之间传递信息。它包含两个关键组件:球面位置编码(SPE)和EPP注意力掩码。

        球面位置编码(SPE):为全景特征图计算SPE,然后将其投影到每个透视特征图上,使得不同格式中的对应像素共享相同的SPE向量。

        EPP注意力掩码:通过增强亲和力矩阵 A 来鼓励注意力机制关注对应像素周围的信息。

5. 布局条件生成

        布局条件:如果提供了房间布局条件,将其渲染为距离图,并使用ControlNet来控制全景分支的生成,从而生成遵循精确空间条件的图像。

6. 解码和输出

        解码:最终的全景潜在映射通过预训练的Stable Diffusion解码器D解码成图像空间,产生最终的全景图像。

7. 训练和优化

        损失函数:在训练过程中,PanFusion结合全景分支和透视分支的损失函数来优化模型参数。这包括对全景分支和透视分支的预测噪声进行监督,以确保生成的全景图像在质量和一致性上优于现有方法。

四、个人理解

1.全局全景分支        

        全局全景分支(Panorama Branch)负责生成全局的全景布局,提供一个连贯的全景“画布”。它工作在全景图像的分辨率下,考虑到全景图像的宽高比(2:1)和球面投影(ERP)几何特性,能够捕捉全局结构和空间一致性,减少全景图像中的重复元素和不一致性问题。

import torch
import torch.nn as nn
import torch.nn.functional as F

class PanoramaBranch(nn.Module):
    def __init__(self):
        super(PanoramaBranch, self).__init__()
        # 假设使用一个简单的UNet结构作为全景分支的示例
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(64, 64, kernel_size=2, stride=2),
            nn.ReLU(),
            nn.Conv2d(64, 3, kernel_size=3, padding=1),
            nn.Tanh()
        )

    def forward(self, x):
        # 编码器
        encoded = self.encoder(x)
        # 解码器
        decoded = self.decoder(encoded)
        return decoded

# 假设输入的全景图像分辨率为1024x512
input_image = torch.randn(1, 3, 512, 1024)  # BCHW
pano_branch = PanoramaBranch()
pano_output = pano_branch(input_image)

2.局部透视分支

        局部透视分支(Perspective Branch)利用Stable Diffusion模型在透视图像生成方面的能力,专注于生成细节丰富的多视角透视图像。它在较低分辨率下工作,通过采样多个相机视角来覆盖整个全景图像,每个视角都对应一个局部的透视图。能够利用SD模型在细节生成方面的优势,同时提供对局部视角的指导,以减轻透视投影下的失真。

class PerspectiveBranch(nn.Module):
    def __init__(self):
        super(PerspectiveBranch, self).__init__()
        # 假设使用一个简化的Stable Diffusion模型作为透视分支的示例
        self.model = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU()
        )

    def forward(self, x):
        # 透视图像生成
        perspective_output = self.model(x)
        return perspective_output

# 假设输入的透视图像分辨率为256x256
input_perspective = torch.randn(1, 3, 256, 256)  # BCHW
pers_branch = PerspectiveBranch()
pers_output = pers_branch(input_perspective)

3.EPPA模块

        EPPA模块通过球面位置编码(SPE)和EPP注意力掩码在全景和透视特征图之间建立联系,从而在两个分支之间传递指导信息。这种信息传递是双向的,全景分支可以向透视分支提供全局上下文信息,而透视分支可以向全景分支提供细节信息,共同优化生成过程。

class EPPAModule(nn.Module):
    def __init__(self, channel_dim):
        super(EPPAModule, self).__init__()
        self.query_linear = nn.Linear(channel_dim, channel_dim)
        self.key_linear = nn.Linear(channel_dim, channel_dim)
        self.value_linear = nn.Linear(channel_dim, channel_dim)

    def forward(self, pano_feat, pers_feat):
        # 计算查询(Q)、键(K)和值(V)
        Q = self.query_linear(pano_feat).unsqueeze(1)
        K = self.key_linear(pers_feat).unsqueeze(0)
        V = self.value_linear(pers_feat)
        
        # 计算注意力分数
        scores = torch.matmul(Q, K.transpose(-1, -2))
        scores = F.softmax(scores, dim=-1)
        
        # 计算输出
        output = torch.matmul(scores, V).squeeze(1)
        return output

# 假设channel_dim为64
channel_dim = 64
eppa_module = EPPAModule(channel_dim)

# 假设pano_feat和pers_feat是输入的特征图
pano_feat = torch.randn(1, channel_dim, 16, 32)  # 全景特征图
pers_feat = torch.randn(1, channel_dim, 8, 16)   # 透视特征图
eppa_output = eppa_module(pano_feat, pers_feat)

五、代码分析

        EPPA(Equirectangular-Perspective Projection Attention)机制是PanFusion模型中用于在全景分支和透视分支之间传递信息的关键组件。它通过球面位置编码(Spherical Positional Encoding, SPE)和EPP注意力掩码来实现。以下是EPPA机制的简化示例代码,以及对每个步骤的详细解释:

1. 球面位置编码(SPE)

        球面位置编码将全景特征图中的极坐标位置映射到高维空间,以便在全景分支和透视分支之间传递位置信息。

import torch
import torch.nn.functional as F

def spherical_positional_encoding(pos_enc_dim, pos):
    """
    pos_enc_dim: 编码维度
    pos: 极坐标位置 (θ, φ)
    """
    th, ph = pos
    enc = torch.cat([torch.sin(2 * torch.pi * th / pos_enc_dim), torch.cos(2 * torch.pi * th / pos_enc_dim)], dim=-1)
    enc = torch.cat([enc, torch.sin(2 * torch.pi * ph / pos_enc_dim), torch.cos(2 * torch.pi * ph / pos_enc_dim)], dim=-1)
    return enc

# 假设pos_enc_dim为64,pos为极坐标位置
pos_enc_dim = 64
pos = torch.tensor([0.5, 0.3])  # 示例极坐标位置
spe = spherical_positional_encoding(pos_enc_dim, pos)

2. EPP注意力掩码

        EPP注意力掩码用于增强全景特征图和透视特征图之间的对应关系,通过高斯核平滑二进制掩码来实现。

def gaussian_kernel(size, sigma=1.0):
    """生成高斯核"""
    x = torch.arange(size, dtype=torch.float32)
    x -= size // 2
    x = x / sigma
    x = torch.exp(-x ** 2 / (2 * sigma ** 2))
    return x / x.sum()

def create_epp_attention_mask(pano_size, pers_size, fov):
    """
    pano_size: 全景特征图大小
    pers_size: 透视特征图大小
    fov: 视场角
    """
    # 创建全景和透视特征图的坐标网格
    pano_coords = torch.stack(torch.meshgrid(torch.linspace(-1, 1, pano_size[0]), torch.linspace(-1, 1, pano_size[1])), dim=-1)
    pers_coords = torch.stack(torch.meshgrid(torch.linspace(-1, 1, pers_size[0]), torch.linspace(-1, 1, pers_size[1])), dim=-1)
    
    # 计算全景和透视特征图之间的对应关系
    mask = torch.zeros(pano_size[0], pano_size[1], pers_size[0], pers_size[1])
    for i in range(pers_size[0]):
        for j in range(pers_size[1]):
            # 将透视坐标转换为全景坐标
            pano_x, pano_y = (i / (pers_size[0] - 1) * 2 - 1) * fov, (j / (pers_size[1] - 1) * 2 - 1) * fov
            pano_x, pano_y = pano_x * pano_size[0] / 2, pano_y * pano_size[1] / 2
            # 计算高斯掩码
            kernel = gaussian_kernel(pano_size[0], sigma=pano_size[0] / 6)
            mask[:, :, i, j] = kernel[int(pano_y):int(pano_y + 1), int(pano_x):int(pano_x + 1)].sum(dim=-1).sum(dim=-1)
    return mask

pano_size = (512, 1024)  # 全景特征图大小
pers_size = (256, 256)   # 透视特征图大小
fov = 90                # 视场角
epp_mask = create_epp_attention_mask(pano_size, pers_size, fov)

3. EPP注意力模块

        EPP注意力模块结合了SPE和EPP注意力掩码,以实现全景分支和透视分支之间的信息传递。

class EPPAttention(torch.nn.Module):
    def __init__(self, channel_dim, pos_enc_dim):
        super(EPPAttention, self).__init__()
        self.query_linear = torch.nn.Linear(channel_dim, channel_dim)
        self.key_linear = torch.nn.Linear(channel_dim, channel_dim)
        self.value_linear = torch.nn.Linear(channel_dim, channel_dim)
        self.pos_enc_dim = pos_enc_dim

    def forward(self, pano_feat, pers_feat, epp_mask):
        """
        pano_feat: 全景特征图
        pers_feat: 透视特征图
        epp_mask: EPP注意力掩码
        """
        # 计算查询(Q)、键(K)和值(V)
        Q = self.query_linear(pano_feat).view(-1, pano_feat.size(1), pano_feat.size(2) * pano_feat.size(3))
        K = self.key_linear(pers_feat).view(-1, pers_feat.size(1), pers_feat.size(2) * pers_feat.size(3))
        V = self.value_linear(pers_feat).view(-1, pers_feat.size(1), pers_feat.size(2) * pers_feat.size(3))

        # 计算注意力分数
        scores = torch.matmul(Q, K.transpose(-1, -2))
        scores = scores / math.sqrt(self.pos_enc_dim)
        scores = scores + epp_mask

        # 应用softmax函数
        attn = F.softmax(scores, dim=-1)

        # 计算输出
        output = torch.matmul(attn, V)
        output = output.view(-1, pano_feat.size(1), pano_feat.size(2), pano_feat.size(3))
        return output

# 假设channel_dim为128,pos_enc_dim为64
channel_dim = 128
pos_enc_dim = 64
epp_attn = EPPAttention(channel_dim, pos_enc_dim)

# 假设pano_feat和pers_feat是输入的特征图
pano_feat = torch.randn(1, channel_dim, 512, 1024)  # 全景特征图
pers_feat = torch.randn(1, channel_dim, 256, 256)    # 透视特征图
output = epp_attn(pano_feat, pers_feat, epp_mask)

        以上代码展示了EPPA机制的核心组成部分,包括球面位置编码、EPP注意力掩码和EPP注意力模块。这些组件共同实现了全景分支和透视分支之间的有效信息传递,从而提高了全景图像的生成质量和一致性。

文章来源于互联网:《PanFusion:Taming Stable Diffusion for Text to 360 Panorama Image Generation》学习——双分支全景图像扩散生成

相关推荐: 最新AI写作系统ChatGPT源码/支持GPT4.0+GPT联网提问/支持ai绘画Midjourney+Prompt应用+MJ以图生图+思维导图生成

一、智能创作系统 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT?小编这里…

赞(0)
未经允许不得转载:5bei.cn大模型教程网 » 《PanFusion:Taming Stable Diffusion for Text to 360 Panorama Image Generation》学习——双分支全景图像扩散生成
分享到: 更多 (0)

AI大模型,我们的未来

小欢软考联系我们