python - 使用 scipy 的 RectBivariateSpline 和 SmoothBivariateSpline 对噪声数据进行样条曲面拟合

标签 python scipy interpolation model-fitting bspline

我正在尝试对一些成像数据进行二维表面拟合。我附上了此类数据的示例,它基本上是一个 1014 x 1014 数组,具有大量噪声。 Example_image 。该数组的一些补丁是无效数据,我将其屏蔽并设置为 NaN 值,如示例图像中的黄色所示。正如您在图像中看到的,有一个从左(较亮)到右(较暗)的背景渐变,我正在尝试将其删除。多项式无法很好地拟合梯度,因此我的目标是进行二维表面二元样条拟合,并减去梯度。

我在 scipy 中尝试了许多任务,但大多数都没有返回理想的结果。

  1. 首先,我尝试了 [RectBivariateSpline] Bivariate structured interpolation of large array with NaN values or mask ),但由于我的图像中含有 NaN,因此运行 RectBivariateSpline 仅给出 NaN 的输出。

  2. 我也尝试过SmoothBivariateSpline ,这是任务的不规则网格版本。我省略了那些具有 NaN 值的像素,并将其余像素转换为一维数组作为输入。但由于数组大小太大而失败。然后我尝试切碎我的数组以尝试在较小的 block 上运行它,但它给出了以下错误并因段错误而退出,我不知道这意味着什么。

    fitpack2.py:1044: 用户警告: 输入错误,未返回近似值。满足以下条件 必须持有: xb<=x[i]<=xe, yb<=y[i]<=ye, w[i]>0, i=0..m-1 如果 iopt==-1,那么 xb

  3. 然后,我尝试首先使用带有线性插值的 griddata 用值填充图像中的 NaN 补丁。由于补丁很大,插值并不理想,但至少它给了我一个没有 NaN 的数组。然后,我使用该数组再次运行 RectBivariateSpline。但输出数组仍然是 NaN。

  4. 我怀疑图像中的噪声破坏了这两个任务的行为,因此我还尝试首先在图像上运行高斯核以使其平滑,然后用网格数据填充 NaN 补丁,然后运行 RectBivariateSpline 或 SmoothBivariateSpline,但它们仍然为我提供带有 NaN 值的数组作为输出。

我不确定我是否正确理解了这两个任务的手册,因此我附上了以下脚本:

#!/usr/bin/python

import matplotlib 
matplotlib.use('qt5agg')
#matplotlib.rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
#matplotlib.rc('text.latex', preamble=r'\usepackage{cmbright}')
#matplotlib.rc('text.latex', preamble=r'\usepackage[scaled]{helvet} \renewcommand\familydefault{\sfdefault} \usepackage[T1]{fontenc}')
#matplotlib.rc('text', usetex=True)

import matplotlib.pyplot as plt
import numpy as np
import astropy.io.fits as pyfits
import scipy.interpolate as sp
from astropy.convolution import convolve
from astropy.convolution import Gaussian2DKernel

#------------------------------------------------------------

#Read in the arrays
hdulistorg = pyfits.open('icmj01jrq_flt.fits')
hdulistorg.info()
errarrorg = np.swapaxes(hdulistorg[1].data, 0,1)
hdulist = pyfits.open('jrq_sci_nan_deep.fits')
hdulist.info()
dataarrorg = np.swapaxes(hdulist[0].data, 0,1)    #image array
errarrorg = np.swapaxes(hdulistorg[1].data, 0,1)  #error array

#Flag some of the problematic values, turn NaNs into 0 for easier handling
dataarr = np.copy(dataarrorg)
w=np.isnan(dataarr)
ww=np.where(dataarr == 0)
www=np.where(dataarr > 100)
wwww=np.where(dataarr < 0)

errarr = 1.0 / (np.copy(errarrorg)+1e-5)   # Try to use 1/error as the estimate for weight below
errarr[w] = 0
errarr[ww] = 0
errarr[www] = 0
errarr[wwww]=0
dataarr[w]= 0
dataarr[ww]= 0
dataarr[www]=0
dataarr[wwww]=0


