/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "_cxcore.h" /****************************************************************************************\ * MinMaxLoc * \****************************************************************************************/ #define CV_MINMAXLOC_ENTRY( _toggle_, srctype, temptype, cn ) \ temptype min_val, max_val; \ int min_loc = 0, max_loc = 0; \ int x, loc = 0, width = size.width*(cn); \ step /= sizeof(src[0]); \ \ min_val = src[0]; \ min_val = max_val = _toggle_( min_val ) #define CV_MINMAXLOC_EXIT( _fin_cast_macro_ ) \ minLoc->x = min_loc; \ maxLoc->x = max_loc; \ minLoc->y = maxLoc->y = 0; \ *minVal = _fin_cast_macro_(min_val); \ *maxVal = _fin_cast_macro_(max_val); \ return CV_OK #define ICV_DEF_MINMAXLOC_1D_CASE_COI( _toggle_, temptype, cn ) \ for( x = 0; x < width; x += (cn), loc++ ) \ { \ temptype val = src[x]; \ val = _toggle_(val); \ \ if( val < min_val ) \ { \ min_val = val; \ min_loc = loc; \ } \ else if( val > max_val ) \ { \ max_val = val; \ max_loc = loc; \ } \ } #define ICV_DEF_MINMAXLOC_FUNC_2D( _toggle_, _fin_cast_macro_, flavor, \ srctype, temptype, extrtype ) \ IPCVAPI_IMPL( CvStatus, \ icvMinMaxIndx_##flavor##_C1R,( const srctype* src, int step, CvSize size, \ extrtype* minVal, extrtype* maxVal, CvPoint* minLoc, CvPoint* maxLoc ), \ (src, step, size, minVal, maxVal, minLoc, maxLoc) ) \ { \ CV_MINMAXLOC_ENTRY( _toggle_, srctype, temptype, 1 ); \ \ for( ; size.height--; src += step ) \ { \ ICV_DEF_MINMAXLOC_1D_CASE_COI( _toggle_, temptype, 1 ); \ } \ \ CV_MINMAXLOC_EXIT( _fin_cast_macro_ ); \ } #define ICV_DEF_MINMAXLOC_FUNC_2D_COI( _toggle_, _fin_cast_macro_, flavor, \ srctype, temptype, extrtype ) \ static CvStatus CV_STDCALL \ icvMinMaxIndx_##flavor##_CnCR( const srctype* src, int step, \ CvSize size, int cn, int coi, \ extrtype* minVal, extrtype* maxVal, \ CvPoint* minLoc, CvPoint* maxLoc ) \ { \ (src) += coi - 1; \ CV_MINMAXLOC_ENTRY( _toggle_, srctype, temptype, cn ); \ \ for( ; size.height--; src += step ) \ { \ ICV_DEF_MINMAXLOC_1D_CASE_COI( _toggle_, temptype, cn ); \ } \ \ CV_MINMAXLOC_EXIT( _fin_cast_macro_ ); \ } #define ICV_DEF_MINMAXLOC_ALL_INT( flavor, srctype, \ _fin_cast_macro_, extrtype ) \ ICV_DEF_MINMAXLOC_FUNC_2D( CV_NOP, _fin_cast_macro_, flavor,\ srctype, int, extrtype ) \ ICV_DEF_MINMAXLOC_FUNC_2D_COI( CV_NOP, _fin_cast_macro_, \ flavor, srctype, int, extrtype ) CV_INLINE float minmax_to_float( int val ) { Cv32suf v; v.i = CV_TOGGLE_FLT(val); return v.f; } CV_INLINE double minmax_to_double( int64 val ) { Cv64suf v; v.i = CV_TOGGLE_DBL(val); return v.f; } #define ICV_DEF_MINMAXLOC_ALL_FLT( flavor, srctype, _toggle_, \ _fin_cast_macro_, extrtype ) \ \ ICV_DEF_MINMAXLOC_FUNC_2D( _toggle_, _fin_cast_macro_, flavor, \ srctype, srctype, extrtype ) \ ICV_DEF_MINMAXLOC_FUNC_2D_COI( _toggle_, _fin_cast_macro_, flavor, \ srctype, srctype, extrtype ) ICV_DEF_MINMAXLOC_ALL_INT( 8u, uchar, CV_CAST_32F, float ) ICV_DEF_MINMAXLOC_ALL_INT( 16u, ushort, CV_CAST_32F, float ) ICV_DEF_MINMAXLOC_ALL_INT( 16s, short, CV_CAST_32F, float ) ICV_DEF_MINMAXLOC_ALL_INT( 32s, int, CV_CAST_64F, double ) ICV_DEF_MINMAXLOC_ALL_FLT( 32f, int, CV_TOGGLE_FLT, minmax_to_float, float ) ICV_DEF_MINMAXLOC_ALL_FLT( 64f, int64, CV_TOGGLE_DBL, minmax_to_double, double ) /****************************************************************************************\ * MinMaxLoc with mask * \****************************************************************************************/ #define CV_MINMAXLOC_MASK_ENTRY( _toggle_, srctype, temptype, cn ) \ temptype min_val = 0, max_val = 0; \ int min_loc = -1, max_loc = -1; \ int x = 0, y, loc = 0, width = size.width; \ step /= sizeof(src[0]); \ \ if( width*(cn) == step && width == maskStep ) \ { \ width *= size.height; \ size.height = 1; \ } \ \ for( y = 0; y < size.height; y++, src += step, \ mask += maskStep ) \ { \ for( x = 0; x < width; x++, loc++ ) \ if( mask[x] != 0 ) \ { \ min_loc = max_loc = loc; \ min_val = (src)[x*(cn)]; \ min_val = max_val = _toggle_( min_val ); \ goto stop_scan; \ } \ } \ \ stop_scan:; #define ICV_DEF_MINMAXLOC_1D_MASK_CASE_COI( _toggle_, temptype, cn ) \ for( ; x < width; x++, loc++ ) \ { \ temptype val = src[x*(cn)]; \ int m = mask[x] != 0; \ val = _toggle_(val); \ \ if( val < min_val && m ) \ { \ min_val = val; \ min_loc = loc; \ } \ else if( val > max_val && m ) \ { \ max_val = val; \ max_loc = loc; \ } \ } #define ICV_DEF_MINMAXLOC_MASK_FUNC_2D( _toggle_, _fin_cast_macro_, flavor, \ srctype, temptype, extrtype ) \ IPCVAPI_IMPL( CvStatus, \ icvMinMaxIndx_##flavor##_C1MR,( const srctype* src, int step, \ const uchar* mask, int maskStep, CvSize size, \ extrtype* minVal, extrtype* maxVal, CvPoint* minLoc, CvPoint* maxLoc ), \ ( src, step, mask, maskStep, size, minVal, maxVal, minLoc, maxLoc) ) \ { \ CV_MINMAXLOC_MASK_ENTRY( _toggle_, srctype, temptype, 1 ); \ \ for( ; y < size.height; y++, src += step, mask += maskStep ) \ { \ ICV_DEF_MINMAXLOC_1D_MASK_CASE_COI( _toggle_, temptype, 1 ) \ x = 0; \ } \ \ CV_MINMAXLOC_EXIT( _fin_cast_macro_ ); \ } #define ICV_DEF_MINMAXLOC_MASK_FUNC_2D_COI( _toggle_, _fin_cast_macro_, \ flavor, srctype, temptype, extrtype ) \ static CvStatus CV_STDCALL \ icvMinMaxIndx_##flavor##_CnCMR( const srctype* src, int step, \ const uchar* mask, int maskStep, CvSize size, int cn, int coi, \ extrtype* minVal, extrtype* maxVal, CvPoint* minLoc, CvPoint* maxLoc ) \ { \ (src) += coi - 1; \ CV_MINMAXLOC_MASK_ENTRY( _toggle_, srctype, temptype, cn ); \ \ for( ; y < size.height; y++, src += step, mask += maskStep ) \ { \ ICV_DEF_MINMAXLOC_1D_MASK_CASE_COI( _toggle_, temptype, cn ) \ x = 0; \ } \ \ CV_MINMAXLOC_EXIT( _fin_cast_macro_ ); \ } #define ICV_DEF_MINMAXLOC_MASK_ALL_INT( flavor, srctype, \ _fin_cast_macro_, extrtype ) \ ICV_DEF_MINMAXLOC_MASK_FUNC_2D( CV_NOP, _fin_cast_macro_, flavor, \ srctype, int, extrtype ) \ ICV_DEF_MINMAXLOC_MASK_FUNC_2D_COI( CV_NOP, _fin_cast_macro_, flavor, \ srctype, int, extrtype ) #define ICV_DEF_MINMAXLOC_MASK_ALL_FLT( flavor, srctype, _toggle_, \ _fin_cast_macro_, extrtype ) \ ICV_DEF_MINMAXLOC_MASK_FUNC_2D( _toggle_, _fin_cast_macro_, flavor, \ srctype, srctype, extrtype ) \ ICV_DEF_MINMAXLOC_MASK_FUNC_2D_COI( _toggle_, _fin_cast_macro_, flavor, \ srctype, srctype, extrtype ) ICV_DEF_MINMAXLOC_MASK_ALL_INT( 8u, uchar, CV_CAST_32F, float ) ICV_DEF_MINMAXLOC_MASK_ALL_INT( 16u, ushort, CV_CAST_32F, float ) ICV_DEF_MINMAXLOC_MASK_ALL_INT( 16s, short, CV_CAST_32F, float ) ICV_DEF_MINMAXLOC_MASK_ALL_INT( 32s, int, CV_CAST_64F, double ) ICV_DEF_MINMAXLOC_MASK_ALL_FLT( 32f, int, CV_TOGGLE_FLT, minmax_to_float, float ) ICV_DEF_MINMAXLOC_MASK_ALL_FLT( 64f, int64, CV_TOGGLE_DBL, minmax_to_double, double ) #define icvMinMaxIndx_8s_C1R 0 #define icvMinMaxIndx_8s_CnCR 0 #define icvMinMaxIndx_8s_C1MR 0 #define icvMinMaxIndx_8s_CnCMR 0 CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, C1R ) CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, CnCR ) CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, C1MR ) CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, CnCMR ) CV_IMPL void cvMinMaxLoc( const void* img, double* _minVal, double* _maxVal, CvPoint* _minLoc, CvPoint* _maxLoc, const void* mask ) { static CvFuncTable minmax_tab, minmaxcoi_tab; static CvFuncTable minmaxmask_tab, minmaxmaskcoi_tab; static int inittab = 0; CV_FUNCNAME("cvMinMaxLoc"); __BEGIN__; int type, depth, cn, coi = 0; int mat_step, mask_step = 0, cont_flag; CvSize size; CvMat stub, maskstub, *mat = (CvMat*)img, *matmask = (CvMat*)mask; CvPoint minloc, maxloc; double minv = 0, maxv = 0; float minvf = 0.f, maxvf = 0.f; void *pmin = &minvf, *pmax = &maxvf; if( !inittab ) { icvInitMinMaxIndxC1RTable( &minmax_tab ); icvInitMinMaxIndxCnCRTable( &minmaxcoi_tab ); icvInitMinMaxIndxC1MRTable( &minmaxmask_tab ); icvInitMinMaxIndxCnCMRTable( &minmaxmaskcoi_tab ); inittab = 1; } if( !CV_IS_MAT(mat) ) CV_CALL( mat = cvGetMat( mat, &stub, &coi )); type = CV_MAT_TYPE( mat->type ); depth = CV_MAT_DEPTH( type ); cn = CV_MAT_CN( type ); size = cvGetMatSize( mat ); if( cn > 1 && coi == 0 ) CV_ERROR( CV_StsBadArg, "" ); if( depth == CV_32S || depth == CV_64F ) pmin = &minv, pmax = &maxv; mat_step = mat->step; cont_flag = mat->type; if( mask ) { CV_CALL( matmask = cvGetMat( matmask, &maskstub )); if( !CV_IS_MASK_ARR( matmask )) CV_ERROR( CV_StsBadMask, "" ); if( !CV_ARE_SIZES_EQ( mat, matmask )) CV_ERROR( CV_StsUnmatchedSizes, "" ); mask_step = matmask->step; cont_flag &= matmask->type; } if( CV_IS_MAT_CONT(cont_flag) ) { size.width *= size.height; size.height = 1; } if( size.height == 1 ) mat_step = mask_step = CV_STUB_STEP; if( !mask ) { if( CV_MAT_CN(type) == 1 || coi == 0 ) { CvFunc2D_1A4P func = (CvFunc2D_1A4P)(minmax_tab.fn_2d[depth]); if( !func ) CV_ERROR( CV_StsBadArg, cvUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, size, pmin, pmax, &minloc, &maxloc )); } else { CvFunc2DnC_1A4P func = (CvFunc2DnC_1A4P)(minmaxcoi_tab.fn_2d[depth]); if( !func ) CV_ERROR( CV_StsBadArg, cvUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, size, cn, coi, pmin, pmax, &minloc, &maxloc )); } } else { if( CV_MAT_CN(type) == 1 || coi == 0 ) { CvFunc2D_2A4P func = (CvFunc2D_2A4P)(minmaxmask_tab.fn_2d[depth]); if( !func ) CV_ERROR( CV_StsBadArg, cvUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr, mask_step, size, pmin, pmax, &minloc, &maxloc )); } else { CvFunc2DnC_2A4P func = (CvFunc2DnC_2A4P)(minmaxmaskcoi_tab.fn_2d[depth]); if( !func ) CV_ERROR( CV_StsBadArg, cvUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr, mask_step, size, cn, coi, pmin, pmax, &minloc, &maxloc )); } } if( matmask || _minLoc || _maxLoc ) { if( minloc.x >= mat->cols ) { minloc.y = minloc.x / mat->cols; minloc.x -= minloc.y * mat->cols; } if( maxloc.x >= mat->cols ) { maxloc.y = maxloc.x / mat->cols; maxloc.x -= maxloc.y * mat->cols; } if( matmask && ((unsigned)minloc.x >= (unsigned)mat->cols || (unsigned)minloc.y >= (unsigned)mat->rows || matmask->data.ptr[minloc.y*matmask->step + minloc.x] == 0 || (unsigned)maxloc.x >= (unsigned)mat->cols || (unsigned)maxloc.y >= (unsigned)mat->rows || matmask->data.ptr[maxloc.y*matmask->step + maxloc.x] == 0) ) { minloc.x = minloc.y = maxloc.x = maxloc.y = -1; minv = maxv = minvf = maxvf = 0; } if( _minLoc ) *_minLoc = minloc; if( _maxLoc ) *_maxLoc = maxloc; } if( depth != CV_32S && depth != CV_64F ) { minv = minvf; maxv = maxvf; } if( _minVal ) *_minVal = minv; if( _maxVal ) *_maxVal = maxv; __END__; } /* End of file */