Home | History | Annotate | Download | only in src
      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 *
     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*
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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 
   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 
   2356 static int icvIsHist( const void * ptr ){
   2357 	return CV_IS_HIST( ((CvHistogram*)ptr) );
   2358 }
   2359 
   2360 static CvHistogram * icvCloneHist( const CvHistogram * src ){
   2361 	CvHistogram * dst=NULL;
   2362 	cvCopyHist(src, &dst);
   2363 	return dst;
   2364 }
   2365 
   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 
   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