本文介绍了深度学习分割任务中Decoder阶段的多种上采样方法。包括规则上采样的Upsample(如双线性插值)、通过周期筛选实现的PixelShuffle、基于最大值位置还原的MaxUnPool2D、需学习参数的Conv2DTranspose(反卷积),以及不规则上采样的grid_sample,并结合示例展示了各方法的效果与特点。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜
在做分割的时候,我们经常会遇到Decoder时对特征进行上采样,比较常见的就是下面这个:
x = F.interpolate(x, scale_factor=2., mode="bilinear")
但除了这个上采样的方法外,还有许多的方法都可以将当前Tensor的大小由[H, W]变为[H*r, W*r]。说不定把这些上采样方法换来换去能找到一个对当前的任务有着更好的效果的上采样方法。
下面我们对一些(了解有限,只知道这么多)常用的上采样方法进行一些介绍。
这里主要是导入一些库以及写几个ndarray和tensor转换的函数,方便显示。
示例图像方面准备了一张李化元(希望下集别刀了)大头照,其他的通道数很多的特征也差不多。
In [21]import cv2import numpy as npimport paddleimport paddle.nn as nnimport paddle.nn.functional as Fimport matplotlib.pyplot as plt
%matplotlib inlinedef to_tensor(image):
# H, W, C -> 1, C, H, W
# uint8 -> float32
# ndarray -> tensor
return paddle.to_tensor(image.transpose((2, 0, 1))[None], dtype="float32")def to_ndarray(tensor):
# 1, C, H, W -> H, W, C
# float32 -> uint8
# tensor -> ndarray
return tensor.squeeze().numpy().transpose((1, 2, 0)).astype("uint8")def show(im1, im2, im3=None):
plt.figure(figsize=(15, 5))
plt.subplot(131);plt.imshow(im1);plt.title("raw image") # 原图
plt.subplot(132);plt.imshow(im2);plt.title("down image") # 下采样后的图
if im3 is not None:
plt.subplot(133);plt.imshow(im3);plt.title("up image") # 上采样后的结果
plt.show()
In [22]
img_path = "lhy.jpg"img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB) # 图像准备
该OP用于调整一个batch中图片的大小。
输入为3-D Tensor时形状为(num_batches, channels
, in_w),输入为4-D Tensor时形状为(num_batches, channels, in_h, in_w)或者(num_batches, in_h, in_w, channels),输入为5-D Tensor时形状为(num_batches, channels, in_d, in_h, in_w)或者(num_batches, in_d, in_h, in_w, channels),并且调整大小只适用于深度,高度和宽度对应的维度。
这个算子和前面说到的F.interpolate差不多,是一个规则上采样的方法,有最近邻法、双线性插值、双三次插值等。
以双线性插值为例,如下图所示,根据离待插值最近的个已知值来计算待插值,每个已知值的权重由距离待插值距离决定,距离越近权重越大。其中P就可以由R1和R2插值而来,而R1和R2分别由Q11/Q21和Q12/Q22插值得到。
图源:https://www.cnblogs.com/yssongest/p/5303151.html
下图看起来的效果不错,将一些锯齿都变得比较平滑了。
In [23]upnet = nn.Upsample(scale_factor=2., mode="BILINEAR") # 放大2倍,以双线性插值的方式进行half_img = cv2.resize(img, None, None, 0.5, 0.5, cv2.INTER_LINEAR) upsample_pred = upnet(to_tensor(half_img)) show(img, half_img, to_ndarray(upsample_pred))
该算子将一个形为[N, C, H, W]或是[N, H, W, C]的Tensor重新排列成形为 [N, C/r**2, H*r, W*r]或 [N, H*r, W*r, C/r**2] 的Tensor。这样做有利于实现步长(stride)为1/r的高效sub-pixel(亚像素)卷积。详见Shi等人在2016年发表的论文 Real Time Single Image and Video Super Resolution Using an Efficient Sub Pixel Convolutional Neural Network 。
PixelShuffle常用在超分之中,经过PixelShuffle上采样会减少通道层的数目。通过卷积先得到 r^2 个通道的特征图(特征图大小和输入低分辨率图像一致),然后通过周期筛选(periodic shuffing)的方法得到这个高分辨率的图像,其中rrr为上采样因子(upscaling factor),也就是图像的扩大倍率。根据下图中后面两个图,比较容易理解PixelShuffle是怎么做的。使用中也常常按照这个流程,先训练得到更多的特征图,再使用PixelShuffle上采样,这样就能保证通道数不变,并放大了图像长宽。
图源:https://www.jianshu.com/p/71d6a9374899
这里由于原图是3通道,长宽各扩大2倍则需要通道数为原来的1/4,因此在这里演示的时候为了显示,在使用PixelShuffle的时候将图像复制了4份叠在一起,组成了12通道的图像,然后在PixelShuffle后变为3通道。
In [28]upnet = nn.PixelShuffle(upscale_factor=2) # 放大2倍,通道数变为1/4half_img = cv2.resize(img, None, None, 0.5, 0.5, cv2.INTER_LINEAR) half_img = np.concatenate([half_img] * 4, axis=-1) # C: 3 -> 12pixelshuffle_pred = upnet(to_tensor(half_img)) show(img, half_img[:, :, :3], to_ndarray(pixelshuffle_pred))
该接口用于构建 MaxUnPool2D 类的一个可调用对象,根据输入的input和最大值位置计算出池化的逆结果。所有非最大值设置为零。
MaxPool和AvgPool分别是对图像进行最大池化和平均池化,而对应的反池化就可以将结果还原到原来的大小。由于AvgPool是一个取平均的操作,反池化直接复制出多份平均值即可,因此没有专门的AvgUnPool函数,直接用Upsample即可。而MaxUnPool需要将最大值还原到对应的位置,因此MaxPool可以设置保存最大值索引的位置,MaxUnPool则需要根据这个位置将最大值还原到原来的位置,并在其他位置补充零。如下图所示:
图源:https://blog.csdn.net/quiet_girl/article/details/84579038
下图中看起来有一些不同的、单独的颜色块,是因为三个通道中的最大值索引是有区别的,因此还原回去也不都是同一个位置。
In [52]upnet = nn.MaxUnPool2D(2, 2) half_img, indices = F.max_pool2d(to_tensor(img), 2, 2, return_mask=True) # 需要返回索引maxunpool_pred = upnet(half_img, indices) # 根据索引找到原始位置show(img, to_ndarray(half_img), to_ndarray(maxunpool_pred))
二维转置卷积层(Convlution2d transpose layer)
该层根据输入(input)、卷积核(kernel)和空洞大小(dilations)、步长(stride)、填充(padding)来计算输出特征层大小或者通过output_size指定输出特征层大小。输入(Input)和输出(Output)为NCHW或NHWC格式,其中N为批尺寸,C为通道数(channel),H为特征层高度,W为特征层宽度。卷积核是MCHW格式,M是输出图像通道数,C是输入图像通道数,H是卷积核高度,W是卷积核宽度。如果组数大于1,C等于输入图像通道数除以组数的结果。转置卷积的计算过程相当于卷积的反向计算。转置卷积又被称为反卷积(但其实并不是真正的反卷积)。欲了解转置卷积层细节,请参考下面的说明和参考文献。如果参数bias_attr不为False, 转置卷积计算会添加偏置项。
不同于上面的上采样操作(如果PixelShuffle没算上前面的卷积步骤),反卷积是一种需要学习的上采样方法,其示意图如下所示。因此反卷积会带来额外的参数,但如果学习的不错,可能会对后续的任务的效果好于不用学习的方法。当然这就见仁见智了。
图源:https://blog.csdn.net/quiet_girl/article/details/84579038
下面为了演示简单训练了100次反卷积的卷积核,当然,直接两个RGB图像的mse_loss和这样搞起来实在是有点坑,效果也不多说,只是表明ConvTranspose是可以训练的。这里的简单训练至少让它看起来像个人了。不过大家也都提到了(也可以看到)反卷积后棋盘格效应 (checkerboard pattern) 出现。
In [49]upnet = nn.Conv2DTranspose(3, 3, 4, 2, 1)
half_img = cv2.resize(img, None, None, 0.5, 0.5, cv2.INTER_LINEAR)
upnet.train() # 训练模式opt = paddle.optimizer.AdamW(0.001, parameters=upnet.parameters())for _ in range(100): # 跑100次
upsample_pred = upnet(to_tensor(half_img))
loss = F.mse_loss(upsample_pred, to_tensor(img))
loss.backward()
opt.step()
upnet.eval() # 评估模式convtranspose_pred = upnet(to_tensor(half_img))
show(img, half_img, to_ndarray(convtranspose_pred))
该OP基于flow field网格的对输入X进行双线性插值采样。网格通常由affine_grid生成, shape为[N, H, W, 2],是shape为[N, H, W]的采样点张量的(x, y)坐标。 其中,x坐标是对输入数据X的第四个维度(宽度维度)的索引,y坐标是第三维度(高维度)的索引,最终输出采样值为采样点的4个最接近的角点的双线性插值结果,输出张量的shape为[N, C, H, W]。
不同于Upsample的规则上采样,grid_sample是一种不规则的上采样,它会依照一个flow-field网格(比如光流,体素流等),根据这个网格中每个位置提供的坐标信息(这里指input中pixel的坐标),将input中对应位置的像素值填充到grid指定的位置,得到最终的输出。在一些有guide结构的网络中,会通过计算边缘流、光流等等,然后使用grid_sample将其他特征按照该网格进行非规则的上采样。grid_sample的示意如下图所示:
图源:https://blog.csdn.net/qq_34914551/article/details/107559031
下面的结果由于直接使用一个上下左右均为-1到1的grid会使得上采样的结果与规则上采样的结果相同,因此为其增加了一点位置的扰动,使得上采样后的结果不相同。
In [65]upnet = F.grid_sample# 创建一个水平和竖直方向都是-1到1的格网h, w = img.shape[:2] h_grid = paddle.linspace(-1.0, 1.0, h).reshape([-1, 1]).tile([w]) w_grid = paddle.linspace(-1.0, 1.0, w).reshape([-1, 1]).tile([h]).transpose((1, 0)) grid = paddle.concat([w_grid.unsqueeze(2), h_grid.unsqueeze(2)], axis=2)[None]# 故意对其进行随机扰动,注释这一行恢复的原图将同1grid += (paddle.randn((1, h, w, 2), dtype="float32") / 200) half_img = cv2.resize(img, None, None, 0.5, 0.5, cv2.INTER_LINEAR) gridsample_pred = upnet(to_tensor(half_img), grid) # 以grid来引导图像上采样show(img, half_img, to_ndarray(gridsample_pred))
# padding
# 则需
# 就可以
# 长宽
# 如下图
# 是一种
# 也不
# 是一个
# 都是
# 所示
# 插值
# https
# input
# qq
# 对象
# channel
# using
# 接口
# html
# batch
# igs
# red
# 排列
# 区别
# ai
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化91478 】
【
技术知识72672 】
【
云计算0 】
【
GEO优化84317 】
【
优选文章0 】
【
营销推广36048 】
【
网络运营41350 】
【
案例网站102563 】
【
AI智能45237 】
相关推荐:
AI在销售CRM软件中的角色:提升效率和客户互动
Jetson SegNet: 语义分割深度探索与实践
利用 Gemini 1.5 Pro 进行超长视频摘要提取
解读诗歌中的女性视角:Shelley Puhak 的作品解析
XRAI Glass:AI赋能的增强现实眼镜,对话新体验
AI虚拟网红打造指南:轻松制作专属社交媒体形象
AI电子书创作革命:AieBookSuite如何颠覆出版行业
经济型游戏PC构建指南:30000卢比畅玩3A游戏
如何用AI生成正则表达式?再也不怕复杂的文本匹配
面试必胜:五大面试技巧助你斩获Offer
掌握解方程技巧:4.2家庭作业难题精讲与分数系数处理
Descript音频编辑终极指南:技巧、AI工具与专业效果
AI Vibe Coding: 快速打造落地页,低代码平台实战教程
豆包AI怎样生成PPT目录页_豆包AI目录自动生成与页码添加【指南】
AI症状自检:最佳AI症状检查器,告别网络庸医!
lumen5怎样从新闻稿生成社交视频_Lumen5新闻稿转社交视频步骤【社媒】
通义千问怎样优化提示词更口语化_通义千问口语化技巧【教程】
AI女友:时尚穿搭与美丽瞬间的完美融合
DeepSeek分析Excel怎么用_DeepSeek分析Excel使用方法详细指南【教程】
如何用AI帮你创建自定义表情符号(Emoji)?聊天斗图更有趣
动漫肌肉美学:盘点最佳动漫肌肉男体格
百度AI助手网页版入口 免安装直接打开入口
Google AI 在教育领域个性化学习路径的构建
Tenorshare PDNob:免费AI图像翻译器,即时转换图像为文本
Kaiber AI视频制作教程:轻松打造吸睛AI视频
Google AI Studio Build模式更新:免费AI应用开发新纪元
Tamilnad Mercantile Bank TMB:如何在线下载账户报表
AI学习秘籍:3个高效黑科技,解锁智能学习新时代
WorkPPT:AI驱动的PPT制作神器,效率提升不止10倍!
ChatGPT官网免费使用入口 ChatGPT在线版官方地址
怎么用AI帮你进行头脑风暴并分类?5分钟输出结构化创意清单
百度搜索ai助手怎么关闭 百度搜索ai对话屏蔽方法
怎么用AI把你的想法变成一幅画?零绘画基础也能当艺术家
AI简历生成工具有哪些_一键生成专业简历的AI工具推荐
提升阅读理解:策略、技巧和有效方法全面指南
AI视频生成器:免费工具,图像转视频和文字转视频
现代集团CES 2026首秀机器人Atlas 发布AI机器人战略
千问怎样调整回答语气_千问语气设置亲切专业等【指南】
ChatGPT怎么写工作汇报 职场办公效率提升与周报生成方法
如何用 ChatGPT 批量处理 Excel 复杂公式
探索都市传说:追寻鳄鱼飞机怪物“Bombardino Crocodilo”
轻松创建引人入胜短视频:Riverside.fm教程
Straico团队案例研究:AI赋能,效率提升的秘诀
5分钟教你用AI生成婚礼流程策划案,备婚新人必备
如何用AI一键给视频自动加字幕
Claude怎么用新功能代码辅助_Claude代码辅助使用攻略【方法】
宠物翻译App评测:与猫狗交流的未来科技?
五大AI视频编辑工具:提升视频创作效率和质量
AI交易机器人:TradingView上无需代码即可构建AI交易机器人指南
LALAL.AI教程:音视频人声分离、降噪终极指南
2025-08-01
南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。