昇思25天学习打卡营第25天 | Pix2Pix实现图像转换

news2024/9/23 17:21:06

Pix2Pix实现图像转换

在这里插入图片描述

Pix2Pix概述

Pix2Pix是一种基于条件生成对抗网络(cGAN, Condition Generative Adversarial Networks)的图像转换模型,由Phillip Isola等人在2017年提出。它能够将语义/标签图像转换为真实图片、灰度图转换为彩色图、航空图转换为地图、白天图转换为夜晚图、线稿图转换为实物图等。Pix2Pix的创新之处在于使用相同的架构和目标函数,通过不同的数据集训练实现多种图像转换任务。

基础原理

cGAN与传统GAN的区别在于,cGAN的生成器以输入图片为指导信息生成“假”图像,而GAN的生成器则以随机噪声为输入。Pix2Pix的生成器使用U-Net结构,通过编码和解码输入图像生成输出图像;判别器使用PatchGAN结构,通过判断图像的局部区域(Patch)来区分真实图像和生成图像。cGAN的目标是通过生成器和判别器的博弈,使生成器生成的图像越来越接近真实图像。

准备工作

配置环境文件

本案例支持在GPU、CPU和Ascend平台的动静态模式下运行。

准备数据

使用指定的数据集,已处理好的外墙(facades)数据集,可直接使用MindSpore读取。

数据展示

from mindspore import dataset as ds
import matplotlib.pyplot as plt

dataset = ds.MindDataset("./dataset/dataset_pix2pix/train.mindrecord", columns_list=["input_images", "target_images"], shuffle=True)
data_iter = next(dataset.create_dict_iterator(output_numpy=True))
# 可视化部分训练数据
plt.figure(figsize=(10, 3), dpi=140)
for i, image in enumerate(data_iter['input_images'][:10], 1):
    plt.subplot(3, 10, i)
    plt.axis("off")
    plt.imshow((image.transpose(1, 2, 0) + 1) / 2)
plt.show()

创建网络

生成器G结构

生成器使用U-Net结构,通过编码和解码输入图像生成输出图像。

import mindspore
import mindspore.nn as nn
import mindspore.ops as ops

class UNetSkipConnectionBlock(nn.Cell):
    def __init__(self, outer_nc, inner_nc, in_planes=None, dropout=False, submodule=None, outermost=False, innermost=False, alpha=0.2, norm_mode='batch'):
        super(UNetSkipConnectionBlock, self).__init__()
        # 定义下采样和上采样的卷积层、激活函数和归一化层
        down_conv = nn.Conv2d(in_planes, inner_nc, kernel_size=4, stride=2, padding=1, has_bias=False, pad_mode='pad')
        down_relu = nn.LeakyReLU(alpha)
        up_relu = nn.ReLU()
        # 定义下采样和上采样的卷积层、激活函数和归一化层
        if outermost:
            up_conv = nn.Conv2dTranspose(inner_nc * 2, outer_nc, kernel_size=4, stride=2, padding=1, pad_mode='pad')
            model = [down_conv] + [submodule] + [up_relu, up_conv, nn.Tanh()]
        elif innermost:
            up_conv = nn.Conv2dTranspose(inner_nc, outer_nc, kernel_size=4, stride=2, padding=1, has_bias=False, pad_mode='pad')
            model = [down_relu, down_conv] + [up_relu, up_conv, nn.BatchNorm2d(outer_nc)]
        else:
            up_conv = nn.Conv2dTranspose(inner_nc * 2, outer_nc, kernel_size=4, stride=2, padding=1, has_bias=False, pad_mode='pad')
            model = [down_relu, down_conv, nn.BatchNorm2d(inner_nc)] + [submodule] + [up_relu, up_conv, nn.BatchNorm2d(outer_nc)]
            if dropout:
                model.append(nn.Dropout(p=0.5))
        self.model = nn.SequentialCell(model)
        self.skip_connections = not outermost

    def construct(self, x):
        out = self.model(x)
        if self.skip_connections:
            out = ops.concat((out, x), axis=1)
        return out
