VQGAN:从图像重建到图像生成

news2024/11/18 21:27:18

本文的目标是作为全新图像生成系统的VQGAN。我已经开始讨论VQGAN的一部分——自编码器(VQVAE:矢量量化变分自动编码器)。VQVAE的概念是对编码器、解码器和码书的同时训练,该码书适用于所有可能的图像。码书是一组256个嵌入向量。具有输入分辨率256x256的任何图像的潜在空间由码书向量的某个子集表示。下面的图片底部显示了VQVAE管道的插图:

cbb92303cc443293c0c1ddda3fcab175.jpeg

编码器将输入图像(256x256像素分辨率)转换为具有16x16条目的潜在空间,每个条目是一个具有256个值的向量(在图1的图表中,潜在空间显示为4x4条目的平面)。然后,潜在空间中的每个条目都更改为来自码书的L2度量最近的向量 —— 这个过程称为矢量量化。因此,潜在空间由16x16的码书索引平面表示。将这个量化的潜在空间发送到解码器,我们得到重建图像。

在VQGAN中,自编码器部分通过一个额外的CNN——基于块的判别器(见图)扩展。判别器具有分类器结构。在图片中显示了VQVAE和判别器之间的交互:重建图像后,它被发送到判别器,判别器为图像块生成类别值。判别器为输入图像和重建图像获得“每个块的类别”空间,并在每个块上验证这些空间之间的类别差异:相同类别(真实)或不同类别(伪造)。判别器参与VQGAN的训练,并试图最大化其损失,但共同的损失 = VQVAE损失 + 判别器损失被最小化。关于VQGAN损失组成的良好解释在这里。在训练步骤中,当训练好的模型进行图像重建时,不使用判别器,它用于改进VQVAE在训练步骤中的质量。判别器在GAN训练的下一步中发挥着重要作用,用于生成新图像。

潜在空间的实际实验

在本节中,我在实践中演示了使用VQGAN进行图像重建,并对潜在空间、码书及其在生成新图像中的作用进行了实验。在这里,我在我的Google Colab中使用以下代码。导入:

import copy
import cv2
import sys


import torch


from PIL import Image
from torchvision import transforms


import matplotlib.pyplot as plt
import numpy as np

Google Drive映射:

from google.colab import drive
drive.mount('/content/gdrive')

Cuda设备设置:

device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

VQGAN的安装和模型下载:

%pip install omegaconf>=2.0.0 pytorch-lightning>=1.0.8 einops>=0.3.0
sys.path.append(".")


!git clone https://github.com/CompVis/taming-transformers
%cd taming-transformers


# download a VQGAN with f=16 (16x compression per spatial dimension) and with a codebook with 1024 entries
!mkdir -p logs/vqgan_imagenet_f16_1024/checkpoints
!mkdir -p logs/vqgan_imagenet_f16_1024/configs
!wget 'https://heibox.uni-heidelberg.de/f/140747ba53464f49b476/?dl=1' -O 'logs/vqgan_imagenet_f16_1024/checkpoints/last.ckpt'
!wget 'https://heibox.uni-heidelberg.de/f/6ecf2af6c658432c8298/?dl=1' -O 'logs/vqgan_imagenet_f16_1024/configs/model.yaml'
# also disable grad to save memory
torch.set_grad_enabled(False)

上面的代码安装了具有代码簿条目数=1024的最小模型。两个用于从文件读取图像并转换为torch张量的实用函数,以及用于显示输入和输出图像的函数:

def get_img_tensor(name,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Resize((256, 256)),
                   ])):
    img = Image.open(name)
    img = transform(img)
    img = img.unsqueeze(0)
    return img
 
def show_results(img, out):
    rec = custom_to_pil(out[0])
    _, ax = plt.subplots(1, 2, figsize=(12, 5))
    if img is not None:
        ax[0].imshow(img[0].permute(1, 2, 0))
    ax[0].axis("off")
    ax[1].imshow(rec)
    ax[1].axis("off")  
    plt.show()

下面的代码包含了使用VQGAN进行图像重建的函数:

from omegaconf import OmegaConf
from taming.models.vqgan import VQModel


def load_config(config_path):
    config = OmegaConf.load(config_path)
    return config


def load_vqgan(config, ckpt_path=None):
    model = VQModel(**config.model.params)
    if ckpt_path is not None:
        sd = torch.load(ckpt_path, map_location="cpu")["state_dict"]
        missing, unexpected = model.load_state_dict(sd, strict=False)
    return model.eval()


