查看: 5906|回复: 3

ValueError: object too deep for desired array

[复制链接]

11

主题

80

帖子

199

积分

注册会员

Rank: 2

积分
199
发表于 2018-9-27 10:39:46 | 显示全部楼层 |阅读模式
我打算将二维高斯函数拟合到显示激光束的图像上,以得到其参数如FWHM和位置。到目前为止,我试图理解如何在Python中定义一个二维高斯函数,以及如何将x和y变量传递给它。
我编写了一个小脚本,它定义了这个函数,绘制了它,给它添加了一些噪声,然后尝试使用curve_fit来匹配它。一切似乎都在工作,除了最后一个步骤,我试图使我的模型函数适应嘈杂的数据。这是我的代码:
  1. import scipy.optimize as opt
  2. import numpy as np
  3. import pylab as plt


  4. #define model function and pass independant variables x and y as a list
  5. def twoD_Gaussian((x,y), amplitude, xo, yo, sigma_x, sigma_y, theta, offset):
  6.     xo = float(xo)
  7.     yo = float(yo)   
  8.     a = (np.cos(theta)**2)/(2*sigma_x**2) + (np.sin(theta)**2)/(2*sigma_y**2)
  9.     b = -(np.sin(2*theta))/(4*sigma_x**2) + (np.sin(2*theta))/(4*sigma_y**2)
  10.     c = (np.sin(theta)**2)/(2*sigma_x**2) + (np.cos(theta)**2)/(2*sigma_y**2)
  11.     return offset + amplitude*np.exp( - (a*((x-xo)**2) + 2*b*(x-xo)*(y-yo) + c*((y-yo)**2)))

  12. # Create x and y indices
  13. x = np.linspace(0, 200, 201)
  14. y = np.linspace(0, 200, 201)
  15. x,y = np.meshgrid(x, y)

  16. #create data
  17. data = twoD_Gaussian((x, y), 3, 100, 100, 20, 40, 0, 10)

  18. # plot twoD_Gaussian data generated above
  19. plt.figure()
  20. plt.imshow(data)
  21. plt.colorbar()

  22. # add some noise to the data and try to fit the data generated beforehand
  23. initial_guess = (3,100,100,20,40,0,10)

  24. data_noisy = data + 0.2*np.random.normal(size=len(x))

  25. popt, pcov = opt.curve_fit(twoD_Gaussian, (x,y), data_noisy, p0 = initial_guess)
复制代码

得到一个错误
ValueError: object too deep for desired array
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python\WinPython-64bit-2.7.6.2\python-2.7.6.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 540, in runfile
    execfile(filename, namespace)
  File "E:/Work Computer/Software/Python/Fitting scripts/2D Gaussian function fit/2D_Gaussian_LevMarq_v2.py", line 39, in <module>
    popt, pcov = opt.curve_fit(twoD_Gaussian, (x,y), data_noisy, p0 = initial_guess)
  File "C:\Python\WinPython-64bit-2.7.6.2\python-2.7.6.amd64\lib\site-packages\scipy\optimize\minpack.py", line 533, in curve_fit
    res = leastsq(func, p0, args=args, full_output=1, **kw)
  File "C:\Python\WinPython-64bit-2.7.6.2\python-2.7.6.amd64\lib\site-packages\scipy\optimize\minpack.py", line 378, in leastsq
    gtol, maxfev, epsfcn, factor, diag)
minpack.error: Result from function call is not a proper array of floats.
回复

使用道具 举报

9

主题

74

帖子

185

积分

注册会员

Rank: 2

积分
185
发表于 2018-9-27 10:41:41 | 显示全部楼层
twoD_Gaussian输出为1D。您可以做的是在最后一行的末尾添加.ravel(),如下所示:
  1. def twoD_Gaussian((x, y), amplitude, xo, yo, sigma_x, sigma_y, theta, offset):
  2.     xo = float(xo)
  3.     yo = float(yo)   
  4.     a = (np.cos(theta)**2)/(2*sigma_x**2) + (np.sin(theta)**2)/(2*sigma_y**2)
  5.     b = -(np.sin(2*theta))/(4*sigma_x**2) + (np.sin(2*theta))/(4*sigma_y**2)
  6.     c = (np.sin(theta)**2)/(2*sigma_x**2) + (np.cos(theta)**2)/(2*sigma_y**2)
  7.     g = offset + amplitude*np.exp( - (a*((x-xo)**2) + 2*b*(x-xo)*(y-yo)
  8.                             + c*((y-yo)**2)))
  9.     return g.ravel()
复制代码

需要重新构造用于绘图的输出,例如:
  1. # Create x and y indices
  2. x = np.linspace(0, 200, 201)
  3. y = np.linspace(0, 200, 201)
  4. x, y = np.meshgrid(x, y)

  5. #create data
  6. data = twoD_Gaussian((x, y), 3, 100, 100, 20, 40, 0, 10)

  7. # plot twoD_Gaussian data generated above
  8. plt.figure()
  9. plt.imshow(data.reshape(201, 201))
  10. plt.colorbar()
  11. Do the fitting as before:
  12. # add some noise to the data and try to fit the data generated beforehand
  13. initial_guess = (3,100,100,20,40,0,10)

  14. data_noisy = data + 0.2*np.random.normal(size=data.shape)

  15. popt, pcov = opt.curve_fit(twoD_Gaussian, (x, y), data_noisy, p0=initial_guess)
  16. And plot the results:
  17. data_fitted = twoD_Gaussian((x, y), *popt)

  18. fig, ax = plt.subplots(1, 1)
  19. ax.hold(True)
  20. ax.imshow(data_noisy.reshape(201, 201), cmap=plt.cm.jet, origin='bottom',
  21.     extent=(x.min(), x.max(), y.min(), y.max()))
  22. ax.contour(x, y, data_fitted.reshape(201, 201), 8, colors='w')
  23. plt.show()
复制代码
回复

使用道具 举报

22

主题

107

帖子

266

积分

中级会员

Rank: 3Rank: 3

积分
266
发表于 2018-9-27 10:42:26 | 显示全部楼层
  1. def twoD_Gaussian(xdata_tuple, amplitude, xo, yo, sigma_x, sigma_y, theta, offset):
  2.     (x, y) = xdata_tuple                                                        
  3.     xo = float(xo)                                                              
  4.     yo = float(yo)                                                              
  5.     a = (np.cos(theta)**2)/(2*sigma_x**2) + (np.sin(theta)**2)/(2*sigma_y**2)   
  6.     b = -(np.sin(2*theta))/(4*sigma_x**2) + (np.sin(2*theta))/(4*sigma_y**2)   
  7.     c = (np.sin(theta)**2)/(2*sigma_x**2) + (np.cos(theta)**2)/(2*sigma_y**2)   
  8.     g = offset + amplitude*np.exp( - (a*((x-xo)**2) + 2*b*(x-xo)*(y-yo)         
  9.                         + c*((y-yo)**2)))                                   
  10.     return g.ravel()
复制代码
回复

使用道具 举报

4

主题

37

帖子

98

积分

注册会员

Rank: 2

积分
98
发表于 2018-9-27 10:43:29 | 显示全部楼层
curve_fit()希望xdata的维度为(2,n*m)而不是(2,n,m)。ydata应该分别有形状(n*m)而不是(n,m)。因此,可以使用ravel()将2D数组压平:
  1. xdata = np.vstack((xx.ravel(),yy.ravel()))
  2. ydata = data_noisy.ravel()
  3. popt, pcov = opt.curve_fit(twoD_Gaussian, xdata, ydata, p0=initial_guess)
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表