基于UNet的生成器
class UNetGenerator(nn.Cell):
    def __init__(self, in_planes, out_planes, ngf=64, n_layers=8, norm_mode='bn', dropout=False):
        super(UNetGenerator, self).__init__()
        # 定义UNet生成器的各个层次
        unet_block = UNetSkipConnectionBlock(ngf * 8, ngf * 8, in_planes=None, submodule=None, norm_mode=norm_mode, innermost=True)
        for _ in range(n_layers - 5):
            unet_block = UNetSkipConnectionBlock(ngf * 8, ngf * 8, in_planes=None, submodule=unet_block, norm_mode=norm_mode, dropout=dropout)
        unet_block = UNetSkipConnectionBlock(ngf * 4, ngf * 8, in_planes=None, submodule=unet_block, norm_mode=norm_mode)
        unet_block = UNetSkipConnectionBlock(ngf * 2, ngf * 4, in_planes=None, submodule=unet_block, norm_mode=norm_mode)
        unet_block = UNetSkipConnectionBlock(ngf, ngf * 2, in_planes=None, submodule=unet_block, norm_mode=norm_mode)
        self.model = UNetSkipConnectionBlock(out_planes, ngf, in_planes=in_planes, submodule=unet_block, outermost=True, norm_mode=norm_mode)

    def construct(self, x):
        return self.model(x)
判别器D结构

判别器使用PatchGAN结构,通过判断图像的局部区域(Patch)来区分真实图像和生成图像。

import mindspore.nn as nn

class ConvNormRelu(nn.Cell):
    def __init__(self, in_planes, out_planes, kernel_size=4, stride=2, alpha=0.2, norm_mode='batch', pad_mode='CONSTANT', use_relu=True, padding=None):
        super(ConvNormRelu, self).__init__()
        norm = nn.BatchNorm2d(out_planes)
        if norm_mode == 'instance':
            norm = nn.BatchNorm2d(out_planes, affine=False)
        has_bias = (norm_mode == 'instance')
        if not padding:
            padding = (kernel_size - 1) // 2
        if pad_mode == 'CONSTANT':
            conv = nn.Conv2d(in_planes, out_planes, kernel_size, stride, pad_mode='pad', has_bias=has_bias, padding=padding)
            layers = [conv, norm]
        else:
            paddings = ((0, 0), (0, 0), (padding, padding), (padding, padding))
            pad = nn.Pad(paddings=paddings, mode=pad_mode)
            conv = nn.Conv2d(in_planes, out_planes, kernel_size, stride, pad_mode='pad', has_bias=has_bias)
            layers = [pad, conv, norm]
        if use_relu:
            relu = nn.ReLU()
            if alpha > 0:
                relu = nn.LeakyReLU(alpha)
            layers.append(relu)
        self.features = nn.SequentialCell(layers)

    def construct(self, x):
        output = self.features(x)
        return output

class Discriminator(nn.Cell):
    def __init__(self, in_planes=6, ndf=64, n_layers=3, alpha=0.2, norm_mode='batch'):
        super(Discriminator, self).__init__()
        kernel_size = 4
        layers = [
            nn.Conv2d(in_planes, ndf, kernel_size, 2, pad_mode='pad', padding=1),
            nn.LeakyReLU(alpha)
        ]
        nf_mult = ndf
        for i in range(1, n_layers):
            nf_mult_prev = nf_mult
            nf_mult = min(2 ** i, 8) * ndf
            layers.append(ConvNormRelu(nf_mult_prev, nf_mult, kernel_size, 2, alpha, norm_mode, padding=1))
        nf_mult_prev = nf_mult
        nf_mult = min(2 ** n_layers, 8) * ndf
        layers.append(ConvNormRelu(nf_mult_prev, nf_mult, kernel_size, 1, alpha, norm_mode, padding=1))
        layers.append(nn.Conv2d(nf_mult, 1, kernel_size, 1, pad_mode='pad', padding=1))
        self.features = nn.SequentialCell(layers)

    def construct(self, x, y):
        x_y = ops.concat((x, y), axis=1)
        output = self.features(x_y)
        return output

Pix2Pix的生成器和判别器初始化

import mindspore.nn as nn
from mindspore.common import initializer as init

继续训练过程

随着训练的进行,我们可以在每个周期结束时保存生成器的检查点,并可视化一些中间结果。我们也可以监控损失的变化来确定模型的训练情况。

训练完成

一旦训练完成,我们可以使用生成器来生成新的图像。通过提供输入图像,生成器可以生成相应的输出图像。

验证生成效果

在训练完成后,我们使用部分数据进行验证,看看生成器的效果。

# 验证生成器效果
from mindspore import load_checkpoint