def preprocess_vqgan(x):
    x = 2.*x - 1.
    return x


def custom_to_pil(x):
    x = x.detach().cpu()
    x = torch.clamp(x, -1., 1.)
    x = (x + 1.)/2.
    x = x.permute(1, 2, 0).numpy()
    x = (255*x).astype(np.uint8)
    x = Image.fromarray(x)
    if not x.mode == "RGB":
        x = x.convert("RGB")
    return x


def reconstruct_with_vqgan(x, model):
    # could also use model(x) for reconstruction but use explicit encoding and decoding here
    z, _, [_, _, indices] = model.encode(x)
    print(f"VQGAN --- {model.__class__.__name__}: latent shape: {z.shape[2:]}")
    xrec = model.decode(z)
    return xrec
  • load_config()、load_vqgan() — 用于加载预训练模型的函数。

  • preprocess_vqgan() — 用于将输入图像张量发送到VQGAN编码器之前进行预处理的函数。

  • custom_to_pil() — 用于VQGAN解码器之后对重建图像张量进行后处理的函数。

  • reconstruct_with_vqgan() — 用于图像重建的函数:它调用编码器,获取图像潜在空间,然后调用解码器以获取重建的图像。

现在一切都准备好进行重建。加载预训练模型:

config1024 = load_config("logs/vqgan_imagenet_f16_1024/configs/model.yaml")
model1024 = load_vqgan(config1024, ckpt_path="logs/vqgan_imagenet_f16_1024/checkpoints/last.ckpt").to(device)

并使用该模型进行图像重建:

img = get_img_tensor("image path")
out = reconstruct_with_vqgan(preprocess_vqgan(img.to(device)), model1024)
show_results(img, out)

图像重建结果的示例:

49cea4fb46e56d3c30897e9d7930687f.jpeg

reconstruct_with_vqgan()依次调用编码器和解码器。让我们看看这些函数:

z, _, [_, _, indices] = model1024.encode(preprocess_vqgan(img.to(device)))
indices = indices.detach().cpu().numpy()

预训练的编码器模型返回形状为(1, 256, 16, 16)的潜在空间z,以及形状为(256)的代码簿向量索引。如果将这些具有索引的代码簿向量按照16x16平面的栅格顺序放置,它们组成了潜在空间。换句话说,如果我有256个适当顺序的索引,我就能够从代码簿创建潜在空间,并调用解码器重建图像。在下面的代码中,我尝试了这个过程。首先,获取代码簿向量:

ind = torch.arange(1024).to(device)
cb = model1024.quantize.get_codebook_entry(ind, None)
print(cb.shape)

上面的代码中,我从代码簿中获取了索引0,...,1023的向量,即整个代码簿(我使用了小的VQGAN模型)。代码簿的形状为(1024, 256)。下面的函数展示了如何从代码簿和256个索引的numpy数组创建潜在空间,并使用解码器获取输出图像:

def cb_construct(cb, indices, img):
    emb = [cb[i] for i in indices]
    zn = torch.stack(emb)


    zn = torch.reshape(zn, (16, 16, 256))
    zn = torch.unsqueeze(zn, 0)
    zn = zn.permute(0, 3, 1, 2)


    xrec = model1024.decode(zn.to(device))
    show_results(img, xrec)

如果我们使用前面代码块中获得的`cb`和`indices`调用这个函数:

cb_construct(cb, indices, img)

我们会得到与图2中完全相同的重建结果。如果我们尝试打乱这些索引并使用打乱的向量解码潜在空间:

indices1 = copy.deepcopy(indices)
np.random.shuffle(indices1)
cb_construct(cb, indices1, img)

我们会得到一张新的带有一些抽象的图像。

4310e1d4ac5cebed6fe9218d24c57494.jpeg

其他一些基于来自其他图片的潜在空间的“抽象艺术”的示例:

15a2675fa1fe2d99854fec04e6996dee.jpeg

2243840a21352b2b392ce841f8cc3a30.jpeg

5f9a4ae89ab1cdbe2624158d522582bb.jpeg

因此,我们通过实验尝试了对于创建任何图像,我们都需要代码簿、以定义顺序的代码簿向量的集合和解码器。直观地说,我们需要一些系统,它能够定义代码簿向量的子集和其索引的顺序,以生成某种类型的逼真图像。

注意:高分辨率图像的潜在空间是由该图像由256x256补丁组成的潜在空间的连接。

