cv2 interpolate插值-align_corners

cv2 interpolate插值-align_cornerstorchinterpo nn functional interpolate input size None scale factor None mode nearest align corners None recompute scale factor None input Tensor 输入数据 size intorTuple int orTuple int int orTuple int int int 输出数据的尺寸

torch interpolate

 torch.nn.functional.interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None, recompute_scale_factor=None) 
  • input (Tensor):输入数据
  • size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int]):输出数据的尺寸
  • scale_factor (float or Tuple[float]):缩放因子
  • mode (str):采样算法
  • align_corners (bool, optional):几何上,我们认为输入和输出的像素是正方形,而不是点。如果设置为True,则输入和输出张量由其角像素的中心点对齐,从而保留角像素处的值。如果设置为False,则输入和输出张量由它们的角像素的角点对齐,插值使用边界外值的边值填充;当scale_factor保持不变时,使该操作独立于输入大小。仅当使用的算法为’linear’, ‘bilinear’, ‘bilinear’or ‘trilinear’时可以使用。默认设置为False

角像素:缩放后四个角的像素值

注意:

  1. scale_factor与size只能设置一个。
  2. 当设置scale_factor时,会对输出size下取整,比如输入[2, 2], scale_factor=2.1, 则输出size为[4.2, 4.2] = [4, 4]。
  3. 当设置scale_factor时,再设置recompute_scale_factor时,会根据输出的实际大小重新计算一下scale_factor。
  4. 用scale_factor不用size是因为scale_factor可以不写死大小,而size会固定输出大小,在处理多分辨率输入图像的时候会有问题。
input:输入Tensor。 size:插值后输出Tensor的空间维度的大小,这个spatial size就是去掉Batch,Channel,Depth维度后剩下的值。比如NCHW的spatial size是HW。 scale_factor(float 或者 Tuple[float]):spatial size的乘数,如果是tuple则必须匹配输入数据的大小。 mode(str):上采样的模式,包含'nearest' | 'linear' | 'bilinear' | 'bicubic' | 'trilinear' | 'area'。 默认是 'nearest'。 align_corners(bool):在几何上,我们将输入和输出的像素视为正方形而不是点。 如果设置为True,则输入和输出张量按其角像素的中心点对齐,保留角像素处的值。 如果设置为False,则输入和输出张量按其角像素的角点对齐,插值使用边缘值填充来处理边界外值,当scale_factor保持不变时,此操作与输入大小无关。 这仅在mode为 'linear' | 'bilinear' | 'bicubic' | 'trilinear'时有效。默认值是False。 recompute_scale_factor(bool):重新计算用于插值计算的 scale_factor。 当 scale_factor 作为参数传递时,它用于计算 output_size。 如果 recompute_scale_factor 为 False 或未指定,则传入的 scale_factor 将用于插值计算。 否则,将根据用于插值计算的输出和输入大小计算新的 scale_factor(即,等价于显示传入output_size)。 请注意,当 scale_factor 是浮点数时,由于舍入和精度问题,重新计算的 scale_factor 可能与传入的不同。

ops_version对导出onnx影响:

op9, op10是Unsample,而op11变成了Resize。

cv2 interpolate插值-align_corners

不同的ops_version对interpolate的支持程度:

F.interpolate nearest bilinear, align_corners=False bilinear, align_corners=True bicubic
op-9 Y Y N N
op-10 Y Y N N
op-11 Y Y Y Y

align_corner的表现行为:

cv2 interpolate插值-align_corners

align_corner

如果设置为True,则输入和输出张量由其角像素的中心点对齐,从而保留角像素处的值。如果设置为False,则输入和输出张量由它们的角像素的角点对齐,插值使用边界外值的边值填充

  • 当align_corners = True时,像素被视为网格的格子上的点,拐角处的像素对齐.可知是点之间是等间距
  • 当align_corners = False时, 像素被视为网格的交叉线上的点, 拐角处的点依然是原图像的拐角像素,但是差值的点间却按照上图的取法取,导致点与点之间是不等距

cv2 interpolate插值-align_cornersopencv, PIL的align_corner为False, mxnet为True,而torch和tensorflow可以设置。


 首先介绍 align_corners=False,它是 pytorch 中 interpolate 的默认选项。这种设定下,我们认定像素值位于像素块的中心,如下图所示:(3*3)

cv2 interpolate插值-align_corners

 对它上采样两倍后,得到下图:(6*6)

cv2 interpolate插值-align_corners

