Python 将二维numpy数组重采样为任意尺寸

Python 将二维numpy数组重采样为任意尺寸,python,arrays,Python,Arrays,我正在寻找一种将numpy 2D数组重新缩放到任意维度的方法,以便重新缩放的数组中的每个单元格都包含它(部分)覆盖的所有单元格的加权平均值 如果新维度是原始维度的倍数,我发现了几种方法来实现这一点。例如,给定一个4x4数组,可以将其重新缩放为2x2数组,其中第一个单元格是原始数组中左上角4个单元格的平均值等。但这些方法似乎都不起作用,例如,当从4x4数组转换为3x3数组时 此图说明了在从4x4(黑色网格)到3x3(红色网格)的情况下,我想做什么: 较小数组中的单元格(0,0)覆盖整个单元格(0

我正在寻找一种将numpy 2D数组重新缩放到任意维度的方法,以便重新缩放的数组中的每个单元格都包含它(部分)覆盖的所有单元格的加权平均值

如果新维度是原始维度的倍数,我发现了几种方法来实现这一点。例如,给定一个4x4数组,可以将其重新缩放为2x2数组,其中第一个单元格是原始数组中左上角4个单元格的平均值等。但这些方法似乎都不起作用,例如,当从4x4数组转换为3x3数组时

此图说明了在从4x4(黑色网格)到3x3(红色网格)的情况下,我想做什么:

较小数组中的单元格(0,0)覆盖整个单元格(0,0)和部分单元格(1,0)、(0,1)和(1,1)。我希望新单元格包含这些单元格的平均值,这些单元格由黄色、绿色、蓝色和橙色区域的面积加权

有没有办法用numpy/scipy做到这一点?这种类型的重新填充是否有名称(在搜索方法时会有所帮助)

给你:#

它使用该软件包轻松计算不同网格单元的重叠,因此您需要获取这些重叠

from matplotlib import pyplot
import numpy
from interval import Interval, IntervalSet

def overlap(rect1, rect2):
  """Calculate the overlap between two rectangles"""
  xInterval = Interval(rect1[0][0], rect1[1][0]) & Interval(rect2[0][0], rect2[1][0])
  yInterval = Interval(rect1[0][1], rect1[1][1]) & Interval(rect2[0][1], rect2[1][1])
  area = (xInterval.upper_bound - xInterval.lower_bound) * (yInterval.upper_bound - yInterval.lower_bound)
  return area


def meanInterp(data, m, n):

  newData = numpy.zeros((m,n))
  mOrig, nOrig = data.shape

  hBoundariesOrig, vBoundariesOrig = numpy.linspace(0,1,mOrig+1), numpy.linspace(0,1,nOrig+1)
  hBoundaries, vBoundaries = numpy.linspace(0,1,m+1), numpy.linspace(0,1,n+1)

  for iOrig in range(mOrig):
    for jOrig in range(nOrig):
      for i in range(m):
        if hBoundaries[i+1] <= hBoundariesOrig[iOrig]: continue
        if hBoundaries[i] >= hBoundariesOrig[iOrig+1]: break
        for j in range(n):
          if vBoundaries[j+1] <= vBoundariesOrig[jOrig]: continue
          if vBoundaries[j] >= vBoundariesOrig[jOrig+1]: break

          boxCoords = ((hBoundaries[i], vBoundaries[j]),(hBoundaries[i+1], vBoundaries[j+1]))
          origBoxCoords = ((hBoundariesOrig[iOrig], vBoundariesOrig[jOrig]),(hBoundariesOrig[iOrig+1], vBoundariesOrig[jOrig+1]))

          newData[i][j] += overlap(boxCoords, origBoxCoords) * data[iOrig][jOrig] / (hBoundaries[1] * vBoundaries[1])

  return newData



fig = pyplot.figure()
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)

m1, n1 = 37,59
m2, n2 = 10,13

