我正在研究一个项目,我试图在kymograph中模拟对象的移动。为此,我将曲线拟合到图像中的每行像素,并附加顶点的位置以近似模拟图像中对象的位置。下面是一个示例图片。
正如您所看到的,在时间序列的早期(图像顶部),对象的位置很好地聚焦,并且可以使用高斯曲线轻松建模。然而,接近时间序列的末尾(在图像的底部),峰值更加分散。我怀疑图像底部的数据将通过建模泊松分布的曲线(下图,右图)更紧密地拟合,而图像顶部/中间的数据将通过高斯更紧密地拟合或多项式曲线(下图,左图)。
对于每行像素,是否有任何方法可以为同一数据拟合多条曲线,然后根据最小二乘拟合对每一条曲线进行评分?通过这种方式,我可以(希望)在模型中途切换模型,以适应我想要跟踪的对象的变化行为。我目前的代码如下:
from PIL import Image
def populateData(picture) :
"""Open an image and populate a list of lists with the grayscale value"""
im = Image.open(picture)
size = im.size
width = size[0]
height = size[1]
allPixels = list(im.getdata())
pixelList = [allPixels[width*i :
width * (i+1)] for i in range(height)]
return(pixelList)
rawData = populateData("testTop.tif")
import numpy as np
from scipy.optimize import curve_fit
def findVertex(listOfRows) :
xList = []
for row in listOfRows :
x = np.arange(len(row))
ffunc = lambda x, a, x0, s: a*np.exp(-0.5*(x-x0)**2/s**2)
p, _ = curve_fit(ffunc, x, row, p0=[100,5,2])
x0 = p[1]
xList.append(x0)
xArray = np.array(xList)
return(xArray)
xValues = findVertex(rawData)
def buildRows(listOfRows) :
yArray = np.arange(len(listOfRows))
return(yArray)
yValues = buildRows(rawData)
from matplotlib import pyplot as plt
from scipy import ndimage
image = ndimage.imread("testTop.tif",flatten=True)
fig = plt.figure()
axes = fig.add_subplot(111)
axes.imshow(image)
axes.plot(xValues, yValues, 'k-')
axes.set_title('testLine')
axes.grid()
axes.set_xlabel('x')
axes.set_ylabel('time')
plt.show()
编辑: 这是我用作输入的文件(testTop.tif)
答案 0 :(得分:0)
您需要在拟合和数据之间找出某种形式的goodness of fit。取当前拟合(高斯)与数据之间的平方差之和除以方差。
sumerrsq = 0.
for i in range(yValues.shape[0]):
sumerrsq += np.power(yValues[i] - xValues[i],2)
goodfit = np.sqrt(sumerrsq/var)
我认为你可以使用曲线拟合的第二个输出(协方差)来得到方差,
p, pcov = curve_fit(ffunc, x, row, p0=[100,5,2])
var = np.diag(pcov)
然后您可以检查goodfit的值,如果还不够,请切换到其他分布。在使用不同的分布时,您可能需要使用不同的误差估计(这假设误差是正态分布的)。
注意,没有数据(并且不确定哪个数组是哪个)我无法测试任何此代码...
答案 1 :(得分:0)
根据curve_fit
docs:
要使用
perr = np.sqrt(np.diag(pcov))
计算参数的一个标准差错误。
因此,如果这是您要比较的值,那么您可以从curve_fit
(您当前分配给_
的那个)获取第二个返回值,使用它来计算{{ 1}}如上所述,并比较多条曲线之间的误差。
答案 2 :(得分:0)
我建议您使用2D拟合模型。 1d高斯分布是基础,但均值和方差取决于位置和时间。然后,您可以根据2D图像数据拟合模型。
如果你想继续使用你的方法,看起来它只是你需要调整的均值和方差的起始值,以便更好地适应大量时间的线。
对于您的问题,您可以为所需的任何分数函数建模,因此您可以执行以下操作:
def score(x,y):
if x < 10:
return x**2 - y
else:
return x - y
因此,为了使用不同范围内的两个不同模型,请遵循此示例。