首先观察绿色框内的像素,我们会发现它们严格遵守了 bilinear 的定义。而对于角上的四个点,其像素值保持了原图的值。边上的点(超出边界的点)则根据角点的值填充。所以,我们从全局来看,内部和边缘处采用了比较不同的规则。 

# align_corners = False # x_ori is the coordinate in original image # x_up is the coordinate in the upsampled image x_ori = (x_up + 0.5) / factor - 0.5

 接下来,我们看看 align_corners=True 情况下,用同样画法对上采样的可视化:(5*5)

cv2 interpolate插值-align_corners

这里像素之间毫无对齐的美感,强迫症看到要爆炸。事实上,在 align_corners=True 的世界观下,上图的画法是错误的。在其世界观里,像素值位于网格上,如下图所示: 

cv2 interpolate插值-align_corners

那么,把它上采样两倍后,我们会得到如下的结果:

cv2 interpolate插值-align_corners


1、align_corners 参数的实验(1*1-1*4)

import torch import torch.nn as nn import torch.nn.functional as F s= [4.] # 由于函数需要浮点数,所以需要加点 s = torch.tensor(s).reshape(1, 1, 1, 1) # 自定义s的通道数和尺寸大小 print(s) # tensor([[[[4.]]]]) x = F.interpolate(s, size=(1,4), mode='bilinear', align_corners=False) print(x) # tensor([[[[4., 4., 4., 4.]]]]) x = F.interpolate(s, size=(32,32), mode='bilinear', align_corners=False) print(x) #tensor([[[[4., 4., 4., ..., 4., 4., 4.], # [4., 4., 4., ..., 4., 4., 4.], # [4., 4., 4., ..., 4., 4., 4.], # ..., # [4., 4., 4., ..., 4., 4., 4.], # [4., 4., 4., ..., 4., 4., 4.], # [4., 4., 4., ..., 4., 4., 4.]]]])

2、align_corners 参数的实验(2*2-4*4)

import torch import torch.nn as nn import torch.nn.functional as F a = [[1., 2.], [4., 5.]] a = torch.tensor(a).reshape(1, 1, 2, 2) x = F.interpolate(a, scale_factor=2, mode='bilinear', align_corners=True) print(x) #tensor([[[[1.0000, 1.3333, 1.6667, 2.0000], # [2.0000, 2.3333, 2.6667, 3.0000], # [3.0000, 3.3333, 3.6667, 4.0000], # [4.0000, 4.3333, 4.6667, 5.0000]]]]) # 等距 # 像素被视为网格的格子上的点,拐角处的像素对齐.可知是点之间是等间距的 y = F.interpolate(a, scale_factor=2, mode='bilinear', align_corners=False) print(y) #tensor([[[[1.0000, 1.2500, 1.7500, 2.0000], # [1.7500, 2.0000, 2.5000, 2.7500], # [3.2500, 3.5000, 4.0000, 4.2500], # [4.0000, 4.2500, 4.7500, 5.0000]]]]) # 不等距 #

3、align_corners 参数的实验(3*3-6*6) 

import torch import torch.nn as nn import torch.nn.functional as F a = [[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]] a = torch.tensor(a).reshape(1, 1, 3, 3) print(a) #tensor([[[[1., 2., 3.], # [4., 5., 6.], # [7., 8., 9.]]]]) #*等价的写法# r = torch.arange(1,10,dtype=torch.float32).view(1,1,3,3) r #tensor([[[[1., 2., 3.], # [4., 5., 6.], # [7., 8., 9.]]]]) #*# x = F.interpolate(a, scale_factor=2, mode='bilinear', align_corners=True) print(x) #tensor([[[[1.0000, 1.4000, 1.8000, 2.2000, 2.6000, 3.0000], # [2.2000, 2.6000, 3.0000, 3.4000, 3.8000, 4.2000], # [3.4000, 3.8000, 4.2000, 4.6000, 5.0000, 5.4000], # [4.6000, 5.0000, 5.4000, 5.8000, 6.2000, 6.6000], # [5.8000, 6.2000, 6.6000, 7.0000, 7.4000, 7.8000], # [7.0000, 7.4000, 7.8000, 8.2000, 8.6000, 9.0000]]]]) # 等距 y = F.interpolate(a, scale_factor=2, mode='bilinear', align_corners=False) print(y) #tensor([[[[1.0000, 1.2500, 1.7500, 2.2500, 2.7500, 3.0000], # [1.7500, 2.0000, 2.5000, 3.0000, 3.5000, 3.7500], # [3.2500, 3.5000, 4.0000, 4.5000, 5.0000, 5.2500], # [4.7500, 5.0000, 5.5000, 6.0000, 6.5000, 6.7500], # [6.2500, 6.5000, 7.0000, 7.5000, 8.0000, 8.2500], # [7.0000, 7.2500, 7.7500, 8.2500, 8.7500, 9.0000]]]]) # 不等距

