Histogram.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * NICE-Core - efficient algebra and computer vision methods
  3. * - libimage - An image/template for new NICE libraries
  4. * See file License for license information.
  5. */
  6. /*****************************************************************************/
  7. /*! \file Histogram.cpp
  8. \brief Histogram class definitions
  9. */
  10. #include <core/image/Histogram.h>
  11. namespace NICE {
  12. Histogram::Histogram() {
  13. _channels = 1;
  14. _min = 0;
  15. _max = 0;
  16. _nobins = 0;
  17. _diff = 0;
  18. _data = NULL;
  19. }
  20. Histogram::Histogram(const Ipp32s& bins) {
  21. _channels = 1;
  22. _min = 0;
  23. _max = 256;
  24. _nobins = bins;
  25. _diff = 256;
  26. _data = new VectorT<value_type>(_nobins,0);
  27. }
  28. Histogram::Histogram(const Ipp32s& min, const Ipp32s& max, const Ipp32s& bins) {
  29. _channels = 1;
  30. _min = min;
  31. _max = max;
  32. _nobins = (bins<0)?_max-_min:bins;
  33. _diff = _max-_min;
  34. _data = new VectorT<value_type>(_nobins,0);
  35. }
  36. Histogram::Histogram(const Image& src, const Ipp32s& min, const Ipp32s& max, const Ipp32s& bins) {
  37. _channels = 1;
  38. _min = min;
  39. _max = max;
  40. _nobins = (bins<0)?_max-_min:bins;
  41. _diff = _max-_min;
  42. _data = new VectorT<value_type>(_nobins,0);
  43. #ifdef NICE_USELIB_IPP
  44. Ipp32u noLevels = _nobins+1;
  45. Ipp32s pLevels[noLevels];
  46. IppStatus ret = ippiHistogramEven_C1R(src.getPixelPointer(), src.getStepsize(),
  47. makeROIFullImage(src),
  48. (Ipp32s*)_data->getDataPointer(),
  49. pLevels, noLevels, min, max);
  50. if(ret!=ippStsNoErr)
  51. fthrow(ImageException, ippGetStatusString(ret));
  52. #else // NICE_USELIB_IPP
  53. const Ipp8u* pSrc;
  54. const Ipp8u* pSrcStart = src.getPixelPointer();
  55. if(_min==0&&_max==256)
  56. for(int y=0; y<src.height(); ++y) {
  57. pSrc = pSrcStart;
  58. for(int x=0; x<src.width(); ++x,++pSrc)
  59. (*_data)[((*pSrc-_min)*_nobins)/_diff]++;
  60. pSrcStart += src.getStepsize();
  61. }
  62. else
  63. for(int y=0; y<src.height(); ++y) {
  64. pSrc = pSrcStart;
  65. for(int x=0; x<src.width(); ++x,++pSrc)
  66. if(isWithin(*pSrc))
  67. (*_data)[((*pSrc-_min)*_nobins)/_diff]++;
  68. pSrcStart += src.getStepsize();
  69. }
  70. #endif // NICE_USELIB_IPP
  71. }
  72. Histogram::Histogram(const Image& src, const Ipp32s& min, const Ipp32s& max,
  73. const Rect& rect, const Ipp32s& bins) {
  74. Rect tgtRect = clipRect(src, rect);
  75. const Image tgtImg = src.subImage(tgtRect);
  76. _channels = 1;
  77. _min = min;
  78. _max = max;
  79. _nobins = (bins<0)?_max-_min:bins;
  80. _diff = _max-_min;
  81. _data = new VectorT<value_type>(_nobins,0);
  82. #ifdef NICE_USELIB_IPP
  83. Ipp32u noLevels = _nobins+1;
  84. Ipp32s pLevels[noLevels];
  85. IppStatus ret = ippiHistogramEven_C1R(tgtImg.getPixelPointer(),
  86. tgtImg.getStepsize(),
  87. makeROIFullImage(tgtImg),
  88. _data->getDataPointer(),
  89. pLevels, noLevels, min, max);
  90. if(ret!=ippStsNoErr)
  91. fthrow(ImageException, ippGetStatusString(ret));
  92. #else // NICE_USELIB_IPP
  93. const Ipp8u* pSrc;
  94. const Ipp8u* pSrcStart = tgtImg.getPixelPointer();
  95. if(_min==0&&_max==256)
  96. for(int y=0; y<tgtImg.height(); ++y) {
  97. pSrc = pSrcStart;
  98. for(int x=0; x<tgtImg.width(); ++x,++pSrc)
  99. (*_data)[((*pSrc-_min)*_nobins)/_diff]++;
  100. pSrcStart += src.getStepsize();
  101. }
  102. else
  103. for(int y=0; y<tgtImg.height(); ++y) {
  104. pSrc = pSrcStart;
  105. for(int x=0; x<tgtImg.width(); ++x,++pSrc)
  106. if(isWithin(*pSrc))
  107. (*_data)[((*pSrc-_min)*_nobins)/_diff]++;
  108. pSrcStart += src.getStepsize();
  109. }
  110. #endif // NICE_USELIB_IPP
  111. }
  112. Histogram::Histogram(const ColorImage& src, const Ipp32s& min, const Ipp32s& max, const Ipp32s& bins) {
  113. _channels = 3;
  114. _min = min;
  115. _max = max;
  116. _nobins = (bins<0)?_max-_min:bins;
  117. _diff = _max-_min;
  118. _data = new VectorT<value_type>(3*_nobins,0);
  119. #ifdef NICE_USELIB_IPP
  120. Ipp32u noLevels = _nobins+1;
  121. Ipp32s *pLevels[_channels];
  122. int nLevels[_channels];
  123. Ipp32s tLevels[3*noLevels];
  124. Ipp32s *pHist[_channels], pmin[_channels], pmax[_channels];
  125. for(int i=0;i<3;i++) {
  126. pHist[i] = (Ipp32s*)(_data->getDataPointer() + i*_nobins);
  127. pLevels[i] = &tLevels[i*noLevels];
  128. nLevels[i] = noLevels;
  129. pmin[i] = _min;
  130. pmax[i] = _max;
  131. }
  132. IppStatus ret = ippiHistogramEven_C3R(src.getPixelPointer(), src.getStepsize(),
  133. makeROIFullImage(src), pHist,
  134. pLevels, nLevels, pmin, pmax);
  135. if(ret!=ippStsNoErr)
  136. fthrow(ImageException, ippGetStatusString(ret));
  137. #else // NICE_USELIB_IPP
  138. const Ipp8u* pSrc;
  139. const Ipp8u* pSrcStart = src.getPixelPointer();
  140. Ipp32u index;
  141. if(_min==0 && _max==256)
  142. for(int y=0; y<src.height(); ++y) {
  143. pSrc = pSrcStart;
  144. for(int x=0; x<src.width(); ++x)
  145. for(int i=0; i<3; ++i,++pSrc) {
  146. index = ((*pSrc-_min)*_nobins)/_diff;
  147. (*_data)[index + i*_nobins]++;
  148. }
  149. pSrcStart += src.getStepsize();
  150. }
  151. else
  152. for(int y=0; y<src.height(); ++y) {
  153. pSrc = pSrcStart;
  154. for(int x=0; x<src.width(); ++x)
  155. for(int i=0; i<3; ++i,++pSrc)
  156. if(isWithin(*pSrc)) {
  157. index = ((*pSrc-_min)*_nobins)/_diff;
  158. (*_data)[index + i*_nobins]++;
  159. }
  160. pSrcStart += src.getStepsize();
  161. }
  162. #endif // NICE_USELIB_IPP
  163. }
  164. Histogram::Histogram(const ColorImage& src, const Ipp32s& min, const Ipp32s& max,
  165. const Ipp32s& bins, const bool noLum) {
  166. _min = min;
  167. _max = max;
  168. _nobins = (bins<0)?_max-_min:bins;
  169. init_b();
  170. _diff = _max-_min;
  171. _channels = (noLum==false)?3:2;
  172. _data = new VectorT<value_type>( (_channels==3)?(_b[0]+_b[1]+_b[2]):(_b[1]+_b[2]), 0 );
  173. const Ipp8u* pSrc;
  174. const Ipp8u* pSrcStart = src.getPixelPointer();
  175. // noLum = false, include lum channel into calculation
  176. if(!noLum) {
  177. if(_min==0 && _max==256)
  178. for(int y=0; y<src.height(); ++y) {
  179. pSrc = pSrcStart;
  180. for(int x=0; x<src.width(); ++x,pSrc+=3)
  181. (*_data)[ ((*pSrc-_min)*_b[0] + (*(pSrc+1)-_min)*_b[1] + (*(pSrc+2)-_min)*_b[2])/_diff ]++;
  182. pSrcStart += src.getStepsize();
  183. }
  184. else
  185. for(int y=0; y<src.height(); ++y) {
  186. pSrc = pSrcStart;
  187. for(int x=0; x<src.width(); ++x,pSrc+=3)
  188. if(isWithin(*pSrc) && isWithin(*(pSrc+1)) && isWithin(*(pSrc+2)) )
  189. (*_data)[ ((*pSrc-_min)*_b[0] + (*(pSrc+1)-_min)*_b[1] + (*(pSrc+2)-_min)*_b[2])/_diff ]++;
  190. pSrcStart += src.getStepsize();
  191. }
  192. }
  193. // first channel is ignored
  194. else {
  195. if(_min==0 && _max==256)
  196. for(int y=0; y<src.height(); ++y) {
  197. pSrc = pSrcStart;
  198. for(int x=0; x<src.width(); ++x,pSrc+=3)
  199. (*_data)[ ((*(pSrc+1)-_min)*_b[1]+(*(pSrc+2)-_min)*_b[2])/_diff ]++;
  200. pSrcStart += src.getStepsize();
  201. }
  202. else
  203. for(int y=0; y<src.height(); ++y) {
  204. pSrc = pSrcStart;
  205. for(int x=0; x<src.width(); ++x,pSrc+=3)
  206. if( isWithin(*(pSrc+1)) && isWithin(*(pSrc+2)) )
  207. (*_data)[ ((*(pSrc+1)-_min)*_b[1]+(*(pSrc+2)-_min)*_b[2])/_diff ]++;
  208. pSrcStart += src.getStepsize();
  209. }
  210. }
  211. }
  212. Ipp32u Histogram::reproject(const Ipp8u& c1, const Ipp8u& c2, const Ipp8u& c3) {
  213. if(channels()==1 || (size()>0 && size()==3*bins()))
  214. fthrow(ImageException,"No combined histogram is used.");
  215. if(_channels==2)
  216. return ((c2-_min)*_b[1]+(c3-_min)*_b[2])/_diff;
  217. else
  218. return ((c1-_min)*_b[0]+(c2-_min)*_b[1]+(c3-_min)*_b[2])/_diff;
  219. }
  220. Histogram::value_type Histogram::sum() const{
  221. return _data->Sum();
  222. }
  223. //
  224. FloatVector* Histogram::normalized() {
  225. FloatVector* result = new FloatVector(size());
  226. Ipp32f sum = static_cast<Ipp32f>(this->sum());
  227. #ifdef NICE_USELIB_IPP
  228. IppStatus ret;
  229. ret = ippsConvert_32s32f(getDataPointer(),
  230. result->getDataPointer(),
  231. size());
  232. if(ret!=ippStsNoErr)
  233. fthrow(ImageException, ippGetStatusString(ret));
  234. ret = ippsNormalize_32f(result->getDataPointer(),
  235. result->getDataPointer(),
  236. result->size(),
  237. 0.0, sum);
  238. if(ret!=ippStsNoErr)
  239. fthrow(ImageException, ippGetStatusString(ret));
  240. #else // NICE_USELIB_IPP
  241. FloatVector::iterator pDst = result->begin();
  242. for(iterator i=begin(); i!=end(); ++i,++pDst)
  243. *pDst = *i/sum;
  244. #endif
  245. return result;
  246. }
  247. IntVector* Histogram::cumulative() {
  248. IntVector* result = new IntVector(size());
  249. IntVector::iterator pDst = result->begin();
  250. *pDst++ = *(_data->begin());
  251. for(VectorT<value_type>::iterator i=begin()+1; i!=end(); ++i,++pDst)
  252. *pDst = *i+*(pDst-1);
  253. return result;
  254. }
  255. //
  256. Ipp32u Histogram::minIndex() const {
  257. return _data->MinIndex();
  258. }
  259. Ipp32u Histogram::maxIndex() const {
  260. return _data->MaxIndex();
  261. }
  262. // // // // // Input / Output // // // // //
  263. bool Histogram::read(const std::string &filename) {
  264. std::ifstream ifs(filename.c_str());
  265. if(!ifs)
  266. return false;
  267. int tsize;
  268. ifs >> tsize >> _channels >> _nobins >> _min >> _max;
  269. init_b();
  270. _diff = _max-_min;
  271. _data = new VectorT<value_type>(tsize);
  272. for(iterator i=begin(); i!=end(); ++i)
  273. ifs >> *i;
  274. ifs.close();
  275. return true;
  276. }
  277. bool Histogram::write(const std::string &filename) {
  278. std::ofstream ofs(filename.c_str());
  279. if(!ofs)
  280. return false;
  281. ofs << size() << "\n" << _channels << "\n" << _nobins << "\n" << _min << "\n" << _max << "\n";
  282. for(iterator i=begin(); i!=end(); ++i)
  283. ofs << *i << "\n";
  284. ofs.close();
  285. return true;
  286. }
  287. } // namespace NICE