开发者

How to generate 2D gaussian with Python?

I can generate Gaussian data with random.gauss(mu, sigma) function, but how can I generate 2D gaussian? Is there any fun开发者_运维问答ction like that?


If you can use numpy, there is numpy.random.multivariate_normal(mean, cov[, size]).

For example, to get 10,000 2D samples:

np.random.multivariate_normal(mean, cov, 10000)

where mean.shape==(2,) and cov.shape==(2,2).


I'd like to add an approximation using exponential functions. This directly generates a 2d matrix which contains a movable, symmetric 2d gaussian.

I should note that I found this code on the scipy mailing list archives and modified it a little.

import numpy as np

def makeGaussian(size, fwhm = 3, center=None):
    """ Make a square gaussian kernel.

    size is the length of a side of the square
    fwhm is full-width-half-maximum, which
    can be thought of as an effective radius.
    """

    x = np.arange(0, size, 1, float)
    y = x[:,np.newaxis]

    if center is None:
        x0 = y0 = size // 2
    else:
        x0 = center[0]
        y0 = center[1]

    return np.exp(-4*np.log(2) * ((x-x0)**2 + (y-y0)**2) / fwhm**2)

For reference and enhancements, it is hosted as a gist here. Pull requests welcome!


Since the standard 2D Gaussian distribution is just the product of two 1D Gaussian distribution, if there are no correlation between the two axes (i.e. the covariant matrix is diagonal), just call random.gauss twice.

def gauss_2d(mu, sigma):
    x = random.gauss(mu, sigma)
    y = random.gauss(mu, sigma)
    return (x, y)


import numpy as np

# define normalized 2D gaussian
def gaus2d(x=0, y=0, mx=0, my=0, sx=1, sy=1):
    return 1. / (2. * np.pi * sx * sy) * np.exp(-((x - mx)**2. / (2. * sx**2.) + (y - my)**2. / (2. * sy**2.)))

x = np.linspace(-5, 5)
y = np.linspace(-5, 5)
x, y = np.meshgrid(x, y) # get 2D variables instead of 1D
z = gaus2d(x, y)

Straightforward implementation and example of the 2D Gaussian function. Here sx and sy are the spreads in x and y direction, mx and my are the center coordinates.


Numpy has a function to do this. It is documented here. Additionally to the method proposed above it allows to draw samples with arbitrary covariance.

Here is a small example, assuming ipython -pylab is started:

samples = multivariate_normal([-0.5, -0.5], [[1, 0],[0, 1]], 1000)
plot(samples[:, 0], samples[:, 1], '.')

samples = multivariate_normal([0.5, 0.5], [[0.1, 0.5],[0.5, 0.6]], 1000)
plot(samples[:, 0], samples[:, 1], '.')


In case someone find this thread and is looking for somethinga little more versatile (like I did), I have modified the code from @giessel. The code below will allow for asymmetry and rotation.

import numpy as np

def makeGaussian2(x_center=0, y_center=0, theta=0, sigma_x = 10, sigma_y=10, x_size=640, y_size=480):
    # x_center and y_center will be the center of the gaussian, theta will be the rotation angle
    # sigma_x and sigma_y will be the stdevs in the x and y axis before rotation
    # x_size and y_size give the size of the frame 

    theta = 2*np.pi*theta/360
    x = np.arange(0,x_size, 1, float)
    y = np.arange(0,y_size, 1, float)
    y = y[:,np.newaxis]
    sx = sigma_x
    sy = sigma_y
    x0 = x_center
    y0 = y_center

    # rotation
    a=np.cos(theta)*x -np.sin(theta)*y
    b=np.sin(theta)*x +np.cos(theta)*y
    a0=np.cos(theta)*x0 -np.sin(theta)*y0
    b0=np.sin(theta)*x0 +np.cos(theta)*y0

    return np.exp(-(((a-a0)**2)/(2*(sx**2)) + ((b-b0)**2) /(2*(sy**2))))


We can try just using the numpy method np.random.normal to generate a 2D gaussian distribution. The sample code is np.random.normal(mean, sigma, (num_samples, 2)).

A sample run by taking mean = 0 and sigma 20 is shown below :

np.random.normal(0, 20, (10,2))

>>array([[ 11.62158316,   3.30702215],
   [-18.49936277, -11.23592946],
   [ -7.54555371,  14.42238838],
   [-14.61531423,  -9.2881661 ],
   [-30.36890026,  -6.2562164 ],
   [-27.77763286, -23.56723819],
   [-18.18876597,  41.83504042],
   [-23.62068377,  21.10615509],
   [ 15.48830184, -15.42140269],
   [ 19.91510876,  26.88563983]])

Hence we got 10 samples in a 2d array with mean = 0 and sigma = 20

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