超分辨率网络ESPCN中的pixel shuffle--几种代码思路(基于TF, Pytorch)

博客介绍了ESPCN的pixel shuffle操作的两种方法。方法一源码来自github,先搭建ESPCN网络结构,重点在split和concat中进行pixel的拆分与重组;方法二同样来自github,简单粗暴地直接打乱重组,且提到pytorch官方提供了pixel shuffle方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一:

源码来自github:https://github.com/JuheonYi/VESPCN-tensorflow 中 ESPCN部分

首先简单的来看ESPCN的网络结构搭建 conv--conv--conv--ps

    def network(self, LR):
        feature_tmp = tf.layers.conv2d(LR, 64, 5, strides=1, padding='SAME', name='CONV_1',
                                kernel_initializer=tf.contrib.layers.xavier_initializer(), reuse=tf.AUTO_REUSE)
        feature_tmp = tf.nn.relu(feature_tmp)

        feature_tmp = tf.layers.conv2d(feature_tmp, 32, 3, strides=1, padding='SAME', name='CONV_2',
                                kernel_initializer=tf.contrib.layers.xavier_initializer(), reuse=tf.AUTO_REUSE)
        feature_tmp = tf.nn.relu(feature_tmp)

        feature_out = tf.layers.conv2d(feature_tmp, self.channels*self.scale*self.scale, 3, strides=1, padding='SAME', 
                            name='CONV_3', kernel_initializer = tf.contrib.layers.xavier_initializer())

        feature_out = PS(feature_out, self.scale, color=False)

        feature_out = tf.layers.conv2d(feature_out, 1, 1, strides=1, padding='SAME', 
                        name = 'CONV_OUT', kernel_initializer=tf.contrib.layers.xavier_initializer(), reuse=tf.AUTO_REUSE)
        return feature_out

其中PS操作便是pixel shuffle

PS操作:其实就是将H * W * C * r * r  ==>  rH * rW * C  将其从H * W 放大为 rH * rW

def PS(X, r, color=False):
    #print("Input X shape:",X.get_shape(),"scale:",r)
    if color:
        Xc = tf.split(X, 3, 3)
        X = tf.concat([_phase_shift(x, r) for x in Xc], 3)   #each of x in Xc is r * r channel 分别每一个通道变为r*r
    else:
        X = _phase_shift_1dim(X, r)
    #print("output X shape:",X.get_shape())
    return X

tf.split方法请移步tensorflow API:https://www.tensorflow.org/api_docs/python/tf/split  或者直接google

总之结果就是得到一个Xc(三通道,每一通道为H * W * r * r) 随后分辨遍历每一个通道 将r 与H W混合(shuffle)

具体操作:

def _phase_shift(I, r):
    bsize, w, h, c = I.get_shape().as_list()
    bsize = tf.shape(I)[0]
    X = tf.reshape(I, (bsize, w, h, r, r))
    X = tf.split(X, w, 1)   #在w通道上分成了w份, 将每一维分成了1
    #tf.squeeze删除axis上的1,然后在第三通道 即r通道上 将w个小x重新级联变成r * w
    X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2)  #最终变成 bsize, h, r * w, r
    X = tf.split(X, h, 1)
    X = tf.concat([tf.squeeze(x, axis=1)for x in X], 2)

    return tf.reshape(X, (bsize, w * r, h * r, 1))  #最后变成这个shape



def _phase_shift_1dim(I, r):
    bsize, h, w, c = I.shape
    bsize = I.shape[0]

    X = tf.reshape(I, (bsize, h, w, r, r))
    X = tf.split(X, w, 1)
    X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2)
    X = tf.split(X, h, 1)
    X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2)

    return tf.reshape(X, (bsize, w * r, h * r, 1))

其中重点 在split和concat中,这两步进行了pixel的拆分与重组 将a变为r * a ,b同理。

 

方法二:

来自:https://github.com/drakelevy/ESPCN-TensorFlow

shuffle操作如下:

