1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
46 ////////////////// Helper functions //////////////////////
48 static const size_t OUT_OF_RANGE = (size_t)1 << (sizeof(size_t)*8 - 2);
51 calcHistLookupTables_8u( const MatND& hist, const SparseMat& shist,
53 const double* uniranges,
54 bool uniform, bool issparse, vector<size_t>& _tab )
56 const int low = 0, high = 256;
57 int i, j, dims = !issparse ? hist.dims : shist.dims();
58 _tab.resize((high-low)*dims);
59 size_t* tab = &_tab[0];
63 for( i = 0; i < dims; i++ )
65 double a = uniranges[i*2];
66 double b = uniranges[i*2+1];
67 int sz = !issparse ? hist.size[i] : shist.size(i);
68 size_t step = !issparse ? hist.step[i] : 1;
70 for( j = low; j < high; j++ )
72 int idx = cvFloor(j*a + b);
74 if( (unsigned)idx < (unsigned)sz )
75 written_idx = idx*step;
77 written_idx = OUT_OF_RANGE;
79 tab[i*(high - low) + j - low] = written_idx;
85 for( i = 0; i < dims; i++ )
87 int limit = std::min(cvCeil(ranges[i][0]), high);
88 int idx = -1, sz = !issparse ? hist.size[i] : shist.size(i);
89 size_t written_idx = OUT_OF_RANGE;
90 size_t step = !issparse ? hist.step[i] : 1;
94 for( ; j < limit; j++ )
95 tab[i*(high - low) + j - low] = written_idx;
97 if( (unsigned)(++idx) < (unsigned)sz )
99 limit = std::min(cvCeil(ranges[i][idx+1]), high);
100 written_idx = idx*step;
104 for( ; j < high; j++ )
105 tab[i*(high - low) + j - low] = OUT_OF_RANGE;
114 static void histPrepareImages( const Mat* images, int nimages, const int* channels,
115 const Mat& mask, int dims, const int* histSize,
116 const float** ranges, bool uniform,
117 vector<uchar*>& ptrs, vector<int>& deltas,
118 Size& imsize, vector<double>& uniranges )
122 CV_Assert( nimages == dims );
124 imsize = images[0].size();
125 int depth = images[0].depth(), esz1 = (int)images[0].elemSize1();
126 bool isContinuous = true;
128 ptrs.resize(dims + 1);
129 deltas.resize((dims + 1)*2);
131 for( i = 0; i < dims; i++ )
137 CV_Assert( images[j].channels() == 1 );
143 for( j = 0; j < nimages; c -= images[j].channels(), j++ )
144 if( c < images[j].channels() )
146 CV_Assert( j < nimages );
149 CV_Assert( images[j].size() == imsize && images[j].depth() == depth );
150 if( !images[j].isContinuous() )
151 isContinuous = false;
152 ptrs[i] = images[j].data + c*esz1;
153 deltas[i*2] = images[j].channels();
154 deltas[i*2+1] = (int)(images[j].step/esz1 - imsize.width*deltas[i*2]);
159 CV_Assert( mask.size() == imsize && mask.channels() == 1 );
160 isContinuous = isContinuous && mask.isContinuous();
161 ptrs[dims] = mask.data;
163 deltas[dims*2 + 1] = (int)(mask.step/mask.elemSize1());
168 imsize.width *= imsize.height;
174 CV_Assert( depth == CV_8U );
176 uniranges.resize( dims*2 );
177 for( i = 0; i < dims; i++ )
180 uniranges[i*2+1] = 0;
185 uniranges.resize( dims*2 );
186 for( i = 0; i < dims; i++ )
188 CV_Assert( ranges[i] && ranges[i][0] < ranges[i][1] );
189 double low = ranges[i][0], high = ranges[i][1];
190 double t = histSize[i]/(high - low);
192 uniranges[i*2+1] = -t*low;
197 for( i = 0; i < dims; i++ )
199 size_t j, n = histSize[i];
200 for( j = 0; j < n; j++ )
201 CV_Assert( ranges[i][j] < ranges[i][j+1] );
207 ////////////////////////////////// C A L C U L A T E H I S T O G R A M ////////////////////////////////////
209 template<typename T> static void
210 calcHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
211 Size imsize, MatND& hist, const float** _ranges,
212 const double* _uniranges, bool uniform )
214 T** ptrs = (T**)&_ptrs[0];
215 const int* deltas = &_deltas[0];
216 uchar* H = hist.data;
217 int i, x, dims = hist.dims;
218 const uchar* mask = _ptrs[dims];
219 int mstep = _deltas[dims*2 + 1];
220 int size[CV_MAX_DIM];
221 size_t hstep[CV_MAX_DIM];
223 for( i = 0; i < dims; i++ )
225 size[i] = hist.size[i];
226 hstep[i] = hist.step[i];
231 const double* uniranges = &_uniranges[0];
235 double a = uniranges[0], b = uniranges[1];
236 int sz = size[0], d0 = deltas[0], step0 = deltas[1];
237 const T* p0 = (const T*)ptrs[0];
239 for( ; imsize.height--; p0 += step0, mask += mstep )
242 for( x = 0; x < imsize.width; x++, p0 += d0 )
244 int idx = cvFloor(*p0*a + b);
245 if( (unsigned)idx < (unsigned)sz )
249 for( x = 0; x < imsize.width; x++, p0 += d0 )
252 int idx = cvFloor(*p0*a + b);
253 if( (unsigned)idx < (unsigned)sz )
260 double a0 = uniranges[0], b0 = uniranges[1], a1 = uniranges[2], b1 = uniranges[3];
261 int sz0 = size[0], sz1 = size[1];
262 int d0 = deltas[0], step0 = deltas[1],
263 d1 = deltas[2], step1 = deltas[3];
264 size_t hstep0 = hstep[0];
265 const T* p0 = (const T*)ptrs[0];
266 const T* p1 = (const T*)ptrs[1];
268 for( ; imsize.height--; p0 += step0, p1 += step1, mask += mstep )
271 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
273 int idx0 = cvFloor(*p0*a0 + b0);
274 int idx1 = cvFloor(*p1*a1 + b1);
275 if( (unsigned)idx0 < (unsigned)sz0 && (unsigned)idx1 < (unsigned)sz1 )
276 ((int*)(H + hstep0*idx0))[idx1]++;
279 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
282 int idx0 = cvFloor(*p0*a0 + b0);
283 int idx1 = cvFloor(*p1*a1 + b1);
284 if( (unsigned)idx0 < (unsigned)sz0 && (unsigned)idx1 < (unsigned)sz1 )
285 ((int*)(H + hstep0*idx0))[idx1]++;
291 double a0 = uniranges[0], b0 = uniranges[1],
292 a1 = uniranges[2], b1 = uniranges[3],
293 a2 = uniranges[4], b2 = uniranges[5];
294 int sz0 = size[0], sz1 = size[1], sz2 = size[2];
295 int d0 = deltas[0], step0 = deltas[1],
296 d1 = deltas[2], step1 = deltas[3],
297 d2 = deltas[4], step2 = deltas[5];
298 size_t hstep0 = hstep[0], hstep1 = hstep[1];
299 const T* p0 = (const T*)ptrs[0];
300 const T* p1 = (const T*)ptrs[1];
301 const T* p2 = (const T*)ptrs[2];
303 for( ; imsize.height--; p0 += step0, p1 += step1, p2 += step2, mask += mstep )
306 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
308 int idx0 = cvFloor(*p0*a0 + b0);
309 int idx1 = cvFloor(*p1*a1 + b1);
310 int idx2 = cvFloor(*p2*a2 + b2);
311 if( (unsigned)idx0 < (unsigned)sz0 &&
312 (unsigned)idx1 < (unsigned)sz1 &&
313 (unsigned)idx2 < (unsigned)sz2 )
314 ((int*)(H + hstep0*idx0 + hstep1*idx1))[idx2]++;
317 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
320 int idx0 = cvFloor(*p0*a0 + b0);
321 int idx1 = cvFloor(*p1*a1 + b1);
322 int idx2 = cvFloor(*p2*a2 + b2);
323 if( (unsigned)idx0 < (unsigned)sz0 &&
324 (unsigned)idx1 < (unsigned)sz1 &&
325 (unsigned)idx2 < (unsigned)sz2 )
326 ((int*)(H + hstep0*idx0 + hstep1*idx1))[idx2]++;
332 for( ; imsize.height--; mask += mstep )
335 for( x = 0; x < imsize.width; x++ )
338 for( i = 0; i < dims; i++ )
340 int idx = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
341 if( (unsigned)idx >= (unsigned)size[i] )
343 ptrs[i] += deltas[i*2];
344 Hptr += idx*hstep[i];
350 for( ; i < dims; i++ )
351 ptrs[i] += deltas[i*2];
354 for( x = 0; x < imsize.width; x++ )
359 for( ; i < dims; i++ )
361 int idx = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
362 if( (unsigned)idx >= (unsigned)size[i] )
364 ptrs[i] += deltas[i*2];
365 Hptr += idx*hstep[i];
371 for( ; i < dims; i++ )
372 ptrs[i] += deltas[i*2];
374 for( i = 0; i < dims; i++ )
375 ptrs[i] += deltas[i*2 + 1];
381 // non-uniform histogram
382 const float* ranges[CV_MAX_DIM];
383 for( i = 0; i < dims; i++ )
384 ranges[i] = &_ranges[i][0];
386 for( ; imsize.height--; mask += mstep )
388 for( x = 0; x < imsize.width; x++ )
393 if( !mask || mask[x] )
394 for( ; i < dims; i++ )
396 float v = (float)*ptrs[i];
397 const float* R = ranges[i];
398 int idx = -1, sz = size[i];
400 while( v >= R[idx+1] && ++idx < sz )
403 if( (unsigned)idx >= (unsigned)sz )
406 ptrs[i] += deltas[i*2];
407 Hptr += idx*hstep[i];
413 for( ; i < dims; i++ )
414 ptrs[i] += deltas[i*2];
417 for( i = 0; i < dims; i++ )
418 ptrs[i] += deltas[i*2 + 1];
425 calcHist_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
426 Size imsize, MatND& hist, const float** _ranges,
427 const double* _uniranges, bool uniform )
429 uchar** ptrs = &_ptrs[0];
430 const int* deltas = &_deltas[0];
431 uchar* H = hist.data;
432 int i, x, dims = hist.dims;
433 const uchar* mask = _ptrs[dims];
434 int mstep = _deltas[dims*2 + 1];
437 calcHistLookupTables_8u( hist, SparseMat(), _ranges, _uniranges, uniform, false, _tab );
438 const size_t* tab = &_tab[0];
442 int d0 = deltas[0], step0 = deltas[1];
444 const uchar* p0 = (const uchar*)ptrs[0];
446 for( ; imsize.height--; p0 += step0, mask += mstep )
452 for( x = 0; x <= imsize.width - 4; x += 4 )
454 int t0 = p0[x], t1 = p0[x+1];
456 t0 = p0[x+2]; t1 = p0[x+3];
462 for( x = 0; x <= imsize.width - 4; x += 4 )
464 int t0 = p0[0], t1 = p0[d0];
467 t0 = p0[0]; t1 = p0[d0];
472 for( ; x < imsize.width; x++, p0 += d0 )
476 for( x = 0; x < imsize.width; x++, p0 += d0 )
481 for( i = 0; i < 256; i++ )
483 size_t hidx = tab[i];
484 if( hidx < OUT_OF_RANGE )
485 *(int*)(H + hidx) += _H[i];
490 int d0 = deltas[0], step0 = deltas[1],
491 d1 = deltas[2], step1 = deltas[3];
492 const uchar* p0 = (const uchar*)ptrs[0];
493 const uchar* p1 = (const uchar*)ptrs[1];
495 for( ; imsize.height--; p0 += step0, p1 += step1, mask += mstep )
498 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
500 size_t idx = tab[*p0] + tab[*p1 + 256];
501 if( idx < OUT_OF_RANGE )
505 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
508 if( mask[x] && (idx = tab[*p0] + tab[*p1 + 256]) < OUT_OF_RANGE )
515 int d0 = deltas[0], step0 = deltas[1],
516 d1 = deltas[2], step1 = deltas[3],
517 d2 = deltas[4], step2 = deltas[5];
519 const uchar* p0 = (const uchar*)ptrs[0];
520 const uchar* p1 = (const uchar*)ptrs[1];
521 const uchar* p2 = (const uchar*)ptrs[2];
523 for( ; imsize.height--; p0 += step0, p1 += step1, p2 += step2, mask += mstep )
526 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
528 size_t idx = tab[*p0] + tab[*p1 + 256] + tab[*p2 + 512];
529 if( idx < OUT_OF_RANGE )
533 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
536 if( mask[x] && (idx = tab[*p0] + tab[*p1 + 256] + tab[*p2 + 512]) < OUT_OF_RANGE )
543 for( ; imsize.height--; mask += mstep )
546 for( x = 0; x < imsize.width; x++ )
549 for( i = 0; i < dims; i++ )
551 size_t idx = tab[*ptrs[i] + i*256];
552 if( idx >= OUT_OF_RANGE )
555 ptrs[i] += deltas[i*2];
561 for( ; i < dims; i++ )
562 ptrs[i] += deltas[i*2];
565 for( x = 0; x < imsize.width; x++ )
570 for( ; i < dims; i++ )
572 size_t idx = tab[*ptrs[i] + i*256];
573 if( idx >= OUT_OF_RANGE )
576 ptrs[i] += deltas[i*2];
582 for( ; i < dims; i++ )
583 ptrs[i] += deltas[i*2];
585 for( i = 0; i < dims; i++ )
586 ptrs[i] += deltas[i*2 + 1];
592 void calcHist( const Mat* images, int nimages, const int* channels,
593 const Mat& mask, MatND& hist, int dims, const int* histSize,
594 const float** ranges, bool uniform, bool accumulate )
596 CV_Assert(dims > 0 && histSize);
597 hist.create(dims, histSize, CV_32F);
600 ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S;
605 hist.convertTo(ihist, CV_32S);
609 vector<double> uniranges;
612 CV_Assert( !mask.data || mask.type() == CV_8UC1 );
613 histPrepareImages( images, nimages, channels, mask, hist.dims, hist.size, ranges,
614 uniform, ptrs, deltas, imsize, uniranges );
615 const double* _uniranges = uniform ? &uniranges[0] : 0;
617 int depth = images[0].depth();
619 calcHist_8u(ptrs, deltas, imsize, ihist, ranges, _uniranges, uniform );
620 else if( depth == CV_32F )
621 calcHist_<float>(ptrs, deltas, imsize, ihist, ranges, _uniranges, uniform );
623 ihist.convertTo(hist, CV_32F);
627 template<typename T> static void
628 calcSparseHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
629 Size imsize, SparseMat& hist, const float** _ranges,
630 const double* _uniranges, bool uniform )
632 T** ptrs = (T**)&_ptrs[0];
633 const int* deltas = &_deltas[0];
634 int i, x, dims = hist.dims();
635 const uchar* mask = _ptrs[dims];
636 int mstep = _deltas[dims*2 + 1];
637 const int* size = hist.hdr->size;
642 const double* uniranges = &_uniranges[0];
644 for( ; imsize.height--; mask += mstep )
646 for( x = 0; x < imsize.width; x++ )
649 if( !mask || mask[x] )
650 for( ; i < dims; i++ )
652 idx[i] = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
653 if( (unsigned)idx[i] >= (unsigned)size[i] )
655 ptrs[i] += deltas[i*2];
659 ++*(int*)hist.ptr(idx, true);
661 for( ; i < dims; i++ )
662 ptrs[i] += deltas[i*2];
664 for( i = 0; i < dims; i++ )
665 ptrs[i] += deltas[i*2 + 1];
670 // non-uniform histogram
671 const float* ranges[CV_MAX_DIM];
672 for( i = 0; i < dims; i++ )
673 ranges[i] = &_ranges[i][0];
675 for( ; imsize.height--; mask += mstep )
677 for( x = 0; x < imsize.width; x++ )
681 if( !mask || mask[x] )
682 for( ; i < dims; i++ )
684 float v = (float)*ptrs[i];
685 const float* R = ranges[i];
686 int j = -1, sz = size[i];
688 while( v >= R[j+1] && ++j < sz )
691 if( (unsigned)j >= (unsigned)sz )
693 ptrs[i] += deltas[i*2];
698 ++*(int*)hist.ptr(idx, true);
700 for( ; i < dims; i++ )
701 ptrs[i] += deltas[i*2];
704 for( i = 0; i < dims; i++ )
705 ptrs[i] += deltas[i*2 + 1];
712 calcSparseHist_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
713 Size imsize, SparseMat& hist, const float** _ranges,
714 const double* _uniranges, bool uniform )
716 uchar** ptrs = (uchar**)&_ptrs[0];
717 const int* deltas = &_deltas[0];
718 int i, x, dims = hist.dims();
719 const uchar* mask = _ptrs[dims];
720 int mstep = _deltas[dims*2 + 1];
724 calcHistLookupTables_8u( MatND(), hist, _ranges, _uniranges, uniform, true, _tab );
725 const size_t* tab = &_tab[0];
727 for( ; imsize.height--; mask += mstep )
729 for( x = 0; x < imsize.width; x++ )
732 if( !mask || mask[x] )
733 for( ; i < dims; i++ )
735 size_t hidx = tab[*ptrs[i] + i*256];
736 if( hidx >= OUT_OF_RANGE )
738 ptrs[i] += deltas[i*2];
743 ++*(int*)hist.ptr(idx,true);
745 for( ; i < dims; i++ )
746 ptrs[i] += deltas[i*2];
748 for( i = 0; i < dims; i++ )
749 ptrs[i] += deltas[i*2 + 1];
754 static void calcHist( const Mat* images, int nimages, const int* channels,
755 const Mat& mask, SparseMat& hist, int dims, const int* histSize,
756 const float** ranges, bool uniform, bool accumulate, bool keepInt )
758 SparseMatIterator it;
762 hist.create(dims, histSize, CV_32F);
764 for( i = 0, N = hist.nzcount(); i < N; i++, ++it )
766 int* value = (int*)it.ptr;
767 *value = cvRound(*(const float*)value);
772 vector<double> uniranges;
775 CV_Assert( !mask.data || mask.type() == CV_8UC1 );
776 histPrepareImages( images, nimages, channels, mask, hist.dims(), hist.hdr->size, ranges,
777 uniform, ptrs, deltas, imsize, uniranges );
779 int depth = images[0].depth();
781 calcSparseHist_8u(ptrs, deltas, imsize, hist, ranges, &uniranges[0], uniform );
782 else if( depth == CV_32F )
783 calcSparseHist_<float>(ptrs, deltas, imsize, hist, ranges, &uniranges[0], uniform );
786 for( i = 0, N = hist.nzcount(); i < N; i++, ++it )
788 int* value = (int*)it.ptr;
789 *(float*)value = (float)*value;
794 void calcHist( const Mat* images, int nimages, const int* channels,
795 const Mat& mask, SparseMat& hist, int dims, const int* histSize,
796 const float** ranges, bool uniform, bool accumulate )
798 calcHist( images, nimages, channels, mask, hist, dims, histSize,
799 ranges, uniform, accumulate, false );
803 /////////////////////////////////////// B A C K P R O J E C T ////////////////////////////////////
806 template<typename T, typename BT> static void
807 calcBackProj_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
808 Size imsize, const MatND& hist, const float** _ranges,
809 const double* _uniranges, float scale, bool uniform )
811 T** ptrs = (T**)&_ptrs[0];
812 const int* deltas = &_deltas[0];
813 uchar* H = hist.data;
814 int i, x, dims = hist.dims;
815 BT* bproj = (BT*)_ptrs[dims];
816 int bpstep = _deltas[dims*2 + 1];
817 int size[CV_MAX_DIM];
818 size_t hstep[CV_MAX_DIM];
820 for( i = 0; i < dims; i++ )
822 size[i] = hist.size[i];
823 hstep[i] = hist.step[i];
828 const double* uniranges = &_uniranges[0];
832 double a = uniranges[0], b = uniranges[1];
833 int sz = size[0], d0 = deltas[0], step0 = deltas[1];
834 const T* p0 = (const T*)ptrs[0];
836 for( ; imsize.height--; p0 += step0, bproj += bpstep )
838 for( x = 0; x < imsize.width; x++, p0 += d0 )
840 int idx = cvFloor(*p0*a + b);
841 bproj[x] = (unsigned)idx < (unsigned)sz ? saturate_cast<BT>(((float*)H)[idx]*scale) : 0;
847 double a0 = uniranges[0], b0 = uniranges[1],
848 a1 = uniranges[2], b1 = uniranges[3];
849 int sz0 = size[0], sz1 = size[1];
850 int d0 = deltas[0], step0 = deltas[1],
851 d1 = deltas[2], step1 = deltas[3];
852 size_t hstep0 = hstep[0];
853 const T* p0 = (const T*)ptrs[0];
854 const T* p1 = (const T*)ptrs[1];
856 for( ; imsize.height--; p0 += step0, p1 += step1, bproj += bpstep )
858 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
860 int idx0 = cvFloor(*p0*a0 + b0);
861 int idx1 = cvFloor(*p1*a1 + b1);
862 bproj[x] = (unsigned)idx0 < (unsigned)sz0 &&
863 (unsigned)idx1 < (unsigned)sz1 ?
864 saturate_cast<BT>(((float*)(H + hstep0*idx0))[idx1]*scale) : 0;
870 double a0 = uniranges[0], b0 = uniranges[1],
871 a1 = uniranges[2], b1 = uniranges[3],
872 a2 = uniranges[4], b2 = uniranges[5];
873 int sz0 = size[0], sz1 = size[1], sz2 = size[2];
874 int d0 = deltas[0], step0 = deltas[1],
875 d1 = deltas[2], step1 = deltas[3],
876 d2 = deltas[4], step2 = deltas[5];
877 size_t hstep0 = hstep[0], hstep1 = hstep[1];
878 const T* p0 = (const T*)ptrs[0];
879 const T* p1 = (const T*)ptrs[1];
880 const T* p2 = (const T*)ptrs[2];
882 for( ; imsize.height--; p0 += step0, p1 += step1, p2 += step2, bproj += bpstep )
884 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
886 int idx0 = cvFloor(*p0*a0 + b0);
887 int idx1 = cvFloor(*p1*a1 + b1);
888 int idx2 = cvFloor(*p2*a2 + b2);
889 bproj[x] = (unsigned)idx0 < (unsigned)sz0 &&
890 (unsigned)idx1 < (unsigned)sz1 &&
891 (unsigned)idx2 < (unsigned)sz2 ?
892 saturate_cast<BT>(((float*)(H + hstep0*idx0 + hstep1*idx1))[idx2]*scale) : 0;
898 for( ; imsize.height--; bproj += bpstep )
900 for( x = 0; x < imsize.width; x++ )
903 for( i = 0; i < dims; i++ )
905 int idx = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
906 if( (unsigned)idx >= (unsigned)size[i] )
908 ptrs[i] += deltas[i*2];
909 Hptr += idx*hstep[i];
913 bproj[x] = saturate_cast<BT>(*(float*)Hptr*scale);
917 for( ; i < dims; i++ )
918 ptrs[i] += deltas[i*2];
921 for( i = 0; i < dims; i++ )
922 ptrs[i] += deltas[i*2 + 1];
928 // non-uniform histogram
929 const float* ranges[CV_MAX_DIM];
930 for( i = 0; i < dims; i++ )
931 ranges[i] = &_ranges[i][0];
933 for( ; imsize.height--; bproj += bpstep )
935 for( x = 0; x < imsize.width; x++ )
938 for( i = 0; i < dims; i++ )
940 float v = (float)*ptrs[i];
941 const float* R = ranges[i];
942 int idx = -1, sz = size[i];
944 while( v >= R[idx+1] && ++idx < sz )
947 if( (unsigned)idx >= (unsigned)sz )
950 ptrs[i] += deltas[i*2];
951 Hptr += idx*hstep[i];
955 bproj[x] = saturate_cast<BT>(*(float*)Hptr*scale);
959 for( ; i < dims; i++ )
960 ptrs[i] += deltas[i*2];
964 for( i = 0; i < dims; i++ )
965 ptrs[i] += deltas[i*2 + 1];
972 calcBackProj_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
973 Size imsize, const MatND& hist, const float** _ranges,
974 const double* _uniranges, float scale, bool uniform )
976 uchar** ptrs = &_ptrs[0];
977 const int* deltas = &_deltas[0];
978 uchar* H = hist.data;
979 int i, x, dims = hist.dims;
980 uchar* bproj = _ptrs[dims];
981 int bpstep = _deltas[dims*2 + 1];
984 calcHistLookupTables_8u( hist, SparseMat(), _ranges, _uniranges, uniform, false, _tab );
985 const size_t* tab = &_tab[0];
989 int d0 = deltas[0], step0 = deltas[1];
991 const uchar* p0 = (const uchar*)ptrs[0];
993 for( i = 0; i < 256; i++ )
995 size_t hidx = tab[i];
996 if( hidx < OUT_OF_RANGE )
997 _H[i] = saturate_cast<uchar>(*(float*)(H + hidx)*scale);
1000 for( ; imsize.height--; p0 += step0, bproj += bpstep )
1004 for( x = 0; x <= imsize.width - 4; x += 4 )
1006 uchar t0 = _H[p0[x]], t1 = _H[p0[x+1]];
1007 bproj[x] = t0; bproj[x+1] = t1;
1008 t0 = _H[p0[x+2]]; t1 = _H[p0[x+3]];
1009 bproj[x+2] = t0; bproj[x+3] = t1;
1014 for( x = 0; x <= imsize.width - 4; x += 4 )
1016 uchar t0 = _H[p0[0]], t1 = _H[p0[d0]];
1017 bproj[x] = t0; bproj[x+1] = t1;
1019 t0 = _H[p0[0]]; t1 = _H[p0[d0]];
1020 bproj[x+2] = t0; bproj[x+3] = t1;
1024 for( ; x < imsize.width; x++, p0 += d0 )
1028 else if( dims == 2 )
1030 int d0 = deltas[0], step0 = deltas[1],
1031 d1 = deltas[2], step1 = deltas[3];
1032 const uchar* p0 = (const uchar*)ptrs[0];
1033 const uchar* p1 = (const uchar*)ptrs[1];
1035 for( ; imsize.height--; p0 += step0, p1 += step1, bproj += bpstep )
1037 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1 )
1039 size_t idx = tab[*p0] + tab[*p1 + 256];
1040 bproj[x] = idx < OUT_OF_RANGE ? saturate_cast<uchar>(*(float*)(H + idx)*scale) : 0;
1044 else if( dims == 3 )
1046 int d0 = deltas[0], step0 = deltas[1],
1047 d1 = deltas[2], step1 = deltas[3],
1048 d2 = deltas[4], step2 = deltas[5];
1049 const uchar* p0 = (const uchar*)ptrs[0];
1050 const uchar* p1 = (const uchar*)ptrs[1];
1051 const uchar* p2 = (const uchar*)ptrs[2];
1053 for( ; imsize.height--; p0 += step0, p1 += step1, p2 += step2, bproj += bpstep )
1055 for( x = 0; x < imsize.width; x++, p0 += d0, p1 += d1, p2 += d2 )
1057 size_t idx = tab[*p0] + tab[*p1 + 256] + tab[*p2 + 512];
1058 bproj[x] = idx < OUT_OF_RANGE ? saturate_cast<uchar>(*(float*)(H + idx)*scale) : 0;
1064 for( ; imsize.height--; bproj += bpstep )
1066 for( x = 0; x < imsize.width; x++ )
1069 for( i = 0; i < dims; i++ )
1071 size_t idx = tab[*ptrs[i] + i*256];
1072 if( idx >= OUT_OF_RANGE )
1074 ptrs[i] += deltas[i*2];
1079 bproj[x] = saturate_cast<uchar>(*(float*)Hptr*scale);
1083 for( ; i < dims; i++ )
1084 ptrs[i] += deltas[i*2];
1087 for( i = 0; i < dims; i++ )
1088 ptrs[i] += deltas[i*2 + 1];
1094 void calcBackProject( const Mat* images, int nimages, const int* channels,
1095 const MatND& hist, Mat& backProject,
1096 const float** ranges, double scale, bool uniform )
1098 vector<uchar*> ptrs;
1100 vector<double> uniranges;
1103 CV_Assert( hist.dims > 0 && hist.data );
1104 backProject.create( images[0].size(), images[0].depth() );
1105 histPrepareImages( images, nimages, channels, backProject, hist.dims, hist.size, ranges,
1106 uniform, ptrs, deltas, imsize, uniranges );
1107 const double* _uniranges = uniform ? &uniranges[0] : 0;
1109 int depth = images[0].depth();
1110 if( depth == CV_8U )
1111 calcBackProj_8u(ptrs, deltas, imsize, hist, ranges, _uniranges, (float)scale, uniform);
1112 else if( depth == CV_32F )
1113 calcBackProj_<float, float>(ptrs, deltas, imsize, hist, ranges, _uniranges, (float)scale, uniform );
1117 template<typename T, typename BT> static void
1118 calcSparseBackProj_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
1119 Size imsize, const SparseMat& hist, const float** _ranges,
1120 const double* _uniranges, float scale, bool uniform )
1122 T** ptrs = (T**)&_ptrs[0];
1123 const int* deltas = &_deltas[0];
1124 int i, x, dims = hist.dims();
1125 BT* bproj = (BT*)_ptrs[dims];
1126 int bpstep = _deltas[dims*2 + 1];
1127 const int* size = hist.hdr->size;
1128 int idx[CV_MAX_DIM];
1129 const SparseMat_<float>& hist_ = (const SparseMat_<float>&)hist;
1133 const double* uniranges = &_uniranges[0];
1134 for( ; imsize.height--; bproj += bpstep )
1136 for( x = 0; x < imsize.width; x++ )
1138 for( i = 0; i < dims; i++ )
1140 idx[i] = cvFloor(*ptrs[i]*uniranges[i*2] + uniranges[i*2+1]);
1141 if( (unsigned)idx[i] >= (unsigned)size[i] )
1143 ptrs[i] += deltas[i*2];
1147 bproj[x] = saturate_cast<BT>(hist_(idx)*scale);
1151 for( ; i < dims; i++ )
1152 ptrs[i] += deltas[i*2];
1155 for( i = 0; i < dims; i++ )
1156 ptrs[i] += deltas[i*2 + 1];
1161 // non-uniform histogram
1162 const float* ranges[CV_MAX_DIM];
1163 for( i = 0; i < dims; i++ )
1164 ranges[i] = &_ranges[i][0];
1166 for( ; imsize.height--; bproj += bpstep )
1168 for( x = 0; x < imsize.width; x++ )
1170 for( i = 0; i < dims; i++ )
1172 float v = (float)*ptrs[i];
1173 const float* R = ranges[i];
1174 int j = -1, sz = size[i];
1176 while( v >= R[j+1] && ++j < sz )
1179 if( (unsigned)j >= (unsigned)sz )
1182 ptrs[i] += deltas[i*2];
1186 bproj[x] = saturate_cast<BT>(hist_(idx)*scale);
1190 for( ; i < dims; i++ )
1191 ptrs[i] += deltas[i*2];
1195 for( i = 0; i < dims; i++ )
1196 ptrs[i] += deltas[i*2 + 1];
1203 calcSparseBackProj_8u( vector<uchar*>& _ptrs, const vector<int>& _deltas,
1204 Size imsize, const SparseMat& hist, const float** _ranges,
1205 const double* _uniranges, float scale, bool uniform )
1207 uchar** ptrs = &_ptrs[0];
1208 const int* deltas = &_deltas[0];
1209 int i, x, dims = hist.dims();
1210 uchar* bproj = _ptrs[dims];
1211 int bpstep = _deltas[dims*2 + 1];
1212 vector<size_t> _tab;
1213 int idx[CV_MAX_DIM];
1215 calcHistLookupTables_8u( MatND(), hist, _ranges, _uniranges, uniform, true, _tab );
1216 const size_t* tab = &_tab[0];
1218 for( ; imsize.height--; bproj += bpstep )
1220 for( x = 0; x < imsize.width; x++ )
1222 for( i = 0; i < dims; i++ )
1224 size_t hidx = tab[*ptrs[i] + i*256];
1225 if( hidx >= OUT_OF_RANGE )
1228 ptrs[i] += deltas[i*2];
1232 bproj[x] = saturate_cast<uchar>(hist.value<float>(idx)*scale);
1236 for( ; i < dims; i++ )
1237 ptrs[i] += deltas[i*2];
1240 for( i = 0; i < dims; i++ )
1241 ptrs[i] += deltas[i*2 + 1];
1246 void calcBackProject( const Mat* images, int nimages, const int* channels,
1247 const SparseMat& hist, Mat& backProject,
1248 const float** ranges, double scale, bool uniform )
1250 vector<uchar*> ptrs;
1252 vector<double> uniranges;
1255 CV_Assert( hist.dims() > 0 );
1256 backProject.create( images[0].size(), images[0].depth() );
1257 histPrepareImages( images, nimages, channels, backProject,
1258 hist.dims(), hist.hdr->size, ranges,
1259 uniform, ptrs, deltas, imsize, uniranges );
1260 const double* _uniranges = uniform ? &uniranges[0] : 0;
1262 int depth = images[0].depth();
1263 if( depth == CV_8U )
1264 calcSparseBackProj_8u(ptrs, deltas, imsize, hist, ranges, _uniranges, (float)scale, uniform);
1265 else if( depth == CV_32F )
1266 calcSparseBackProj_<float, float>(ptrs, deltas, imsize, hist, ranges, _uniranges, (float)scale, uniform );
1270 ////////////////// C O M P A R E H I S T O G R A M S ////////////////////////
1272 double compareHist( const MatND& H1, const MatND& H2, int method )
1274 NAryMatNDIterator it(H1, H2);
1278 CV_Assert( H1.type() == H2.type() && H1.type() == CV_32F );
1280 double s1 = 0, s2 = 0, s11 = 0, s12 = 0, s22 = 0;
1282 CV_Assert( it.planes[0].isContinuous() && it.planes[1].isContinuous() );
1284 for( i = 0; i < it.nplanes; i++, ++it )
1286 const float* h1 = (const float*)it.planes[0].data;
1287 const float* h2 = (const float*)it.planes[1].data;
1288 len = it.planes[0].rows*it.planes[0].cols;
1290 if( method == CV_COMP_CHISQR )
1292 for( i = 0; i < len; i++ )
1294 double a = h1[i] - h2[i];
1295 double b = h1[i] + h2[i];
1296 if( fabs(b) > FLT_EPSILON )
1300 else if( method == CV_COMP_CORREL )
1302 for( i = 0; i < len; i++ )
1314 else if( method == CV_COMP_INTERSECT )
1316 for( i = 0; i < len; i++ )
1317 result += std::min(h1[i], h2[i]);
1319 else if( method == CV_COMP_BHATTACHARYYA )
1321 for( i = 0; i < len; i++ )
1325 result += std::sqrt(a*b);
1331 CV_Error( CV_StsBadArg, "Unknown comparison method" );
1334 if( method == CV_COMP_CORREL )
1337 for( i = 0; i < H1.dims; i++ )
1338 total *= H1.size[i];
1339 double scale = 1./total;
1340 double num = s12 - s1*s2*scale;
1341 double denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale);
1342 result = std::abs(denom2) > DBL_EPSILON ? num/std::sqrt(denom2) : 1.;
1344 else if( method == CV_COMP_BHATTACHARYYA )
1347 s1 = fabs(s1) > FLT_EPSILON ? 1./std::sqrt(s1) : 1.;
1348 result = std::sqrt(std::max(1. - result*s1, 0.));
1355 double compareHist( const SparseMat& H1, const SparseMat& H2, int method )
1358 int i, dims = H1.dims();
1360 CV_Assert( dims > 0 && dims == H2.dims() && H1.type() == H2.type() && H1.type() == CV_32F );
1361 for( i = 0; i < dims; i++ )
1362 CV_Assert( H1.size(i) == H2.size(i) );
1364 const SparseMat *PH1 = &H1, *PH2 = &H2;
1365 if( PH1->nzcount() > PH2->nzcount() )
1366 std::swap(PH1, PH2);
1368 SparseMatConstIterator it = PH1->begin();
1369 int N1 = (int)PH1->nzcount(), N2 = (int)PH2->nzcount();
1371 if( method == CV_COMP_CHISQR )
1373 for( i = 0; i < N1; i++, ++it )
1375 float v1 = it.value<float>();
1376 const SparseMat::Node* node = it.node();
1377 float v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
1384 if( fabs(b) > FLT_EPSILON )
1390 for( i = 0; i < N2; i++, ++it )
1392 float v2 = it.value<float>();
1393 const SparseMat::Node* node = it.node();
1394 if( !PH1->find<float>(node->idx, (size_t*)&node->hashval) )
1398 else if( method == CV_COMP_CORREL )
1400 double s1 = 0, s2 = 0, s11 = 0, s12 = 0, s22 = 0;
1402 for( i = 0; i < N1; i++, ++it )
1404 double v1 = it.value<float>();
1405 const SparseMat::Node* node = it.node();
1406 s12 += v1*PH2->value<float>(node->idx, (size_t*)&node->hashval);
1412 for( i = 0; i < N2; i++, ++it )
1414 double v2 = it.value<float>();
1420 for( i = 0; i < H1.dims(); i++ )
1421 total *= H1.size(i);
1422 double scale = 1./total;
1423 double num = s12 - s1*s2*scale;
1424 double denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale);
1425 result = std::abs(denom2) > DBL_EPSILON ? num/std::sqrt(denom2) : 1.;
1427 else if( method == CV_COMP_INTERSECT )
1429 for( i = 0; i < N1; i++, ++it )
1431 float v1 = it.value<float>();
1432 const SparseMat::Node* node = it.node();
1433 float v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
1435 result += std::min(v1, v2);
1438 else if( method == CV_COMP_BHATTACHARYYA )
1440 double s1 = 0, s2 = 0;
1442 for( i = 0; i < N1; i++, ++it )
1444 double v1 = it.value<float>();
1445 const SparseMat::Node* node = it.node();
1446 double v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
1447 result += std::sqrt(v1*v2);
1452 for( i = 0; i < N2; i++, ++it )
1453 s2 += it.value<float>();
1456 s1 = fabs(s1) > FLT_EPSILON ? 1./std::sqrt(s1) : 1.;
1457 result = std::sqrt(std::max(1. - result*s1, 0.));
1460 CV_Error( CV_StsBadArg, "Unknown comparison method" );
1468 const int CV_HIST_DEFAULT_TYPE = CV_32F;
1470 /* Creates new histogram */
1472 cvCreateHist( int dims, int *sizes, CvHistType type, float** ranges, int uniform )
1474 CvHistogram *hist = 0;
1476 if( (unsigned)dims > CV_MAX_DIM )
1477 CV_Error( CV_BadOrder, "Number of dimensions is out of range" );
1480 CV_Error( CV_HeaderIsNull, "Null <sizes> pointer" );
1482 hist = (CvHistogram *)cvAlloc( sizeof( CvHistogram ));
1483 hist->type = CV_HIST_MAGIC_VAL + ((int)type & 1);
1484 if (uniform) hist->type|= CV_HIST_UNIFORM_FLAG;
1487 if( type == CV_HIST_ARRAY )
1489 hist->bins = cvInitMatNDHeader( &hist->mat, dims, sizes,
1490 CV_HIST_DEFAULT_TYPE );
1491 cvCreateData( hist->bins );
1493 else if( type == CV_HIST_SPARSE )
1494 hist->bins = cvCreateSparseMat( dims, sizes, CV_HIST_DEFAULT_TYPE );
1496 CV_Error( CV_StsBadArg, "Invalid histogram type" );
1499 cvSetHistBinRanges( hist, ranges, uniform );
1505 /* Creates histogram wrapping header for given array */
1506 CV_IMPL CvHistogram*
1507 cvMakeHistHeaderForArray( int dims, int *sizes, CvHistogram *hist,
1508 float *data, float **ranges, int uniform )
1511 CV_Error( CV_StsNullPtr, "Null histogram header pointer" );
1514 CV_Error( CV_StsNullPtr, "Null data pointer" );
1517 hist->type = CV_HIST_MAGIC_VAL;
1518 hist->bins = cvInitMatNDHeader( &hist->mat, dims, sizes, CV_HIST_DEFAULT_TYPE, data );
1523 CV_Error( CV_StsBadArg, "Only uniform bin ranges can be used here "
1524 "(to avoid memory allocation)" );
1525 cvSetHistBinRanges( hist, ranges, uniform );
1533 cvReleaseHist( CvHistogram **hist )
1536 CV_Error( CV_StsNullPtr, "" );
1540 CvHistogram* temp = *hist;
1542 if( !CV_IS_HIST(temp))
1543 CV_Error( CV_StsBadArg, "Invalid histogram header" );
1546 if( CV_IS_SPARSE_HIST( temp ))
1547 cvReleaseSparseMat( (CvSparseMat**)&temp->bins );
1550 cvReleaseData( temp->bins );
1555 cvFree( &temp->thresh2 );
1561 cvClearHist( CvHistogram *hist )
1563 if( !CV_IS_HIST(hist) )
1564 CV_Error( CV_StsBadArg, "Invalid histogram header" );
1565 cvZero( hist->bins );
1569 // Clears histogram bins that are below than threshold
1571 cvThreshHist( CvHistogram* hist, double thresh )
1573 if( !CV_IS_HIST(hist) )
1574 CV_Error( CV_StsBadArg, "Invalid histogram header" );
1576 if( !CV_IS_SPARSE_MAT(hist->bins) )
1579 cvGetMat( hist->bins, &mat, 0, 1 );
1580 cvThreshold( &mat, &mat, thresh, 0, CV_THRESH_TOZERO );
1584 CvSparseMat* mat = (CvSparseMat*)hist->bins;
1585 CvSparseMatIterator iterator;
1588 for( node = cvInitSparseMatIterator( mat, &iterator );
1589 node != 0; node = cvGetNextSparseNode( &iterator ))
1591 float* val = (float*)CV_NODE_VAL( mat, node );
1592 if( *val <= thresh )
1599 // Normalizes histogram (make sum of the histogram bins == factor)
1601 cvNormalizeHist( CvHistogram* hist, double factor )
1605 if( !CV_IS_HIST(hist) )
1606 CV_Error( CV_StsBadArg, "Invalid histogram header" );
1608 if( !CV_IS_SPARSE_HIST(hist) )
1611 cvGetMat( hist->bins, &mat, 0, 1 );
1612 sum = cvSum( &mat ).val[0];
1613 if( fabs(sum) < DBL_EPSILON )
1615 cvScale( &mat, &mat, factor/sum, 0 );
1619 CvSparseMat* mat = (CvSparseMat*)hist->bins;
1620 CvSparseMatIterator iterator;
1624 for( node = cvInitSparseMatIterator( mat, &iterator );
1625 node != 0; node = cvGetNextSparseNode( &iterator ))
1627 sum += *(float*)CV_NODE_VAL(mat,node);
1630 if( fabs(sum) < DBL_EPSILON )
1632 scale = (float)(factor/sum);
1634 for( node = cvInitSparseMatIterator( mat, &iterator );
1635 node != 0; node = cvGetNextSparseNode( &iterator ))
1637 *(float*)CV_NODE_VAL(mat,node) *= scale;
1643 // Retrieves histogram global min, max and their positions
1645 cvGetMinMaxHistValue( const CvHistogram* hist,
1646 float *value_min, float* value_max,
1647 int* idx_min, int* idx_max )
1649 double minVal, maxVal;
1650 int i, dims, size[CV_MAX_DIM];
1652 if( !CV_IS_HIST(hist) )
1653 CV_Error( CV_StsBadArg, "Invalid histogram header" );
1655 dims = cvGetDims( hist->bins, size );
1657 if( !CV_IS_SPARSE_HIST(hist) )
1660 CvPoint minPt, maxPt;
1662 cvGetMat( hist->bins, &mat, 0, 1 );
1663 cvMinMaxLoc( &mat, &minVal, &maxVal, &minPt, &maxPt );
1668 *idx_min = minPt.y + minPt.x;
1670 *idx_max = maxPt.y + maxPt.x;
1672 else if( dims == 2 )
1675 idx_min[0] = minPt.y, idx_min[1] = minPt.x;
1677 idx_max[0] = maxPt.y, idx_max[1] = maxPt.x;
1679 else if( idx_min || idx_max )
1681 int imin = minPt.y*mat.cols + minPt.x;
1682 int imax = maxPt.y*mat.cols + maxPt.x;
1685 for( i = dims - 1; i >= 0; i-- )
1689 int t = imin / size[i];
1690 idx_min[i] = imin - t*size[i];
1696 int t = imax / size[i];
1697 idx_max[i] = imax - t*size[i];
1705 CvSparseMat* mat = (CvSparseMat*)hist->bins;
1706 CvSparseMatIterator iterator;
1710 CvSparseNode* minNode = 0;
1711 CvSparseNode* maxNode = 0;
1712 const int *_idx_min = 0, *_idx_max = 0;
1715 for( node = cvInitSparseMatIterator( mat, &iterator );
1716 node != 0; node = cvGetNextSparseNode( &iterator ))
1718 int value = *(int*)CV_NODE_VAL(mat,node);
1719 value = CV_TOGGLE_FLT(value);
1735 _idx_min = CV_NODE_IDX(mat,minNode);
1736 _idx_max = CV_NODE_IDX(mat,maxNode);
1737 m.i = CV_TOGGLE_FLT(minv); minVal = m.f;
1738 m.i = CV_TOGGLE_FLT(maxv); maxVal = m.f;
1742 minVal = maxVal = 0;
1745 for( i = 0; i < dims; i++ )
1748 idx_min[i] = _idx_min ? _idx_min[i] : -1;
1750 idx_max[i] = _idx_max ? _idx_max[i] : -1;
1755 *value_min = (float)minVal;
1758 *value_max = (float)maxVal;
1762 // Compares two histograms using one of a few methods
1764 cvCompareHist( const CvHistogram* hist1,
1765 const CvHistogram* hist2,
1769 int size1[CV_MAX_DIM], size2[CV_MAX_DIM], total = 1;
1771 if( !CV_IS_HIST(hist1) || !CV_IS_HIST(hist2) )
1772 CV_Error( CV_StsBadArg, "Invalid histogram header[s]" );
1774 if( CV_IS_SPARSE_MAT(hist1->bins) != CV_IS_SPARSE_MAT(hist2->bins))
1775 CV_Error(CV_StsUnmatchedFormats, "One of histograms is sparse and other is not");
1777 if( !CV_IS_SPARSE_MAT(hist1->bins) )
1779 cv::MatND H1((const CvMatND*)hist1->bins), H2((const CvMatND*)hist2->bins);
1780 return cv::compareHist(H1, H2, method);
1783 int dims1 = cvGetDims( hist1->bins, size1 );
1784 int dims2 = cvGetDims( hist2->bins, size2 );
1786 if( dims1 != dims2 )
1787 CV_Error( CV_StsUnmatchedSizes,
1788 "The histograms have different numbers of dimensions" );
1790 for( i = 0; i < dims1; i++ )
1792 if( size1[i] != size2[i] )
1793 CV_Error( CV_StsUnmatchedSizes, "The histograms have different sizes" );
1798 CvSparseMat* mat1 = (CvSparseMat*)(hist1->bins);
1799 CvSparseMat* mat2 = (CvSparseMat*)(hist2->bins);
1800 CvSparseMatIterator iterator;
1801 CvSparseNode *node1, *node2;
1803 if( mat1->heap->active_count > mat2->heap->active_count )
1806 CV_SWAP( mat1, mat2, t );
1809 if( method == CV_COMP_CHISQR )
1811 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
1812 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
1814 double v1 = *(float*)CV_NODE_VAL(mat1,node1);
1815 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1), 0, 0, &node1->hashval );
1820 double v2 = *(float*)node2_data;
1823 if( fabs(b) > DBL_EPSILON )
1828 for( node2 = cvInitSparseMatIterator( mat2, &iterator );
1829 node2 != 0; node2 = cvGetNextSparseNode( &iterator ))
1831 double v2 = *(float*)CV_NODE_VAL(mat2,node2);
1832 if( !cvPtrND( mat1, CV_NODE_IDX(mat2,node2), 0, 0, &node2->hashval ))
1836 else if( method == CV_COMP_CORREL )
1838 double s1 = 0, s11 = 0;
1839 double s2 = 0, s22 = 0;
1841 double num, denom2, scale = 1./total;
1843 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
1844 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
1846 double v1 = *(float*)CV_NODE_VAL(mat1,node1);
1847 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1),
1848 0, 0, &node1->hashval );
1851 double v2 = *(float*)node2_data;
1858 for( node2 = cvInitSparseMatIterator( mat2, &iterator );
1859 node2 != 0; node2 = cvGetNextSparseNode( &iterator ))
1861 double v2 = *(float*)CV_NODE_VAL(mat2,node2);
1866 num = s12 - s1*s2*scale;
1867 denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale);
1868 result = fabs(denom2) > DBL_EPSILON ? num/sqrt(denom2) : 1;
1870 else if( method == CV_COMP_INTERSECT )
1872 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
1873 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
1875 float v1 = *(float*)CV_NODE_VAL(mat1,node1);
1876 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1),
1877 0, 0, &node1->hashval );
1880 float v2 = *(float*)node2_data;
1888 else if( method == CV_COMP_BHATTACHARYYA )
1890 double s1 = 0, s2 = 0;
1892 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
1893 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
1895 double v1 = *(float*)CV_NODE_VAL(mat1,node1);
1896 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1),
1897 0, 0, &node1->hashval );
1901 double v2 = *(float*)node2_data;
1902 result += sqrt(v1 * v2);
1906 for( node1 = cvInitSparseMatIterator( mat2, &iterator );
1907 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
1909 double v2 = *(float*)CV_NODE_VAL(mat2,node1);
1914 s1 = fabs(s1) > FLT_EPSILON ? 1./sqrt(s1) : 1.;
1915 result = 1. - result*s1;
1916 result = sqrt(MAX(result,0.));
1919 CV_Error( CV_StsBadArg, "Unknown comparison method" );
1924 // copies one histogram to another
1926 cvCopyHist( const CvHistogram* src, CvHistogram** _dst )
1930 int i, dims1, dims2;
1931 int size1[CV_MAX_DIM], size2[CV_MAX_DIM], total = 1;
1932 float* ranges[CV_MAX_DIM];
1937 CV_Error( CV_StsNullPtr, "Destination double pointer is NULL" );
1941 if( !CV_IS_HIST(src) || (dst && !CV_IS_HIST(dst)) )
1942 CV_Error( CV_StsBadArg, "Invalid histogram header[s]" );
1944 is_sparse = CV_IS_SPARSE_MAT(src->bins);
1945 dims1 = cvGetDims( src->bins, size1 );
1946 for( i = 0; i < dims1; i++ )
1949 if( dst && is_sparse == CV_IS_SPARSE_MAT(dst->bins))
1951 dims2 = cvGetDims( dst->bins, size2 );
1953 if( dims1 == dims2 )
1955 for( i = 0; i < dims1; i++ )
1956 if( size1[i] != size2[i] )
1965 cvReleaseHist( _dst );
1966 dst = cvCreateHist( dims1, size1, !is_sparse ? CV_HIST_ARRAY : CV_HIST_SPARSE, 0, 0 );
1970 if( CV_HIST_HAS_RANGES( src ))
1972 if( CV_IS_UNIFORM_HIST( src ))
1974 for( i = 0; i < dims1; i++ )
1975 ranges[i] = (float*)src->thresh[i];
1979 thresh = src->thresh2;
1980 cvSetHistBinRanges( dst, thresh, CV_IS_UNIFORM_HIST(src));
1983 cvCopy( src->bins, dst->bins );
1987 // Sets a value range for every histogram bin
1989 cvSetHistBinRanges( CvHistogram* hist, float** ranges, int uniform )
1991 int dims, size[CV_MAX_DIM], total = 0;
1995 CV_Error( CV_StsNullPtr, "NULL ranges pointer" );
1997 if( !CV_IS_HIST(hist) )
1998 CV_Error( CV_StsBadArg, "Invalid histogram header" );
2000 dims = cvGetDims( hist->bins, size );
2001 for( i = 0; i < dims; i++ )
2006 for( i = 0; i < dims; i++ )
2009 CV_Error( CV_StsNullPtr, "One of <ranges> elements is NULL" );
2010 hist->thresh[i][0] = ranges[i][0];
2011 hist->thresh[i][1] = ranges[i][1];
2014 hist->type |= CV_HIST_UNIFORM_FLAG + CV_HIST_RANGES_FLAG;
2020 if( !hist->thresh2 )
2022 hist->thresh2 = (float**)cvAlloc(
2023 dims*sizeof(hist->thresh2[0])+
2024 total*sizeof(hist->thresh2[0][0]));
2026 dim_ranges = (float*)(hist->thresh2 + dims);
2028 for( i = 0; i < dims; i++ )
2030 float val0 = -FLT_MAX;
2033 CV_Error( CV_StsNullPtr, "One of <ranges> elements is NULL" );
2035 for( j = 0; j <= size[i]; j++ )
2037 float val = ranges[i][j];
2039 CV_Error(CV_StsOutOfRange, "Bin ranges should go in ascenting order");
2040 val0 = dim_ranges[j] = val;
2043 hist->thresh2[i] = dim_ranges;
2044 dim_ranges += size[i] + 1;
2047 hist->type |= CV_HIST_RANGES_FLAG;
2048 hist->type &= ~CV_HIST_UNIFORM_FLAG;
2054 cvCalcArrHist( CvArr** img, CvHistogram* hist, int accumulate, const CvArr* mask )
2056 if( !CV_IS_HIST(hist))
2057 CV_Error( CV_StsBadArg, "Bad histogram pointer" );
2060 CV_Error( CV_StsNullPtr, "Null double array pointer" );
2062 int size[CV_MAX_DIM];
2063 int i, dims = cvGetDims( hist->bins, size);
2064 bool uniform = CV_IS_UNIFORM_HIST(hist);
2066 cv::vector<cv::Mat> images(dims);
2067 for( i = 0; i < dims; i++ )
2068 images[i] = cv::cvarrToMat(img[i]);
2072 _mask = cv::cvarrToMat(mask);
2074 const float* uranges[CV_MAX_DIM] = {0};
2075 const float** ranges = 0;
2077 if( hist->type & CV_HIST_RANGES_FLAG )
2079 ranges = (const float**)hist->thresh2;
2082 for( i = 0; i < dims; i++ )
2083 uranges[i] = &hist->thresh[i][0];
2088 if( !CV_IS_SPARSE_HIST(hist) )
2090 cv::MatND H((const CvMatND*)hist->bins);
2091 cv::calcHist( &images[0], (int)images.size(), 0, _mask,
2092 H, H.dims, H.size, ranges, uniform, accumulate != 0 );
2096 CvSparseMat* sparsemat = (CvSparseMat*)hist->bins;
2099 cvZero( hist->bins );
2100 cv::SparseMat sH(sparsemat);
2101 cv::calcHist( &images[0], (int)images.size(), 0, _mask, sH, sH.dims(),
2102 sH.dims() > 0 ? sH.hdr->size : 0, ranges, uniform, accumulate != 0, true );
2105 cvZero( sparsemat );
2107 cv::SparseMatConstIterator it = sH.begin();
2108 int nz = (int)sH.nzcount();
2109 for( i = 0; i < nz; i++, ++it )
2110 *(float*)cvPtrND(sparsemat, it.node()->idx, 0, -2) = (float)*(const int*)it.ptr;
2116 cvCalcArrBackProject( CvArr** img, CvArr* dst, const CvHistogram* hist )
2118 if( !CV_IS_HIST(hist))
2119 CV_Error( CV_StsBadArg, "Bad histogram pointer" );
2122 CV_Error( CV_StsNullPtr, "Null double array pointer" );
2124 int size[CV_MAX_DIM];
2125 int i, dims = cvGetDims( hist->bins, size );
2127 bool uniform = CV_IS_UNIFORM_HIST(hist);
2128 const float* uranges[CV_MAX_DIM] = {0};
2129 const float** ranges = 0;
2131 if( hist->type & CV_HIST_RANGES_FLAG )
2133 ranges = (const float**)hist->thresh2;
2136 for( i = 0; i < dims; i++ )
2137 uranges[i] = &hist->thresh[i][0];
2142 cv::vector<cv::Mat> images(dims);
2143 for( i = 0; i < dims; i++ )
2144 images[i] = cv::cvarrToMat(img[i]);
2146 cv::Mat _dst = cv::cvarrToMat(dst);
2148 CV_Assert( _dst.size() == images[0].size() && _dst.depth() == images[0].depth() );
2150 if( !CV_IS_SPARSE_HIST(hist) )
2152 cv::MatND H((const CvMatND*)hist->bins);
2153 cv::calcBackProject( &images[0], (int)images.size(),
2154 0, H, _dst, ranges, 1, uniform );
2158 cv::SparseMat sH((const CvSparseMat*)hist->bins);
2159 cv::calcBackProject( &images[0], (int)images.size(),
2160 0, sH, _dst, ranges, 1, uniform );
2165 ////////////////////// B A C K P R O J E C T P A T C H /////////////////////////
2168 cvCalcArrBackProjectPatch( CvArr** arr, CvArr* dst, CvSize patch_size, CvHistogram* hist,
2169 int method, double norm_factor )
2171 CvHistogram* model = 0;
2173 IplImage imgstub[CV_MAX_DIM], *img[CV_MAX_DIM];
2175 CvMat dststub, *dstmat;
2180 if( !CV_IS_HIST(hist))
2181 CV_Error( CV_StsBadArg, "Bad histogram pointer" );
2184 CV_Error( CV_StsNullPtr, "Null double array pointer" );
2186 if( norm_factor <= 0 )
2187 CV_Error( CV_StsOutOfRange,
2188 "Bad normalization factor (set it to 1.0 if unsure)" );
2190 if( patch_size.width <= 0 || patch_size.height <= 0 )
2191 CV_Error( CV_StsBadSize, "The patch width and height must be positive" );
2193 dims = cvGetDims( hist->bins );
2194 cvNormalizeHist( hist, norm_factor );
2196 for( i = 0; i < dims; i++ )
2199 mat = cvGetMat( arr[i], &stub, 0, 0 );
2200 img[i] = cvGetImage( mat, &imgstub[i] );
2204 dstmat = cvGetMat( dst, &dststub, 0, 0 );
2205 if( CV_MAT_TYPE( dstmat->type ) != CV_32FC1 )
2206 CV_Error( CV_StsUnsupportedFormat, "Resultant image must have 32fC1 type" );
2208 if( dstmat->cols != img[0]->width - patch_size.width + 1 ||
2209 dstmat->rows != img[0]->height - patch_size.height + 1 )
2210 CV_Error( CV_StsUnmatchedSizes,
2211 "The output map must be (W-w+1 x H-h+1), "
2212 "where the input images are (W x H) each and the patch is (w x h)" );
2214 cvCopyHist( hist, &model );
2216 size = cvGetMatSize(dstmat);
2218 roi.width = patch_size.width;
2219 roi.height = patch_size.height;
2221 for( y = 0; y < size.height; y++ )
2223 for( x = 0; x < size.width; x++ )
2229 cvCalcHist( img, model );
2230 cvNormalizeHist( model, norm_factor );
2231 result = cvCompareHist( model, hist, method );
2232 CV_MAT_ELEM( *dstmat, float, y, x ) = (float)result;
2236 cvReleaseHist( &model );
2240 // Calculates Bayes probabilistic histograms
2242 cvCalcBayesianProb( CvHistogram** src, int count, CvHistogram** dst )
2247 CV_Error( CV_StsNullPtr, "NULL histogram array pointer" );
2250 CV_Error( CV_StsOutOfRange, "Too small number of histograms" );
2252 for( i = 0; i < count; i++ )
2254 if( !CV_IS_HIST(src[i]) || !CV_IS_HIST(dst[i]) )
2255 CV_Error( CV_StsBadArg, "Invalid histogram header" );
2257 if( !CV_IS_MATND(src[i]->bins) || !CV_IS_MATND(dst[i]->bins) )
2258 CV_Error( CV_StsBadArg, "The function supports dense histograms only" );
2261 cvZero( dst[0]->bins );
2262 // dst[0] = src[0] + ... + src[count-1]
2263 for( i = 0; i < count; i++ )
2264 cvAdd( src[i]->bins, dst[0]->bins, dst[0]->bins );
2266 cvDiv( 0, dst[0]->bins, dst[0]->bins );
2268 // dst[i] = src[i]*(1/dst[0])
2269 for( i = count - 1; i >= 0; i-- )
2270 cvMul( src[i]->bins, dst[0]->bins, dst[i]->bins );
2275 cvCalcProbDensity( const CvHistogram* hist, const CvHistogram* hist_mask,
2276 CvHistogram* hist_dens, double scale )
2279 CV_Error( CV_StsOutOfRange, "scale must be positive" );
2281 if( !CV_IS_HIST(hist) || !CV_IS_HIST(hist_mask) || !CV_IS_HIST(hist_dens) )
2282 CV_Error( CV_StsBadArg, "Invalid histogram pointer[s]" );
2285 CvArr* arrs[] = { hist->bins, hist_mask->bins, hist_dens->bins };
2287 CvNArrayIterator iterator;
2289 cvInitNArrayIterator( 3, arrs, 0, stubs, &iterator );
2291 if( CV_MAT_TYPE(iterator.hdr[0]->type) != CV_32FC1 )
2292 CV_Error( CV_StsUnsupportedFormat, "All histograms must have 32fC1 type" );
2296 const float* srcdata = (const float*)(iterator.ptr[0]);
2297 const float* maskdata = (const float*)(iterator.ptr[1]);
2298 float* dstdata = (float*)(iterator.ptr[2]);
2301 for( i = 0; i < iterator.size.width; i++ )
2303 float s = srcdata[i];
2304 float m = maskdata[i];
2305 if( s > FLT_EPSILON )
2307 dstdata[i] = (float)(m*scale/s);
2309 dstdata[i] = (float)scale;
2311 dstdata[i] = (float)0;
2314 while( cvNextNArraySlice( &iterator ));
2319 CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr )
2321 CvMat sstub, *src = cvGetMat(srcarr, &sstub);
2322 CvMat dstub, *dst = cvGetMat(dstarr, &dstub);
2324 CV_Assert( CV_ARE_SIZES_EQ(src, dst) && CV_ARE_TYPES_EQ(src, dst) &&
2325 CV_MAT_TYPE(src->type) == CV_8UC1 );
2326 CvSize size = cvGetMatSize(src);
2327 if( CV_IS_MAT_CONT(src->type & dst->type) )
2329 size.width *= size.height;
2333 const int hist_sz = 256;
2335 memset(hist, 0, sizeof(hist));
2337 for( y = 0; y < size.height; y++ )
2339 const uchar* sptr = src->data.ptr + src->step*y;
2340 for( x = 0; x < size.width; x++ )
2344 float scale = 255.f/(size.width*size.height);
2346 uchar lut[hist_sz+1];
2348 for( int i = 0; i < hist_sz; i++ )
2351 int val = cvRound(sum*scale);
2352 lut[i] = CV_CAST_8U(val);
2356 for( y = 0; y < size.height; y++ )
2358 const uchar* sptr = src->data.ptr + src->step*y;
2359 uchar* dptr = dst->data.ptr + dst->step*y;
2360 for( x = 0; x < size.width; x++ )
2361 dptr[x] = lut[sptr[x]];
2366 void cv::equalizeHist( const Mat& src, Mat& dst )
2368 dst.create( src.size(), src.type() );
2369 CvMat _src = src, _dst = dst;
2370 cvEqualizeHist( &_src, &_dst );
2373 /* Implementation of RTTI and Generic Functions for CvHistogram */
2374 #define CV_TYPE_NAME_HIST "opencv-hist"
2376 static int icvIsHist( const void * ptr )
2378 return CV_IS_HIST( ((CvHistogram*)ptr) );
2381 static CvHistogram * icvCloneHist( const CvHistogram * src )
2383 CvHistogram * dst=NULL;
2384 cvCopyHist(src, &dst);
2388 static void *icvReadHist( CvFileStorage * fs, CvFileNode * node )
2390 CvHistogram * h = 0;
2393 int have_ranges = 0;
2395 h = (CvHistogram *)cvAlloc( sizeof(CvHistogram) );
2397 type = cvReadIntByName( fs, node, "type", 0 );
2398 is_uniform = cvReadIntByName( fs, node, "is_uniform", 0 );
2399 have_ranges = cvReadIntByName( fs, node, "have_ranges", 0 );
2400 h->type = CV_HIST_MAGIC_VAL | type |
2401 (is_uniform ? CV_HIST_UNIFORM_FLAG : 0) |
2402 (have_ranges ? CV_HIST_RANGES_FLAG : 0);
2404 if(type == CV_HIST_ARRAY)
2406 // read histogram bins
2407 CvMatND* mat = (CvMatND*)cvReadByName( fs, node, "mat" );
2408 int i, sizes[CV_MAX_DIM];
2410 if(!CV_IS_MATND(mat))
2411 CV_Error( CV_StsError, "Expected CvMatND");
2413 for(i=0; i<mat->dims; i++)
2414 sizes[i] = mat->dim[i].size;
2416 cvInitMatNDHeader( &(h->mat), mat->dims, sizes, mat->type, mat->data.ptr );
2417 h->bins = &(h->mat);
2419 // take ownership of refcount pointer as well
2420 h->mat.refcount = mat->refcount;
2422 // increase refcount so freeing temp header doesn't free data
2423 cvIncRefData( mat );
2425 // free temporary header
2426 cvReleaseMatND( &mat );
2430 h->bins = cvReadByName( fs, node, "bins" );
2431 if(!CV_IS_SPARSE_MAT(h->bins)){
2432 CV_Error( CV_StsError, "Unknown Histogram type");
2439 int i, dims, size[CV_MAX_DIM], total = 0;
2441 CvFileNode * thresh_node;
2443 dims = cvGetDims( h->bins, size );
2444 for( i = 0; i < dims; i++ )
2447 thresh_node = cvGetFileNodeByName( fs, node, "thresh" );
2449 CV_Error( CV_StsError, "'thresh' node is missing");
2450 cvStartReadRawData( fs, thresh_node, &reader );
2454 for(i=0; i<dims; i++)
2455 cvReadRawDataSlice( fs, &reader, 2, h->thresh[i], "f" );
2461 h->thresh2 = (float**)cvAlloc(
2462 dims*sizeof(h->thresh2[0])+
2463 total*sizeof(h->thresh2[0][0]));
2464 dim_ranges = (float*)(h->thresh2 + dims);
2465 for(i=0; i < dims; i++)
2467 h->thresh2[i] = dim_ranges;
2468 cvReadRawDataSlice( fs, &reader, size[i]+1, dim_ranges, "f" );
2469 dim_ranges += size[i] + 1;
2477 static void icvWriteHist( CvFileStorage* fs, const char* name,
2478 const void* struct_ptr, CvAttrList /*attributes*/ )
2480 const CvHistogram * hist = (const CvHistogram *) struct_ptr;
2481 int sizes[CV_MAX_DIM];
2484 int is_uniform, have_ranges;
2486 cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_HIST );
2488 is_uniform = (CV_IS_UNIFORM_HIST(hist) ? 1 : 0);
2489 have_ranges = (hist->type & CV_HIST_RANGES_FLAG ? 1 : 0);
2491 cvWriteInt( fs, "type", (hist->type & 1) );
2492 cvWriteInt( fs, "is_uniform", is_uniform );
2493 cvWriteInt( fs, "have_ranges", have_ranges );
2494 if(!CV_IS_SPARSE_HIST(hist))
2495 cvWrite( fs, "mat", &(hist->mat) );
2497 cvWrite( fs, "bins", hist->bins );
2501 dims = cvGetDims( hist->bins, sizes );
2502 cvStartWriteStruct( fs, "thresh", CV_NODE_SEQ + CV_NODE_FLOW );
2504 for(i=0; i<dims; i++){
2505 cvWriteRawData( fs, hist->thresh[i], 2, "f" );
2509 for(i=0; i<dims; i++){
2510 cvWriteRawData( fs, hist->thresh2[i], sizes[i]+1, "f" );
2513 cvEndWriteStruct( fs );
2516 cvEndWriteStruct( fs );
2520 CvType hist_type( CV_TYPE_NAME_HIST, icvIsHist, (CvReleaseFunc)cvReleaseHist,
2521 icvReadHist, icvWriteHist, (CvCloneFunc)icvCloneHist );