如何将浮点数数组插值平滑地填充到更大的数组中?

12

我在Swift中卡住了插值。有人能帮我吗?

我想将浮点数组(例如[0,0,100,25,0,0,0,25,0,0,0])插入到另一个给定大小的数组中(例如128)。我找到了一篇文章(使用线性插值构造新数据点),展示了如何实现这个东西。

有两种方式(可以看到下面的结果,它们的表现如何):

  • 使用vDSP_vgenp进行线性插值和
  • 更平滑(但不适用于我的目的)的插值使用vDSP_vlint

问题是这两种技术都没有实现我的期望,这在截图3中说明。如何使我的插值分布更平滑?我想看到一个立方体状的曲线

初始图:

Screenshot 1

线性插值:

import Accelerate

let n = vDSP_Length(128)
let stride = vDSP_Stride(1)

let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let indices: [Float] = [0, 11, 23, 34, 46, 58, 69, 81, 93, 104, 116]

var result = [Float](repeating: 0, count: Int(n))

vDSP_vgenp(values, stride, indices, stride, &result, stride, n, vDSP_Length(values.count))

截图2

平滑插值:

import Accelerate
import AVFoundation

let n = vDSP_Length(1024)
let stride = vDSP_Stride(1)

let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let denominator = Float(n) / Float(values.count - 1)

let control: [Float] = (0 ... n).map {
    let x = Float($0) / denominator
    return floor(x) + simd_smoothstep(0, 1, simd_fract(x))
}

var result = [Float](repeating: 0, count: Int(n))

vDSP_vlint(values, control, stride, &result, stride, n, vDSP_Length(values.count))

屏幕截图3


9
我虽然无法回答你的问题,但我必须说,这是一个非常好的问题,特别是对于第一次发帖的人来说!清晰的问题陈述、展示了努力的证明、代码示例、实际与预期结果。做得很好,欢迎! - Alexander
非常感谢@Alexander-ReinstateMonica!我尽力展示了我想解决的问题^_^ - aibek
1个回答

0

可能吧。我见过这个函数,但不知道参数应该是什么样子的,尤其是第二个参数_ __B: UnsafePointer<Float>。他们说:“单精度实数输入向量。整数部分是索引A中的下标,小数部分是插值常量”。对我来说没有头绪,什么是小数和什么是整数部分。也许您能解释一下吗? - aibek
参数与您在线性插值函数中使用的相同。诀窍是更改输入函数及其坐标(以及所需的输出坐标),使它们很好地重叠。调整输入函数,使其形式为f(i),其中i是整数序列(从0到max)。然后调整所需的输出函数g(j),使其坐标沿着相同的轴落在值也在0到max之间。这些输出函数坐标通常会落在输入函数中使用的整数值之间的某个位置。 - KeithB
@aiba 单精度向量和双精度向量,只是指Float和Double。如果您查看文档,您会发现只有指针类型发生了变化 https://developer.apple.com/documentation/accelerate/1449771-vdsp_vgenp https://developer.apple.com/documentation/accelerate/1450645-vdsp_vgenpd我认为这也在Swift文档的浮点数部分得到了很好的解释 https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html您还可以打印Float.pi和Double.pi的值,以查看它们之间的区别。 - Steven
3
整数部分在逗号之前,小数部分在逗号之后。此外,我认为你需要进行三次样条插值而不是线性插值。我还没有找到如何使用Accelerate Framework实现这一点,但是有一个可以做同样事情的库。https://github.com/gscalzo/SwiftCubicSpline - Steven
1
谢谢大家的回答!我采用了@Steven的建议并使用了CubicSpline。 - aibek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接