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 ) \ 88IPCVAPI_IMPL( CvStatus, \ 89icvMinMaxIndx_##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 ) \ 106static CvStatus CV_STDCALL \ 107icvMinMaxIndx_##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 131CV_INLINE float minmax_to_float( int val ) 132{ 133 Cv32suf v; 134 v.i = CV_TOGGLE_FLT(val); 135 return v.f; 136} 137 138CV_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 153ICV_DEF_MINMAXLOC_ALL_INT( 8u, uchar, CV_CAST_32F, float ) 154ICV_DEF_MINMAXLOC_ALL_INT( 16u, ushort, CV_CAST_32F, float ) 155ICV_DEF_MINMAXLOC_ALL_INT( 16s, short, CV_CAST_32F, float ) 156ICV_DEF_MINMAXLOC_ALL_INT( 32s, int, CV_CAST_64F, double ) 157ICV_DEF_MINMAXLOC_ALL_FLT( 32f, int, CV_TOGGLE_FLT, minmax_to_float, float ) 158ICV_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 ) \ 215IPCVAPI_IMPL( CvStatus, \ 216icvMinMaxIndx_##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 ) \ 235static CvStatus CV_STDCALL \ 236icvMinMaxIndx_##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 268ICV_DEF_MINMAXLOC_MASK_ALL_INT( 8u, uchar, CV_CAST_32F, float ) 269ICV_DEF_MINMAXLOC_MASK_ALL_INT( 16u, ushort, CV_CAST_32F, float ) 270ICV_DEF_MINMAXLOC_MASK_ALL_INT( 16s, short, CV_CAST_32F, float ) 271ICV_DEF_MINMAXLOC_MASK_ALL_INT( 32s, int, CV_CAST_64F, double ) 272ICV_DEF_MINMAXLOC_MASK_ALL_FLT( 32f, int, CV_TOGGLE_FLT, minmax_to_float, float ) 273ICV_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 280CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, C1R ) 281CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, CnCR ) 282CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, C1MR ) 283CV_DEF_INIT_FUNC_TAB_2D( MinMaxIndx, CnCMR ) 284 285 286CV_IMPL void 287cvMinMaxLoc( 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