array = [0.01,0.04,0.04....1] # len10
期望结果
[0.11,0.44,1] # len 3
[1e-4,2e-4,....1] # len 100
# 例子用的是 f(x)=x^2
这不是整数间距的缩放,所以用普通的resample方法好像难以解决该问题【改采样率】
我尝试重待采样数组,再线性的化为与目标长度相同的数组
def _lineResample(x1, y1, x2, y2, x):
'''
:param x1:pointA x
:param y1: pointA y
:param x2: pointB x
:param y2: pointB y
:param x: x in llineAB
:return: y in lineAB
'''
return (y2 - y1)*(x - x1) / (x2 - x1) + y1
def resampleBylen(orig_numpy, target_numpy_len: int):
# 将orig重采样为和target一样长度的
orig_numpy_len = len(orig_numpy)
if orig_numpy_len == target_numpy_len:
return orig_numpy
scale = target_numpy_len/orig_numpy_len
big_orig_numpy ,sr = resample(orig_numpy,8000,8000*(int(scale)+1))
big_orig_numpy = big_orig_numpy.tolist()
big_orig_numpy_len = len(big_orig_numpy)
result = []
for i in range(target_numpy_len):
absPostion = i*big_orig_numpy_len/target_numpy_len
left = int(absPostion)
right = left+1
y = _lineResample(left,big_orig_numpy[left],right,big_orig_numpy[right],absPostion)
result.append(y)
但是不但效果不好,而且消耗时间惊人的长
不知道如何解决这个问题
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()
一个性能友好的实现方式
思路:先对原始数组缩放
再进行插值,线插是我试下来比较满意的,如果你有其他需求请自行更换
这个问题的另一个回答是针对图形的重采样,有兴趣也可以看下
上 代 码 !
import scipy.interpolate as interpolate
def resamplrBylen(orig_list:list,target_len:int):
'''
同于标准重采样,此函数将len(list1)=x 从采样为len(list2)=y;y为指定的值,list2为输出
:param orig_list: 是list,重采样的源列表:list1
:param target_len: 重采样的帧数:y
:return: 重采样后的数组:list2
'''
orig_list_len =len(orig_list)
k = target_len/orig_list_len
x = [x*k for x in range(orig_list_len)]
x[-1] = 3572740
if x[-1]!=target_len:
# 线性更改越界结尾
x1=x[-2];y1=orig_list[-2];x2=x[-1];y2=orig_list[-1]
y_resa = (y2 - y1) * (target_len - x1) / (x2 - x1) + y1
x[-1] = target_len;orig_list[-1]=y_resa
# 使用了线性的插值方法,也可以根据需要改成其他的。推荐是线性
f = interpolate.interp1d(x,orig_list,'linear')
del x
resample_list = f([x for x in range(target_len)])
return resample_list