转载至 Cubic interpolation

On this page you can find explanation about ( n -)cubic interpolation and implementations in Java and C++.
Anything at this page may be copied and modified.
Please contact me if you find an error.

Cubic interpolation

If the values of a function f(x) and its derivative are known at x=0 and x=1, then the function can be interpolated on the interval [0,1] using a third degree polynomial. This is called cubic interpolation. The formula of this polynomial can be easily derived.

A third degree polynomial and its derivative:

The values of the polynomial and its derivative at x=0 and x=1:

The four equations above can be rewritten to this:

And there we have our cubic interpolation formula.

Interpolation is often used to interpolate between a list of values. In that case we don't know the derivative of the function. We could simply use derivative 0 at every point, but we obtain smoother curves when we use the slope of a line between the previous and the next point as the derivative at a point. In that case the resulting polynomial is called a Catmull-Rom spline. Suppose you have the values p0, p1, p2and p3 at respectively x=-1, x=0, x=1, and x=2. Then we can assign the values of f(0), f(1), f'(0) and f'(1) using the formulas below to interpolate between p1 and p2.

Combining the last four formulas and the preceding four, we get:

So our cubic interpolation formula becomes:

For example:

For the green curve:

The first and the last interval

We used the two points left of the interval and the two points right of the inverval as inputs for the interpolation function. But what if we want to interpolate between the first two or last two elements of a list? Then we have no p0 or no p3. The solution is to imagine an extra point at each end of the list. In other words, we have to make up a value for p0 and p3 when interpolating the leftmost and rightmost interval respectively. Two ways to do this are:

  • Repeat the first and the last point.
    Left: p0 = p1
    Right: p3 = p2
  • Let the end point be in the middle of a line between the imaginary point and the point next to the end point.
    Left: p0 = 2p1 - p2
    Right: p3 = 2p2 - p1

Bicubic interpolation

Bicubic interpolation is cubic interpolation in two dimensions. I'll only consider the case where we want to interpolate a two dimensional grid. We can use the cubic interpolation formula to construct the bicubic interpolation formula.

Suppose we have the 16 points pij, with i and j going from 0 to 3 and with pij located at (i-1, j-1). Then we can interpolate the area [0,1] x [0,1] by first interpolating the four columns and then interpolating the results in the horizontal direction. The formula becomes:

Bicubic interpolation can be used to resize images. However, this is (currently) out of the scope of this article. Please don't ask me questions about that.

Java implementation

public class CubicInterpolator
{public static double getValue (double[] p, double x) {return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0])));}
}public class BicubicInterpolator extends CubicInterpolator
{private double[] arr = new double[4];public double getValue (double[][] p, double x, double y) {arr[0] = getValue(p[0], y);arr[1] = getValue(p[1], y);arr[2] = getValue(p[2], y);arr[3] = getValue(p[3], y);return getValue(arr, x);}
}public class TricubicInterpolator extends BicubicInterpolator
{private double[] arr = new double[4];public double getValue (double[][][] p, double x, double y, double z) {arr[0] = getValue(p[0], y, z);arr[1] = getValue(p[1], y, z);arr[2] = getValue(p[2], y, z);arr[3] = getValue(p[3], y, z);return getValue(arr, x);}
}

C++ implementation

#include <iostream>
#include <assert.h>double cubicInterpolate (double p[4], double x) {return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0])));
}double bicubicInterpolate (double p[4][4], double x, double y) {double arr[4];arr[0] = cubicInterpolate(p[0], y);arr[1] = cubicInterpolate(p[1], y);arr[2] = cubicInterpolate(p[2], y);arr[3] = cubicInterpolate(p[3], y);return cubicInterpolate(arr, x);
}double tricubicInterpolate (double p[4][4][4], double x, double y, double z) {double arr[4];arr[0] = bicubicInterpolate(p[0], y, z);arr[1] = bicubicInterpolate(p[1], y, z);arr[2] = bicubicInterpolate(p[2], y, z);arr[3] = bicubicInterpolate(p[3], y, z);return cubicInterpolate(arr, x);
}double nCubicInterpolate (int n, double* p, double coordinates[]) {assert(n > 0);if (n == 1) {return cubicInterpolate(p, *coordinates);}else {double arr[4];int skip = 1 << (n - 1) * 2;arr[0] = nCubicInterpolate(n - 1, p, coordinates + 1);arr[1] = nCubicInterpolate(n - 1, p + skip, coordinates + 1);arr[2] = nCubicInterpolate(n - 1, p + 2*skip, coordinates + 1);arr[3] = nCubicInterpolate(n - 1, p + 3*skip, coordinates + 1);return cubicInterpolate(arr, *coordinates);}
}int main () {// Create arraydouble p[4][4] = {{1,3,3,4}, {7,2,3,4}, {1,6,3,6}, {2,5,7,2}};// Interpolatestd::cout << bicubicInterpolate(p, 0.1, 0.2) << '\n';// Or use the nCubicInterpolate functiondouble co[2] = {0.1, 0.2};std::cout << nCubicInterpolate(2, (double*) p, co) << '\n';
}

