latest version v1.9 - last update 10 Apr 2010 |
Estimates the position of M overlapping blobs by applying the EM-algorithm and estimating the parameters of a gaussian mixture model that fits the blobs. More...
#include <ltiBlobEM.h>
Classes | |
class | gaussEllipse |
An internal class of lti::blobEM for handling 2D gaussian ellipses. More... | |
class | parameters |
the parameters for the class blobEM More... | |
Public Member Functions | |
blobEM () | |
blobEM (const blobEM &other) | |
virtual | ~blobEM () |
virtual const char * | getTypeName () const |
bool | apply (const channel8 &src, std::vector< gaussEllipse > &elem) |
bool | apply (const channel8 &src, const int &components) |
blobEM & | copy (const blobEM &other) |
blobEM & | operator= (const blobEM &other) |
virtual functor * | clone () const |
const parameters & | getParameters () const |
Manual control | |
bool | initialize (const channel8 &src, const std::vector< gaussEllipse > &elem) |
bool | initialize (const channel8 &src, const int &components) |
double | iterate () |
bool | computeEllipses (std::vector< gaussEllipse > &ellipses) |
void | reset () |
State access | |
const int & | getIterations () const |
const int & | getM () const |
const int & | getN () const |
const std::vector< double > & | getAlphas () const |
const std::vector< tpoint < double > > & | getCenters () const |
const std::vector< matrix < double > > & | getCovariances () const |
const double & | getQ () const |
const double & | getQDiff () const |
Estimates the position of M overlapping blobs by applying the EM-algorithm and estimating the parameters of a gaussian mixture model that fits the blobs.
As input a distance transformed image of the blobs or similar is expected and a vector of ellipses for representing a gaussian distribution component.
For a description of the EM-algorithm see Jeff Bilmes A Gentle Tutorial of the EM Algorithm and its Application to Parameter Estimation for Gaussian Mixture and Hidden Markov Models, Technical Report TR-97-021 by the International Computer Science Institute, Berkeley, Ca.
For usage of this functor please see the following examples and hints:
// Typedef for better readability typedef lti::blobEM::gaussEllipse TEllipse; // Vector of ellipses std::vector<TEllipse>& allEllipses; // Create one ellipse with center(10,10), eigenvalues 100 and 20 // and 45 degrees orientation TEllipse oneEllipse(lti::tpoint<double>(10,10),100,20,lti::Pi/4); // Constrain ellipse properties oneEllipse.constrainShape = true; oneEllipse.constrainArea = true; oneEllipse.areaTolerance = 0.2; oneEllipse.constrainAngle = true; oneEllipse.angleTolerance = lti::Pi/8; // Create another ellipse with the same properties as the first // but center(50,50). This ellipse will be unconstrained (default) TEllipse anotherEllipse; anotherEllipse.fromEllipse(oneEllipse); // is not copy operator! // copies only properties // angle, center, lambda1,2 anotherEllipse.center = lti::tpoint<double>(50,50); allEllipses.push_back(oneEllipse); allEllipses.push_back(anotherEllipse);
// prepare functor lti::blobEM em; lti::blobEM::parameters emParam; emParam.maxIterations = 10; // number of maximum allowed iterations emParam.convergenceThreshold = -1; // force maximum iterations em.setParameters(emParam); ////////////////////////////////////////////////////////////////////////// // Apply with allEllipses but make sure that initialization is good, // since result stongly depends on initialization. // Result will be delivered back in allEllipses. aChnl8 should be a // distance transform of a binary image (see lti::distanceTransform) em.apply(aChnl8,allEllipses); ////////////////////////////////////////////////////////////////////////// // Alternatively you can apply without knowing how to initialize by // merely specifying the number of ellipses (here 2). These will be // set randomly then. // You must explicitly request the resulting ellipses afterwards // by calling computeEllipses(...) em.apply(aChnl8,2); em.computeEllipses(allEllipses); ////////////////////////////////////////////////////////////////////////// // Another possibility is to control the iterations manually em.initialize(aChnl8,allEllipses); // OR em.initialize(aChnl8,2); // perfom iterations em.iterate(); em.iterate(); while (em.getQDiff()>0) { // the Q value is maximized by EM. QDiff will be > 0 // As long as Q increases. To get valid QDiff, we have // to perform two iterations before this loop. em.iterate(); } em.computeEllipses(allEllipses); // If you are interested in the internal state of the functor use // the getXXX(...) methods, which deliver const references (i.e. // you don't have to copy them, if you only want to see them) std::vector< lti::matrix<double> >& covariances = em.getCovariances(); std::vector< lti::vector<double> >& centers = em.getCenters(); std::vector< double >& alphas = em.getAlphas(); // For a description of their meaning refer to the given bibliography
lti::blobEM::blobEM | ( | ) |
default constructor
lti::blobEM::blobEM | ( | const blobEM & | other | ) |
copy constructor
other | the object to be copied |
virtual lti::blobEM::~blobEM | ( | ) | [virtual] |
destructor
bool lti::blobEM::apply | ( | const channel8 & | src, | |
const int & | components | |||
) |
Calls initialize() once, then iterate() several times until maximum number of iterations or abortion criterion reached (percental increase of Q value below given threshold).
src | channel8 with the source data. Should be distance transform of a binary image. | |
components | number of mixture components. Will be initialized randomly. For deterministic initialization use other apply method. |
bool lti::blobEM::apply | ( | const channel8 & | src, | |
std::vector< gaussEllipse > & | elem | |||
) |
Calls initialize() once, then iterate() several times until maximum number of iterations or abortion criterion reached (percental increase of Q value below given threshold).
src | channel8 with the source data. Should be distance transform of a binary image. | |
elem | vector of blobEM::gaussEllipse with initial distribution parameters, represented by 2D-ellipses. Result of EM iteration is also left here. |
virtual functor* lti::blobEM::clone | ( | ) | const [virtual] |
returns a pointer to a clone of this functor.
Implements lti::functor.
bool lti::blobEM::computeEllipses | ( | std::vector< gaussEllipse > & | ellipses | ) |
compute and return ellipses based on internal covariances and centers
copy data of "other" functor.
other | the functor to be copied |
Reimplemented from lti::functor.
const std::vector<double>& lti::blobEM::getAlphas | ( | ) | const |
Access the vector of the M mixture component weights.
const std::vector<tpoint<double> >& lti::blobEM::getCenters | ( | ) | const |
Access the centers of the M center components.
const std::vector<matrix<double> >& lti::blobEM::getCovariances | ( | ) | const |
Access the covariance matrices of the M center components.
const int& lti::blobEM::getIterations | ( | ) | const |
Access the number of iterations so far.
const int& lti::blobEM::getM | ( | ) | const |
Access the number of components.
const int& lti::blobEM::getN | ( | ) | const |
Access the number of data elements considered.
const parameters& lti::blobEM::getParameters | ( | ) | const |
returns used parameters
Reimplemented from lti::functor.
const double& lti::blobEM::getQ | ( | ) | const |
Access the Q value, that is maximized by EM.
const double& lti::blobEM::getQDiff | ( | ) | const |
Access the difference of current and last Q value.
virtual const char* lti::blobEM::getTypeName | ( | ) | const [virtual] |
returns the name of this type ("blobEM")
Reimplemented from lti::functor.
bool lti::blobEM::initialize | ( | const channel8 & | src, | |
const int & | components | |||
) |
Explicitly initialize this functor, for example if you intend to perform each iteration singly.
Initializes with M random ellipses, with M = components
bool lti::blobEM::initialize | ( | const channel8 & | src, | |
const std::vector< gaussEllipse > & | elem | |||
) |
Explicitly initialize this functor, for example if you intend to perform each iteration singly.
Initializes with the given ellipses.
double lti::blobEM::iterate | ( | ) |
perform one single EM iteration.
returns the total Q value, that has to be maximized by EM. Note: Call initialize() first !!!
void lti::blobEM::reset | ( | ) |
reset this functors internal members and the working data