Taming Transformer

Taming Transformer模型是图像生成器的第二阶段。它经过训练,可以生成新图像潜在空间的索引序列。生成从初始条件处理开始。以下是该模型处理的条件图像类型:

625ff6db35a923c2c1c2ff802f61ff74.jpeg

<输入类型+输入代码>作为初始参数发送到模型。输入代码意味着条件图像潜在空间的代码簿向量集合。该模型经过训练,以使用先前预测的索引来预测当前索引。第一个索引是基于输入代码预测的。变压器预测可能的下一个索引的分布(图1)。如果输入图像分辨率为256x256,则使用先前预测的所有索引来预测当前索引。对于高分辨率图像,每个补丁仅使用滑动窗口中相邻补丁的先前预测的索引来进行预测,如下图所示:

9daddd5473e85d3020c4c9958877a352.jpeg

Taming Transformer使用第一阶段训练的VQGAN和鉴别器模型作为骨干。训练步骤如下:预测整个补丁的代码簿索引分布,将预测的索引发送到解码器并获取输出补丁,将输出补丁发送到鉴别器并获取补丁特征,然后计算输入特征(从输入代码获得)和输出特征之间的交叉熵损失。

我使用这个Google Colab进行实验,从分割掩模生成新图像。我使用了Colab中提供的输入数据。以下是对于相同分割掩模的3次不同运行的结果:

2e69df86641b8bb80c9ce1f32ddaf611.jpeg

分割掩模可能包含高达182个对象类别(掩模值从1到182)。

关于Taming Transformer + VQGAN系统的结论:

1. 该系统能够使用基于条件图像的输入配置生成高质量逼真图像。

2. 该系统可以用于图像扩展:例如,可以将条件图像作为顶部图像部分发送到系统中,输出图像将包含这个顶部部分 + 生成的底部部分。

3. 根据输入类型,需要对条件图像进行特殊的预处理,例如适当配置分割掩模。

4. 该系统用于生成与条件图像相似的新图像,但不能用于更改条件图像的风格。

CLIP + VQGAN系统用于新图像生成

首先,我继续使用第2节中的代码。在下面的代码中,我更改编码后的图像潜在空间 —— 将其乘以0.7:

img = get_img_tensor("image path")
z, _, [_, _, indices] = model1024.encode(preprocess_vqgan(img.to(device)))
out = model1024.decode(0.7 * z)
show_results(img, out)

结果是,我得到了另一种风格的冬季风景。

f687a42b026fb2f9c66df60acee3fd32.jpeg

我可以以另一种方式改变潜在空间,例如,将潜在空间的每个向量的第70个元素乘以50:

ind = 70
z, _, [_, _, indices] = model1024.encode(img.to(device))


z = z.permute(1, 0, 2, 3)
z = [z[i] for i in range(256)]
z[ind] = z[ind] * 50
z = torch.stack(z)
z = z.permute(1, 0, 2, 3)


out = model1024.decode(z)
show_results(img, out)

风景风格以另一种方式改变:

f7daf6ed988e22888face09b5ceab485.jpeg

在这两个实验中,我“忘记”了代码簿索引,整体改变了潜在空间。

CLIP + VQGAN系统的思想类似:通过整体改变潜在空间来以期望的方式改变图像。CLIP充当鉴别器的角色,它理解期望图像的文本描述并产生损失值。CLIP是一个经过训练的系统,用于查找图像与文本之间的相似性。

生成过程类似于通过改变潜在空间权重进行训练:CLIP产生文本描述的嵌入向量,VQGAN解码潜在空间并获取图像,然后CLIP产生图像的嵌入向量,CLIP + VQGAN系统计算其与输入文本描述的嵌入向量的余弦相似度。该系统的目标是最大化相似性(相似性在区间(0,1)内)。为了实现这个目标,系统在反向传播步骤中改变潜在空间中的权重。主要挑战是在反向传播期间传递梯度的技巧,因为VQGAN和CLIP并不是系统的骨干,只是加载的预训练模型。我尝试了来自这个Google Colab的CLIP + VQGAN实现。我根据输入文本描述更改了输入图像,以在图像中获得视频效果。下面的图片显示了一些结果:

文本提示:“积雪覆盖的云杉”。

图像变换:

ad47b79b260a113274d0f47541092a43.jpeg

文本提示:“积雪覆盖的冷杉枝和松果”。

图像变换:

18bcf96eca29346240d5b956256277d7.jpeg

