Here I will cover a method of generating a 2 dimensional gaussian very fast and to the finest resolution available when using integer storage.

Let's declare a Gaussian interface using a simple singleton construct:

class Gaussian { private: static Gaussian *singleton; //!< the singleton pointer public: static float *table; //!< table of gaussian values static unsigned int tablesize;//!< gaussian table size Gaussian(unsigned int size); ~Gaussian(); //! call this when you want to delete the interface static void Delete() { delete singleton; } //! generates a quantized 2d gaussian distribution into an integer array //! notes: it is up to the caller to delete the array after they are done using it //! size works better if it is not divisible by 2 for symmetry purposes //! scale is the maximum of the gaussian; the map will fall off to 0 at the edge from quantization static unsigned int *GenerateMap(unsigned char size, float scale); };

You can also use an STL::vector for the 1d reference table.

Now onto the actual meat:

#define GAUSSEXPMAX 10.f //!< values less than e^-10 are assumed to be 0 // initialize our stuff float *Gaussian::table= 0; unsigned int Gaussian::tablesize= 0; Gaussian *Gaussian::singleton= 0; Gaussian::Gaussian(unsigned int size) { singleton= this; tablesize= size; table= new float[size]; // generates a 1d reference table of values of e^0 to e^-10 // values beyond e^-GAUSSEXPMAX are assumed to be about 0 for (unsigned short x= 0; x < size; ++x) table[x]= expf(-x*GAUSSEXPMAX/size); } Gaussian::~Gaussian() { delete []table; singleton= 0; }

What follows is the main quantized 2d map generator; this could be easily expanded to make an N-dimensional gaussian. The 2d map (size x size) is returned by the function as a 1d array but the caller already knows the width of the 2d array from the size parameter. The scale is the value to scale the gaussian curve by, higher values result in a taller curve.

unsigned int *Gaussian::GenerateMap(unsigned char size, float scale) { unsigned int *array, *array_ptr, index; int x, y, min= -size/2, max= (size+1)/2; unsigned int y_sq; float std_dev; // allocate room for the gaussian map array_ptr= array= new unsigned int[size*size]; // trust me on this derivation std_dev= (float)( size/(2*sqrt(2*log(scale))) ); // precalculate the scaling factor to be multiplied by distance^2 // the -GAUSSEXPMAX factors out from the table generation std_dev= tablesize / (2*std_dev*std_dev * GAUSSEXPMAX); // generate the map for (y= min; y < max; ++y) { y_sq= y*y; for (x= min; x < max; ++x) { index= (unsigned int)( (x*x + y_sq)*std_dev ); // get the power to raise e to if (index > tablesize-1) index= tablesize-1; // prevent overflow *array_ptr++= (unsigned int)(table[(unsigned short)index]*scale); } } return array; }That's pretty much it. Accessing the gaussian map is as simple as Gaussian::table[0 ... Gaussian::tablesize]

No Comments yet, be the first!