# 加载生成器模型
load_checkpoint("results/ckpt/Generator.ckpt", net_generator)

# 可视化函数
def visualize_result(input_image, generated_image, target_image, epoch, idx):
    plt.figure(figsize=(15, 5), dpi=140)
    plt.subplot(1, 3, 1)
    plt.axis("off")
    plt.title("Input Image")
    plt.imshow((input_image.transpose(1, 2, 0) + 1) / 2)

    plt.subplot(1, 3, 2)
    plt.axis("off")
    plt.title("Generated Image")
    plt.imshow((generated_image.transpose(1, 2, 0) + 1) / 2)

    plt.subplot(1, 3, 3)
    plt.axis("off")
    plt.title("Target Image")
    plt.imshow((target_image.transpose(1, 2, 0) + 1) / 2)
    
    plt.suptitle(f"Epoch {epoch}, Step {idx}")
    plt.show()

# 验证集
val_dataset = ds.MindDataset("./dataset/dataset_pix2pix/val.mindrecord", columns_list=["input_images", "target_images"], shuffle=False)

# 验证生成器
val_data_iter = val_dataset.create_dict_iterator(output_numpy=True)
for idx, data in enumerate(val_data_iter):
    input_image = Tensor(data["input_images"])
    target_image = Tensor(data["target_images"])
    generated_image = net_generator(input_image)
    visualize_result(input_image.asnumpy(), generated_image.asnumpy(), target_image.asnumpy(), epoch_num, idx)
    if idx >= 5:  # 仅展示部分验证结果
        break

在这里插入图片描述

通过本文教程,我们使用MindSpore实现了Pix2Pix模型,包括数据准备、生成器和判别器的搭建、训练和验证。在训练过程中,我们使用了cGAN和L1损失的组合来优化生成器。最终,我们展示了模型的训练效果和生成结果。

在实际应用中,Pix2Pix模型可以用于各种图像到图像的转换任务,比如从卫星图像生成地图、将灰度图像转换为彩色图像等。希望本文的教程对您理解Pix2Pix模型有所帮助,并能在实际项目中应用此模型。

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

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

相关文章

永劫无间:排位赛游戏攻略大全!VMOS云手机辅助攻略!

在《永劫无间》中,排位赛和金乌玩法是提升实力和展示技巧的绝佳途径。以下是详细的攻略建议,帮助玩家在游戏中取得更好的成绩。 排位赛 英雄们齐聚“聚窟洲”,为争夺“不朽面具”展开激烈的战斗。排位赛是玩家展示实力的重要平台&#xff0c…

六方云笔试总结

1. (1)题目 外部变量,指的是处于函数外部的全局静态变量,所以选c (2)知识点 1. static (1)函数外部的全局变量 当一个变量在函数外部定义并使用static关键字修饰时,这…

函数的学习(二)

1.函数嵌套 在C语言中,函数的嵌套是指在一个函数内部调用另一个函数。通过函数的嵌套,可以将程序的功能细化,提高代码的可读性和可维护性。函数的嵌套可以是直接嵌套,也可以是间接嵌套。 直接嵌套是指一个函数直接在另一个函数内…

华彩38载 同心筑未来—中华财险客户节盛大启幕!

活动主题:华彩38载 同心筑未来—中华财险客户节金融知识有奖问答 活动时间:2024年7月26日至9月15日 参与方式:① 微信搜索并关注公众号“中华财险宁波分公司”进入答题活动页面,点击“开始答题”即可开始答题;②规定…

ComfyUI-MuseTalk部署依赖mmcv

ComfyUI-MuseTalk部署依赖mmcv ComfyUI-MuseTalk是MuseTalk基于ComfyUI的自定义节点插件。MMPose 是一款基于 PyTorch 的“人体姿态”分析的开源工具箱,是 OpenMMLab 项目的成员之一。OpenMMLab 团队致力于构建了深度学习时代最具影响力的开源计算机视觉算法系统&am…

【C++标准库】介绍及使用string类

string 一.string类介绍二.string类的静态成员变量三.string类的常用接口1.构造函数(constructor)2.析构函数(destructor)3.运算符重载(operator)1.operator2.operator[]3.operator4.operator 4.string的四…

SecureCrt设置豆沙绿

绿豆沙色能有效的减轻长时间用电脑的用眼疲劳! 色调:85,饱和度:123,亮度:205;RGB颜色红:199,绿:237,蓝:204; 十六进制颜色…