文本提示1:“黑色大象轮廓上的白色和红色点”。

文本提示2:“黑色大象轮廓上的白色和红色花朵”。

图像变换:

f65f0c7f35dcba56282f1752259e2bcf.jpeg

以及从噪音生成的新年艺术的示例:

文本提示:“新年云杉水彩细节”。

a18aa7deabc686d9408139881d6cb187.jpeg

关于CLIP + VQGAN系统的结论:

与Taming Transformer + VQGAN系统相反,CLIP + VQGAN系统更适用于艺术而不是逼真图像生成。它能够以不同风格生成图像,接受用户以最方便的形式输入,即以文本描述的形式。

结论

我之前(关于自动编码器)和现在的帖子的目标是逐步追踪VQGAN的新图像生成概念的发展:

  • 用于图像压缩的自动编码器 -> 相对较小的图像潜在空间,特定数据集的图像重建。

  • 向量量化自动编码器 -> 基于代码簿和向量量化技术的图像潜在空间,任何图像的高质量图像重建。

  • Taming Transformers + VQGAN -> 根据矢量指数预测生成的代码簿向量的新图像。

  • CLIP + VQGAN -> 根据文本描述改变图像潜在空间的新图像生成。

·  END  ·

HAPPY LIFE

f800ebbaf493a1667d679053a0497d45.png

本文仅供学习交流使用,如有侵权请联系作者删除

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1384801.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

毕业设计:基于python微博舆情分析系统+可视化+Django框架 K-means聚类算法(源码)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

Material Design 进阶(十一)——Chip,ChipGroup,ChipDrawable使用

流式布局标签发展历程 第一阶段&#xff1a;实现这种界面的时候&#xff0c;基本都是自定义一个控件&#xff0c;然后在Java代码中动态的 添加一个个的TextView&#xff0c;还需要计算布局宽度/高度&#xff0c;进行换行等等处理&#xff0c;比较复杂;第二阶段&#xff1a;使用…

CSC8021_computer network_The Transport Layer

Role of the transport layer • The transport layer is responsible for providing a reliable end-to-end connection between two application processes in a network • Abstracting away the physical subnet • Does not involve intermediate nodes • Takes a netwo…

Centos源码编译安装Redis

Redis是常用的内容使用工具&#xff0c;每次安装服务器都需要安装Redis 为了减少重复工作&#xff0c;写了一个脚本自动安装Redis&#xff0c;如下 #!/bin/sh #下载源码 curl -O http://download.redis.io/redis-stable.tar.gz # 解压缩 tar zxf redis-stable.tar.gz cd redi…

【Redis集群】docker实现3主3从扩缩容架构配置案例

一&#xff0c;集群规划及准备工作 架构实现&#xff1a;Redis3主3从 二&#xff0c;搭建命令 第一步&#xff0c;创建6台服务&#xff1a; docker run -d --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/data redis:6.0.8 --clust…

照片删除了怎么恢复回来

照片&#xff0c;对我们来说&#xff0c;这两个字眼再熟悉不过了&#xff0c;每一张照片都包含无比重要的意义&#xff0c;相信在大家的心目中&#xff0c;这些包含意义的照片都是无价的。怎样找回删除的照片&#xff1f; 既然这些照片对我们来说意义非凡&#xff0c;那如果不小…

超详细的搭建压测平台笔记

0、前言 最近重新回来学习熊哥的极客教程&#xff0c;结合自己学习的shell编程和Docker的指令学习&#xff0c;对熊哥的一些操作做bash脚本自动化&#xff0c;将搭建压测平台的步骤做记录&#xff0c;目的是分享搭建过程。 过程中会安装docker,mysql,redis,influxdb,grafana,…

分布形态的度量_峰度系数的探讨

集中趋势和离散程度是数据分布的两个重要特征,但要全面了解数据分布的特点&#xff0c;还应掌握数据分布的形态。 描述数据分布形态的度量有偏度系数和峰度系数, 其中偏度系数描述数据的对称性,峰度系数描述与正态分布的偏离程度。 峰度系数反映分布峰的尖峭程度的重要指标. 当…

2024--Django平台开发-Redis集群(十一)

内容回顾 主从复制。 哨兵&#xff1a;实例启动了&#xff0c;哨兵节点没启动&#xff0c;Python通过redis-py连接报错。一定要确保实例节点和哨兵节点都启动了。 搭建集群用的是虚拟机的多台centos服务器&#xff0c;你在跟着学习的时候&#xff0c;一定要全部都是虚拟机&am…