Bicubic interpolation polynomial

This section provides an alternative way to calculate bicubic interpolation. For most purposes this way is probably less practical and efficient than the way it is done above.

We can rewrite the formula for bicubic interpolation as a multivariate polynomial:

With these values for aij, the coefficients:

In Java code we can write this as:

public class CachedBicubicInterpolator
{private double a00, a01, a02, a03;private double a10, a11, a12, a13;private double a20, a21, a22, a23;private double a30, a31, a32, a33;public void updateCoefficients (double[][] p) {a00 = p[1][1];a01 = -.5*p[1][0] + .5*p[1][2];a02 = p[1][0] - 2.5*p[1][1] + 2*p[1][2] - .5*p[1][3];a03 = -.5*p[1][0] + 1.5*p[1][1] - 1.5*p[1][2] + .5*p[1][3];a10 = -.5*p[0][1] + .5*p[2][1];a11 = .25*p[0][0] - .25*p[0][2] - .25*p[2][0] + .25*p[2][2];a12 = -.5*p[0][0] + 1.25*p[0][1] - p[0][2] + .25*p[0][3] + .5*p[2][0] - 1.25*p[2][1] + p[2][2] - .25*p[2][3];a13 = .25*p[0][0] - .75*p[0][1] + .75*p[0][2] - .25*p[0][3] - .25*p[2][0] + .75*p[2][1] - .75*p[2][2] + .25*p[2][3];a20 = p[0][1] - 2.5*p[1][1] + 2*p[2][1] - .5*p[3][1];a21 = -.5*p[0][0] + .5*p[0][2] + 1.25*p[1][0] - 1.25*p[1][2] - p[2][0] + p[2][2] + .25*p[3][0] - .25*p[3][2];a22 = p[0][0] - 2.5*p[0][1] + 2*p[0][2] - .5*p[0][3] - 2.5*p[1][0] + 6.25*p[1][1] - 5*p[1][2] + 1.25*p[1][3] + 2*p[2][0] - 5*p[2][1] + 4*p[2][2] - p[2][3] - .5*p[3][0] + 1.25*p[3][1] - p[3][2] + .25*p[3][3];a23 = -.5*p[0][0] + 1.5*p[0][1] - 1.5*p[0][2] + .5*p[0][3] + 1.25*p[1][0] - 3.75*p[1][1] + 3.75*p[1][2] - 1.25*p[1][3] - p[2][0] + 3*p[2][1] - 3*p[2][2] + p[2][3] + .25*p[3][0] - .75*p[3][1] + .75*p[3][2] - .25*p[3][3];a30 = -.5*p[0][1] + 1.5*p[1][1] - 1.5*p[2][1] + .5*p[3][1];a31 = .25*p[0][0] - .25*p[0][2] - .75*p[1][0] + .75*p[1][2] + .75*p[2][0] - .75*p[2][2] - .25*p[3][0] + .25*p[3][2];a32 = -.5*p[0][0] + 1.25*p[0][1] - p[0][2] + .25*p[0][3] + 1.5*p[1][0] - 3.75*p[1][1] + 3*p[1][2] - .75*p[1][3] - 1.5*p[2][0] + 3.75*p[2][1] - 3*p[2][2] + .75*p[2][3] + .5*p[3][0] - 1.25*p[3][1] + p[3][2] - .25*p[3][3];a33 = .25*p[0][0] - .75*p[0][1] + .75*p[0][2] - .25*p[0][3] - .75*p[1][0] + 2.25*p[1][1] - 2.25*p[1][2] + .75*p[1][3] + .75*p[2][0] - 2.25*p[2][1] + 2.25*p[2][2] - .75*p[2][3] - .25*p[3][0] + .75*p[3][1] - .75*p[3][2] + .25*p[3][3];}public double getValue (double x, double y) {double x2 = x * x;double x3 = x2 * x;double y2 = y * y;double y3 = y2 * y;return (a00 + a01 * y + a02 * y2 + a03 * y3) +(a10 + a11 * y + a12 * y2 + a13 * y3) * x +(a20 + a21 * y + a22 * y2 + a23 * y3) * x2 +(a30 + a31 * y + a32 * y2 + a33 * y3) * x3;}
}