#Make a gaussian kernel smoothed data  
maskarr = np.copy(errarr)    #For masking the nan regions so they dun get smoothed 
maskarr[:]=0
maskarr[w]=1
maskarr[ww]=1
maskarr[www]=1
maskarr[wwww]=1
gauss = Gaussian2DKernel(stddev=5)
condataarr = convolve(dataarr,gauss,normalize_kernel=True,boundary='extend',mask=maskarr)
condataarr[w]=0
conerrarr = np.copy(errarr)


#Setting x,y arrays for the Spline functions
nx, ny = (1014,1014)
x = np.linspace(0, 1013, nx)
y = np.linspace(0, 1013, ny)
xv, yv = np.meshgrid(x, y)


#Make an 1D version of these 2D arrays
dataarrflat = np.ravel(condataarr[0:200,0:200])   #Try only a small chunk!
xvflat = np.ravel(xv[0:200,0:200])
yvflat = np.ravel(yv[0:200,0:200])
errarrflat = np.ravel(conerrarr[0:200,0:200]) 
notnanloc = np.where(dataarrflat != 0)            #Not NaNs

#SmoothBivariateSpline! 
rect_S_spline = sp.SmoothBivariateSpline(xvflat[notnanloc], yvflat[notnanloc], dataarrflat[notnanloc],w=errarrflat[notnanloc], kx=3, ky=3)


#Also try using grid data to fix the grid?
gddataarr = np.copy(condataarr)
gddataarrflat = np.ravel(gddataarr)
gdloc = np.where(gddataarrflat != 0)              #Not NaNs
gdxvflat = np.ravel(xv)
gdyvflat = np.ravel(yv)
xyarr = np.c_[gdxvflat[gdloc],gdyvflat[gdloc]]
x_grid, y_grid = np.mgrid[0:1013:1014j,0:1013:1014j]

grid_z2 = sp.griddata(xyarr, gddataarrflat[gdloc], (x_grid, y_grid), method='linear')
plt.imshow(grid_z2.T)
#plt.show()

#RectBivariatSpline
rect_B_spline = sp.RectBivariateSpline(x, y, grid_z2.T)



#Result grid (same as input for now)
xnew = np.arange(0, 1013, 1)
ynew = np.arange(0, 1013, 1)
znewS = rect_S_spline(xnew, ynew)
znewB = rect_B_spline(xnew, ynew)
print 'znewS', znewS
print 'znewB', znewB


#Write FITS files
condataarr = np.swapaxes(condataarr, 0, 1)
hdu2 = pyfits.PrimaryHDU(condataarr)
hdulist2 = pyfits.HDUList([hdu2])
hdulist2.writeto('contest.fits',overwrite=True)
hdulist2.close()

hdu3 = pyfits.PrimaryHDU(znewS)
hdulist3 = pyfits.HDUList([hdu3])
hdulist3.writeto('Stest.fits',overwrite=True)
hdulist3.close()

最佳答案

我不能完全解决你的问题,但我有一些代码将 FORTRAN 插值例程与 python 连接起来。您可以直接从 python 调用例程,不需要 fortran。

您可以在此 github 页面找到代码及其描述 https://github.com/haakoan/inter

关于python - 使用 scipy 的 RectBivariateSpline 和 SmoothBivariateSpline 对噪声数据进行样条曲面拟合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42572743/

相关文章:

python - 在python中部分解压参数

python - 类型错误 : type() takes 1 or 3 arguments

python - 如何从python中的二面角计算笛卡尔坐标

python - scipy.sparse.coo_matrix 如何快速找到全零列,填充 1 并标准化

python - 使用 Delaunay 三角剖分 (n-dim) 进行插值

java - 数组插值

python - 将数据帧有效转换为大型数据集中的列表

python - spdiags() 函数在 Python 中未按预期工作

algorithm - 用于降尺度的双三次插值

Matlab 3D 插值