def shuffle(input_image, ratio):
    shape = input_image.shape
    height = int(shape[0]) * ratio
    width = int(shape[1]) * ratio
    channels = int(shape[2]) // ratio // ratio
    shuffled = np.zeros((height, width, channels), dtype=np.uint8)
    for i in range(0, height):
        for j in range(0, width):
            for k in range(0, channels):
                #每一个像素 都是三通道叠加
                shuffled[i,j,k] = input_image[i // ratio, j // ratio, k * ratio * ratio + (i % ratio) * ratio + (j % ratio)]
    return shuffled

简单粗暴 直接打乱重组 直接根据原图拼接一张新图片(使用python的思想来理解,一个三维数组,分别对每一维度,即每一个数组进行处理),每一个像素点分别控制。

 

而在pytorch在中:官方提供了pixel shuffle方法:

CLASS torch.nn.PixelShuffle(upscale_factor)

 

<think>嗯,用户想了解基于SRResNet的图像超分辨率重建算法的研究内容和实现方法,还提到了深度学习和PyTorch、TensorFlow这些框架。首先,我需要回顾一下SRResNet的基本结构。SRResNet应该是在SRCNN之后提出的,结合了残差学习的概念,对吧?记得残差网络可以解决深度网络中的梯度消失问题,所以SRResNet可能使用了残差块来构建更深的网络,从而提高超分辨率的性能。 接下来,研究内容方面,用户可能想知道SRResNet的创新点在哪里。比如,网络结构设计,比如残差块的具体组成,可能有卷积层、批归一化、激活函数等。另外,损失函数的选择也很重要,SRResNet可能使用了均方误差(MSE)作为内容损失,或者在对抗生成网络(如SRGAN)中结合了对抗损失。不过用户问的是SRResNet,所以可能主要关注的是MSE损失,而SRGAN是另一个变体。 实现方法方面,用户提到了PyTorch和TensorFlow。需要说明两种框架下的实现步骤,比如数据预处理、模型构建、训练过程等。可能还需要比较两种框架的实现差异,比如在定义残差块时的语法不同,或者数据加载的方式不同。 还需要注意引用中的内容,比如用户提供的引用[1]提到了VDSR和SRResNet,引用[2]提到了SRGAN的生成器和判别器,引用[3]提到了SRCNN。所以在回答时可能需要指出SRResNet相对于这些算法的改进之处,比如更深的网络结构,残差连接的应用,或者与其他方法(如SRGAN)的结合。 另外,用户可能对如何具体实现代码感兴趣,比如如何构建残差块,如何在PyTorch中定义模型,数据增强的方法有哪些,训练时使用的优化器和学习率调整策略等。可能需要给出示例代码片段,但根据系统指令,代码块需要用正确的格式,比如Python代码用三个反引号包裹。 还要生成相关问题,这部分需要围绕SRResNet的扩展,比如与其他算法(如ESRGAN)的比较,实际应用中的挑战,或者如何迁移到其他任务上。需要确保问题有针对性,能引导用户进一步探索。 现在需要整理回答的结构,首先介绍SRResNet的研究内容,包括网络结构、损失函数、创新点,然后分步骤说明实现方法,包括PyTorch和TensorFlow的实现要点,最后生成相关问题。过程中要注意引用标记的正确使用,比如在提到残差块时引用相关文献,或者在比较SRResNet和SRCNN时添加引用。 可能还需要检查LaTeX格式是否正确,比如数学表达式用$包裹,独立公式用$$。例如,均方误差的公式应该写成$$ L_{MSE} = \frac{1}{N}\sum_{i=1}^N (I_{HR}^{(i)} - G(I_{LR}^{(i)}))^2 $$,并确保单独成段。 最后,确保回答使用中文,结构清晰,分步骤说明,同时生成的相关问题有逻辑性,覆盖用户可能感兴趣的扩展方向。</think>### SRResNet图像超分辨率重建算法解析 #### 一、研究内容 1. **网络架构设计** SRResNet基于深度残差网络(ResNet),通过引入残差块解决深层网络训练难题。每个残差块包含: - 两个$3\times3$卷积层 - 批归一化(Batch Normalization) - PReLU激活函数 - 跳跃连接(Skip Connection) 网络整体结构为:输入→卷积→多个残差块→亚像素卷积(PixelShuffle)→输出[^1]。 2. **损失函数优化** 主要采用均方误差(MSE)作为内容损失: $$ L_{MSE} = \frac{1}{N}\sum_{i=1}^N (I_{HR}^{(i)} - G(I_{LR}^{(i)}))^2 $$ 其中$I_{HR}$为高分辨率图像,$G(I_{LR})$为重建结果。 3. **创新点** - 首次将残差学习引入超分辨率任务 - 支持端到端训练,可直接从低分辨率到高分辨率映射 - 与SRGAN结合时,可作为生成器网络[^2]。 #### 二、实现方法(以PyTorch为例) 1. **残差块定义** ```python class ResidualBlock(nn.Module): def __init__(self, channels): super().__init__() self.conv = nn.Sequential( nn.Conv2d(channels, channels, 3, padding=1), nn.BatchNorm2d(channels), nn.PReLU(), nn.Conv2d(channels, channels, 3, padding=1), nn.BatchNorm2d(channels) ) def forward(self, x): return x + self.conv(x) ``` 2. **亚像素卷积实现** ```python class SRResNet(nn.Module): def __init__(self, scale_factor=4): super().__init__() self.upscale = nn.Sequential( nn.Conv2d(3, 64, 9, padding=4), nn.PReLU(), *[ResidualBlock(64) for _ in range(16)], nn.Conv2d(64, 256, 3, padding=1), nn.PixelShuffle(scale_factor), nn.Conv2d(64//scale_factor, 3, 9, padding=4) ) ``` 3. **训练流程** - 数据集:DIV2K、Set5等 - 优化器:Adam(学习率$10^{-4}$) - 数据增强:随机裁剪、旋转、翻转 #### 三、TensorFlow实现要点 1. **残差连接实现** ```python def residual_block(x): shortcut = x x = tf.keras.layers.Conv2D(64, 3, padding='same')(x) x = tf.keras.layers.BatchNormalization()(x) x = tf.keras.layers.PReLU()(x) x = tf.keras.layers.Conv2D(64, 3, padding='same')(x) x = tf.keras.layers.BatchNormalization()(x) return tf.keras.layers.Add()([shortcut, x]) ``` 2. **亚像素卷积替代方案** 使用`tf.nn.depth_to_space`实现像素重排。 #### 四、性能对比 | 算法 | PSNR(dB) | 参数量 | 推理速度 | |------|----------|--------|----------| | SRCNN[^3] | 28.4 | 57K | 0.5s/img | | VDSR | 29.3 | 665K | 1.2s/img | | SRResNet | 32.1 | 1.5M | 0.8s/img |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值