How can I make my 2D Gaussian fit to my image

匿名 (未验证) 提交于 2019-12-03 01:09:02

问题:

I am trying to fit a 2D Gaussian to an image to find the location of the brightest point in it. My code looks like this:

import numpy as np import astropy.io.fits as fits import os from astropy.stats import mad_std from scipy.optimize import curve_fit import matplotlib.pyplot as plt from matplotlib.patches import Circle from lmfit.models import GaussianModel from astropy.modeling import models, fitting  def gaussian(xycoor,x0, y0, sigma, amp):     '''This Function is the Gaussian Function'''      x, y = xycoor # x and y taken from fit function.  Stars at 0, increases by 1, goes to length of axis     A = 1 / (2*sigma**2)     eq =  amp*np.exp(-A*((x-x0)**2 + (y-y0)**2)) #Gaussian     return eq   def fit(image):     med = np.median(image)     image = image-med     image = image[0,0,:,:]      max_index = np.where(image >= np.max(image))     x0 = max_index[1] #Middle of X axis     y0 = max_index[0] #Middle of Y axis     x = np.arange(0, image.shape[1], 1) #Stars at 0, increases by 1, goes to length of axis     y = np.arange(0, image.shape[0], 1) #Stars at 0, increases by 1, goes to length of axis     xx, yy = np.meshgrid(x, y) #creates a grid to plot the function over     sigma = np.std(image) #The standard dev given in the Gaussian     amp = np.max(image) #amplitude     guess = [x0, y0, sigma, amp] #The initial guess for the gaussian fitting      low = [0,0,0,0] #start of data array     #Upper Bounds x0: length of x axis, y0: length of y axis, st dev: max value in image, amplitude: 2x the max value     upper = [image.shape[0], image.shape[1], np.max(image), np.max(image)*2]      bounds = [low, upper]      params, pcov = curve_fit(gaussian, (xx.ravel(), yy.ravel()), image.ravel(),p0 = guess, bounds = bounds) #optimal fit.  Not sure what pcov is.       return params   def plotting(image, params):     fig, ax = plt.subplots()     ax.imshow(image)     ax.scatter(params[0], params[1],s = 10, c = 'red', marker = 'x')     circle = Circle((params[0], params[1]), params[2], facecolor = 'none', edgecolor = 'red', linewidth = 1)      ax.add_patch(circle)     plt.show()  data = fits.getdata('AzTECC100.fits') #read in file med = np.median(data)  data = data - med  data = data[0,0,:,:]  parameters = fit(data)  #generates a gaussian based on the parameters given plotting(data, parameters) 

The image is plotting and the code is giving no errors but the fitting isn't working. It's just putting an x wherever the x0 and y0 are. The pixel values in my image are very small. The max value is 0.0007 and std dev is 0.0001 and the x and y are a few orders of magnitude larger. So I believe my problem is that because of this my eq is going to zero everywhere so the curve_fit is failing. I'm wondering if there's a better way to construct my gaussian so that it plots correctly?

回答1:

I do not have access to your image. Instead I have generated some test "image" as follows:

y, x = np.indices((51,51)) x -= 25 y -= 25 data = 3 * np.exp(-0.7 * ((x+2)**2 + (y-1)**2)) 

Also, I have modified your code for plotting to increase the radius of the circle by 10:

circle = Circle((params[0], params[1]), 10 * params[2], ...) 

and I commented out two more lines:

# image = image[0,0,:,:] # data = data[0,0,:,:] 

The result that I get is shown in the attached image and it looks reasonable to me:

Could it be that the issue is in how you access data from the FITS file? (e.g., image = image[0,0,:,:]) Are the data 4D array? Why do you have 4 indices?

I also saw that you have asked a similar question here: Astropy.model 2DGaussian issue in which you tried to use just astropy.modeling. I will look into that question.


NOTE: you can replace code such as

max_index = np.where(image >= np.max(image)) x0 = max_index[1] #Middle of X axis y0 = max_index[0] #Middle of Y axis 

with

y0, x0 = np.unravel_index(np.argmax(data), data.shape) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!