This implementation can run faster than the implementation above when getValue is called multiple times for one call to updateCoefficients.

Similar implementations could be written for other dimensions than two.

Cubic interpolation相关推荐

  1. Cubic interpolation立方插值

    原文地址:http://www.paulinternet.nl/?page=bicubic On this page you can find explanation about ( n -)cubi ...

  2. matlab中二维插值中cubic方法的实现原理(个人见解)

    通过查找matlab的帮助程序,对离散数据格网化采用的方法有如下5种: griddata(..., METHOD) where METHOD is one of         'nearest'   ...

  3. C++:实现量化相关的Interpolation插值测试实例

    C++:实现量化相关的Interpolation插值测试实例 #include "interpolations.hpp" #include "utilities.hpp& ...

  4. matlab中内插cubic,matlab中二维插值中cubic方法的实现原理(个人见解)

    通过查找matlab的帮助程序,对离散数据格网化采用的方法有如下5种: griddata(..., METHOD) where METHOD is one of 'nearest'   - Neare ...

  5. 干货 | 20个教程,掌握时间序列的特征分析(附代码)

    作者 | Selva Prabhakaran 译者 | Tianyu 责编 | Jane 出品 | AI科技大本营(ID: rgznai100) [导语]时间序列是指以固定时间为间隔的序列值.本篇教程 ...

  6. GROMACS运行参数之md.mdp文件详解

    GROMACS(5.1.4)教程:蛋白质配体复合物 官网:点击打开链接 李老师博客:点击打开链接 蛋白质配体复合物模拟md运行过程中需要用到输入文件md.mdp,现对里面的各种编辑项目做简单注释. # ...

  7. GROMACS运行参数之npt.mdp文件详解

    GROMACS(5.1.4)教程:蛋白质配体复合物 官网:点击打开链接 李老师博客:点击打开链接 蛋白质配体复合物模拟npt平衡过程中需要用到输入文件npt.mdp,现对里面的各种编辑项目做简单注释. ...

  8. GROMACS运行参数之nvt.mdp文件详解

    GROMACS(5.1.4)教程:蛋白质配体复合物 官网:点击打开链接 李老师博客:点击打开链接 蛋白质配体复合物模拟nvt平衡过程中需要用到输入文件nvt.mdp,现对里面的各种编辑项目做简单注释. ...

  9. 独家 | Python时间序列分析:一项基于案例的全面指南

    作者: Selva Prabhakaran 翻译:陈超校对:王可汗本文约7500字,建议阅读20+分钟本文介绍了时间序列的定义.特征并结合实例给出了时间序列在Python中评价指标和方法. 时间序列是 ...

最新文章

  1. php怎么实现自动售货,PHP自动化售货发卡网源码+教程
  2. 《我想进大厂》之mysql夺命连环13问
  3. 量子信息技术研究现状与未来
  4. 快速理解平衡二叉树、B-tree、B+tree、B*tree
  5. 为什么要阅读——兼分享《首先,打破一切常规》[中译文]:世界顶级管理者的成功秘诀/(美)马库斯·白金汉,(美)柯特·科夫曼 著...
  6. VTK:可视化之BackfaceCulling
  7. [javaSE] 数组(排序-冒泡排序)
  8. 小程序请求php接口返回错误$HTTP_RAW_POST_DATA is deprecated......
  9. java初中级程序员面试宝典-蚂蚁课堂
  10. HTML translate 属性
  11. Visio绘制网络模型
  12. 新浪开发者平台(Sina App Engine)初探
  13. Wps文件如何转成word文档
  14. 制作一款精美的 Qt IFW 安装程序
  15. 鸟哥的Linux私房菜 读书笔记
  16. 如何解决跟这台计算机连接的一个usb设备运行不正常
  17. XAI Explainable AI 模型可解释性(3)
  18. K-means聚类分析
  19. FastStone Capture安装包正版激活码使用说明
  20. Spring Kafka实战(3)—message listener创建方式探讨

热门文章

  1. 简述新图像文件格式——SVG
  2. LeetCode1619删除某些元素后的数组均值(java)
  3. usb xhci babble error问题解决
  4. CJOJ 1659 【中学高级本】倒酒
  5. elementUI el-table 动态添加一行且保证每行数据相互独立,防止v-for影响每行
  6. Swarm and shipyard
  7. 「学IT一定要看」一些学习的建议
  8. [netfilter]-ip_rcv包转发流程
  9. 民宿平台airbnb是如何动态定价的
  10. MAC 升级php 到7.1