Tôi đã nghĩ ra một giải pháp khá thanh lịch (IMHO), vì vậy tôi không thể cưỡng lại việc đăng nó: Show
Tôi bản đồ để Trong Sử dụng lớp như thế này:
Tôi đã không giải quyết các điều kiện biên giới ở đây, vì đơn giản. Như nó là, 18 hữu ích 2 bình luận chia sẻ Giải pháp hợp lý là gì phần lớn phụ thuộc vào câu hỏi bạn đang cố gắng trả lời với các pixel được nội suy - báo trước: ngoại suy trên dữ liệu bị thiếu có thể dẫn đến câu trả lời rất sai lầm! Chức năng cơ sở xuyên tâm Nội suy / Làm mịn hạt nhân Về các giải pháp thực tế có sẵn trong Python, một cách để điền các pixel đó vào sẽ là sử dụng cách triển khai nội suy Hàm cơ sở hướng tâm của Scipy (xem tại đây ) nhằm mục đích làm mịn / nội suy dữ liệu phân tán. Với ma trận của bạn
Điều này dẫn đến nội suy sau của dữ liệu mà bạn đã liên kết ở trên, mặc dù có vẻ hợp lý, nhưng nó làm nổi bật tỷ lệ mẫu bị thiếu so với dữ liệu thực là bất lợi như thế nào: Hồi quy quy trình Gaussian / Kriging Nội suy Kriging có sẵn thông qua triển khai Hồi quy quy trình Gaussian (bản thân nó dựa trên hộp công cụ DACE Kriging cho Matlab) trong thư viện scikit-learning. Điều này có thể được gọi như sau:
Điều này tạo ra một phép nội suy rất giống với ví dụ Hàm cơ sở Radial ở trên. Trong cả hai trường hợp, có rất nhiều tham số để khám phá - sự lựa chọn của những tham số này phần lớn phụ thuộc vào các giả định mà bạn có thể đưa ra về dữ liệu. (Một ưu điểm của hạt nhân tuyến tính được sử dụng trong ví dụ RBF ở trên là nó không có tham số miễn phí) Inpainting Cuối cùng sang một bên, một giải pháp hoàn toàn có động cơ trực quan sẽ là sử dụng chức năng inpainting của OpenCV , mặc dù điều này giả định mảng 8bit (0 - 255) và không có cách giải thích toán học đơn giản. 46 hữu ích 0 bình luận chia sẻ There are several general interpolation facilities available in SciPy, for data in 1, 2, and higher dimensions: Nội dung chính
1-D interpolation (interp1d)#The >>> from scipy.interpolate import interp1d >>> x = np.linspace(0, 10, num=11, endpoint=True) >>> y = np.cos(-x**2/9.0) >>> f = interp1d(x, y) >>> f2 = interp1d(x, y, kind='cubic') >>> xnew = np.linspace(0, 10, num=41, endpoint=True) >>> import matplotlib.pyplot as plt >>> plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--') >>> plt.legend(['data', 'linear', 'cubic'], loc='best') >>> plt.show() Another set of interpolations in >>> from scipy.interpolate import interp1d >>> x = np.linspace(0, 10, num=11, endpoint=True) >>> y = np.cos(-x**2/9.0) >>> f1 = interp1d(x, y, kind='nearest') >>> f2 = interp1d(x, y, kind='previous') >>> f3 = interp1d(x, y, kind='next') >>> xnew = np.linspace(0, 10, num=1001, endpoint=True) >>> import matplotlib.pyplot as plt >>> plt.plot(x, y, 'o') >>> plt.plot(xnew, f1(xnew), '-', xnew, f2(xnew), '--', xnew, f3(xnew), ':') >>> plt.legend(['data', 'nearest', 'previous', 'next'], loc='best') >>> plt.show() Multivariate data interpolation (griddata)#Suppose you have multidimensional data, for instance, for an underlying function f(x, y) you only know the values at points (x[i], y[i]) that do not form a regular grid. Suppose we want to interpolate the 2-D function >>> def func(x, y): ... return x*(1-x)*np.cos(4*np.pi*x) * np.sin(4*np.pi*y**2)**2 on a grid in [0, 1]x[0, 1] >>> grid_x, grid_y = np.mgrid[0:1:100j, 0:1:200j] but we only know its values at 1000 data points: >>> rng = np.random.default_rng() >>> points = rng.random((1000, 2)) >>> values = func(points[:,0], points[:,1]) This can be done with >>> from scipy.interpolate import griddata >>> grid_z0 = griddata(points, values, (grid_x, grid_y), method='nearest') >>> grid_z1 = griddata(points, values, (grid_x, grid_y), method='linear') >>> grid_z2 = griddata(points, values, (grid_x, grid_y), method='cubic') One can see that the exact result is reproduced by all of the methods to some degree, but for this smooth function the piecewise cubic interpolant gives the best results: >>> import matplotlib.pyplot as plt >>> plt.subplot(221) >>> plt.imshow(func(grid_x, grid_y).T, extent=(0,1,0,1), origin='lower') >>> plt.plot(points[:,0], points[:,1], 'k.', ms=1) >>> plt.title('Original') >>> plt.subplot(222) >>> plt.imshow(grid_z0.T, extent=(0,1,0,1), origin='lower') >>> plt.title('Nearest') >>> plt.subplot(223) >>> plt.imshow(grid_z1.T, extent=(0,1,0,1), origin='lower') >>> plt.title('Linear') >>> plt.subplot(224) >>> plt.imshow(grid_z2.T, extent=(0,1,0,1), origin='lower') >>> plt.title('Cubic') >>> plt.gcf().set_size_inches(6, 6) >>> plt.show() Multivariate data interpolation on a regular grid (RegularGridInterpolator)#Suppose you have n-dimensional
data on a regular grid, and you want to interpolate it. In such a case, >>> import matplotlib.pyplot as plt >>> from scipy.interpolate import RegularGridInterpolator Suppose we want to interpolate this 2-D function. >>> def F(u, v): ... return u * np.cos(u * v) + v * np.sin(u * v) Suppose we only know some data on a regular grid. >>> fit_points = [np.linspace(0, 3, 8), np.linspace(0, 3, 8)] >>> values = F(*np.meshgrid(*fit_points, indexing='ij')) Creating test points and true values for evaluations. >>> ut, vt = np.meshgrid(np.linspace(0, 3, 80), np.linspace(0, 3, 80), indexing='ij') >>> true_values = F(ut, vt) >>> test_points = np.array([ut.ravel(), vt.ravel()]).T We can creat interpolator and interpolate test points using each method. >>> interp = RegularGridInterpolator(fit_points, values) >>> fig, axes = plt.subplots(2, 3, figsize=(10, 6)) >>> axes = axes.ravel() >>> fig_index = 0 >>> for method in ['linear', 'nearest', 'slinear', 'cubic', 'quintic']: ... im = interp(test_points, method=method).reshape(80, 80) ... axes[fig_index].imshow(im) ... axes[fig_index].set_title(method) ... axes[fig_index].axis("off") ... fig_index += 1 >>> axes[fig_index].imshow(true_values) >>> axes[fig_index].set_title("True values") >>> fig.tight_layout() >>> fig.show() As expected, the higher degree spline interpolations are closest to the true values, though are more expensive to compute than with linear or nearest. The slinear interpolation also matches the linear interpolation. Spline interpolation#Spline interpolation in 1-D: Procedural (interpolate.splXXX)#Spline interpolation requires two essential steps: (1) a spline representation of the curve is computed, and (2) the spline is evaluated at the desired points. In order to find the spline representation, there are two different ways to represent a curve and obtain (smoothing) spline coefficients: directly and parametrically. The direct method finds
the spline representation of a curve in a 2-D plane using the function For curves in N-D space the function The keyword argument, s , is used to specify the amount of smoothing to perform during the spline fit. The default value of \(s\) is \(s=m-\sqrt{2m}\) where \(m\) is the number of data-points being fit. Therefore, if no smoothing is desired a value of \(\mathbf{s}=0\) should be passed to the routines. Once the spline representation of the data has been determined, functions are available for evaluating the spline ( >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from scipy import interpolate Cubic-spline >>> x = np.arange(0, 2*np.pi+np.pi/4, 2*np.pi/8) >>> y = np.sin(x) >>> tck = interpolate.splrep(x, y, s=0) >>> xnew = np.arange(0, 2*np.pi, np.pi/50) >>> ynew = interpolate.splev(xnew, tck, der=0) >>> plt.figure() >>> plt.plot(x, y, 'x', xnew, ynew, xnew, np.sin(xnew), x, y, 'b') >>> plt.legend(['Linear', 'Cubic Spline', 'True']) >>> plt.axis([-0.05, 6.33, -1.05, 1.05]) >>> plt.title('Cubic-spline interpolation') >>> plt.show() Derivative of spline >>> yder = interpolate.splev(xnew, tck, der=1) >>> plt.figure() >>> plt.plot(xnew, yder, xnew, np.cos(xnew),'--') >>> plt.legend(['Cubic Spline', 'True']) >>> plt.axis([-0.05, 6.33, -1.05, 1.05]) >>> plt.title('Derivative estimation from spline') >>> plt.show() All derivatives of spline >>> yders = interpolate.spalde(xnew, tck) >>> plt.figure() >>> for i in range(len(yders[0])): ... plt.plot(xnew, [d[i] for d in yders], '--', label=f"{i} derivative") >>> plt.legend() >>> plt.axis([-0.05, 6.33, -1.05, 1.05]) >>> plt.title('All derivatives of a B-spline') >>> plt.show() Integral of spline >>> def integ(x, tck, constant=-1): ... x = np.atleast_1d(x) ... out = np.zeros(x.shape, dtype=x.dtype) ... for n in range(len(out)): ... out[n] = interpolate.splint(0, x[n], tck) ... out += constant ... return out >>> yint = integ(xnew, tck) >>> plt.figure() >>> plt.plot(xnew, yint, xnew, -np.cos(xnew), '--') >>> plt.legend(['Cubic Spline', 'True']) >>> plt.axis([-0.05, 6.33, -1.05, 1.05]) >>> plt.title('Integral estimation from spline') >>> plt.show() Roots of spline >>> interpolate.sproot(tck) array([3.1416]) # may vary Notice that >>> x = np.linspace(-np.pi/4, 2.*np.pi + np.pi/4, 21) >>> y = np.sin(x) >>> tck = interpolate.splrep(x, y, s=0) >>> interpolate.sproot(tck) array([0., 3.1416]) Parametric spline >>> t = np.arange(0, 1.1, .1) >>> x = np.sin(2*np.pi*t) >>> y = np.cos(2*np.pi*t) >>> tck, u = interpolate.splprep([x, y], s=0) >>> unew = np.arange(0, 1.01, 0.01) >>> out = interpolate.splev(unew, tck) >>> plt.figure() >>> plt.plot(x, y, 'x', out[0], out[1], np.sin(2*np.pi*unew), np.cos(2*np.pi*unew), x, y, 'b') >>> plt.legend(['Linear', 'Cubic Spline', 'True']) >>> plt.axis([-1.05, 1.05, -1.05, 1.05]) >>> plt.title('Spline of parametrically-defined curve') >>> plt.show() Spline interpolation in 1-d: Object-oriented (UnivariateSpline)#The spline-fitting capabilities described above are also available via an objected-oriented interface. The 1-D splines are objects of the The UnivariateSpline class can also be used to smooth data by providing a non-zero value of the smoothing parameter s, with the same meaning as the s keyword of the The >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from scipy import interpolate InterpolatedUnivariateSpline >>> x = np.arange(0, 2*np.pi+np.pi/4, 2*np.pi/8) >>> y = np.sin(x) >>> s = interpolate.InterpolatedUnivariateSpline(x, y) >>> xnew = np.arange(0, 2*np.pi, np.pi/50) >>> ynew = s(xnew) >>> plt.figure() >>> plt.plot(x, y, 'x', xnew, ynew, xnew, np.sin(xnew), x, y, 'b') >>> plt.legend(['Linear', 'InterpolatedUnivariateSpline', 'True']) >>> plt.axis([-0.05, 6.33, -1.05, 1.05]) >>> plt.title('InterpolatedUnivariateSpline') >>> plt.show() LSQUnivarateSpline with non-uniform knots >>> t = [np.pi/2-.1, np.pi/2+.1, 3*np.pi/2-.1, 3*np.pi/2+.1] >>> s = interpolate.LSQUnivariateSpline(x, y, t, k=2) >>> ynew = s(xnew) >>> plt.figure() >>> plt.plot(x, y, 'x', xnew, ynew, xnew, np.sin(xnew), x, y, 'b') >>> plt.legend(['Linear', 'LSQUnivariateSpline', 'True']) >>> plt.axis([-0.05, 6.33, -1.05, 1.05]) >>> plt.title('Spline with Specified Interior Knots') >>> plt.show() 2-D spline representation: Procedural (bisplrep)#For (smooth) spline-fitting to a 2-D surface, the function To evaluate the 2-D spline and its partial derivatives (up to the order of the spline), the function It is important to note that 2-D interpolation should not be used to find the spline representation of images. The algorithm used is not amenable to large numbers of input points. The signal-processing toolbox contains more appropriate algorithms for finding the spline representation of an image. The 2-D interpolation commands are intended for use when interpolating a 2-D function as shown in the example
that follows. This example uses the >>> import numpy as np >>> from scipy import interpolate >>> import matplotlib.pyplot as plt Define function over a sparse 20x20 grid >>> x_edges, y_edges = np.mgrid[-1:1:21j, -1:1:21j] >>> x = x_edges[:-1, :-1] + np.diff(x_edges[:2, 0])[0] / 2. >>> y = y_edges[:-1, :-1] + np.diff(y_edges[0, :2])[0] / 2. >>> z = (x+y) * np.exp(-6.0*(x*x+y*y)) >>> plt.figure() >>> lims = dict(cmap='RdBu_r', vmin=-0.25, vmax=0.25) >>> plt.pcolormesh(x_edges, y_edges, z, shading='flat', **lims) >>> plt.colorbar() >>> plt.title("Sparsely sampled function.") >>> plt.show() Interpolate function over a new 70x70 grid >>> xnew_edges, ynew_edges = np.mgrid[-1:1:71j, -1:1:71j] >>> xnew = xnew_edges[:-1, :-1] + np.diff(xnew_edges[:2, 0])[0] / 2. >>> ynew = ynew_edges[:-1, :-1] + np.diff(ynew_edges[0, :2])[0] / 2. >>> tck = interpolate.bisplrep(x, y, z, s=0) >>> znew = interpolate.bisplev(xnew[:,0], ynew[0,:], tck) >>> plt.figure() >>> plt.pcolormesh(xnew_edges, ynew_edges, znew, shading='flat', **lims) >>> plt.colorbar() >>> plt.title("Interpolated function.") >>> plt.show() 2-D spline representation: Object-oriented (BivariateSpline)#The Using radial basis functions for smoothing/interpolation#Radial basis functions can be used for smoothing/interpolating scattered data in N dimensions, but should be used with caution for extrapolation outside of the observed data range. 1-D Example#This example compares the usage of the >>> import numpy as np >>> from scipy.interpolate import Rbf, InterpolatedUnivariateSpline >>> import matplotlib.pyplot as plt >>> # setup data >>> x = np.linspace(0, 10, 9) >>> y = np.sin(x) >>> xi = np.linspace(0, 10, 101) >>> # use fitpack2 method >>> ius = InterpolatedUnivariateSpline(x, y) >>> yi = ius(xi) >>> plt.subplot(2, 1, 1) >>> plt.plot(x, y, 'bo') >>> plt.plot(xi, yi, 'g') >>> plt.plot(xi, np.sin(xi), 'r') >>> plt.title('Interpolation using univariate spline') >>> # use RBF method >>> rbf = Rbf(x, y) >>> fi = rbf(xi) >>> plt.subplot(2, 1, 2) >>> plt.plot(x, y, 'bo') >>> plt.plot(xi, fi, 'g') >>> plt.plot(xi, np.sin(xi), 'r') >>> plt.title('Interpolation using RBF - multiquadrics') >>> plt.show() 2-D Example#This example shows how to interpolate scattered 2-D data: >>> import numpy as np >>> from scipy.interpolate import Rbf >>> import matplotlib.pyplot as plt >>> from matplotlib import cm >>> # 2-d tests - setup scattered data >>> rng = np.random.default_rng() >>> x = rng.random(100)*4.0-2.0 >>> y = rng.random(100)*4.0-2.0 >>> z = x*np.exp(-x**2-y**2) >>> edges = np.linspace(-2.0, 2.0, 101) >>> centers = edges[:-1] + np.diff(edges[:2])[0] / 2. >>> XI, YI = np.meshgrid(centers, centers) >>> # use RBF >>> rbf = Rbf(x, y, z, epsilon=2) >>> ZI = rbf(XI, YI) >>> # plot the result >>> plt.subplot(1, 1, 1) >>> X_edges, Y_edges = np.meshgrid(edges, edges) >>> lims = dict(cmap='RdBu_r', vmin=-0.4, vmax=0.4) >>> plt.pcolormesh(X_edges, Y_edges, ZI, shading='flat', **lims) >>> plt.scatter(x, y, 100, z, edgecolor='w', lw=0.1, **lims) >>> plt.title('RBF interpolation - multiquadrics') >>> plt.xlim(-2, 2) >>> plt.ylim(-2, 2) >>> plt.colorbar() |