3步阐述搜索框做了什么事情

搜索功能是几乎每个产品的通用标配功能,一个看似简单的搜索框背后,其实隐含了大量的设计思考和技术壁垒。本文将从三个部分阐述,为何搜索框并不简单。 本文将从搜索场景的思考、基于步骤的搜索设计以及搜索数据的追踪3个部分,对产…

今日arXiv最热大模型论文:北京大学最新综述:视觉大模型中的漏洞与攻防对抗

近年来,视觉语言大模型(LVLM)在文本转图像、视觉问答等任务中大放异彩,背后离不开海量数据、强大算力和复杂参数的支撑。 但是!大模型看似庞大的身躯背后却有一颗脆弱的“心脏”,极易受到攻击。攻击者可以…

史上最全,网工必考证书大盘点,竟然有20多个?

最近很多朋友来咨询,作为网工能考什么证书?证书那么多要怎么选择?哪个性价比高、哪个回报大等等等等的问题。 不难看出,大家最近这个想要学习和提升的势头很猛,毕竟现在这个环境下,属实是不好过了&#xff…

FPGA开发——数码管的使用(二)

一、概述 在上一篇文章中我们针对单个数码管的静态显示和动态显示进行了一个设计和实现,这篇文章中我们针对多个数码管同时显示进行一个设计。这里和上一篇文章唯一不同的是就是数码管位选进行了一个改变,原来是单个数码管的显示,所以位选就直…

Android Studio运行报错:module java.base dose not “opens java.io“ to unnamed module

今天第一次使用Android Studio运行一个安卓工程,报如图错误,应该是环境问题。 解决: 右上角的设置图标->settings->Buid,Execution,Deployment->Build Tools->Gradle->Gradle JDK->选择本地环境的java_home jdk(怎么安装…

docker镜像不可用

现在阿里、163等docker镜像基本不能使用,不能pull镜像了。 1.腾讯云内部 腾讯云服务器内部可用镜像(当然,需要先有一个腾讯云服务器):https://mirror.ccs.tencentyun.com 配置方法,vi /etc/docker/daemon…

C++—— IO流

一、C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf()和printf()。 scanf():从标准输入设备(键盘)中读取数据,并将值存放在变量中。 printf():将指定的文字/字符串输出到标准输出设备(…

Python 聊天机器人项目-8-学习使用 NLTK 和 Keras 构建您的第一个聊天机器人

一、前言 该文章仅作为个人学习使用 二、正文 项目源代码:Python 聊天机器人项目 - 学习使用 NLTK 和 Keras 构建您的第一个聊天机器人 - DataFlair (data-flair.training) 数据集:https://data-flair.training/blogs/download-python-chatbot-data-…

Web3时代:科技与物联网的完美结合

随着信息技术的不断进步和物联网应用的普及,Web3技术作为下一代互联网的重要组成部分,正逐渐与物联网技术深度融合,共同开创了新的科技时代。本文将深入探讨Web3技术与物联网的结合,探索它们如何共同推动未来科技发展的新趋势和应…

【32单片机篇】项目:智能排队控制系统

一、项目需求 1. 红外传感器检测有人通过并计数; 2. 计数值显示在LCD1602; 3. 允许通过时,LED1闪烁,蜂鸣器不响,继电器不闭合; 4. 不允许通过时,LED2闪烁,蜂鸣器响,继电…

工信部:2024上半年我国信息安全领域收入909亿元

2024年上半年软件业经济运行情况 上半年,我国软件和信息技术服务业(以下简称“软件业”)运行态势良好,软件业务收入和利润均保持两位数增长,软件业务出口收入增速由负转正,主要大省持续向好发展。 一、总…

光纤基础科普

这部分主要介绍光纤的常见接口(四种)、光纤传输的种类、光模块的封装类型。 文章目录 一、光纤的常见接口二、光模块封装三、光纤传输种类 一、光纤的常见接口 光纤接口种类繁多,这里给出常用的四种 (1)SC 型光纤接…

C++静态成员变量和静态成员函数

演示代码如下&#xff1a; #include<iostream> using namespace std;class Person { public://静态成员函数 所有对象共享一个函数&#xff0c;且只能调用静态成员变量 ******static void func(){m_A 300;cout << "静态成员函数调用" << endl;}/…