直接比较两个光谱之间的亚像素位移-并获得可信的误差


9

我有同一个天文物体的两个光谱。基本问题是:如何计算这些光谱之间的相对位移,并在该位移上获得准确的误差?

如果您仍在我身边,请提供更多详细信息。每个光谱将是一个具有x值(波长),y值(通量)和误差的数组。波长偏移将是子像素。假设像素是规则间隔的,并且将只有一个波长偏移应用于整个光谱。因此,最终答案将类似于:0.35 +/- 0.25像素。

这两个光谱将是许多无特征的连续体,它们被一些不容易建模(且不是周期性的)的相当复杂的吸收特征(凹陷)所打断。我想找到一种直接比较两个光谱的方法。

每个人的第一个本能是进行互相关,但是随着子像素的移动,您将不得不在光谱之间进行插值(首先要进行平滑处理?),而且,错误似乎很难纠正。

我目前的方法是通过与高斯核卷积来平滑数据,然后对平滑结果进行样条化处理,并比较两个样条化谱线-但我不信任它(尤其是错误)。

有人知道正确执行此操作的方法吗?

这是一个简短的python程序,将产生两个可以播放的玩具光谱,这些光谱偏移了0.4个像素(写在toy1.ascii和toy2.ascii中)。即使此玩具模型使用了简单的高斯特征,也要假设实际数据不能与简单的模型拟合。

import numpy as np
import random as ra
import scipy.signal as ss
arraysize = 1000
fluxlevel = 100.0
noise = 2.0
signal_std = 15.0
signal_depth = 40.0
gaussian = lambda x: np.exp(-(mu-x)**2/ (2 * signal_std))
mu = 500.1
np.savetxt('toy1.ascii', zip(np.arange(arraysize), np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth), np.ones(arraysize) * noise))
mu = 500.5
np.savetxt('toy2.ascii', zip(np.arange(arraysize), np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth), np.ones(arraysize) * noise))

如果我理解正确,那么问题听起来与图像配准类似,只是您在一个轴上只有一个线性子像素移位。也许尝试诸如相位相关之类的标准图像配准技术?
Paul R

如果您在一个信号中存在纯粹的延迟(即您所说的波长参数的偏移),则可以利用傅立叶变换属性将时间延迟转换为频域中的线性相位偏移。如果两个样本没有因不同的测量噪声或干扰而损坏,这可能会起作用。
杰森R

1
这个线程可能是useful- dsp.stackexchange.com/questions/2321/...
吉姆·克莱

1
您有可测试的实际数据吗?您给出的噪声值太大,以至于互相关无法精确到子样本。这是它在多次噪声2.0和偏移0.7(在绘图的x轴上= 1000.7)运行时发现的,例如:i.stack.imgur.com/UK5JD.png
endolith 2012年

Answers:


5

我认为使用互相关并内插峰会很好。如互相关之前的上采样有用吗?,在互相关之前进行插值或上采样实际上并不会为您提供更多信息。有关子样本峰的信息包含在其周围的样本中。您只需要以最小的错误提取它。我在这里收集了一些笔记。

最简单的方法是二次/抛物线插值,这是我有一个Python示例这里如果您的光谱是基于高斯窗口,或者峰恰好恰好落在样本之间的中点,那应该是准确的,但否则会有些误差。因此,在您的情况下,您可能想使用更好的东西。

这是更复杂但更准确的估算器列表。“在以上方法中,奎因的第二个估计量的RMS误差最小。”

我不知道数学原理,但是本文说,他们的抛物线插补理论上的准确度是FFT箱宽度的5%。

在互相关输出上使用FFT插值不会有任何偏差误差,因此,如果您想要非常好的精度,那是最好的。如果需要在精度和计算速度之间取得平衡,建议先进行一些FFT插值,然后再进行其他估计之一的处理,以获得“足够好”的结果。

这仅使用抛物线拟合,但是如果噪声很低,它将为偏移量输出正确的值:

def parabolic_polyfit(f, x, n):
    a, b, c = polyfit(arange(x-n//2, x+n//2+1), f[x-n//2:x+n//2+1], 2)
    xv = -0.5 * b/a
    yv = a * xv**2 + b * xv + c

    return (xv, yv)

arraysize = 1001
fluxlevel = 100.0
noise = 0.3 # 2.0 is too noisy for sub-sample accuracy
signal_std = 15.0
signal_depth = 40.0
gaussian = lambda x: np.exp(-(mu-x)**2/ (2 * signal_std))
mu = 500.1
a_flux = np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth)
mu = 500.8
b_flux = np.array([ra.normalvariate(fluxlevel, noise) for x in range(arraysize)] - gaussian(np.arange(arraysize)) * signal_depth)

a_flux -= np.mean(a_flux)
b_flux -= np.mean(b_flux)

corr = ss.fftconvolve(b_flux, a_flux[::-1])

peak = np.argmax(corr)
px, py = parabolic_polyfit(corr, peak, 13)

px = px - (len(a_flux) - 1)
print px

在此处输入图片说明 在此处输入图片说明

样本中的噪声产生的结果变化幅度大于整个样本,因此我降低了噪声。使用更多的峰点拟合曲线有助于在某种程度上收紧估计,但是我不确定这是否在统计上有效,并且对于较低噪声的情况,这实际上会使估计更糟。

在噪声= 0.2和三点拟合的情况下,对于偏移= 0.4,它给出的值为0.398和0.402。

在噪声= 2.0和13点拟合的情况下,对于偏移= 0.4,它给出的值为0.156和0.595。


我正在尝试解决此确切的图像注册问题。我需要亚像素精度(0.1可能就足够了),但最重要的是不需要偏差,因此插值方法不起作用。有什么好的(并在python中实现的)方法吗?零填充方法可以使用,但是太昂贵了,无法实用。
keflavich 2012年

@kelavich:您是否测试了所有插值方法并发现不可接受的偏差?建议的方法是组合了一些零填充,然后由低错误插值。我不知道其他任何方法,但是我敢打赌,这将为您提供足够的准确性。
endolith

是的,我发现线性和二阶插值中的偏差不可接受。我已经尝试过FFT零填充,但是结果却以高频振铃为主……您是否有可能添加零填充示例?
keflavich 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.