1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
21 //
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.
25 //
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.
28 //
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.
39 //
40 //M*/
41 #include "_cv.h"
42
43 /* Creates new histogram */
44 CvHistogram *
cvCreateHist(int dims,int * sizes,CvHistType type,float ** ranges,int uniform)45 cvCreateHist( int dims, int *sizes, CvHistType type, float** ranges, int uniform )
46 {
47 CvHistogram *hist = 0;
48
49 CV_FUNCNAME( "cvCreateHist" );
50 __BEGIN__;
51
52 if( (unsigned)dims > CV_MAX_DIM )
53 CV_ERROR( CV_BadOrder, "Number of dimensions is out of range" );
54
55 if( !sizes )
56 CV_ERROR( CV_HeaderIsNull, "Null <sizes> pointer" );
57
58 CV_CALL( hist = (CvHistogram *)cvAlloc( sizeof( CvHistogram )));
59
60 hist->type = CV_HIST_MAGIC_VAL;
61 hist->thresh2 = 0;
62 hist->bins = 0;
63 if( type == CV_HIST_ARRAY )
64 {
65 CV_CALL( hist->bins = cvInitMatNDHeader( &hist->mat, dims, sizes,
66 CV_HIST_DEFAULT_TYPE ));
67 CV_CALL( cvCreateData( hist->bins ));
68 }
69 else if( type == CV_HIST_SPARSE )
70 {
71 CV_CALL( hist->bins = cvCreateSparseMat( dims, sizes, CV_HIST_DEFAULT_TYPE ));
72 }
73 else
74 {
75 CV_ERROR( CV_StsBadArg, "Invalid histogram type" );
76 }
77
78 if( ranges )
79 CV_CALL( cvSetHistBinRanges( hist, ranges, uniform ));
80
81 __END__;
82
83 if( cvGetErrStatus() < 0 )
84 cvReleaseHist( &hist );
85
86 return hist;
87 }
88
89
90 /* Creates histogram wrapping header for given array */
91 CV_IMPL CvHistogram*
cvMakeHistHeaderForArray(int dims,int * sizes,CvHistogram * hist,float * data,float ** ranges,int uniform)92 cvMakeHistHeaderForArray( int dims, int *sizes, CvHistogram *hist,
93 float *data, float **ranges, int uniform )
94 {
95 CvHistogram* result = 0;
96
97 CV_FUNCNAME( "cvMakeHistHeaderForArray" );
98
99 __BEGIN__;
100
101 if( !hist )
102 CV_ERROR( CV_StsNullPtr, "Null histogram header pointer" );
103
104 if( !data )
105 CV_ERROR( CV_StsNullPtr, "Null data pointer" );
106
107 hist->thresh2 = 0;
108 hist->type = CV_HIST_MAGIC_VAL;
109 CV_CALL( hist->bins = cvInitMatNDHeader( &hist->mat, dims, sizes,
110 CV_HIST_DEFAULT_TYPE, data ));
111
112 if( ranges )
113 {
114 if( !uniform )
115 CV_ERROR( CV_StsBadArg, "Only uniform bin ranges can be used here "
116 "(to avoid memory allocation)" );
117 CV_CALL( cvSetHistBinRanges( hist, ranges, uniform ));
118 }
119
120 result = hist;
121
122 __END__;
123
124 if( cvGetErrStatus() < 0 && hist )
125 {
126 hist->type = 0;
127 hist->bins = 0;
128 }
129
130 return result;
131 }
132
133
134 CV_IMPL void
cvReleaseHist(CvHistogram ** hist)135 cvReleaseHist( CvHistogram **hist )
136 {
137 CV_FUNCNAME( "cvReleaseHist" );
138
139 __BEGIN__;
140
141 if( !hist )
142 CV_ERROR( CV_StsNullPtr, "" );
143
144 if( *hist )
145 {
146 CvHistogram* temp = *hist;
147
148 if( !CV_IS_HIST(temp))
149 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
150
151 *hist = 0;
152
153 if( CV_IS_SPARSE_HIST( temp ))
154 cvRelease( &temp->bins );
155 else
156 {
157 cvReleaseData( temp->bins );
158 temp->bins = 0;
159 }
160
161 if( temp->thresh2 )
162 cvFree( &temp->thresh2 );
163
164 cvFree( &temp );
165 }
166
167 __END__;
168 }
169
170 CV_IMPL void
cvClearHist(CvHistogram * hist)171 cvClearHist( CvHistogram *hist )
172 {
173 CV_FUNCNAME( "cvClearHist" );
174
175 __BEGIN__;
176
177 if( !CV_IS_HIST(hist) )
178 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
179
180 cvZero( hist->bins );
181
182 __END__;
183 }
184
185
186 // Clears histogram bins that are below than threshold
187 CV_IMPL void
cvThreshHist(CvHistogram * hist,double thresh)188 cvThreshHist( CvHistogram* hist, double thresh )
189 {
190 CV_FUNCNAME( "cvThreshHist" );
191
192 __BEGIN__;
193
194 if( !CV_IS_HIST(hist) )
195 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
196
197 if( !CV_IS_SPARSE_MAT(hist->bins) )
198 {
199 CvMat mat;
200 CV_CALL( cvGetMat( hist->bins, &mat, 0, 1 ));
201 CV_CALL( cvThreshold( &mat, &mat, thresh, 0, CV_THRESH_TOZERO ));
202 }
203 else
204 {
205 CvSparseMat* mat = (CvSparseMat*)hist->bins;
206 CvSparseMatIterator iterator;
207 CvSparseNode *node;
208
209 for( node = cvInitSparseMatIterator( mat, &iterator );
210 node != 0; node = cvGetNextSparseNode( &iterator ))
211 {
212 float* val = (float*)CV_NODE_VAL( mat, node );
213 if( *val <= thresh )
214 *val = 0;
215 }
216 }
217
218 __END__;
219 }
220
221
222 // Normalizes histogram (make sum of the histogram bins == factor)
223 CV_IMPL void
cvNormalizeHist(CvHistogram * hist,double factor)224 cvNormalizeHist( CvHistogram* hist, double factor )
225 {
226 double sum = 0;
227
228 CV_FUNCNAME( "cvNormalizeHist" );
229 __BEGIN__;
230
231 if( !CV_IS_HIST(hist) )
232 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
233
234 if( !CV_IS_SPARSE_HIST(hist) )
235 {
236 CvMat mat;
237 CV_CALL( cvGetMat( hist->bins, &mat, 0, 1 ));
238 CV_CALL( sum = cvSum( &mat ).val[0] );
239 if( fabs(sum) < DBL_EPSILON )
240 sum = 1;
241 CV_CALL( cvScale( &mat, &mat, factor/sum, 0 ));
242 }
243 else
244 {
245 CvSparseMat* mat = (CvSparseMat*)hist->bins;
246 CvSparseMatIterator iterator;
247 CvSparseNode *node;
248 float scale;
249
250 for( node = cvInitSparseMatIterator( mat, &iterator );
251 node != 0; node = cvGetNextSparseNode( &iterator ))
252 {
253 sum += *(float*)CV_NODE_VAL(mat,node);
254 }
255
256 if( fabs(sum) < DBL_EPSILON )
257 sum = 1;
258 scale = (float)(factor/sum);
259
260 for( node = cvInitSparseMatIterator( mat, &iterator );
261 node != 0; node = cvGetNextSparseNode( &iterator ))
262 {
263 *(float*)CV_NODE_VAL(mat,node) *= scale;
264 }
265 }
266
267 __END__;
268 }
269
270
271 // Retrieves histogram global min, max and their positions
272 CV_IMPL void
cvGetMinMaxHistValue(const CvHistogram * hist,float * value_min,float * value_max,int * idx_min,int * idx_max)273 cvGetMinMaxHistValue( const CvHistogram* hist,
274 float *value_min, float* value_max,
275 int* idx_min, int* idx_max )
276 {
277 double minVal, maxVal;
278
279 CV_FUNCNAME( "cvGetMinMaxHistValue" );
280
281 __BEGIN__;
282
283 int i, dims, size[CV_MAX_DIM];
284
285 if( !CV_IS_HIST(hist) )
286 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
287
288 dims = cvGetDims( hist->bins, size );
289
290 if( !CV_IS_SPARSE_HIST(hist) )
291 {
292 CvMat mat;
293 CvPoint minPt, maxPt;
294
295 CV_CALL( cvGetMat( hist->bins, &mat, 0, 1 ));
296 CV_CALL( cvMinMaxLoc( &mat, &minVal, &maxVal, &minPt, &maxPt ));
297
298 if( dims == 1 )
299 {
300 if( idx_min )
301 *idx_min = minPt.y + minPt.x;
302 if( idx_max )
303 *idx_max = maxPt.y + maxPt.x;
304 }
305 else if( dims == 2 )
306 {
307 if( idx_min )
308 idx_min[0] = minPt.y, idx_min[1] = minPt.x;
309 if( idx_max )
310 idx_max[0] = maxPt.y, idx_max[1] = maxPt.x;
311 }
312 else if( idx_min || idx_max )
313 {
314 int imin = minPt.y*mat.cols + minPt.x;
315 int imax = maxPt.y*mat.cols + maxPt.x;
316 int i;
317
318 for( i = dims - 1; i >= 0; i-- )
319 {
320 if( idx_min )
321 {
322 int t = imin / size[i];
323 idx_min[i] = imin - t*size[i];
324 imin = t;
325 }
326
327 if( idx_max )
328 {
329 int t = imax / size[i];
330 idx_max[i] = imax - t*size[i];
331 imax = t;
332 }
333 }
334 }
335 }
336 else
337 {
338 CvSparseMat* mat = (CvSparseMat*)hist->bins;
339 CvSparseMatIterator iterator;
340 CvSparseNode *node;
341 int minv = INT_MAX;
342 int maxv = INT_MIN;
343 CvSparseNode* minNode = 0;
344 CvSparseNode* maxNode = 0;
345 const int *_idx_min = 0, *_idx_max = 0;
346 Cv32suf m;
347
348 for( node = cvInitSparseMatIterator( mat, &iterator );
349 node != 0; node = cvGetNextSparseNode( &iterator ))
350 {
351 int value = *(int*)CV_NODE_VAL(mat,node);
352 value = CV_TOGGLE_FLT(value);
353 if( value < minv )
354 {
355 minv = value;
356 minNode = node;
357 }
358
359 if( value > maxv )
360 {
361 maxv = value;
362 maxNode = node;
363 }
364 }
365
366 if( minNode )
367 {
368 _idx_min = CV_NODE_IDX(mat,minNode);
369 _idx_max = CV_NODE_IDX(mat,maxNode);
370 m.i = CV_TOGGLE_FLT(minv); minVal = m.f;
371 m.i = CV_TOGGLE_FLT(maxv); maxVal = m.f;
372 }
373 else
374 {
375 minVal = maxVal = 0;
376 }
377
378 for( i = 0; i < dims; i++ )
379 {
380 if( idx_min )
381 idx_min[i] = _idx_min ? _idx_min[i] : -1;
382 if( idx_max )
383 idx_max[i] = _idx_max ? _idx_max[i] : -1;
384 }
385 }
386
387 if( value_min )
388 *value_min = (float)minVal;
389
390 if( value_max )
391 *value_max = (float)maxVal;
392
393 __END__;
394 }
395
396
397 // Compares two histograms using one of a few methods
398 CV_IMPL double
cvCompareHist(const CvHistogram * hist1,const CvHistogram * hist2,int method)399 cvCompareHist( const CvHistogram* hist1,
400 const CvHistogram* hist2,
401 int method )
402 {
403 double _result = -1;
404
405 CV_FUNCNAME( "cvCompareHist" );
406
407 __BEGIN__;
408
409 int i, dims1, dims2;
410 int size1[CV_MAX_DIM], size2[CV_MAX_DIM], total = 1;
411 double result = 0;
412
413 if( !CV_IS_HIST(hist1) || !CV_IS_HIST(hist2) )
414 CV_ERROR( CV_StsBadArg, "Invalid histogram header[s]" );
415
416 if( CV_IS_SPARSE_MAT(hist1->bins) != CV_IS_SPARSE_MAT(hist2->bins))
417 CV_ERROR(CV_StsUnmatchedFormats, "One of histograms is sparse and other is not");
418
419 CV_CALL( dims1 = cvGetDims( hist1->bins, size1 ));
420 CV_CALL( dims2 = cvGetDims( hist2->bins, size2 ));
421
422 if( dims1 != dims2 )
423 CV_ERROR( CV_StsUnmatchedSizes,
424 "The histograms have different numbers of dimensions" );
425
426 for( i = 0; i < dims1; i++ )
427 {
428 if( size1[i] != size2[i] )
429 CV_ERROR( CV_StsUnmatchedSizes, "The histograms have different sizes" );
430 total *= size1[i];
431 }
432
433
434 if( !CV_IS_SPARSE_MAT(hist1->bins))
435 {
436 union { float* fl; uchar* ptr; } v;
437 float *ptr1, *ptr2;
438 v.fl = 0;
439 CV_CALL( cvGetRawData( hist1->bins, &v.ptr ));
440 ptr1 = v.fl;
441 CV_CALL( cvGetRawData( hist2->bins, &v.ptr ));
442 ptr2 = v.fl;
443
444 switch( method )
445 {
446 case CV_COMP_CHISQR:
447 for( i = 0; i < total; i++ )
448 {
449 double a = ptr1[i] - ptr2[i];
450 double b = ptr1[i] + ptr2[i];
451 if( fabs(b) > DBL_EPSILON )
452 result += a*a/b;
453 }
454 break;
455 case CV_COMP_CORREL:
456 {
457 double s1 = 0, s11 = 0;
458 double s2 = 0, s22 = 0;
459 double s12 = 0;
460 double num, denom2, scale = 1./total;
461
462 for( i = 0; i < total; i++ )
463 {
464 double a = ptr1[i];
465 double b = ptr2[i];
466
467 s12 += a*b;
468 s1 += a;
469 s11 += a*a;
470 s2 += b;
471 s22 += b*b;
472 }
473
474 num = s12 - s1*s2*scale;
475 denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale);
476 result = fabs(denom2) > DBL_EPSILON ? num/sqrt(denom2) : 1;
477 }
478 break;
479 case CV_COMP_INTERSECT:
480 for( i = 0; i < total; i++ )
481 {
482 float a = ptr1[i];
483 float b = ptr2[i];
484 if( a <= b )
485 result += a;
486 else
487 result += b;
488 }
489 break;
490 case CV_COMP_BHATTACHARYYA:
491 {
492 double s1 = 0, s2 = 0;
493 for( i = 0; i < total; i++ )
494 {
495 double a = ptr1[i];
496 double b = ptr2[i];
497 result += sqrt(a*b);
498 s1 += a;
499 s2 += b;
500 }
501 s1 *= s2;
502 s1 = fabs(s1) > FLT_EPSILON ? 1./sqrt(s1) : 1.;
503 result = 1. - result*s1;
504 result = sqrt(MAX(result,0.));
505 }
506 break;
507 default:
508 CV_ERROR( CV_StsBadArg, "Unknown comparison method" );
509 }
510 }
511 else
512 {
513 CvSparseMat* mat1 = (CvSparseMat*)(hist1->bins);
514 CvSparseMat* mat2 = (CvSparseMat*)(hist2->bins);
515 CvSparseMatIterator iterator;
516 CvSparseNode *node1, *node2;
517
518 if( mat1->heap->active_count > mat2->heap->active_count )
519 {
520 CvSparseMat* t;
521 CV_SWAP( mat1, mat2, t );
522 }
523
524 switch( method )
525 {
526 case CV_COMP_CHISQR:
527 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
528 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
529 {
530 double v1 = *(float*)CV_NODE_VAL(mat1,node1);
531 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1), 0, 0, &node1->hashval );
532 if( !node2_data )
533 result += v1;
534 else
535 {
536 double v2 = *(float*)node2_data;
537 double a = v1 - v2;
538 double b = v1 + v2;
539 if( fabs(b) > DBL_EPSILON )
540 result += a*a/b;
541 }
542 }
543
544 for( node2 = cvInitSparseMatIterator( mat2, &iterator );
545 node2 != 0; node2 = cvGetNextSparseNode( &iterator ))
546 {
547 double v2 = *(float*)CV_NODE_VAL(mat2,node2);
548 if( !cvPtrND( mat1, CV_NODE_IDX(mat2,node2), 0, 0, &node2->hashval ))
549 result += v2;
550 }
551 break;
552 case CV_COMP_CORREL:
553 {
554 double s1 = 0, s11 = 0;
555 double s2 = 0, s22 = 0;
556 double s12 = 0;
557 double num, denom2, scale = 1./total;
558
559 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
560 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
561 {
562 double v1 = *(float*)CV_NODE_VAL(mat1,node1);
563 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1),
564 0, 0, &node1->hashval );
565 if( node2_data )
566 {
567 double v2 = *(float*)node2_data;
568 s12 += v1*v2;
569 }
570 s1 += v1;
571 s11 += v1*v1;
572 }
573
574 for( node2 = cvInitSparseMatIterator( mat2, &iterator );
575 node2 != 0; node2 = cvGetNextSparseNode( &iterator ))
576 {
577 double v2 = *(float*)CV_NODE_VAL(mat2,node2);
578 s2 += v2;
579 s22 += v2*v2;
580 }
581
582 num = s12 - s1*s2*scale;
583 denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale);
584 result = fabs(denom2) > DBL_EPSILON ? num/sqrt(denom2) : 1;
585 }
586 break;
587 case CV_COMP_INTERSECT:
588 {
589 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
590 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
591 {
592 float v1 = *(float*)CV_NODE_VAL(mat1,node1);
593 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1),
594 0, 0, &node1->hashval );
595 if( node2_data )
596 {
597 float v2 = *(float*)node2_data;
598 if( v1 <= v2 )
599 result += v1;
600 else
601 result += v2;
602 }
603 }
604 }
605 break;
606 case CV_COMP_BHATTACHARYYA:
607 {
608 double s1 = 0, s2 = 0;
609
610 for( node1 = cvInitSparseMatIterator( mat1, &iterator );
611 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
612 {
613 double v1 = *(float*)CV_NODE_VAL(mat1,node1);
614 uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1),
615 0, 0, &node1->hashval );
616 s1 += v1;
617 if( node2_data )
618 {
619 double v2 = *(float*)node2_data;
620 result += sqrt(v1 * v2);
621 }
622 }
623
624 for( node1 = cvInitSparseMatIterator( mat2, &iterator );
625 node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
626 {
627 double v2 = *(float*)CV_NODE_VAL(mat2,node1);
628 s2 += v2;
629 }
630
631 s1 *= s2;
632 s1 = fabs(s1) > FLT_EPSILON ? 1./sqrt(s1) : 1.;
633 result = 1. - result*s1;
634 result = sqrt(MAX(result,0.));
635 }
636 break;
637 default:
638 CV_ERROR( CV_StsBadArg, "Unknown comparison method" );
639 }
640 }
641
642 _result = result;
643
644 __END__;
645
646 return _result;
647 }
648
649 // copies one histogram to another
650 CV_IMPL void
cvCopyHist(const CvHistogram * src,CvHistogram ** _dst)651 cvCopyHist( const CvHistogram* src, CvHistogram** _dst )
652 {
653 CV_FUNCNAME( "cvCopyHist" );
654
655 __BEGIN__;
656
657 int eq = 0;
658 int is_sparse;
659 int i, dims1, dims2;
660 int size1[CV_MAX_DIM], size2[CV_MAX_DIM], total = 1;
661 float* ranges[CV_MAX_DIM];
662 float** thresh = 0;
663 CvHistogram* dst;
664
665 if( !_dst )
666 CV_ERROR( CV_StsNullPtr, "Destination double pointer is NULL" );
667
668 dst = *_dst;
669
670 if( !CV_IS_HIST(src) || (dst && !CV_IS_HIST(dst)) )
671 CV_ERROR( CV_StsBadArg, "Invalid histogram header[s]" );
672
673 is_sparse = CV_IS_SPARSE_MAT(src->bins);
674 CV_CALL( dims1 = cvGetDims( src->bins, size1 ));
675 for( i = 0; i < dims1; i++ )
676 total *= size1[i];
677
678 if( dst && is_sparse == CV_IS_SPARSE_MAT(dst->bins))
679 {
680 CV_CALL( dims2 = cvGetDims( dst->bins, size2 ));
681
682 if( dims1 == dims2 )
683 {
684 for( i = 0; i < dims1; i++ )
685 if( size1[i] != size2[i] )
686 break;
687 }
688
689 eq = i == dims1;
690 }
691
692 if( !eq )
693 {
694 cvReleaseHist( _dst );
695 CV_CALL( dst = cvCreateHist( dims1, size1,
696 !is_sparse ? CV_HIST_ARRAY : CV_HIST_SPARSE, 0, 0 ));
697 *_dst = dst;
698 }
699
700 if( CV_HIST_HAS_RANGES( src ))
701 {
702 if( CV_IS_UNIFORM_HIST( src ))
703 {
704 for( i = 0; i < dims1; i++ )
705 ranges[i] = (float*)src->thresh[i];
706 thresh = ranges;
707 }
708 else
709 thresh = src->thresh2;
710 CV_CALL( cvSetHistBinRanges( dst, thresh, CV_IS_UNIFORM_HIST(src)));
711 }
712
713 CV_CALL( cvCopy( src->bins, dst->bins ));
714
715 __END__;
716 }
717
718
719 // Sets a value range for every histogram bin
720 CV_IMPL void
cvSetHistBinRanges(CvHistogram * hist,float ** ranges,int uniform)721 cvSetHistBinRanges( CvHistogram* hist, float** ranges, int uniform )
722 {
723 CV_FUNCNAME( "cvSetHistBinRanges" );
724
725 __BEGIN__;
726
727 int dims, size[CV_MAX_DIM], total = 0;
728 int i, j;
729
730 if( !ranges )
731 CV_ERROR( CV_StsNullPtr, "NULL ranges pointer" );
732
733 if( !CV_IS_HIST(hist) )
734 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
735
736 CV_CALL( dims = cvGetDims( hist->bins, size ));
737 for( i = 0; i < dims; i++ )
738 total += size[i]+1;
739
740 if( uniform )
741 {
742 for( i = 0; i < dims; i++ )
743 {
744 if( !ranges[i] )
745 CV_ERROR( CV_StsNullPtr, "One of <ranges> elements is NULL" );
746 hist->thresh[i][0] = ranges[i][0];
747 hist->thresh[i][1] = ranges[i][1];
748 }
749
750 hist->type |= CV_HIST_UNIFORM_FLAG + CV_HIST_RANGES_FLAG;
751 }
752 else
753 {
754 float* dim_ranges;
755
756 if( !hist->thresh2 )
757 {
758 CV_CALL( hist->thresh2 = (float**)cvAlloc(
759 dims*sizeof(hist->thresh2[0])+
760 total*sizeof(hist->thresh2[0][0])));
761 }
762 dim_ranges = (float*)(hist->thresh2 + dims);
763
764 for( i = 0; i < dims; i++ )
765 {
766 float val0 = -FLT_MAX;
767
768 if( !ranges[i] )
769 CV_ERROR( CV_StsNullPtr, "One of <ranges> elements is NULL" );
770
771 for( j = 0; j <= size[i]; j++ )
772 {
773 float val = ranges[i][j];
774 if( val <= val0 )
775 CV_ERROR(CV_StsOutOfRange, "Bin ranges should go in ascenting order");
776 val0 = dim_ranges[j] = val;
777 }
778
779 hist->thresh2[i] = dim_ranges;
780 dim_ranges += size[i] + 1;
781 }
782
783 hist->type |= CV_HIST_RANGES_FLAG;
784 hist->type &= ~CV_HIST_UNIFORM_FLAG;
785 }
786
787 __END__;
788 }
789
790
791 #define ICV_HIST_DUMMY_IDX (INT_MIN/3)
792
793 static CvStatus
icvCalcHistLookupTables8u(const CvHistogram * hist,int dims,int * size,int * tab)794 icvCalcHistLookupTables8u( const CvHistogram* hist, int dims, int* size, int* tab )
795 {
796 const int lo = 0, hi = 256;
797 int is_sparse = CV_IS_SPARSE_HIST( hist );
798 int have_range = CV_HIST_HAS_RANGES(hist);
799 int i, j;
800
801 if( !have_range || CV_IS_UNIFORM_HIST(hist))
802 {
803 for( i = 0; i < dims; i++ )
804 {
805 double a = have_range ? hist->thresh[i][0] : 0;
806 double b = have_range ? hist->thresh[i][1] : 256;
807 int sz = size[i];
808 double scale = sz/(b - a);
809 int step = 1;
810
811 if( !is_sparse )
812 step = ((CvMatND*)(hist->bins))->dim[i].step/sizeof(float);
813
814 for( j = lo; j < hi; j++ )
815 {
816 int idx = cvFloor((j - a)*scale);
817 if( (unsigned)idx < (unsigned)sz )
818 idx *= step;
819 else
820 idx = ICV_HIST_DUMMY_IDX;
821
822 tab[i*(hi - lo) + j - lo] = idx;
823 }
824 }
825 }
826 else
827 {
828 for( i = 0; i < dims; i++ )
829 {
830 double limit = hist->thresh2[i][0];
831 int idx = -1, write_idx = ICV_HIST_DUMMY_IDX, sz = size[i];
832 int step = 1;
833
834 if( !is_sparse )
835 step = ((CvMatND*)(hist->bins))->dim[i].step/sizeof(float);
836
837 if( limit > hi )
838 limit = hi;
839
840 j = lo;
841 for(;;)
842 {
843 for( ; j < limit; j++ )
844 tab[i*(hi - lo) + j - lo] = write_idx;
845
846 if( (unsigned)(++idx) < (unsigned)sz )
847 {
848 limit = hist->thresh2[i][idx+1];
849 if( limit > hi )
850 limit = hi;
851 write_idx = idx*step;
852 }
853 else
854 {
855 for( ; j < hi; j++ )
856 tab[i*(hi - lo) + j - lo] = ICV_HIST_DUMMY_IDX;
857 break;
858 }
859 }
860 }
861 }
862
863 return CV_OK;
864 }
865
866
867 /***************************** C A L C H I S T O G R A M *************************/
868
869 // Calculates histogram for one or more 8u arrays
870 static CvStatus CV_STDCALL
icvCalcHist_8u_C1R(uchar ** img,int step,uchar * mask,int maskStep,CvSize size,CvHistogram * hist)871 icvCalcHist_8u_C1R( uchar** img, int step, uchar* mask, int maskStep,
872 CvSize size, CvHistogram* hist )
873 {
874 int* tab;
875 int is_sparse = CV_IS_SPARSE_HIST(hist);
876 int dims, histsize[CV_MAX_DIM];
877 int i, x;
878 CvStatus status;
879
880 dims = cvGetDims( hist->bins, histsize );
881
882 tab = (int*)cvStackAlloc( dims*256*sizeof(int));
883 status = icvCalcHistLookupTables8u( hist, dims, histsize, tab );
884
885 if( status < 0 )
886 return status;
887
888 if( !is_sparse )
889 {
890 int total = 1;
891 int* bins = ((CvMatND*)(hist->bins))->data.i;
892
893 for( i = 0; i < dims; i++ )
894 total *= histsize[i];
895
896 if( dims <= 3 && total >= -ICV_HIST_DUMMY_IDX )
897 return CV_BADSIZE_ERR; // too big histogram
898
899 switch( dims )
900 {
901 case 1:
902 {
903 int tab1d[256];
904 memset( tab1d, 0, sizeof(tab1d));
905
906 for( ; size.height--; img[0] += step )
907 {
908 uchar* ptr = img[0];
909 if( !mask )
910 {
911 for( x = 0; x <= size.width - 4; x += 4 )
912 {
913 int v0 = ptr[x];
914 int v1 = ptr[x+1];
915
916 tab1d[v0]++;
917 tab1d[v1]++;
918
919 v0 = ptr[x+2];
920 v1 = ptr[x+3];
921
922 tab1d[v0]++;
923 tab1d[v1]++;
924 }
925
926 for( ; x < size.width; x++ )
927 tab1d[ptr[x]]++;
928 }
929 else
930 {
931 for( x = 0; x < size.width; x++ )
932 if( mask[x] )
933 tab1d[ptr[x]]++;
934 mask += maskStep;
935 }
936 }
937
938 for( i = 0; i < 256; i++ )
939 {
940 int idx = tab[i];
941 if( idx >= 0 )
942 bins[idx] += tab1d[i];
943 }
944 }
945 break;
946 case 2:
947 for( ; size.height--; img[0] += step, img[1] += step )
948 {
949 uchar* ptr0 = img[0];
950 uchar* ptr1 = img[1];
951 if( !mask )
952 {
953 for( x = 0; x < size.width; x++ )
954 {
955 int v0 = ptr0[x];
956 int v1 = ptr1[x];
957 int idx = tab[v0] + tab[256+v1];
958
959 if( idx >= 0 )
960 bins[idx]++;
961 }
962 }
963 else
964 {
965 for( x = 0; x < size.width; x++ )
966 {
967 if( mask[x] )
968 {
969 int v0 = ptr0[x];
970 int v1 = ptr1[x];
971
972 int idx = tab[v0] + tab[256+v1];
973
974 if( idx >= 0 )
975 bins[idx]++;
976 }
977 }
978 mask += maskStep;
979 }
980 }
981 break;
982 case 3:
983 for( ; size.height--; img[0] += step, img[1] += step, img[2] += step )
984 {
985 uchar* ptr0 = img[0];
986 uchar* ptr1 = img[1];
987 uchar* ptr2 = img[2];
988 if( !mask )
989 {
990 for( x = 0; x < size.width; x++ )
991 {
992 int v0 = ptr0[x];
993 int v1 = ptr1[x];
994 int v2 = ptr2[x];
995 int idx = tab[v0] + tab[256+v1] + tab[512+v2];
996
997 if( idx >= 0 )
998 bins[idx]++;
999 }
1000 }
1001 else
1002 {
1003 for( x = 0; x < size.width; x++ )
1004 {
1005 if( mask[x] )
1006 {
1007 int v0 = ptr0[x];
1008 int v1 = ptr1[x];
1009 int v2 = ptr2[x];
1010 int idx = tab[v0] + tab[256+v1] + tab[512+v2];
1011
1012 if( idx >= 0 )
1013 bins[idx]++;
1014 }
1015 }
1016 mask += maskStep;
1017 }
1018 }
1019 break;
1020 default:
1021 for( ; size.height--; )
1022 {
1023 if( !mask )
1024 {
1025 for( x = 0; x < size.width; x++ )
1026 {
1027 int* binptr = bins;
1028 for( i = 0; i < dims; i++ )
1029 {
1030 int idx = tab[i*256 + img[i][x]];
1031 if( idx < 0 )
1032 break;
1033 binptr += idx;
1034 }
1035 if( i == dims )
1036 binptr[0]++;
1037 }
1038 }
1039 else
1040 {
1041 for( x = 0; x < size.width; x++ )
1042 {
1043 if( mask[x] )
1044 {
1045 int* binptr = bins;
1046 for( i = 0; i < dims; i++ )
1047 {
1048 int idx = tab[i*256 + img[i][x]];
1049 if( idx < 0 )
1050 break;
1051 binptr += idx;
1052 }
1053 if( i == dims )
1054 binptr[0]++;
1055 }
1056 }
1057 mask += maskStep;
1058 }
1059
1060 for( i = 0; i < dims; i++ )
1061 img[i] += step;
1062 }
1063 }
1064 }
1065 else
1066 {
1067 CvSparseMat* mat = (CvSparseMat*)(hist->bins);
1068 int node_idx[CV_MAX_DIM];
1069
1070 for( ; size.height--; )
1071 {
1072 if( !mask )
1073 {
1074 for( x = 0; x < size.width; x++ )
1075 {
1076 for( i = 0; i < dims; i++ )
1077 {
1078 int idx = tab[i*256 + img[i][x]];
1079 if( idx < 0 )
1080 break;
1081 node_idx[i] = idx;
1082 }
1083 if( i == dims )
1084 {
1085 int* bin = (int*)cvPtrND( mat, node_idx, 0, 1 );
1086 bin[0]++;
1087 }
1088 }
1089 }
1090 else
1091 {
1092 for( x = 0; x < size.width; x++ )
1093 {
1094 if( mask[x] )
1095 {
1096 for( i = 0; i < dims; i++ )
1097 {
1098 int idx = tab[i*256 + img[i][x]];
1099 if( idx < 0 )
1100 break;
1101 node_idx[i] = idx;
1102 }
1103 if( i == dims )
1104 {
1105 int* bin = (int*)cvPtrND( mat, node_idx, 0, 1, 0 );
1106 bin[0]++;
1107 }
1108 }
1109 }
1110 mask += maskStep;
1111 }
1112
1113 for( i = 0; i < dims; i++ )
1114 img[i] += step;
1115 }
1116 }
1117
1118 return CV_OK;
1119 }
1120
1121
1122 // Calculates histogram for one or more 32f arrays
1123 static CvStatus CV_STDCALL
icvCalcHist_32f_C1R(float ** img,int step,uchar * mask,int maskStep,CvSize size,CvHistogram * hist)1124 icvCalcHist_32f_C1R( float** img, int step, uchar* mask, int maskStep,
1125 CvSize size, CvHistogram* hist )
1126 {
1127 int is_sparse = CV_IS_SPARSE_HIST(hist);
1128 int uniform = CV_IS_UNIFORM_HIST(hist);
1129 int dims, histsize[CV_MAX_DIM];
1130 double uni_range[CV_MAX_DIM][2];
1131 int i, x;
1132
1133 dims = cvGetDims( hist->bins, histsize );
1134 step /= sizeof(img[0][0]);
1135
1136 if( uniform )
1137 {
1138 for( i = 0; i < dims; i++ )
1139 {
1140 double t = histsize[i]/((double)hist->thresh[i][1] - hist->thresh[i][0]);
1141 uni_range[i][0] = t;
1142 uni_range[i][1] = -t*hist->thresh[i][0];
1143 }
1144 }
1145
1146 if( !is_sparse )
1147 {
1148 CvMatND* mat = (CvMatND*)(hist->bins);
1149 int* bins = mat->data.i;
1150
1151 if( uniform )
1152 {
1153 switch( dims )
1154 {
1155 case 1:
1156 {
1157 double a = uni_range[0][0], b = uni_range[0][1];
1158 int sz = histsize[0];
1159
1160 for( ; size.height--; img[0] += step )
1161 {
1162 float* ptr = img[0];
1163
1164 if( !mask )
1165 {
1166 for( x = 0; x <= size.width - 4; x += 4 )
1167 {
1168 int v0 = cvFloor(ptr[x]*a + b);
1169 int v1 = cvFloor(ptr[x+1]*a + b);
1170
1171 if( (unsigned)v0 < (unsigned)sz )
1172 bins[v0]++;
1173 if( (unsigned)v1 < (unsigned)sz )
1174 bins[v1]++;
1175
1176 v0 = cvFloor(ptr[x+2]*a + b);
1177 v1 = cvFloor(ptr[x+3]*a + b);
1178
1179 if( (unsigned)v0 < (unsigned)sz )
1180 bins[v0]++;
1181 if( (unsigned)v1 < (unsigned)sz )
1182 bins[v1]++;
1183 }
1184
1185 for( ; x < size.width; x++ )
1186 {
1187 int v0 = cvFloor(ptr[x]*a + b);
1188 if( (unsigned)v0 < (unsigned)sz )
1189 bins[v0]++;
1190 }
1191 }
1192 else
1193 {
1194 for( x = 0; x < size.width; x++ )
1195 if( mask[x] )
1196 {
1197 int v0 = cvFloor(ptr[x]*a + b);
1198 if( (unsigned)v0 < (unsigned)sz )
1199 bins[v0]++;
1200 }
1201 mask += maskStep;
1202 }
1203 }
1204 }
1205 break;
1206 case 2:
1207 {
1208 double a0 = uni_range[0][0], b0 = uni_range[0][1];
1209 double a1 = uni_range[1][0], b1 = uni_range[1][1];
1210 int sz0 = histsize[0], sz1 = histsize[1];
1211 int step0 = ((CvMatND*)(hist->bins))->dim[0].step/sizeof(float);
1212
1213 for( ; size.height--; img[0] += step, img[1] += step )
1214 {
1215 float* ptr0 = img[0];
1216 float* ptr1 = img[1];
1217
1218 if( !mask )
1219 {
1220 for( x = 0; x < size.width; x++ )
1221 {
1222 int v0 = cvFloor( ptr0[x]*a0 + b0 );
1223 int v1 = cvFloor( ptr1[x]*a1 + b1 );
1224
1225 if( (unsigned)v0 < (unsigned)sz0 &&
1226 (unsigned)v1 < (unsigned)sz1 )
1227 bins[v0*step0 + v1]++;
1228 }
1229 }
1230 else
1231 {
1232 for( x = 0; x < size.width; x++ )
1233 {
1234 if( mask[x] )
1235 {
1236 int v0 = cvFloor( ptr0[x]*a0 + b0 );
1237 int v1 = cvFloor( ptr1[x]*a1 + b1 );
1238
1239 if( (unsigned)v0 < (unsigned)sz0 &&
1240 (unsigned)v1 < (unsigned)sz1 )
1241 bins[v0*step0 + v1]++;
1242 }
1243 }
1244 mask += maskStep;
1245 }
1246 }
1247 }
1248 break;
1249 default:
1250 for( ; size.height--; )
1251 {
1252 if( !mask )
1253 {
1254 for( x = 0; x < size.width; x++ )
1255 {
1256 int* binptr = bins;
1257 for( i = 0; i < dims; i++ )
1258 {
1259 int idx = cvFloor((double)img[i][x]*uni_range[i][0]
1260 + uni_range[i][1]);
1261 if( (unsigned)idx >= (unsigned)histsize[i] )
1262 break;
1263 binptr += idx*(mat->dim[i].step/sizeof(float));
1264 }
1265 if( i == dims )
1266 binptr[0]++;
1267 }
1268 }
1269 else
1270 {
1271 for( x = 0; x < size.width; x++ )
1272 {
1273 if( mask[x] )
1274 {
1275 int* binptr = bins;
1276 for( i = 0; i < dims; i++ )
1277 {
1278 int idx = cvFloor((double)img[i][x]*uni_range[i][0]
1279 + uni_range[i][1]);
1280 if( (unsigned)idx >= (unsigned)histsize[i] )
1281 break;
1282 binptr += idx*(mat->dim[i].step/sizeof(float));
1283 }
1284 if( i == dims )
1285 binptr[0]++;
1286 }
1287 }
1288 mask += maskStep;
1289 }
1290
1291 for( i = 0; i < dims; i++ )
1292 img[i] += step;
1293 }
1294 }
1295 }
1296 else
1297 {
1298 for( ; size.height--; )
1299 {
1300 for( x = 0; x < size.width; x++ )
1301 {
1302 if( !mask || mask[x] )
1303 {
1304 int* binptr = bins;
1305 for( i = 0; i < dims; i++ )
1306 {
1307 float v = img[i][x];
1308 float* thresh = hist->thresh2[i];
1309 int idx = -1, sz = histsize[i];
1310
1311 while( v >= thresh[idx+1] && ++idx < sz )
1312 /* nop */;
1313
1314 if( (unsigned)idx >= (unsigned)sz )
1315 break;
1316
1317 binptr += idx*(mat->dim[i].step/sizeof(float));
1318 }
1319 if( i == dims )
1320 binptr[0]++;
1321 }
1322 }
1323
1324 for( i = 0; i < dims; i++ )
1325 img[i] += step;
1326 if( mask )
1327 mask += maskStep;
1328 }
1329 }
1330 }
1331 else
1332 {
1333 CvSparseMat* mat = (CvSparseMat*)(hist->bins);
1334 int node_idx[CV_MAX_DIM];
1335
1336 for( ; size.height--; )
1337 {
1338 if( uniform )
1339 {
1340 for( x = 0; x < size.width; x++ )
1341 {
1342 if( !mask || mask[x] )
1343 {
1344 for( i = 0; i < dims; i++ )
1345 {
1346 int idx = cvFloor(img[i][x]*uni_range[i][0]
1347 + uni_range[i][1]);
1348 if( (unsigned)idx >= (unsigned)histsize[i] )
1349 break;
1350 node_idx[i] = idx;
1351 }
1352 if( i == dims )
1353 {
1354 int* bin = (int*)cvPtrND( mat, node_idx, 0, 1, 0 );
1355 bin[0]++;
1356 }
1357 }
1358 }
1359 }
1360 else
1361 {
1362 for( x = 0; x < size.width; x++ )
1363 {
1364 if( !mask || mask[x] )
1365 {
1366 for( i = 0; i < dims; i++ )
1367 {
1368 float v = img[i][x];
1369 float* thresh = hist->thresh2[i];
1370 int idx = -1, sz = histsize[i];
1371
1372 while( v >= thresh[idx+1] && ++idx < sz )
1373 /* nop */;
1374
1375 if( (unsigned)idx >= (unsigned)sz )
1376 break;
1377
1378 node_idx[i] = idx;
1379 }
1380 if( i == dims )
1381 {
1382 int* bin = (int*)cvPtrND( mat, node_idx, 0, 1, 0 );
1383 bin[0]++;
1384 }
1385 }
1386 }
1387 }
1388
1389 for( i = 0; i < dims; i++ )
1390 img[i] += step;
1391
1392 if( mask )
1393 mask += maskStep;
1394 }
1395 }
1396
1397 return CV_OK;
1398 }
1399
1400
1401 CV_IMPL void
cvCalcArrHist(CvArr ** img,CvHistogram * hist,int do_not_clear,const CvArr * mask)1402 cvCalcArrHist( CvArr** img, CvHistogram* hist,
1403 int do_not_clear, const CvArr* mask )
1404 {
1405 CV_FUNCNAME( "cvCalcHist" );
1406
1407 __BEGIN__;
1408
1409 uchar* ptr[CV_MAX_DIM];
1410 uchar* maskptr = 0;
1411 int maskstep = 0, step = 0;
1412 int i, dims;
1413 int cont_flag = -1;
1414 CvMat stub0, *mat0 = 0;
1415 CvMatND dense;
1416 CvSize size;
1417
1418 if( !CV_IS_HIST(hist))
1419 CV_ERROR( CV_StsBadArg, "Bad histogram pointer" );
1420
1421 if( !img )
1422 CV_ERROR( CV_StsNullPtr, "Null double array pointer" );
1423
1424 CV_CALL( dims = cvGetDims( hist->bins ));
1425
1426 for( i = 0; i < dims; i++ )
1427 {
1428 CvMat stub, *mat = (CvMat*)img[i];
1429 CV_CALL( mat = cvGetMat( mat, i == 0 ? &stub0 : &stub, 0, 1 ));
1430
1431 if( CV_MAT_CN( mat->type ) != 1 )
1432 CV_ERROR( CV_BadNumChannels, "Only 1-channel arrays are allowed here" );
1433
1434 if( i == 0 )
1435 {
1436 mat0 = mat;
1437 step = mat0->step;
1438 }
1439 else
1440 {
1441 if( !CV_ARE_SIZES_EQ( mat0, mat ))
1442 CV_ERROR( CV_StsUnmatchedSizes, "Not all the planes have equal sizes" );
1443
1444 if( mat0->step != mat->step )
1445 CV_ERROR( CV_StsUnmatchedSizes, "Not all the planes have equal steps" );
1446
1447 if( !CV_ARE_TYPES_EQ( mat0, mat ))
1448 CV_ERROR( CV_StsUnmatchedFormats, "Not all the planes have equal types" );
1449 }
1450
1451 cont_flag &= mat->type;
1452 ptr[i] = mat->data.ptr;
1453 }
1454
1455 if( mask )
1456 {
1457 CvMat stub, *mat = (CvMat*)mask;
1458 CV_CALL( mat = cvGetMat( mat, &stub, 0, 1 ));
1459
1460 if( !CV_IS_MASK_ARR(mat))
1461 CV_ERROR( CV_StsBadMask, "Bad mask array" );
1462
1463 if( !CV_ARE_SIZES_EQ( mat0, mat ))
1464 CV_ERROR( CV_StsUnmatchedSizes,
1465 "Mask size does not match to other arrays\' size" );
1466 maskptr = mat->data.ptr;
1467 maskstep = mat->step;
1468 cont_flag &= mat->type;
1469 }
1470
1471 size = cvGetMatSize(mat0);
1472 if( CV_IS_MAT_CONT( cont_flag ))
1473 {
1474 size.width *= size.height;
1475 size.height = 1;
1476 maskstep = step = CV_STUB_STEP;
1477 }
1478
1479 if( !CV_IS_SPARSE_HIST(hist))
1480 {
1481 dense = *(CvMatND*)hist->bins;
1482 dense.type = (dense.type & ~CV_MAT_TYPE_MASK) | CV_32SC1;
1483 }
1484
1485 if( !do_not_clear )
1486 {
1487 CV_CALL( cvZero( hist->bins ));
1488 }
1489 else if( !CV_IS_SPARSE_HIST(hist))
1490 {
1491 CV_CALL( cvConvert( (CvMatND*)hist->bins, &dense ));
1492 }
1493 else
1494 {
1495 CvSparseMat* mat = (CvSparseMat*)(hist->bins);
1496 CvSparseMatIterator iterator;
1497 CvSparseNode* node;
1498
1499 for( node = cvInitSparseMatIterator( mat, &iterator );
1500 node != 0; node = cvGetNextSparseNode( &iterator ))
1501 {
1502 Cv32suf* val = (Cv32suf*)CV_NODE_VAL( mat, node );
1503 val->i = cvRound( val->f );
1504 }
1505 }
1506
1507 if( CV_MAT_DEPTH(mat0->type) > CV_8S && !CV_HIST_HAS_RANGES(hist))
1508 CV_ERROR( CV_StsBadArg, "histogram ranges must be set (via cvSetHistBinRanges) "
1509 "before calling the function" );
1510
1511 switch( CV_MAT_DEPTH(mat0->type) )
1512 {
1513 case CV_8U:
1514 IPPI_CALL( icvCalcHist_8u_C1R( ptr, step, maskptr, maskstep, size, hist ));
1515 break;
1516 case CV_32F:
1517 {
1518 union { uchar** ptr; float** fl; } v;
1519 v.ptr = ptr;
1520 IPPI_CALL( icvCalcHist_32f_C1R( v.fl, step, maskptr, maskstep, size, hist ));
1521 }
1522 break;
1523 default:
1524 CV_ERROR( CV_StsUnsupportedFormat, "Unsupported array type" );
1525 }
1526
1527 if( !CV_IS_SPARSE_HIST(hist))
1528 {
1529 CV_CALL( cvConvert( &dense, (CvMatND*)hist->bins ));
1530 }
1531 else
1532 {
1533 CvSparseMat* mat = (CvSparseMat*)(hist->bins);
1534 CvSparseMatIterator iterator;
1535 CvSparseNode* node;
1536
1537 for( node = cvInitSparseMatIterator( mat, &iterator );
1538 node != 0; node = cvGetNextSparseNode( &iterator ))
1539 {
1540 Cv32suf* val = (Cv32suf*)CV_NODE_VAL( mat, node );
1541 val->f = (float)val->i;
1542 }
1543 }
1544
1545 __END__;
1546 }
1547
1548
1549 /***************************** B A C K P R O J E C T *****************************/
1550
1551 // Calculates back project for one or more 8u arrays
1552 static CvStatus CV_STDCALL
icvCalcBackProject_8u_C1R(uchar ** img,int step,uchar * dst,int dstStep,CvSize size,const CvHistogram * hist)1553 icvCalcBackProject_8u_C1R( uchar** img, int step, uchar* dst, int dstStep,
1554 CvSize size, const CvHistogram* hist )
1555 {
1556 const int small_hist_size = 1<<12;
1557 int* tab = 0;
1558 int is_sparse = CV_IS_SPARSE_HIST(hist);
1559 int dims, histsize[CV_MAX_DIM];
1560 int i, x;
1561 CvStatus status;
1562
1563 dims = cvGetDims( hist->bins, histsize );
1564
1565 tab = (int*)cvStackAlloc( dims*256*sizeof(int));
1566 status = icvCalcHistLookupTables8u( hist, dims, histsize, tab );
1567 if( status < 0 )
1568 return status;
1569
1570 if( !is_sparse )
1571 {
1572 int total = 1;
1573 CvMatND* mat = (CvMatND*)(hist->bins);
1574 float* bins = mat->data.fl;
1575 uchar* buffer = 0;
1576
1577 for( i = 0; i < dims; i++ )
1578 total *= histsize[i];
1579
1580 if( dims <= 3 && total >= -ICV_HIST_DUMMY_IDX )
1581 return CV_BADSIZE_ERR; // too big histogram
1582
1583 if( dims > 1 && total <= small_hist_size && CV_IS_MAT_CONT(mat->type))
1584 {
1585 buffer = (uchar*)cvAlloc(total);
1586 if( !buffer )
1587 return CV_OUTOFMEM_ERR;
1588 for( i = 0; i < total; i++ )
1589 {
1590 int v = cvRound(bins[i]);
1591 buffer[i] = CV_CAST_8U(v);
1592 }
1593 }
1594
1595 switch( dims )
1596 {
1597 case 1:
1598 {
1599 uchar tab1d[256];
1600 for( i = 0; i < 256; i++ )
1601 {
1602 int idx = tab[i];
1603 if( idx >= 0 )
1604 {
1605 int v = cvRound(bins[idx]);
1606 tab1d[i] = CV_CAST_8U(v);
1607 }
1608 else
1609 tab1d[i] = 0;
1610 }
1611
1612 for( ; size.height--; img[0] += step, dst += dstStep )
1613 {
1614 uchar* ptr = img[0];
1615 for( x = 0; x <= size.width - 4; x += 4 )
1616 {
1617 uchar v0 = tab1d[ptr[x]];
1618 uchar v1 = tab1d[ptr[x+1]];
1619
1620 dst[x] = v0;
1621 dst[x+1] = v1;
1622
1623 v0 = tab1d[ptr[x+2]];
1624 v1 = tab1d[ptr[x+3]];
1625
1626 dst[x+2] = v0;
1627 dst[x+3] = v1;
1628 }
1629
1630 for( ; x < size.width; x++ )
1631 dst[x] = tab1d[ptr[x]];
1632 }
1633 }
1634 break;
1635 case 2:
1636 for( ; size.height--; img[0] += step, img[1] += step, dst += dstStep )
1637 {
1638 uchar* ptr0 = img[0];
1639 uchar* ptr1 = img[1];
1640
1641 if( buffer )
1642 {
1643 for( x = 0; x < size.width; x++ )
1644 {
1645 int v0 = ptr0[x];
1646 int v1 = ptr1[x];
1647 int idx = tab[v0] + tab[256+v1];
1648 int v = 0;
1649
1650 if( idx >= 0 )
1651 v = buffer[idx];
1652
1653 dst[x] = (uchar)v;
1654 }
1655 }
1656 else
1657 {
1658 for( x = 0; x < size.width; x++ )
1659 {
1660 int v0 = ptr0[x];
1661 int v1 = ptr1[x];
1662 int idx = tab[v0] + tab[256+v1];
1663 int v = 0;
1664
1665 if( idx >= 0 )
1666 {
1667 v = cvRound(bins[idx]);
1668 v = CV_CAST_8U(v);
1669 }
1670
1671 dst[x] = (uchar)v;
1672 }
1673 }
1674 }
1675 break;
1676 case 3:
1677 for( ; size.height--; img[0] += step, img[1] += step,
1678 img[2] += step, dst += dstStep )
1679 {
1680 uchar* ptr0 = img[0];
1681 uchar* ptr1 = img[1];
1682 uchar* ptr2 = img[2];
1683
1684 if( buffer )
1685 {
1686 for( x = 0; x < size.width; x++ )
1687 {
1688 int v0 = ptr0[x];
1689 int v1 = ptr1[x];
1690 int v2 = ptr2[x];
1691 int idx = tab[v0] + tab[256+v1] + tab[512+v2];
1692 int v = 0;
1693
1694 if( idx >= 0 )
1695 v = buffer[idx];
1696
1697 dst[x] = (uchar)v;
1698 }
1699 }
1700 else
1701 {
1702 for( x = 0; x < size.width; x++ )
1703 {
1704 int v0 = ptr0[x];
1705 int v1 = ptr1[x];
1706 int v2 = ptr2[x];
1707 int idx = tab[v0] + tab[256+v1] + tab[512+v2];
1708 int v = 0;
1709
1710 if( idx >= 0 )
1711 {
1712 v = cvRound(bins[idx]);
1713 v = CV_CAST_8U(v);
1714 }
1715 dst[x] = (uchar)v;
1716 }
1717 }
1718 }
1719 break;
1720 default:
1721 for( ; size.height--; dst += dstStep )
1722 {
1723 if( buffer )
1724 {
1725 for( x = 0; x < size.width; x++ )
1726 {
1727 uchar* binptr = buffer;
1728 int v = 0;
1729
1730 for( i = 0; i < dims; i++ )
1731 {
1732 int idx = tab[i*256 + img[i][x]];
1733 if( idx < 0 )
1734 break;
1735 binptr += idx;
1736 }
1737
1738 if( i == dims )
1739 v = binptr[0];
1740
1741 dst[x] = (uchar)v;
1742 }
1743 }
1744 else
1745 {
1746 for( x = 0; x < size.width; x++ )
1747 {
1748 float* binptr = bins;
1749 int v = 0;
1750
1751 for( i = 0; i < dims; i++ )
1752 {
1753 int idx = tab[i*256 + img[i][x]];
1754 if( idx < 0 )
1755 break;
1756 binptr += idx;
1757 }
1758
1759 if( i == dims )
1760 {
1761 v = cvRound( binptr[0] );
1762 v = CV_CAST_8U(v);
1763 }
1764
1765 dst[x] = (uchar)v;
1766 }
1767 }
1768
1769 for( i = 0; i < dims; i++ )
1770 img[i] += step;
1771 }
1772 }
1773
1774 cvFree( &buffer );
1775 }
1776 else
1777 {
1778 CvSparseMat* mat = (CvSparseMat*)(hist->bins);
1779 int node_idx[CV_MAX_DIM];
1780
1781 for( ; size.height--; dst += dstStep )
1782 {
1783 for( x = 0; x < size.width; x++ )
1784 {
1785 int v = 0;
1786
1787 for( i = 0; i < dims; i++ )
1788 {
1789 int idx = tab[i*256 + img[i][x]];
1790 if( idx < 0 )
1791 break;
1792 node_idx[i] = idx;
1793 }
1794 if( i == dims )
1795 {
1796 float* bin = (float*)cvPtrND( mat, node_idx, 0, 1, 0 );
1797 v = cvRound(bin[0]);
1798 v = CV_CAST_8U(v);
1799 }
1800
1801 dst[x] = (uchar)v;
1802 }
1803
1804 for( i = 0; i < dims; i++ )
1805 img[i] += step;
1806 }
1807 }
1808
1809 return CV_OK;
1810 }
1811
1812
1813 // Calculates back project for one or more 32f arrays
1814 static CvStatus CV_STDCALL
icvCalcBackProject_32f_C1R(float ** img,int step,float * dst,int dstStep,CvSize size,const CvHistogram * hist)1815 icvCalcBackProject_32f_C1R( float** img, int step, float* dst, int dstStep,
1816 CvSize size, const CvHistogram* hist )
1817 {
1818 int is_sparse = CV_IS_SPARSE_HIST(hist);
1819 int uniform = CV_IS_UNIFORM_HIST(hist);
1820 int dims, histsize[CV_MAX_DIM];
1821 double uni_range[CV_MAX_DIM][2];
1822 int i, x;
1823
1824 dims = cvGetDims( hist->bins, histsize );
1825 step /= sizeof(img[0][0]);
1826 dstStep /= sizeof(dst[0]);
1827
1828 if( uniform )
1829 {
1830 for( i = 0; i < dims; i++ )
1831 {
1832 double t = ((double)histsize[i])/
1833 ((double)hist->thresh[i][1] - hist->thresh[i][0]);
1834 uni_range[i][0] = t;
1835 uni_range[i][1] = -t*hist->thresh[i][0];
1836 }
1837 }
1838
1839 if( !is_sparse )
1840 {
1841 CvMatND* mat = (CvMatND*)(hist->bins);
1842 float* bins = mat->data.fl;
1843
1844 if( uniform )
1845 {
1846 switch( dims )
1847 {
1848 case 1:
1849 {
1850 double a = uni_range[0][0], b = uni_range[0][1];
1851 int sz = histsize[0];
1852
1853 for( ; size.height--; img[0] += step, dst += dstStep )
1854 {
1855 float* ptr = img[0];
1856
1857 for( x = 0; x <= size.width - 4; x += 4 )
1858 {
1859 int v0 = cvFloor(ptr[x]*a + b);
1860 int v1 = cvFloor(ptr[x+1]*a + b);
1861
1862 if( (unsigned)v0 < (unsigned)sz )
1863 dst[x] = bins[v0];
1864 else
1865 dst[x] = 0;
1866
1867 if( (unsigned)v1 < (unsigned)sz )
1868 dst[x+1] = bins[v1];
1869 else
1870 dst[x+1] = 0;
1871
1872 v0 = cvFloor(ptr[x+2]*a + b);
1873 v1 = cvFloor(ptr[x+3]*a + b);
1874
1875 if( (unsigned)v0 < (unsigned)sz )
1876 dst[x+2] = bins[v0];
1877 else
1878 dst[x+2] = 0;
1879
1880 if( (unsigned)v1 < (unsigned)sz )
1881 dst[x+3] = bins[v1];
1882 else
1883 dst[x+3] = 0;
1884 }
1885
1886 for( ; x < size.width; x++ )
1887 {
1888 int v0 = cvFloor(ptr[x]*a + b);
1889
1890 if( (unsigned)v0 < (unsigned)sz )
1891 dst[x] = bins[v0];
1892 else
1893 dst[x] = 0;
1894 }
1895 }
1896 }
1897 break;
1898 case 2:
1899 {
1900 double a0 = uni_range[0][0], b0 = uni_range[0][1];
1901 double a1 = uni_range[1][0], b1 = uni_range[1][1];
1902 int sz0 = histsize[0], sz1 = histsize[1];
1903 int step0 = ((CvMatND*)(hist->bins))->dim[0].step/sizeof(float);
1904
1905 for( ; size.height--; img[0] += step, img[1] += step, dst += dstStep )
1906 {
1907 float* ptr0 = img[0];
1908 float* ptr1 = img[1];
1909
1910 for( x = 0; x < size.width; x++ )
1911 {
1912 int v0 = cvFloor( ptr0[x]*a0 + b0 );
1913 int v1 = cvFloor( ptr1[x]*a1 + b1 );
1914
1915 if( (unsigned)v0 < (unsigned)sz0 &&
1916 (unsigned)v1 < (unsigned)sz1 )
1917 dst[x] = bins[v0*step0 + v1];
1918 else
1919 dst[x] = 0;
1920 }
1921 }
1922 }
1923 break;
1924 default:
1925 for( ; size.height--; dst += dstStep )
1926 {
1927 for( x = 0; x < size.width; x++ )
1928 {
1929 float* binptr = bins;
1930
1931 for( i = 0; i < dims; i++ )
1932 {
1933 int idx = cvFloor(img[i][x]*uni_range[i][0]
1934 + uni_range[i][1]);
1935 if( (unsigned)idx >= (unsigned)histsize[i] )
1936 break;
1937 binptr += idx*(mat->dim[i].step/sizeof(float));
1938 }
1939 if( i == dims )
1940 dst[x] = binptr[0];
1941 else
1942 dst[x] = 0;
1943 }
1944 }
1945
1946 for( i = 0; i < dims; i++ )
1947 img[i] += step;
1948 }
1949 }
1950 else
1951 {
1952 for( ; size.height--; dst += dstStep )
1953 {
1954 for( x = 0; x < size.width; x++ )
1955 {
1956 float* binptr = bins;
1957 for( i = 0; i < dims; i++ )
1958 {
1959 float v = img[i][x];
1960 float* thresh = hist->thresh2[i];
1961 int idx = -1, sz = histsize[i];
1962
1963 while( v >= thresh[idx+1] && ++idx < sz )
1964 /* nop */;
1965
1966 if( (unsigned)idx >= (unsigned)sz )
1967 break;
1968
1969 binptr += idx*(mat->dim[i].step/sizeof(float));
1970 }
1971 if( i == dims )
1972 dst[x] = binptr[0];
1973 else
1974 dst[x] = 0;
1975 }
1976
1977 for( i = 0; i < dims; i++ )
1978 img[i] += step;
1979 }
1980 }
1981 }
1982 else
1983 {
1984 CvSparseMat* mat = (CvSparseMat*)(hist->bins);
1985 int node_idx[CV_MAX_DIM];
1986
1987 for( ; size.height--; dst += dstStep )
1988 {
1989 if( uniform )
1990 {
1991 for( x = 0; x < size.width; x++ )
1992 {
1993 for( i = 0; i < dims; i++ )
1994 {
1995 int idx = cvFloor(img[i][x]*uni_range[i][0]
1996 + uni_range[i][1]);
1997 if( (unsigned)idx >= (unsigned)histsize[i] )
1998 break;
1999 node_idx[i] = idx;
2000 }
2001 if( i == dims )
2002 {
2003 float* bin = (float*)cvPtrND( mat, node_idx, 0, 1, 0 );
2004 dst[x] = bin[0];
2005 }
2006 else
2007 dst[x] = 0;
2008 }
2009 }
2010 else
2011 {
2012 for( x = 0; x < size.width; x++ )
2013 {
2014 for( i = 0; i < dims; i++ )
2015 {
2016 float v = img[i][x];
2017 float* thresh = hist->thresh2[i];
2018 int idx = -1, sz = histsize[i];
2019
2020 while( v >= thresh[idx+1] && ++idx < sz )
2021 /* nop */;
2022
2023 if( (unsigned)idx >= (unsigned)sz )
2024 break;
2025
2026 node_idx[i] = idx;
2027 }
2028 if( i == dims )
2029 {
2030 float* bin = (float*)cvPtrND( mat, node_idx, 0, 1, 0 );
2031 dst[x] = bin[0];
2032 }
2033 else
2034 dst[x] = 0;
2035 }
2036 }
2037
2038 for( i = 0; i < dims; i++ )
2039 img[i] += step;
2040 }
2041 }
2042
2043 return CV_OK;
2044 }
2045
2046
2047 CV_IMPL void
cvCalcArrBackProject(CvArr ** img,CvArr * dst,const CvHistogram * hist)2048 cvCalcArrBackProject( CvArr** img, CvArr* dst, const CvHistogram* hist )
2049 {
2050 CV_FUNCNAME( "cvCalcArrBackProject" );
2051
2052 __BEGIN__;
2053
2054 uchar* ptr[CV_MAX_DIM];
2055 uchar* dstptr = 0;
2056 int dststep = 0, step = 0;
2057 int i, dims;
2058 int cont_flag = -1;
2059 CvMat stub0, *mat0 = 0;
2060 CvSize size;
2061
2062 if( !CV_IS_HIST(hist))
2063 CV_ERROR( CV_StsBadArg, "Bad histogram pointer" );
2064
2065 if( !img )
2066 CV_ERROR( CV_StsNullPtr, "Null double array pointer" );
2067
2068 CV_CALL( dims = cvGetDims( hist->bins ));
2069
2070 for( i = 0; i <= dims; i++ )
2071 {
2072 CvMat stub, *mat = (CvMat*)(i < dims ? img[i] : dst);
2073 CV_CALL( mat = cvGetMat( mat, i == 0 ? &stub0 : &stub, 0, 1 ));
2074
2075 if( CV_MAT_CN( mat->type ) != 1 )
2076 CV_ERROR( CV_BadNumChannels, "Only 1-channel arrays are allowed here" );
2077
2078 if( i == 0 )
2079 {
2080 mat0 = mat;
2081 step = mat0->step;
2082 }
2083 else
2084 {
2085 if( !CV_ARE_SIZES_EQ( mat0, mat ))
2086 CV_ERROR( CV_StsUnmatchedSizes, "Not all the planes have equal sizes" );
2087
2088 if( mat0->step != mat->step )
2089 CV_ERROR( CV_StsUnmatchedSizes, "Not all the planes have equal steps" );
2090
2091 if( !CV_ARE_TYPES_EQ( mat0, mat ))
2092 CV_ERROR( CV_StsUnmatchedFormats, "Not all the planes have equal types" );
2093 }
2094
2095 cont_flag &= mat->type;
2096 if( i < dims )
2097 ptr[i] = mat->data.ptr;
2098 else
2099 {
2100 dstptr = mat->data.ptr;
2101 dststep = mat->step;
2102 }
2103 }
2104
2105 size = cvGetMatSize(mat0);
2106 if( CV_IS_MAT_CONT( cont_flag ))
2107 {
2108 size.width *= size.height;
2109 size.height = 1;
2110 dststep = step = CV_STUB_STEP;
2111 }
2112
2113 if( CV_MAT_DEPTH(mat0->type) > CV_8S && !CV_HIST_HAS_RANGES(hist))
2114 CV_ERROR( CV_StsBadArg, "histogram ranges must be set (via cvSetHistBinRanges) "
2115 "before calling the function" );
2116
2117 switch( CV_MAT_DEPTH(mat0->type) )
2118 {
2119 case CV_8U:
2120 IPPI_CALL( icvCalcBackProject_8u_C1R( ptr, step, dstptr, dststep, size, hist ));
2121 break;
2122 case CV_32F:
2123 {
2124 union { uchar** ptr; float** fl; } v;
2125 v.ptr = ptr;
2126 IPPI_CALL( icvCalcBackProject_32f_C1R( v.fl, step,
2127 (float*)dstptr, dststep, size, hist ));
2128 }
2129 break;
2130 default:
2131 CV_ERROR( CV_StsUnsupportedFormat, "Unsupported array type" );
2132 }
2133
2134 __END__;
2135 }
2136
2137
2138 ////////////////////// B A C K P R O J E C T P A T C H /////////////////////////
2139
2140 CV_IMPL void
cvCalcArrBackProjectPatch(CvArr ** arr,CvArr * dst,CvSize patch_size,CvHistogram * hist,int method,double norm_factor)2141 cvCalcArrBackProjectPatch( CvArr** arr, CvArr* dst, CvSize patch_size, CvHistogram* hist,
2142 int method, double norm_factor )
2143 {
2144 CvHistogram* model = 0;
2145
2146 CV_FUNCNAME( "cvCalcArrBackProjectPatch" );
2147
2148 __BEGIN__;
2149
2150 IplImage imgstub[CV_MAX_DIM], *img[CV_MAX_DIM];
2151 IplROI roi;
2152 CvMat dststub, *dstmat;
2153 int i, dims;
2154 int x, y;
2155 CvSize size;
2156
2157 if( !CV_IS_HIST(hist))
2158 CV_ERROR( CV_StsBadArg, "Bad histogram pointer" );
2159
2160 if( !arr )
2161 CV_ERROR( CV_StsNullPtr, "Null double array pointer" );
2162
2163 if( norm_factor <= 0 )
2164 CV_ERROR( CV_StsOutOfRange,
2165 "Bad normalization factor (set it to 1.0 if unsure)" );
2166
2167 if( patch_size.width <= 0 || patch_size.height <= 0 )
2168 CV_ERROR( CV_StsBadSize, "The patch width and height must be positive" );
2169
2170 CV_CALL( dims = cvGetDims( hist->bins ));
2171 CV_CALL( cvCopyHist( hist, &model ));
2172 CV_CALL( cvNormalizeHist( hist, norm_factor ));
2173
2174 for( i = 0; i < dims; i++ )
2175 {
2176 CvMat stub, *mat;
2177 CV_CALL( mat = cvGetMat( arr[i], &stub, 0, 0 ));
2178 CV_CALL( img[i] = cvGetImage( mat, &imgstub[i] ));
2179 img[i]->roi = &roi;
2180 }
2181
2182 CV_CALL( dstmat = cvGetMat( dst, &dststub, 0, 0 ));
2183 if( CV_MAT_TYPE( dstmat->type ) != CV_32FC1 )
2184 CV_ERROR( CV_StsUnsupportedFormat, "Resultant image must have 32fC1 type" );
2185
2186 if( dstmat->cols != img[0]->width - patch_size.width + 1 ||
2187 dstmat->rows != img[0]->height - patch_size.height + 1 )
2188 CV_ERROR( CV_StsUnmatchedSizes,
2189 "The output map must be (W-w+1 x H-h+1), "
2190 "where the input images are (W x H) each and the patch is (w x h)" );
2191
2192 size = cvGetMatSize(dstmat);
2193 roi.coi = 0;
2194 roi.width = patch_size.width;
2195 roi.height = patch_size.height;
2196
2197 for( y = 0; y < size.height; y++ )
2198 {
2199 for( x = 0; x < size.width; x++ )
2200 {
2201 double result;
2202
2203 roi.xOffset = x;
2204 roi.yOffset = y;
2205
2206 CV_CALL( cvCalcHist( img, model ));
2207
2208 CV_CALL( cvNormalizeHist( model, norm_factor ));
2209 CV_CALL( result = cvCompareHist( model, hist, method ));
2210 CV_MAT_ELEM( *dstmat, float, y, x ) = (float)result;
2211 }
2212 }
2213
2214 __END__;
2215
2216 cvReleaseHist( &model );
2217 }
2218
2219
2220 // Calculates Bayes probabilistic histograms
2221 CV_IMPL void
cvCalcBayesianProb(CvHistogram ** src,int count,CvHistogram ** dst)2222 cvCalcBayesianProb( CvHistogram** src, int count, CvHistogram** dst )
2223 {
2224 CV_FUNCNAME( "cvCalcBayesianProb" );
2225
2226 __BEGIN__;
2227
2228 int i;
2229
2230 if( !src || !dst )
2231 CV_ERROR( CV_StsNullPtr, "NULL histogram array pointer" );
2232
2233 if( count < 2 )
2234 CV_ERROR( CV_StsOutOfRange, "Too small number of histograms" );
2235
2236 for( i = 0; i < count; i++ )
2237 {
2238 if( !CV_IS_HIST(src[i]) || !CV_IS_HIST(dst[i]) )
2239 CV_ERROR( CV_StsBadArg, "Invalid histogram header" );
2240
2241 if( !CV_IS_MATND(src[i]->bins) || !CV_IS_MATND(dst[i]->bins) )
2242 CV_ERROR( CV_StsBadArg, "The function supports dense histograms only" );
2243 }
2244
2245 cvZero( dst[0]->bins );
2246 // dst[0] = src[0] + ... + src[count-1]
2247 for( i = 0; i < count; i++ )
2248 CV_CALL( cvAdd( src[i]->bins, dst[0]->bins, dst[0]->bins ));
2249
2250 CV_CALL( cvDiv( 0, dst[0]->bins, dst[0]->bins ));
2251
2252 // dst[i] = src[i]*(1/dst[0])
2253 for( i = count - 1; i >= 0; i-- )
2254 CV_CALL( cvMul( src[i]->bins, dst[0]->bins, dst[i]->bins ));
2255
2256 __END__;
2257 }
2258
2259
2260 CV_IMPL void
cvCalcProbDensity(const CvHistogram * hist,const CvHistogram * hist_mask,CvHistogram * hist_dens,double scale)2261 cvCalcProbDensity( const CvHistogram* hist, const CvHistogram* hist_mask,
2262 CvHistogram* hist_dens, double scale )
2263 {
2264 CV_FUNCNAME( "cvCalcProbDensity" );
2265
2266 __BEGIN__;
2267
2268 if( scale <= 0 )
2269 CV_ERROR( CV_StsOutOfRange, "scale must be positive" );
2270
2271 if( !CV_IS_HIST(hist) || !CV_IS_HIST(hist_mask) || !CV_IS_HIST(hist_dens) )
2272 CV_ERROR( CV_StsBadArg, "Invalid histogram pointer[s]" );
2273
2274 {
2275 CvArr* arrs[] = { hist->bins, hist_mask->bins, hist_dens->bins };
2276 CvMatND stubs[3];
2277 CvNArrayIterator iterator;
2278
2279 CV_CALL( cvInitNArrayIterator( 3, arrs, 0, stubs, &iterator ));
2280
2281 if( CV_MAT_TYPE(iterator.hdr[0]->type) != CV_32FC1 )
2282 CV_ERROR( CV_StsUnsupportedFormat, "All histograms must have 32fC1 type" );
2283
2284 do
2285 {
2286 const float* srcdata = (const float*)(iterator.ptr[0]);
2287 const float* maskdata = (const float*)(iterator.ptr[1]);
2288 float* dstdata = (float*)(iterator.ptr[2]);
2289 int i;
2290
2291 for( i = 0; i < iterator.size.width; i++ )
2292 {
2293 float s = srcdata[i];
2294 float m = maskdata[i];
2295 if( s > FLT_EPSILON )
2296 if( m <= s )
2297 dstdata[i] = (float)(m*scale/s);
2298 else
2299 dstdata[i] = (float)scale;
2300 else
2301 dstdata[i] = (float)0;
2302 }
2303 }
2304 while( cvNextNArraySlice( &iterator ));
2305 }
2306
2307 __END__;
2308 }
2309
2310
cvEqualizeHist(const CvArr * src,CvArr * dst)2311 CV_IMPL void cvEqualizeHist( const CvArr* src, CvArr* dst )
2312 {
2313 CvHistogram* hist = 0;
2314 CvMat* lut = 0;
2315
2316 CV_FUNCNAME( "cvEqualizeHist" );
2317
2318 __BEGIN__;
2319
2320 int i, hist_sz = 256;
2321 CvSize img_sz;
2322 float scale;
2323 float* h;
2324 int sum = 0;
2325 int type;
2326
2327 CV_CALL( type = cvGetElemType( src ));
2328 if( type != CV_8UC1 )
2329 CV_ERROR( CV_StsUnsupportedFormat, "Only 8uC1 images are supported" );
2330
2331 CV_CALL( hist = cvCreateHist( 1, &hist_sz, CV_HIST_ARRAY ));
2332 CV_CALL( lut = cvCreateMat( 1, 256, CV_8UC1 ));
2333 CV_CALL( cvCalcArrHist( (CvArr**)&src, hist ));
2334 CV_CALL( img_sz = cvGetSize( src ));
2335 scale = 255.f/(img_sz.width*img_sz.height);
2336 h = (float*)cvPtr1D( hist->bins, 0 );
2337
2338 for( i = 0; i < hist_sz; i++ )
2339 {
2340 sum += cvRound(h[i]);
2341 lut->data.ptr[i] = (uchar)cvRound(sum*scale);
2342 }
2343
2344 lut->data.ptr[0] = 0;
2345 CV_CALL( cvLUT( src, dst, lut ));
2346
2347 __END__;
2348
2349 cvReleaseHist(&hist);
2350 cvReleaseMat(&lut);
2351 }
2352
2353 /* Implementation of RTTI and Generic Functions for CvHistogram */
2354 #define CV_TYPE_NAME_HIST "opencv-hist"
2355
icvIsHist(const void * ptr)2356 static int icvIsHist( const void * ptr ){
2357 return CV_IS_HIST( ((CvHistogram*)ptr) );
2358 }
2359
icvCloneHist(const CvHistogram * src)2360 static CvHistogram * icvCloneHist( const CvHistogram * src ){
2361 CvHistogram * dst=NULL;
2362 cvCopyHist(src, &dst);
2363 return dst;
2364 }
2365
icvReadHist(CvFileStorage * fs,CvFileNode * node)2366 static void *icvReadHist( CvFileStorage * fs, CvFileNode * node ){
2367 CvHistogram * h = 0;
2368 int is_uniform = 0;
2369 int have_ranges = 0;
2370
2371 CV_FUNCNAME("icvReadHist");
2372 __BEGIN__;
2373
2374 CV_CALL( h = (CvHistogram *) cvAlloc( sizeof(CvHistogram) ));
2375
2376 is_uniform = cvReadIntByName( fs, node, "is_uniform", 0 );
2377 have_ranges = cvReadIntByName( fs, node, "have_ranges", 0);
2378 h->type = CV_HIST_MAGIC_VAL |
2379 (is_uniform ? CV_HIST_UNIFORM_FLAG : 0) |
2380 (have_ranges ? CV_HIST_RANGES_FLAG : 0);
2381
2382 if(is_uniform){
2383 // read histogram bins
2384 CvMatND * mat = (CvMatND *) cvReadByName( fs, node, "mat" );
2385 int sizes[CV_MAX_DIM];
2386 int i;
2387 if(!CV_IS_MATND(mat)){
2388 CV_ERROR( CV_StsError, "Expected CvMatND");
2389 }
2390 for(i=0; i<mat->dims; i++){
2391 sizes[i] = mat->dim[i].size;
2392 }
2393
2394 cvInitMatNDHeader( &(h->mat), mat->dims, sizes, mat->type, mat->data.ptr );
2395 h->bins = &(h->mat);
2396
2397 // take ownership of refcount pointer as well
2398 h->mat.refcount = mat->refcount;
2399
2400 // increase refcount so freeing temp header doesn't free data
2401 cvIncRefData( mat );
2402
2403 // free temporary header
2404 cvReleaseMatND( &mat );
2405 }
2406 else{
2407 h->bins = cvReadByName( fs, node, "bins" );
2408 if(!CV_IS_SPARSE_MAT(h->bins)){
2409 CV_ERROR( CV_StsError, "Unknown Histogram type");
2410 }
2411 }
2412
2413 // read thresholds
2414 if(have_ranges){
2415 int i;
2416 int dims;
2417 int size[CV_MAX_DIM];
2418 int total = 0;
2419 CvSeqReader reader;
2420 CvFileNode * thresh_node;
2421
2422 CV_CALL( dims = cvGetDims( h->bins, size ));
2423 for( i = 0; i < dims; i++ ){
2424 total += size[i]+1;
2425 }
2426
2427 thresh_node = cvGetFileNodeByName( fs, node, "thresh" );
2428 if(!thresh_node){
2429 CV_ERROR( CV_StsError, "'thresh' node is missing");
2430 }
2431 cvStartReadRawData( fs, thresh_node, &reader );
2432
2433 if(is_uniform){
2434 for(i=0; i<dims; i++){
2435 cvReadRawDataSlice( fs, &reader, 2, h->thresh[i], "f" );
2436 }
2437 h->thresh2 = NULL;
2438 }
2439 else{
2440 float* dim_ranges;
2441 CV_CALL( h->thresh2 = (float**)cvAlloc(
2442 dims*sizeof(h->thresh2[0])+
2443 total*sizeof(h->thresh2[0][0])));
2444 dim_ranges = (float*)(h->thresh2 + dims);
2445 for(i=0; i < dims; i++){
2446 h->thresh2[i] = dim_ranges;
2447 cvReadRawDataSlice( fs, &reader, size[i]+1, dim_ranges, "f" );
2448 dim_ranges += size[i] + 1;
2449 }
2450 }
2451
2452 }
2453
2454 __END__;
2455
2456 return h;
2457 }
2458
icvWriteHist(CvFileStorage * fs,const char * name,const void * struct_ptr,CvAttrList)2459 static void icvWriteHist( CvFileStorage* fs, const char* name, const void* struct_ptr,
2460 CvAttrList /*attributes*/ ){
2461 const CvHistogram * hist = (const CvHistogram *) struct_ptr;
2462 int sizes[CV_MAX_DIM];
2463 int dims;
2464 int i;
2465 int is_uniform, have_ranges;
2466
2467 CV_FUNCNAME("icvWriteHist");
2468 __BEGIN__;
2469
2470 cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_HIST );
2471
2472 is_uniform = (CV_IS_UNIFORM_HIST(hist) ? 1 : 0);
2473 have_ranges = (hist->type & CV_HIST_RANGES_FLAG ? 1 : 0);
2474
2475 cvWriteInt( fs, "is_uniform", is_uniform );
2476 cvWriteInt( fs, "have_ranges", have_ranges );
2477 if(CV_IS_UNIFORM_HIST(hist)){
2478 cvWrite( fs, "mat", &(hist->mat) );
2479 }
2480 else if(CV_IS_SPARSE_HIST(hist)){
2481 cvWrite( fs, "bins", hist->bins );
2482 }
2483 else{
2484 CV_ERROR( CV_StsError, "Unknown Histogram Type" );
2485 }
2486
2487 // write thresholds
2488 if(have_ranges){
2489 dims = cvGetDims( hist->bins, sizes );
2490 cvStartWriteStruct( fs, "thresh", CV_NODE_SEQ + CV_NODE_FLOW );
2491 if(is_uniform){
2492 for(i=0; i<dims; i++){
2493 cvWriteRawData( fs, hist->thresh[i], 2, "f" );
2494 }
2495 }
2496 else{
2497 for(i=0; i<dims; i++){
2498 cvWriteRawData( fs, hist->thresh2[i], sizes[i]+1, "f" );
2499 }
2500 }
2501 cvEndWriteStruct( fs );
2502 }
2503
2504 cvEndWriteStruct( fs );
2505 __END__;
2506 }
2507
2508
2509 CvType hist_type( CV_TYPE_NAME_HIST, icvIsHist, (CvReleaseFunc)cvReleaseHist,
2510 icvReadHist, icvWriteHist, (CvCloneFunc)icvCloneHist );
2511
2512 /* End of file. */
2513
2514