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 
     42 #include "_cxcore.h"
     43 
     44 /****************************************************************************************\
     45 *                                     MinMaxLoc                                          *
     46 \****************************************************************************************/
     47 
     48 #define CV_MINMAXLOC_ENTRY( _toggle_, srctype, temptype, cn ) \
     49     temptype min_val, max_val;                  \
     50     int min_loc = 0, max_loc = 0;               \
     51     int x, loc = 0, width = size.width*(cn);    \
     52     step /= sizeof(src[0]);                     \
     53                                                 \
     54     min_val = src[0];                           \
     55     min_val = max_val = _toggle_( min_val )
     56 
     57 
     58 #define CV_MINMAXLOC_EXIT( _fin_cast_macro_ )   \
     59     minLoc->x = min_loc;                        \
     60     maxLoc->x = max_loc;                        \
     61     minLoc->y = maxLoc->y = 0;                  \
     62     *minVal = _fin_cast_macro_(min_val);        \
     63     *maxVal = _fin_cast_macro_(max_val);        \
     64     return CV_OK
     65 
     66 
     67 #define ICV_DEF_MINMAXLOC_1D_CASE_COI( _toggle_, temptype, cn ) \
     68     for( x = 0; x < width; x += (cn), loc++ )   \
     69     {                                           \
     70         temptype val = src[x];                  \
     71         val = _toggle_(val);                    \
     72                                                 \
     73         if( val < min_val )                     \
     74         {                                       \
     75             min_val = val;                      \
     76             min_loc = loc;                      \
     77         }                                       \
     78         else if( val > max_val )                \
     79         {                                       \
     80             max_val = val;                      \
     81             max_loc = loc;                      \
     82         }                                       \
     83     }
     84 
     85 
     86 #define ICV_DEF_MINMAXLOC_FUNC_2D( _toggle_, _fin_cast_macro_, flavor,      \
     87                                    srctype, temptype, extrtype )            \
     88 IPCVAPI_IMPL( CvStatus,                                                     \
     89 icvMinMaxIndx_##flavor##_C1R,( const srctype* src, int step, CvSize size,   \
     90     extrtype* minVal, extrtype* maxVal, CvPoint* minLoc, CvPoint* maxLoc ), \
     91     (src, step, size, minVal, maxVal, minLoc, maxLoc) )                     \
     92 {                                                                           \
     93     CV_MINMAXLOC_ENTRY( _toggle_, srctype, temptype, 1 );                   \
     94                                                                             \
     95     for( ; size.height--; src += step )                                     \
     96     {                                                                       \
     97         ICV_DEF_MINMAXLOC_1D_CASE_COI( _toggle_, temptype, 1 );             \
     98     }                                                                       \
     99                                                                             \
    100     CV_MINMAXLOC_EXIT( _fin_cast_macro_ );                                  \
    101 }
    102 
    103 
    104 #define ICV_DEF_MINMAXLOC_FUNC_2D_COI( _toggle_, _fin_cast_macro_, flavor,  \
    105                                        srctype, temptype, extrtype )        \
    106 static CvStatus CV_STDCALL                                                  \
    107 icvMinMaxIndx_##flavor##_CnCR( const srctype* src, int step,                \
    108                           CvSize size, int cn, int coi,                     \
    109                           extrtype* minVal, extrtype* maxVal,               \
    110                           CvPoint* minLoc, CvPoint* maxLoc )                \
    111 {                                                                           \
    112     (src) += coi - 1;                                                       \
    113     CV_MINMAXLOC_ENTRY( _toggle_, srctype, temptype, cn );                  \
    114                                                                             \
    115     for( ; size.height--; src += step )                                     \
    116     {                                                                       \
    117         ICV_DEF_MINMAXLOC_1D_CASE_COI( _toggle_, temptype, cn );            \
    118     }                                                                       \
    119                                                                             \
    120     CV_MINMAXLOC_EXIT( _fin_cast_macro_ );                                  \
    121 }
    122 
    123 
    124 #define ICV_DEF_MINMAXLOC_ALL_INT( flavor, srctype,             \
    125                                    _fin_cast_macro_, extrtype ) \
    126     ICV_DEF_MINMAXLOC_FUNC_2D( CV_NOP, _fin_cast_macro_, flavor,\
    127                                srctype, int, extrtype )         \
    128     ICV_DEF_MINMAXLOC_FUNC_2D_COI( CV_NOP, _fin_cast_macro_,    \
    129                             flavor, srctype, int, extrtype )
    130 
    131 CV_INLINE float minmax_to_float( int val )
    132 {
    133     Cv32suf v;
    134     v.i = CV_TOGGLE_FLT(val);
    135     return v.f;
    136 }
    137 
    138 CV_INLINE double minmax_to_double( int64 val )
    139 {
    140     Cv64suf v;
    141     v.i = CV_TOGGLE_DBL(val);
    142     return v.f;
    143 }
    144 
    145 #define ICV_DEF_MINMAXLOC_ALL_FLT( flavor, srctype, _toggle_,           \
    146                                    _fin_cast_macro_, extrtype )         \
    147                                                                         \
    148     ICV_DEF_MINMAXLOC_FUNC_2D( _toggle_, _fin_cast_macro_, flavor,      \
    149                                 srctype, srctype, extrtype )            \
    150     ICV_DEF_MINMAXLOC_FUNC_2D_COI( _toggle_, _fin_cast_macro_, flavor,  \
    151                                 srctype, srctype, extrtype )
    152 
    153 ICV_DEF_MINMAXLOC_ALL_INT( 8u, uchar, CV_CAST_32F, float )
    154 ICV_DEF_MINMAXLOC_ALL_INT( 16u, ushort, CV_CAST_32F, float )
    155 ICV_DEF_MINMAXLOC_ALL_INT( 16s, short, CV_CAST_32F, float )
    156 ICV_DEF_MINMAXLOC_ALL_INT( 32s, int, CV_CAST_64F, double )
    157 ICV_DEF_MINMAXLOC_ALL_FLT( 32f, int, CV_TOGGLE_FLT, minmax_to_float, float )
    158 ICV_DEF_MINMAXLOC_ALL_FLT( 64f, int64, CV_TOGGLE_DBL, minmax_to_double, double )
    159 
    160 
    161 /****************************************************************************************\
    162 *                              MinMaxLoc with mask                                       *
    163 \****************************************************************************************/
    164 
    165 #define CV_MINMAXLOC_MASK_ENTRY( _toggle_, srctype, temptype, cn )  \
    166     temptype min_val = 0, max_val = 0;                              \
    167     int min_loc = -1, max_loc = -1;                                 \
    168     int x = 0, y, loc = 0, width = size.width;                      \
    169     step /= sizeof(src[0]);                                         \
    170                                                                     \
    171     if( width*(cn) == step && width == maskStep )                   \
    172     {                                                               \
    173         width *= size.height;                                       \
    174         size.height = 1;                                            \
    175     }                                                               \
    176                                                                     \
    177     for( y = 0; y < size.height; y++, src += step,                  \
    178                                       mask += maskStep )            \
    179     {                                                               \
    180         for( x = 0; x < width; x++, loc++ )                         \
    181             if( mask[x] != 0 )                                      \
    182             {                                                       \
    183                 min_loc = max_loc = loc;                            \
    184                 min_val = (src)[x*(cn)];                            \
    185                 min_val = max_val = _toggle_( min_val );            \
    186                 goto stop_scan;                                     \
    187             }                                                       \
    188     }                                                               \
    189                                                                     \
    190     stop_scan:;
    191 
    192 
    193 #define ICV_DEF_MINMAXLOC_1D_MASK_CASE_COI( _toggle_, temptype, cn ) \
    194     for( ; x < width; x++, loc++ )      \
    195     {                                   \
    196         temptype val = src[x*(cn)];     \
    197         int m = mask[x] != 0;           \
    198         val = _toggle_(val);            \
    199                                         \
    200         if( val < min_val && m )        \
    201         {                               \
    202             min_val = val;              \
    203             min_loc = loc;              \
    204         }                               \
    205         else if( val > max_val && m )   \
    206         {                               \
    207             max_val = val;              \
    208             max_loc = loc;              \
    209         }                               \
    210     }
    211 
    212 
    213 #define ICV_DEF_MINMAXLOC_MASK_FUNC_2D( _toggle_, _fin_cast_macro_, flavor, \
    214                                         srctype, temptype, extrtype )       \
    215 IPCVAPI_IMPL( CvStatus,                                                     \
    216 icvMinMaxIndx_##flavor##_C1MR,( const srctype* src, int step,               \
    217     const uchar* mask, int maskStep, CvSize size,                           \
    218     extrtype* minVal, extrtype* maxVal, CvPoint* minLoc, CvPoint* maxLoc ), \
    219     ( src, step, mask, maskStep, size, minVal, maxVal, minLoc, maxLoc) )    \
    220 {                                                                           \
    221     CV_MINMAXLOC_MASK_ENTRY( _toggle_, srctype, temptype, 1 );              \
    222                                                                             \
    223     for( ; y < size.height; y++, src += step, mask += maskStep )            \
    224     {                                                                       \
    225         ICV_DEF_MINMAXLOC_1D_MASK_CASE_COI( _toggle_, temptype, 1 )         \
    226         x = 0;                                                              \
    227     }                                                                       \
    228                                                                             \
    229     CV_MINMAXLOC_EXIT( _fin_cast_macro_ );                                  \
    230 }
    231 
    232 
    233 #define ICV_DEF_MINMAXLOC_MASK_FUNC_2D_COI( _toggle_, _fin_cast_macro_,     \
    234                                     flavor, srctype, temptype, extrtype )   \
    235 static CvStatus CV_STDCALL                                                  \
    236 icvMinMaxIndx_##flavor##_CnCMR( const srctype* src, int step,               \
    237     const uchar* mask, int maskStep, CvSize size, int cn, int coi,          \
    238     extrtype* minVal, extrtype* maxVal, CvPoint* minLoc, CvPoint* maxLoc )  \
    239 {                                                                           \
    240     (src) += coi - 1;                                                       \
    241     CV_MINMAXLOC_MASK_ENTRY( _toggle_, srctype, temptype, cn );             \
    242                                                                             \
    243     for( ; y < size.height; y++, src += step, mask += maskStep )            \
    244     {                                                                       \
    245         ICV_DEF_MINMAXLOC_1D_MASK_CASE_COI( _toggle_, temptype, cn )        \
    246         x = 0;                                                              \
    247     }                                                                       \
    248                                                                             \
    249     CV_MINMAXLOC_EXIT( _fin_cast_macro_ );                                  \
    250 }
    251 
    252 
    253 
    254 #define ICV_DEF_MINMAXLOC_MASK_ALL_INT( flavor, srctype,                    \
    255                                         _fin_cast_macro_, extrtype )        \
    256     ICV_DEF_MINMAXLOC_MASK_FUNC_2D( CV_NOP, _fin_cast_macro_, flavor,       \
    257                                     srctype, int, extrtype )                \
    258     ICV_DEF_MINMAXLOC_MASK_FUNC_2D_COI( CV_NOP, _fin_cast_macro_, flavor,   \
    259                                     srctype, int, extrtype )
    260 
    261 #define ICV_DEF_MINMAXLOC_MASK_ALL_FLT( flavor, srctype, _toggle_,          \
    262                                         _fin_cast_macro_, extrtype )        \
    263     ICV_DEF_MINMAXLOC_MASK_FUNC_2D( _toggle_, _fin_cast_macro_, flavor,     \
    264                                     srctype, srctype, extrtype )            \
    265     ICV_DEF_MINMAXLOC_MASK_FUNC_2D_COI( _toggle_, _fin_cast_macro_, flavor, \
    266                                     srctype, srctype, extrtype )
    267 
    268 ICV_DEF_MINMAXLOC_MASK_ALL_INT( 8u, uchar, CV_CAST_32F, float )
    269 ICV_DEF_MINMAXLOC_MASK_ALL_INT( 16u, ushort, CV_CAST_32F, float )
    270 ICV_DEF_MINMAXLOC_MASK_ALL_INT( 16s, short, CV_CAST_32F, float )
    271 ICV_DEF_MINMAXLOC_MASK_ALL_INT( 32s, int, CV_CAST_64F, double )
    272 ICV_DEF_MINMAXLOC_MASK_ALL_FLT( 32f, int, CV_TOGGLE_FLT, minmax_to_float, float )
    273 ICV_DEF_MINMAXLOC_MASK_ALL_FLT( 64f, int64, CV_TOGGLE_DBL, minmax_to_double, double )
    274 
    275 #define icvMinMaxIndx_8s_C1R    0
    276 #define icvMinMaxIndx_8s_CnCR   0
    277 #define icvMinMaxIndx_8s_C1MR   0
    278 #define icvMinMaxIndx_8s_CnCMR  0
    279 
    280 CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, C1R )
    281 CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, CnCR )
    282 CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, C1MR )
    283 CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, CnCMR )
    284 
    285 
    286 CV_IMPL  void
    287 cvMinMaxLoc( const void* img, double* _minVal, double* _maxVal,
    288              CvPoint* _minLoc, CvPoint* _maxLoc, const void* mask )
    289 {
    290     static CvFuncTable minmax_tab, minmaxcoi_tab;
    291     static CvFuncTable minmaxmask_tab, minmaxmaskcoi_tab;
    292     static int inittab = 0;
    293 
    294     CV_FUNCNAME("cvMinMaxLoc");
    295 
    296     __BEGIN__;
    297 
    298     int type, depth, cn, coi = 0;
    299     int mat_step, mask_step = 0, cont_flag;
    300     CvSize size;
    301     CvMat stub, maskstub, *mat = (CvMat*)img, *matmask = (CvMat*)mask;
    302     CvPoint minloc, maxloc;
    303     double minv = 0, maxv = 0;
    304     float minvf = 0.f, maxvf = 0.f;
    305     void *pmin = &minvf, *pmax = &maxvf;
    306 
    307     if( !inittab )
    308     {
    309         icvInitMinMaxIndxC1RTable( &minmax_tab );
    310         icvInitMinMaxIndxCnCRTable( &minmaxcoi_tab );
    311         icvInitMinMaxIndxC1MRTable( &minmaxmask_tab );
    312         icvInitMinMaxIndxCnCMRTable( &minmaxmaskcoi_tab );
    313         inittab = 1;
    314     }
    315 
    316     if( !CV_IS_MAT(mat) )
    317         CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
    318 
    319     type = CV_MAT_TYPE( mat->type );
    320     depth = CV_MAT_DEPTH( type );
    321     cn = CV_MAT_CN( type );
    322     size = cvGetMatSize( mat );
    323 
    324     if( cn > 1 && coi == 0 )
    325         CV_ERROR( CV_StsBadArg, "" );
    326 
    327     if( depth == CV_32S || depth == CV_64F )
    328         pmin = &minv, pmax = &maxv;
    329 
    330     mat_step = mat->step;
    331     cont_flag = mat->type;
    332 
    333     if( mask )
    334     {
    335         CV_CALL( matmask = cvGetMat( matmask, &maskstub ));
    336 
    337         if( !CV_IS_MASK_ARR( matmask ))
    338             CV_ERROR( CV_StsBadMask, "" );
    339 
    340         if( !CV_ARE_SIZES_EQ( mat, matmask ))
    341             CV_ERROR( CV_StsUnmatchedSizes, "" );
    342 
    343         mask_step = matmask->step;
    344         cont_flag &= matmask->type;
    345     }
    346 
    347     if( CV_IS_MAT_CONT(cont_flag) )
    348     {
    349         size.width *= size.height;
    350         size.height = 1;
    351     }
    352 
    353     if( size.height == 1 )
    354         mat_step = mask_step = CV_STUB_STEP;
    355 
    356     if( !mask )
    357     {
    358         if( CV_MAT_CN(type) == 1 || coi == 0 )
    359         {
    360             CvFunc2D_1A4P func = (CvFunc2D_1A4P)(minmax_tab.fn_2d[depth]);
    361 
    362             if( !func )
    363                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    364 
    365             IPPI_CALL( func( mat->data.ptr, mat_step, size,
    366                              pmin, pmax, &minloc, &maxloc ));
    367         }
    368         else
    369         {
    370             CvFunc2DnC_1A4P func = (CvFunc2DnC_1A4P)(minmaxcoi_tab.fn_2d[depth]);
    371 
    372             if( !func )
    373                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    374 
    375             IPPI_CALL( func( mat->data.ptr, mat_step, size, cn, coi,
    376                              pmin, pmax, &minloc, &maxloc ));
    377         }
    378     }
    379     else
    380     {
    381         if( CV_MAT_CN(type) == 1 || coi == 0 )
    382         {
    383             CvFunc2D_2A4P func = (CvFunc2D_2A4P)(minmaxmask_tab.fn_2d[depth]);
    384 
    385             if( !func )
    386                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    387 
    388             IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr,
    389                              mask_step, size,
    390                              pmin, pmax, &minloc, &maxloc ));
    391         }
    392         else
    393         {
    394             CvFunc2DnC_2A4P func = (CvFunc2DnC_2A4P)(minmaxmaskcoi_tab.fn_2d[depth]);
    395 
    396             if( !func )
    397                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    398 
    399             IPPI_CALL( func( mat->data.ptr, mat_step,
    400                              matmask->data.ptr, mask_step, size, cn, coi,
    401                              pmin, pmax, &minloc, &maxloc ));
    402         }
    403     }
    404 
    405     if( matmask || _minLoc || _maxLoc )
    406     {
    407         if( minloc.x >= mat->cols )
    408         {
    409             minloc.y = minloc.x / mat->cols;
    410             minloc.x -= minloc.y * mat->cols;
    411         }
    412 
    413         if( maxloc.x >= mat->cols )
    414         {
    415             maxloc.y = maxloc.x / mat->cols;
    416             maxloc.x -= maxloc.y * mat->cols;
    417         }
    418 
    419         if( matmask && ((unsigned)minloc.x >= (unsigned)mat->cols ||
    420             (unsigned)minloc.y >= (unsigned)mat->rows ||
    421             matmask->data.ptr[minloc.y*matmask->step + minloc.x] == 0 ||
    422             (unsigned)maxloc.x >= (unsigned)mat->cols ||
    423             (unsigned)maxloc.y >= (unsigned)mat->rows ||
    424             matmask->data.ptr[maxloc.y*matmask->step + maxloc.x] == 0) )
    425         {
    426             minloc.x = minloc.y = maxloc.x = maxloc.y = -1;
    427             minv = maxv = minvf = maxvf = 0;
    428         }
    429 
    430         if( _minLoc )
    431             *_minLoc = minloc;
    432 
    433         if( _maxLoc )
    434             *_maxLoc = maxloc;
    435     }
    436 
    437     if( depth != CV_32S && depth != CV_64F )
    438     {
    439         minv = minvf;
    440         maxv = maxvf;
    441     }
    442 
    443     if( _minVal )
    444         *_minVal = minv;
    445 
    446     if( _maxVal )
    447         *_maxVal = maxv;
    448 
    449     __END__;
    450 }
    451 
    452 /*  End of file  */
    453