/*
* NICE-Core - efficient algebra and computer vision methods
* - libimage - An image library
* See file License for license information.
*/
#ifndef LIMUN_HISTOGRAM_H
#define LIMUN_HISTOGRAM_H
#include "core/image/ippwrapper.h"
#include "core/image/RectT.h"
#include "core/image/ImageT.h"
#include "core/image/ColorImageT.h"
#include "core/vector/VectorT.h"
namespace NICE {
/**
* A class for histograms
*/
class Histogram {
public:
//! STL-like typedef for type of elements
typedef Ipp32s value_type;
//! STL-like typedef for element reference
typedef value_type& reference;
//! STL-like typedef for const element reference
typedef const value_type& const_reference;
//! STL-like typedef for iterator
typedef value_type* iterator;
//! STL-like typedef for const iterator
typedef const value_type* const_iterator;
/**
* @name Constructors, factory methods and destructor
* \{
*/
/**
* \}
* @name Histogram
* \{
*/
/**
* Default constructor.
*/
Histogram();
/**
* Create a empty histogram with \c bins bins.
* @param bins number of histogram bins
*/
Histogram(const Ipp32s& bins);
/**
* Create a empty histogram with values in the area of \c min to \c max with \c bins equal bins.
* @param min lower boundary (included)
* @param max upper boundary (not included)
* @param bins number of histogram bins (if negativ, (\c max - \c min) bins will be used)
*/
Histogram(const Ipp32s& min, const Ipp32s& max, const Ipp32s& bins=-1);
/**
* Calculate a histogram from the source gray image \c src with \c bins equal bins.
* Only values in the area of \c min to \c max are taken into account during calculation.
* @param src source image
* @param min lower boundary (included)
* @param max upper boundary (not included)
* @param bins number of histogram bins (if negativ, (\c max - \c min) bins will be used)
*/
Histogram(const Image& src, const Ipp32s& min, const Ipp32s& max, const Ipp32s& bins=-1);
/**
* Calculate a histogram from target \c rect of the source gray image \c src with \c bins equal bins.
* Only values in the area of \c min to \c max are taken into account during calculation.
* @param src source image
* @param min lower boundary (included)
* @param max upper boundary (not included)
* @param rect target rect
* @param bins number of histogram bins (if negativ, (\c max - \c min) bins will be used)
*/
Histogram(const Image& src, const Ipp32s& min, const Ipp32s& max,
const Rect& rect, const Ipp32s& bins=-1);
/**
* Calculate a histogram from the source color image \c src with \c bins equal bins.
* The resulting histogram is of size = 3*\c bins .
* Only values in the area of \c min to \c max are taken into account during calculation.
* @param src source image
* @param min lower boundary (included)
* @param max upper boundary (not included)
* @param bins number of histogram bins (if negativ, (\c max - \c min) bins will be used)
*/
Histogram(const ColorImage& src, const Ipp32s& min, const Ipp32s& max, const Ipp32s& bins=-1);
/**
* Destructor.
*/
virtual ~Histogram() {
delete _data;
}
/**
* \}
* @name Combined Color Histogram
* \{
*/
/**
* Calculate a combined histogram for the source color image \c src with \c bins equal bins per colorchannel.
* The resulting histogram is of size (\c bins^2 + \c bins ) if \c noLum == true or
* (\c bins^3 + \c bins^2 + \c bins) if \c noLum == false
* @param src source color image
* @param min lower boundary (included)
* @param max upper boundary (not included)
* @param bins number of histogram bins (if negativ, (\c max - \c min) bins will be used)
* @param noLum specifies if the first color channel will be ignored, set to \b true to ignore
*/
Histogram(const ColorImage& src, const Ipp32s& min, const Ipp32s& max,
const Ipp32s& bins, const bool noLum);
/**
* If a combined binned histogram was created, reproject will retrieve the index
* of the color (\c c1 , \c c2 , \c c3 ) .
* If the histogram was created with \c noLum == \b true, value \c c1 will be ignored.
* @param c1 value for the first color channel
* @param c2 value for the second color channel
* @param c3 value for the third color channel
* @return Ipp32u
* @throws ImageException if no combined histogram is used
*/
Ipp32u reproject(const Ipp8u& c1, const Ipp8u& c2, const Ipp8u& c3);
/**
* \}
* @name Access Data
* \{
*/
/**
* Access to elements.
* @param i Index
* @return reference
*/
inline reference operator[](const ptrdiff_t i) {
return (*_data)[i];
}
/**
* Read access to elements.
* @param i Index
* @return const_reference
*/
inline const_reference operator[](const ptrdiff_t i) const {
return (*_data)[i];
}
/**
* Access to range checked elements.
* @param i Index
* @return reference
*/
inline reference operator()(const ptrdiff_t i) {
if(isWithin(i))
return (*_data)[i];
else
fthrow(ImageException, "Index out of range.");
}
/**
* Range checked access to histogram bins.
* @param i Index
* @return const_reference
* @throws ImageException if \c i is out of range (\b minIndex() to \b maxIndex() ).
*/
inline const_reference operator()(const ptrdiff_t i) const {
if(isWithin(i))
return (*_data)[i];
else
fthrow(ImageException, "Index out of range.");
}
/**
* Get an iterator pointing to the first element.
* @return iterator
*/
inline iterator begin() {
return _data->begin();
}
/**
* Get a const_iterator pointing to the first element.
* @return const_iterator
*/
inline const_iterator begin() const {
return _data->begin();
}
/**
* Get an iterator pointing beyond the last element.
* @return iterator
*/
inline iterator end() {
return _data->end();
}
/**
* Get an iterator pointing beyond the last element.
* @return const_iterator
*/
inline const_iterator end() const {
return _data->end();
}
/**
* Get a data pointer to the internal memory.
* @return iterator
*/
inline iterator getDataPointer() {
return _data->getDataPointer();
}
/**
* Get a const pointer to the internal memory.
*/
inline const_iterator getDataPointer() const {
return _data->getDataPointer();
}
/**
* Assign \c v to all bins of the histogram.
* @param v value to assign
*/
inline void set(const value_type v) {
*_data = v;
}
/**
* Increase bin \c index by 1.
*/
inline void increaseBin(const value_type index) {
(*_data)[index]++;
}
/**
* \}
* @name Operators
* \{
*/
/**
* Copy data from \c v to \c this.
* @param v new data
* @return \c *this
*/
inline Histogram& operator=(const Histogram& v);
/**
* Set all bins to value \c element
* @param element new value of all bins
*/
inline Histogram& operator=(const_reference element);
/**
* \}
* @name Tools
* \{
*/
/**
* Check if the value is within the border \b minBorder() to \b maxBorder() .
* @return true if \c val is within the border from \b minBorder() to \b maxBorder() .
*/
bool isWithin(const ptrdiff_t i) const {
return i>=_min && i<_max;
}
/**
* Calculate the sum of all bins.
* @return value_type
*/
value_type sum() const;
/**
* \}
* @name Basic Properties
* \{
*/
/**
* Return the maximum value of all bins.
* @return value_type
*/
value_type min() const {
return _data->Min();
}
/**
* Return the minimum value of all bins.
* @return value_type
*/
value_type max() const {
return _data->Max();
}
/**
* Return the index of the minimum value of all bins.
* @return Ipp32u
*/
Ipp32u minIndex() const;
/**
* Return the index of the maximum value of all bins.
* @return Ipp32u
*/
Ipp32u maxIndex() const;
/**
* Return the number of bins per channel
* @return Ipp32u
*/
Ipp32u bins() const {
return _nobins;
}
/**
* Return the number of color channels the histogram was created from
* @return Ipp32u
*/
Ipp32u channels() const {
return _channels;
}
/**
* Return the minimum border of the histogram value range.
* @return Ipp32s
*/
Ipp32s minBorder() const {
return _min;
}
/**
* Return the maximum border of the histogram value range.
* @return Ipp32s
*/
Ipp32s maxBorder() const {
return _max;
}
/**
* Return the size of the histogram.
* @return Ipp32s
*/
Ipp32u size() const {
return _data->size();
}
/**
* \}
* @name Transformations
* \{
*/
/**
* Calculate a cumulative histogram.
* @return Pointer to IntVector
*/
IntVector* cumulative();
/**
* Calculate a normalized histogram.
* @return Pointer to FloatVector
*/
FloatVector* normalized();
/**
* \}
* @name IO Functions
* \{
*/
/**
* Read a histogram from a file \c filename .
* @param filename source file where to read from
* @return true if the histogram could be read, false if an error occoured
*/
bool read(const std::string &filename);
/**
* Write a histogram to a file \c filename .
* @param filename source file where to write the histogram
* @return true if the histogram could be writed, false if an error occoured
*/
bool write(const std::string &filename);
/**
* \}
*/
private:
VectorT* _data;
Ipp32u _channels, _nobins;
Ipp32s _min, _max;
// needed for faster reprojection
Ipp32u _b[3];
Ipp32u _diff;
// little helperfunction to init b
void init_b() {
_b[2] = _nobins;
_b[1] = _nobins*_b[2];
_b[0] = _nobins*_b[1];
}
};
inline Histogram& Histogram::operator=(const Histogram& v) {
_min = v.min();
_max = v.max();
_nobins = v.bins();
_channels = v.channels();
_diff = _max-_min;
// delete old data
if(_data==NULL)
_data = new VectorT(v.size());
else
if(_data->size()!=v.size())
_data->resize(v.size());
#ifdef NICE_USELIB_IPP
ippsCopy(v.getDataPointer(), _data->getDataPointer(), _data->size());
#else
memcpy(_data->getDataPointer(), v.getDataPointer(), _data->size()*sizeof(value_type));
#endif
return *this;
}
inline Histogram& Histogram::operator=(const_reference element) {
*_data = element;
return *this;
}
/**
* @name Operators
* \{
*/
/**
* Add histograms \c a and \c b .
* @return Histogram
* @throws ImageException will be thrown if the size of \c a and \c b are not equal.
*/
inline const Histogram operator+(const Histogram& a, const Histogram& b)
{
if(a.size()!=b.size())
fthrow(ImageException,"Histogram size is not equal.");
Histogram result(a.minBorder(), a.maxBorder(), a.bins());
Histogram::iterator r = result.begin();
Histogram::const_iterator j = b.begin();
for(Histogram::const_iterator i=a.begin(); i!=a.end(); ++i,++j,++r)
*r = *i+*j;
return result;
}
/**
* Add histogram \c a to \c this and overwrite \c this .
* @return Histogram
* @throws ImageException will be thrown if the size of \c a and \c b are not equal.
*/
inline Histogram& operator+=(Histogram& a, const Histogram& b)
{
if(a.size()!=b.size())
fthrow(ImageException,"Histogram size is not equal.");
Histogram::const_iterator j = b.begin();
for(Histogram::iterator i=a.begin(); i!=a.end(); ++i,++j)
*i += *j;
return a;
}
/**
* Compare \c a with \c b .
* @param a source histogram
* @param b histogram to compare with
* @return \b true if \c a and \c b are equal, \b false if not or if the size of \c a and \c b are not equal.
*/
inline bool operator==(const Histogram& a, const Histogram& b)
{
if(a.size()!=b.size())
return false;
Histogram::const_iterator j = b.begin();
for(Histogram::const_iterator i=a.begin(); i!=a.end(); ++i,++j)
if(*i != *j)
return false;
return true;
}
/**
* Compare Histogram \c a with \c b .
* @param a source histogram
* @param b histogram to compare with
* @return true if \c a and \c b are not equal or if the size of a and b is not equal
*/
inline bool operator!=(const Histogram& a, const Histogram& b)
{
if(a.size()!=b.size())
return true;
Histogram::const_iterator j = b.begin();
for(Histogram::const_iterator i=a.begin(); i!=a.end(); ++i,++j)
if(*i == *j)
return false;
return true;
}
/**
* \}
*/
} // namespace
#endif // LIMUN_HISTOGRAM_H