dataGrid1 = numpy.random.rand(m1, n1)
dataGrid2 = meanInterp(dataGrid1, m2, n2)

mat1 = ax1.matshow(dataGrid1, cmap="YlOrRd")
mat2 = ax2.matshow(dataGrid2, cmap="YlOrRd")

#make both plots square
ax1.set_aspect(float(n1)/float(m1))
ax2.set_aspect(float(n2)/float(m2))



pyplot.show()
从matplotlib导入pyplot
进口numpy
从间隔导入间隔、间隔集
def重叠(rect1、rect2):
“”“计算两个矩形之间的重叠”“”
xInterval=Interval(rect1[0][0],rect1[1][0])&Interval(rect2[0][0],rect2[1][0])
yInterval=Interval(rect1[0][1],rect1[1][1])&Interval(rect2[0][1],rect2[1][1])
面积=(xInterval.upper\u界-xInterval.lower\u界)*(yInterval.upper\u界-yInterval.lower\u界)
返回区
def平均值(数据,m,n):
newData=numpy.zeros((m,n))
mOrig,nOrig=data.shape
hBoundariesOrig,vBoundariesOrig=numpy.linspace(0,1,mOrig+1),numpy.linspace(0,1,nOrig+1)
hBoundaries,vBoundaries=numpy.linspace(0,1,m+1),numpy.linspace(0,1,n+1)
对于范围内的iOrig(mOrig):
对于范围内的jOrig(nOrig):
对于范围内的i(m):
如果hBoundaries[i+1]=hBoundariesOrig[iOrig+1]:中断
对于范围(n)内的j:
如果vBoundaries[j+1]=vBoundariesOrig[jOrig+1]:中断
boxCoords=((b边界[i],b边界[j]),(b边界[i+1],b边界[j+1]))
OrigBoundariesorig[iOrig],vBoundariesOrig[jOrig]),(hBoundariesOrig[iOrig+1],vBoundariesOrig[jOrig+1])
新数据[i][j]+=重叠(boxCoords,origBoxCoords)*数据[iOrig][jOrig]/(hBoundaries[1]*vBoundaries[1])
返回新数据
图=pyplot.figure()
ax1=图add_子批次(1,2,1)
ax2=图add_子批次(1,2,2)
m1,n1=37,59
m2,n2=10,13
dataGrid1=numpy.random.rand(m1,n1)
dataGrid2=meanInterp(dataGrid1、m2、n2)
mat1=ax1.matshow(dataGrid1,cmap=“YlOrRd”)
mat2=ax2.matshow(dataGrid2,cmap=“YlOrRd”)
#使两块地都成正方形
ax1.设置相位(浮点(n1)/浮点(m1))
ax2.设置方向(浮动(n2)/浮动(m2))
pyplot.show()
以下是两个具有不同网格的示例:

下采样也是可能的。


做完这件事后,我确信我所做的一切都是某种形式的。如果您希望在大型列表上执行此操作,则需要提高效率,因为这将非常缓慢。

您所讨论的是所谓的插值,在numpy/scipy中有几种方法可以执行此操作。(编辑:将链接更新为更好的示例)我已经尝试了几种插值方法,但没有一种方法能给出我描述的结果。不过,你所描述的正是插值,你只需决定是线性还是样条曲线,或者其他一些指标。我很确定
线性插值
会给你你想要的加权平均值。我认为不会。线性插值给出一个点的平均值,该值由到相邻网格点的距离加权。我想要的是新单元格覆盖区域的加权平均值,如图所示。在某些情况下(如4x4->2x2下采样),这是相同的,但在其他情况下(如4x4->3x3)则不是。非常感谢!这似乎就是我想要的,尽管正如你所说,我可能必须用C语言或其他语言来实现这一点,以获得可接受的性能。我以前也在研究图像采样算法。也许有某种算法可以做到这一点,但我没能找到它。我仍然很想知道这种类型的重采样是否有一个名称。