cv2 interpolate插值-align_corners


 补充说明:

由于图像双线性插值只会用相邻的4个点,因此上述公式双线性插值的分母都是1。opencv中的源码如下,用了一些优化手段,比如用整数计算代替float(下面代码中的*2048就是变11位小数为整数,最后有两个连乘,因此>>22位),以及源图像和目标图像几何中心的对齐
– SrcX=(dstX+0.5)* (srcWidth/dstWidth) -0.5
– SrcY=(dstY+0.5) * (srcHeight/dstHeight)-0.5


这个要重点说一下,源图像和目标图像的原点(0,0)均选择左上角,然后根据插值公式计算目标图像每点像素,假设你需要将一幅5×5的图像缩小成3×3,那么源图像和目标图像各个像素之间的对应关系如下。如果没有这个中心对齐,根据基本公式去算,就会得到左边这样的结果;而用了对齐,就会得到右边的结果:




cv2 interpolate插值-align_corners

 原本的插值公式:

(原本的)srcX=dstX*(srcW/dstW)  eg:srcX=0(5/3)=0 

(中心对齐)srcX=(0+0.5)/(5/3)-0.5=1/3


中心点对齐的缩放在卷积网络结构设计中的注意事项

  • OpenCV缩放图片是基于中心点对齐的,
  • Pytorch中 mode=‘bilinear’, align_corners=False 与OpenCV中的保持一致,
  • Pytorch中 mode=‘bilinear’, align_corners=True 与TensorFlow中的align_corners=True的条件下保持一致。

tensorFlow的resize_bilinear并未中心对齐,坐标计算方式为

align_corners=False:

align_corners=True:

参考博客:

一文看懂align_corners – 知乎

cv2.reisze, interpolate采样比较 – bairuiworld – 博客园

【上采样问题】双线性插值的几何中心点重合与align_corners_Hali_Botebie的博客-CSDN博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212237.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午8:30
下一篇 2026年3月18日 下午8:30


相关推荐

  • Unity键盘钩子[通俗易懂]

    Unity键盘钩子[通俗易懂]http://blog.csdn.net/qq452626100/article/details/52398830privatestaticintKeyboardHookProc(intnCode,Int32wParam,IntPtrlParam){ if(nCode==HC_ACTION ) { varkc=(KeyCode)(wParam+97-65)

    2022年5月28日
    52
  • 关于constexpr

    关于constexprconstexpr 关键字让用户显式的声明函数或对象构造函数在编译期会成为常数 可以用于数组的定义 constexprint nbsp nbsp return10 intmain nbsp nbsp nbsp nbsp inta func nbsp nbsp nbsp nbsp return0

    2026年3月17日
    2
  • 深度学习图像标注工具汇总

    深度学习图像标注工具汇总对于监督学习算法而言,数据决定了任务的上限,而算法只是在不断逼近这个上限。世界上最遥远的距离就是我们用同一个模型,但是却有不同的任务。

    2022年6月1日
    42
  • 2批处理for循环中截取字符串_批处理for循环嵌套

    2批处理for循环中截取字符串_批处理for循环嵌套一、参数/dfor/d%%变量in(集)do命令/d参数是指定仅对目录而不是文件执行的for命令。例1:在命令行输入(不是在批处理,之后不再解释)for/d%ain(c:\*.*)doecho%a运行会把C盘根目录下的全部目录分次显示出来,而不显示文件名看起来有点乱,如果把命令提示回显关闭就清晰了:for/d%ain(c:\*….

    2022年10月12日
    4
  • android原生系统怎么下载地址,安卓全机型原生官方ROM下载地址

    android原生系统怎么下载地址,安卓全机型原生官方ROM下载地址还是如题,都是安卓原生原官方下载地址,其实很多都可以百度搜的,然而你们就喜欢用别人转的,里面要是加点佐料很高兴?我这都是官方地址,不自己转,只给地址,自己下去,有些访问比较慢,下载速度有些也慢,因为大部分是国外地址,但是关键是干净纯洁啊!每个ROM支持的机型都不同,自己找把,Z2在这些ROM里都是叫ZUKZ2plus,或者是lenovoZ2plus,或者Z2plus,别跟PRO搞混,不能混刷,…

    2022年6月19日
    47
  • 【转载】VS工具使用——代码生成函数关系图

    【转载】VS工具使用——代码生成函数关系图

    2021年11月18日
    94

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号