Mysql-redoLog

Redo Log redo log进行刷盘的效率要远高于数据页刷盘,具体表现如下 redo log体积小,只记录了哪一页修改的内容,因此体积小,刷盘快 redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快Redo log 格式 在MySQL的InnoDB存储引擎中,redo log(重做日志)被用…

【UEFI基础】EDK网络框架(VLAN)

VLAN VLAN代码综述 在MNP中有很多的VLAN介绍&#xff0c;MNP存在的一个重要原因也是为了处理VLAN&#xff0c;而本文介绍的NetworkPkg\VlanConfigDxe\VlanConfigDxe.inf其实只是一个帮助模块&#xff0c;真正的VLAN配置还是在MNP中。 VLAN同样是一个UEFI Driver Model&#…

pytorch一致数据增强—异用增强

前作 [1] 介绍了一种用 pytorch 模仿 MONAI 实现多幅图&#xff08;如&#xff1a;image 与 label&#xff09;同用 random seed 保证一致变换的写法&#xff0c;核心是 MultiCompose 类和 to_multi 包装函数。不过 [1] 没考虑不同图用不同 augmentation 的情况&#xff0c;如&…

adb 常用命令汇总

目录 adb 常用命令 1、显示已连接的设备列表 2、进入设备 3、安装 APK 文件到设备 4、卸载指定包名的应用 5、从设备中复制文件到本地 6、将本地文件复制到设备 7、查看设备日志信息 8、重启设备 9、截取设备屏幕截图 10、屏幕分辨率 11、屏幕密度 12、显示设备的…

Linux 压缩与解压缩

参考资料 linux 压缩和解压缩命令gz、tar、zip、bz2tar命令 – 压缩和解压缩文件 目录 一. gzip命令1.1 压缩1.1.1 -k 压缩后保留源文件1.1.2 -l 查看压缩文件中的文件信息1.1.3 -r 递归压缩文件夹中的所有文件 1.2 解压缩 二. zip命令2.1 zip 压缩2.1.1 -r 压缩文件夹2.1.2 压…

Android中的anr定位指导与建议

1.背景 8月份安卓出现了一次直播间卡死(ANR)问题&#xff0c;且由于排查难度较大&#xff0c;持续了较长时间。本文针对如何快速定位安卓端出现ANR问题进行总结和探讨. 这里大致补充一下当时的情况,当时看到情景的是从某一个特定的场景下进入直播间后整个直播间界面立刻就卡住…

css3 2D与3D转换

css3 2D与3D转换 前言2D变形旋转变形 rotate()transform-origin属性 缩放变形 scale()斜切变形 skew()位移变形 translate() 3D变形3D旋转 rotateX() | rotateY()perspective属性 空间移动 制作一个正方体结语 前言 网页设计不再局限于平面&#xff0c;而是充满了立体感和动态…

【ESP32接入语言大模型之智谱清言】

1. 智谱清言 讲解视频&#xff1a; 随着人工智能技术的不断发展&#xff0c;自然语言处理领域也得到了广泛的关注和应用。智谱清言作为千亿参数对话模型 基于ChatGLM2模型开发&#xff0c;支持多轮对话&#xff0c;具备内容创作、信息归纳总结等能力。可以快速注册体验中国版…

Linux系统使用超详细(十)~vi/vim命令①

vi/vim命令有很多&#xff0c;其实只有少数的用法对于我们日常工作中起到了很大帮助&#xff0c;但是既然我选择梳理Linux的学习笔记&#xff0c;那么一定全力把自己的理解和学习笔记的内容认真整理汇总&#xff0c;内容或许有错误&#xff0c;还请发现的C友们发现了及时指出。…

小程序基础学习(发送请求)

原理 通过js发起wx.request的方法发送请求并接受相应数据 实例&#xff08;一&#xff09; 参数&#xff1a; url:请求网址地址&#xff0c; success:请求成功执行的函数&#xff0c; fail:请求失败执行的函数 请求返回的数据 实例&#xff08;二&#xff09; 参数&#xff1…

如何用LLM和自有知识库搭建智能agent?

用LangChain建立知识库&#xff0c;文末中也推荐其他方案。 项目源码&#xff1a;ChatPDF实现 LangChain Indexes使用 对加载的内容进行索引&#xff0c;在indexes中提供了一些功能&#xff1a; Document Loaders&#xff0c;加载文档Text Splitters&#xff0c;文档切分V…