| /*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" |
| |
| /****************************************************************************************\ |
| * N o r m * |
| \****************************************************************************************/ |
| |
| #define ICV_NORM_CASE( _op_, \ |
| _update_op_, worktype, len ) \ |
| \ |
| for( ; x <= (len) - 4; x += 4 ) \ |
| { \ |
| worktype t0 = (src)[x]; \ |
| worktype t1 = (src)[x+1]; \ |
| t0 = _op_(t0); \ |
| t1 = _op_(t1); \ |
| norm = _update_op_( norm, t0 ); \ |
| norm = _update_op_( norm, t1 ); \ |
| \ |
| t0 = (src)[x+2]; \ |
| t1 = (src)[x+3]; \ |
| t0 = _op_(t0); \ |
| t1 = _op_(t1); \ |
| norm = _update_op_( norm, t0 ); \ |
| norm = _update_op_( norm, t1 ); \ |
| } \ |
| \ |
| for( ; x < (len); x++ ) \ |
| { \ |
| worktype t0 = (src)[x]; \ |
| t0 = (worktype)_op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } |
| |
| |
| #define ICV_NORM_COI_CASE( _op_, \ |
| _update_op_, worktype, len, cn ) \ |
| \ |
| for( ; x < (len); x++ ) \ |
| { \ |
| worktype t0 = (src)[x*(cn)]; \ |
| t0 = (worktype)_op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } |
| |
| |
| #define ICV_NORM_DIFF_CASE( _op_, \ |
| _update_op_, worktype, len ) \ |
| \ |
| for( ; x <= (len) - 4; x += 4 ) \ |
| { \ |
| worktype t0 = (src1)[x] - (src2)[x];\ |
| worktype t1 = (src1)[x+1]-(src2)[x+1];\ |
| \ |
| t0 = _op_(t0); \ |
| t1 = _op_(t1); \ |
| \ |
| norm = _update_op_( norm, t0 ); \ |
| norm = _update_op_( norm, t1 ); \ |
| \ |
| t0 = (src1)[x+2] - (src2)[x+2]; \ |
| t1 = (src1)[x+3] - (src2)[x+3]; \ |
| \ |
| t0 = _op_(t0); \ |
| t1 = _op_(t1); \ |
| \ |
| norm = _update_op_( norm, t0 ); \ |
| norm = _update_op_( norm, t1 ); \ |
| } \ |
| \ |
| for( ; x < (len); x++ ) \ |
| { \ |
| worktype t0 = (src1)[x] - (src2)[x];\ |
| t0 = (worktype)_op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } |
| |
| |
| #define ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, worktype, len, cn ) \ |
| for( ; x < (len); x++ ) \ |
| { \ |
| worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \ |
| t0 = (worktype)_op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } |
| |
| |
| /* |
| The algorithm and its multiple variations below |
| below accumulates the norm by blocks of size "block_size". |
| Each block may span across multiple lines and it is |
| not necessary aligned by row boundaries. Within a block |
| the norm is accumulated to intermediate light-weight |
| type (worktype). It really makes sense for 8u, 16s, 16u types |
| and L1 & L2 norms, where worktype==int and normtype==int64. |
| In other cases a simpler algorithm is used |
| */ |
| #define ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D( name, _op_, _update_op_, \ |
| post_func, arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ |
| CvSize size, double* _norm ), (src, step, size, _norm) ) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| \ |
| for( ; size.height--; src += step ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_CASE( _op_, _update_op_, worktype, limit );\ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_NOHINT_FUNC_2D( name, _op_, _update_op_, \ |
| post_func, arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ |
| CvSize size, double* _norm ), (src, step, size, _norm) ) \ |
| { \ |
| normtype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| \ |
| for( ; size.height--; src += step ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| /* |
| In IPP only 32f flavors of norm functions are with hint. |
| For float worktype==normtype==double, thus the block algorithm, |
| described above, is not necessary. |
| */ |
| #define ICV_DEF_NORM_HINT_FUNC_2D( name, _op_, _update_op_, \ |
| post_func, arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ |
| CvSize size, double* _norm, CvHintAlgorithm /*hint*/ ), \ |
| (src, step, size, _norm, cvAlgHintAccurate) ) \ |
| { \ |
| normtype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| \ |
| for( ; size.height--; src += step ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D_COI( name, _op_, \ |
| _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src, int step, \ |
| CvSize size, int cn, int coi, double* _norm ) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| src += coi - 1; \ |
| \ |
| for( ; size.height--; src += step ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_COI_CASE( _op_, _update_op_, \ |
| worktype, limit, cn ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_NOHINT_FUNC_2D_COI( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src, int step, \ |
| CvSize size, int cn, int coi, double* _norm ) \ |
| { \ |
| normtype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| src += coi - 1; \ |
| \ |
| for( ; size.height--; src += step ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_COI_CASE( _op_, _update_op_, \ |
| worktype, size.width, cn ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D( name, _op_, \ |
| _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ |
| const arrtype* src2, int step2, CvSize size, double* _norm),\ |
| (src1, step1, src2, step2, size, _norm)) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2 ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_DIFF_CASE( _op_, _update_op_, \ |
| worktype, limit ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ |
| const arrtype* src2, int step2, CvSize size, double* _norm),\ |
| ( src1, step1, src2, step2, size, _norm )) \ |
| { \ |
| normtype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2 ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_DIFF_CASE( _op_, _update_op_, \ |
| worktype, size.width ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_HINT_FUNC_2D( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ |
| const arrtype* src2, int step2, CvSize size, double* _norm, \ |
| CvHintAlgorithm /*hint*/ ), \ |
| (src1, step1, src2, step2, size, _norm, cvAlgHintAccurate ))\ |
| { \ |
| normtype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2 ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_DIFF_CASE( _op_, _update_op_, \ |
| worktype, size.width ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\ |
| _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ |
| const arrtype* src2, int step2, CvSize size, \ |
| int cn, int coi, double* _norm ) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| src1 += coi - 1; \ |
| src2 += coi - 1; \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2 ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \ |
| worktype, limit, cn ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ |
| const arrtype* src2, int step2, CvSize size, \ |
| int cn, int coi, double* _norm ) \ |
| { \ |
| normtype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| src1 += coi - 1; \ |
| src2 += coi - 1; \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2 ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \ |
| worktype, size.width, cn ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| /****************************************************************************************\ |
| * N o r m with M A S K * |
| \****************************************************************************************/ |
| |
| #define ICV_NORM_MASK_CASE( _op_, \ |
| _update_op_, worktype, len ) \ |
| { \ |
| for( ; x <= (len) - 2; x += 2 ) \ |
| { \ |
| worktype t0; \ |
| if( mask[x] ) \ |
| { \ |
| t0 = (src)[x]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| if( mask[x+1] ) \ |
| { \ |
| t0 = (src)[x+1]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| } \ |
| \ |
| for( ; x < (len); x++ ) \ |
| if( mask[x] ) \ |
| { \ |
| worktype t0 = (src)[x]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| } |
| |
| |
| #define ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, worktype, len ) \ |
| { \ |
| for( ; x <= (len) - 2; x += 2 ) \ |
| { \ |
| worktype t0; \ |
| if( mask[x] ) \ |
| { \ |
| t0 = (src1)[x] - (src2)[x]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| if( mask[x+1] ) \ |
| { \ |
| t0 = (src1)[x+1] - (src2)[x+1]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| } \ |
| \ |
| for( ; x < (len); x++ ) \ |
| if( mask[x] ) \ |
| { \ |
| worktype t0 = (src1)[x] - (src2)[x];\ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| } |
| |
| |
| #define ICV_NORM_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn ) \ |
| { \ |
| for( ; x < (len); x++ ) \ |
| if( mask[x] ) \ |
| { \ |
| worktype t0 = (src)[x*(cn)]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| } |
| |
| |
| #define ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn )\ |
| { \ |
| for( ; x < (len); x++ ) \ |
| if( mask[x] ) \ |
| { \ |
| worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \ |
| t0 = _op_(t0); \ |
| norm = _update_op_( norm, t0 ); \ |
| } \ |
| } |
| |
| |
| #define ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D( name, _op_, \ |
| _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ |
| const uchar* mask, int maskstep, CvSize size, double* _norm ),\ |
| (src, step, mask, maskstep, size, _norm) ) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| \ |
| for( ; size.height--; src += step, mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_MASK_CASE( _op_, _update_op_, \ |
| worktype, limit ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( name, _op_, _update_op_,\ |
| post_func, arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ |
| const uchar* mask, int maskstep, CvSize size, double* _norm ),\ |
| (src, step, mask, maskstep, size, _norm) ) \ |
| { \ |
| normtype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| \ |
| for( ; size.height--; src += step, mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_MASK_CASE( _op_, _update_op_, \ |
| worktype, size.width ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\ |
| _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src, int step, \ |
| const uchar* mask, int maskstep, CvSize size, \ |
| int cn, int coi, double* _norm ) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| src += coi - 1; \ |
| \ |
| for( ; size.height--; src += step, mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \ |
| worktype, limit, cn ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src, int step, \ |
| const uchar* mask, int maskstep, CvSize size, \ |
| int cn, int coi, double* _norm ) \ |
| { \ |
| normtype norm = 0; \ |
| step /= sizeof(src[0]); \ |
| src += coi - 1; \ |
| \ |
| for( ; size.height--; src += step, mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \ |
| worktype, size.width, cn ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| |
| #define ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D( name, \ |
| _op_, _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ |
| const arrtype* src2, int step2, const uchar* mask, \ |
| int maskstep, CvSize size, double* _norm ), \ |
| (src1, step1, src2, step2, mask, maskstep, size, _norm )) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2, \ |
| mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \ |
| worktype, limit ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ |
| const arrtype* src2, int step2, const uchar* mask, \ |
| int maskstep, CvSize size, double* _norm ), \ |
| (src1, step1, src2, step2, mask, maskstep, size, _norm )) \ |
| { \ |
| normtype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2, \ |
| mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \ |
| worktype, size.width ); \ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, \ |
| _op_, _update_op_, post_func, arrtype, \ |
| normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ |
| const arrtype* src2, int step2, const uchar* mask, \ |
| int maskstep, CvSize size, int cn, int coi, double* _norm ) \ |
| { \ |
| int remaining = block_size; \ |
| normtype total_norm = 0; \ |
| worktype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| src1 += coi - 1; \ |
| src2 += coi - 1; \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2, \ |
| mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| while( x < size.width ) \ |
| { \ |
| int limit = MIN( remaining, size.width - x ); \ |
| remaining -= limit; \ |
| limit += x; \ |
| ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \ |
| worktype, limit, cn ); \ |
| if( remaining == 0 ) \ |
| { \ |
| remaining = block_size; \ |
| total_norm += (normtype)norm; \ |
| norm = 0; \ |
| } \ |
| } \ |
| } \ |
| \ |
| total_norm += (normtype)norm; \ |
| *_norm = post_func((double)total_norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| #define ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( name, _op_, \ |
| _update_op_, post_func, \ |
| arrtype, normtype, worktype, block_size ) \ |
| static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ |
| const arrtype* src2, int step2, const uchar* mask, \ |
| int maskstep, CvSize size, int cn, int coi, double* _norm ) \ |
| { \ |
| normtype norm = 0; \ |
| step1 /= sizeof(src1[0]); \ |
| step2 /= sizeof(src2[0]); \ |
| src1 += coi - 1; \ |
| src2 += coi - 1; \ |
| \ |
| for( ; size.height--; src1 += step1, src2 += step2, \ |
| mask += maskstep ) \ |
| { \ |
| int x = 0; \ |
| ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \ |
| worktype, size.width, cn );\ |
| } \ |
| \ |
| *_norm = post_func((double)norm); \ |
| return CV_OK; \ |
| } |
| |
| |
| //////////////////////////////////// The macros expanded ///////////////////////////////// |
| |
| |
| #define ICV_DEF_NORM_FUNC_ALL_C(flavor, _abs_, _abs_diff_, arrtype, worktype)\ |
| \ |
| ICV_DEF_NORM_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1R, \ |
| _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCR, \ |
| _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1R, \ |
| _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCR, \ |
| _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1MR, \ |
| _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCMR, \ |
| _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1MR, \ |
| _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ |
| \ |
| ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCMR,\ |
| _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) |
| |
| |
| ICV_DEF_NORM_FUNC_ALL_C( 8u, CV_NOP, CV_IABS, uchar, int ) |
| ICV_DEF_NORM_FUNC_ALL_C( 16u, CV_NOP, CV_IABS, ushort, int ) |
| ICV_DEF_NORM_FUNC_ALL_C( 16s, CV_IABS, CV_IABS, short, int ) |
| // there is no protection from overflow |
| // (otherwise we had to do everything in int64's or double's) |
| ICV_DEF_NORM_FUNC_ALL_C( 32s, CV_IABS, CV_IABS, int, int ) |
| ICV_DEF_NORM_FUNC_ALL_C( 32f, fabs, fabs, float, double ) |
| ICV_DEF_NORM_FUNC_ALL_C( 64f, fabs, fabs, double, double ) |
| |
| #define ICV_DEF_NORM_FUNC_ALL_L1( flavor, _abs_, _abs_diff_, hintp_func, nohint_func,\ |
| arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L1_##flavor##_C1R, \ |
| _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCR, \ |
| _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1R, \ |
| _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCR, \ |
| _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L1_##flavor##_C1MR, \ |
| _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCMR, \ |
| _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1MR, \ |
| _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCMR,\ |
| _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) |
| |
| |
| ICV_DEF_NORM_FUNC_ALL_L1( 8u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK, |
| uchar, int64, int, 1 << 23 ) |
| ICV_DEF_NORM_FUNC_ALL_L1( 16u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK, |
| ushort, int64, int, 1 << 15 ) |
| ICV_DEF_NORM_FUNC_ALL_L1( 16s, CV_IABS, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK, |
| short, int64, int, 1 << 15 ) |
| // there is no protection from overflow on abs() stage. |
| // (otherwise we had to do everything in int64's or double's) |
| ICV_DEF_NORM_FUNC_ALL_L1( 32s, fabs, fabs, NOHINT, NOHINT, |
| int, double, double, INT_MAX ) |
| ICV_DEF_NORM_FUNC_ALL_L1( 32f, fabs, fabs, HINT, NOHINT, |
| float, double, double, INT_MAX ) |
| ICV_DEF_NORM_FUNC_ALL_L1( 64f, fabs, fabs, NOHINT, NOHINT, |
| double, double, double, INT_MAX ) |
| |
| |
| #define ICV_DEF_NORM_FUNC_ALL_L2( flavor, hintp_func, nohint_func, arrtype, \ |
| normtype, worktype, block_size, sqr_macro ) \ |
| \ |
| ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L2_##flavor##_C1R, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCR, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1R, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCR, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L2_##flavor##_C1MR, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCMR, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1MR, \ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ |
| \ |
| ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCMR,\ |
| sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) |
| |
| |
| ICV_DEF_NORM_FUNC_ALL_L2( 8u, NOHINT_BLOCK, NOHINT_BLOCK, uchar, |
| int64, int, 1 << 15, CV_SQR_8U ) |
| ICV_DEF_NORM_FUNC_ALL_L2( 16u, NOHINT, NOHINT, ushort, |
| double, double, INT_MAX, CV_SQR ) |
| ICV_DEF_NORM_FUNC_ALL_L2( 16s, NOHINT, NOHINT, short, |
| double, double, INT_MAX, CV_SQR ) |
| // there is no protection from overflow on abs() stage. |
| // (otherwise we had to do everything in int64's or double's) |
| ICV_DEF_NORM_FUNC_ALL_L2( 32s, NOHINT, NOHINT, int, |
| double, double, INT_MAX, CV_SQR ) |
| ICV_DEF_NORM_FUNC_ALL_L2( 32f, HINT, NOHINT, float, |
| double, double, INT_MAX, CV_SQR ) |
| ICV_DEF_NORM_FUNC_ALL_L2( 64f, NOHINT, NOHINT, double, |
| double, double, INT_MAX, CV_SQR ) |
| |
| |
| #define ICV_DEF_INIT_NORM_TAB_2D( FUNCNAME, FLAG ) \ |
| static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab ) \ |
| { \ |
| tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##FLAG; \ |
| tab->fn_2d[CV_8S] = 0; \ |
| tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_##FLAG; \ |
| tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_##FLAG; \ |
| tab->fn_2d[CV_32S] = (void*)icv##FUNCNAME##_32s_##FLAG; \ |
| tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##FLAG; \ |
| tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_##FLAG; \ |
| } |
| |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1R ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1R ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1R ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1R ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1R ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1R ) |
| |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCR ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCR ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCR ) |
| |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1MR ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1MR ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1MR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1MR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1MR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1MR ) |
| |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCMR ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCMR ) |
| ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCMR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCMR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCMR ) |
| ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCMR ) |
| |
| |
| static void icvInitNormTabs( CvFuncTable* norm_tab, CvFuncTable* normmask_tab ) |
| { |
| icvInitNorm_InfC1RTable( &norm_tab[0] ); |
| icvInitNorm_L1C1RTable( &norm_tab[1] ); |
| icvInitNorm_L2C1RTable( &norm_tab[2] ); |
| icvInitNormDiff_InfC1RTable( &norm_tab[3] ); |
| icvInitNormDiff_L1C1RTable( &norm_tab[4] ); |
| icvInitNormDiff_L2C1RTable( &norm_tab[5] ); |
| |
| icvInitNorm_InfCnCRTable( &norm_tab[6] ); |
| icvInitNorm_L1CnCRTable( &norm_tab[7] ); |
| icvInitNorm_L2CnCRTable( &norm_tab[8] ); |
| icvInitNormDiff_InfCnCRTable( &norm_tab[9] ); |
| icvInitNormDiff_L1CnCRTable( &norm_tab[10] ); |
| icvInitNormDiff_L2CnCRTable( &norm_tab[11] ); |
| |
| icvInitNorm_InfC1MRTable( &normmask_tab[0] ); |
| icvInitNorm_L1C1MRTable( &normmask_tab[1] ); |
| icvInitNorm_L2C1MRTable( &normmask_tab[2] ); |
| icvInitNormDiff_InfC1MRTable( &normmask_tab[3] ); |
| icvInitNormDiff_L1C1MRTable( &normmask_tab[4] ); |
| icvInitNormDiff_L2C1MRTable( &normmask_tab[5] ); |
| |
| icvInitNorm_InfCnCMRTable( &normmask_tab[6] ); |
| icvInitNorm_L1CnCMRTable( &normmask_tab[7] ); |
| icvInitNorm_L2CnCMRTable( &normmask_tab[8] ); |
| icvInitNormDiff_InfCnCMRTable( &normmask_tab[9] ); |
| icvInitNormDiff_L1CnCMRTable( &normmask_tab[10] ); |
| icvInitNormDiff_L2CnCMRTable( &normmask_tab[11] ); |
| } |
| |
| |
| CV_IMPL double |
| cvNorm( const void* imgA, const void* imgB, int normType, const void* mask ) |
| { |
| static CvFuncTable norm_tab[12]; |
| static CvFuncTable normmask_tab[12]; |
| static int inittab = 0; |
| |
| double norm = 0, norm_diff = 0; |
| |
| CV_FUNCNAME("cvNorm"); |
| |
| __BEGIN__; |
| |
| int type, depth, cn, is_relative; |
| CvSize size; |
| CvMat stub1, *mat1 = (CvMat*)imgB; |
| CvMat stub2, *mat2 = (CvMat*)imgA; |
| int mat2_flag = CV_MAT_CONT_FLAG; |
| int mat1_step, mat2_step, mask_step = 0; |
| int coi = 0, coi2 = 0; |
| |
| if( !mat1 ) |
| { |
| mat1 = mat2; |
| mat2 = 0; |
| } |
| |
| is_relative = mat2 && (normType & CV_RELATIVE); |
| normType &= ~CV_RELATIVE; |
| |
| switch( normType ) |
| { |
| case CV_C: |
| case CV_L1: |
| case CV_L2: |
| case CV_DIFF_C: |
| case CV_DIFF_L1: |
| case CV_DIFF_L2: |
| normType = (normType & 7) >> 1; |
| break; |
| default: |
| CV_ERROR( CV_StsBadFlag, "" ); |
| } |
| |
| /* light variant */ |
| if( CV_IS_MAT(mat1) && (!mat2 || CV_IS_MAT(mat2)) && !mask ) |
| { |
| if( mat2 ) |
| { |
| if( !CV_ARE_TYPES_EQ( mat1, mat2 )) |
| CV_ERROR( CV_StsUnmatchedFormats, "" ); |
| |
| if( !CV_ARE_SIZES_EQ( mat1, mat2 )) |
| CV_ERROR( CV_StsUnmatchedSizes, "" ); |
| |
| mat2_flag = mat2->type; |
| } |
| |
| size = cvGetMatSize( mat1 ); |
| type = CV_MAT_TYPE(mat1->type); |
| depth = CV_MAT_DEPTH(type); |
| cn = CV_MAT_CN(type); |
| |
| if( CV_IS_MAT_CONT( mat1->type & mat2_flag )) |
| { |
| size.width *= size.height; |
| |
| if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE && normType == 2 /* CV_L2 */ ) |
| { |
| if( depth == CV_32F ) |
| { |
| const float* src1data = mat1->data.fl; |
| int size0 = size.width *= cn; |
| |
| if( !mat2 || is_relative ) |
| { |
| do |
| { |
| double t = src1data[size.width-1]; |
| norm += t*t; |
| } |
| while( --size.width ); |
| } |
| |
| if( mat2 ) |
| { |
| const float* src2data = mat2->data.fl; |
| size.width = size0; |
| |
| do |
| { |
| double t = src1data[size.width-1] - src2data[size.width-1]; |
| norm_diff += t*t; |
| } |
| while( --size.width ); |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| norm = sqrt(norm); |
| EXIT; |
| } |
| |
| if( depth == CV_64F ) |
| { |
| const double* src1data = mat1->data.db; |
| int size0 = size.width *= cn; |
| |
| if( !mat2 || is_relative ) |
| { |
| do |
| { |
| double t = src1data[size.width-1]; |
| norm += t*t; |
| } |
| while( --size.width ); |
| } |
| |
| if( mat2 ) |
| { |
| const double* src2data = mat2->data.db; |
| size.width = size0; |
| |
| do |
| { |
| double t = src1data[size.width-1] - src2data[size.width-1]; |
| norm_diff += t*t; |
| } |
| while( --size.width ); |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| norm = sqrt(norm); |
| EXIT; |
| } |
| } |
| size.height = 1; |
| mat1_step = mat2_step = CV_STUB_STEP; |
| } |
| else |
| { |
| mat1_step = mat1->step; |
| mat2_step = mat2 ? mat2->step : 0; |
| } |
| } |
| else if( !CV_IS_MATND(mat1) && !CV_IS_MATND(mat2) ) |
| { |
| CV_CALL( mat1 = cvGetMat( mat1, &stub1, &coi )); |
| |
| if( mat2 ) |
| { |
| CV_CALL( mat2 = cvGetMat( mat2, &stub2, &coi2 )); |
| |
| if( !CV_ARE_TYPES_EQ( mat1, mat2 )) |
| CV_ERROR( CV_StsUnmatchedFormats, "" ); |
| |
| if( !CV_ARE_SIZES_EQ( mat1, mat2 )) |
| CV_ERROR( CV_StsUnmatchedSizes, "" ); |
| |
| if( coi != coi2 && CV_MAT_CN( mat1->type ) > 1 ) |
| CV_ERROR( CV_BadCOI, "" ); |
| |
| mat2_flag = mat2->type; |
| } |
| |
| size = cvGetMatSize( mat1 ); |
| type = CV_MAT_TYPE(mat1->type); |
| depth = CV_MAT_DEPTH(type); |
| cn = CV_MAT_CN(type); |
| mat1_step = mat1->step; |
| mat2_step = mat2 ? mat2->step : 0; |
| |
| if( !mask && CV_IS_MAT_CONT( mat1->type & mat2_flag )) |
| { |
| size.width *= size.height; |
| size.height = 1; |
| mat1_step = mat2_step = CV_STUB_STEP; |
| } |
| } |
| else |
| { |
| CvArr* arrs[] = { mat1, mat2 }; |
| CvMatND stubs[2]; |
| CvNArrayIterator iterator; |
| int pass_hint; |
| |
| if( !inittab ) |
| { |
| icvInitNormTabs( norm_tab, normmask_tab ); |
| inittab = 1; |
| } |
| |
| if( mask ) |
| CV_ERROR( CV_StsBadMask, |
| "This operation on multi-dimensional arrays does not support mask" ); |
| |
| CV_CALL( cvInitNArrayIterator( 1 + (mat2 != 0), arrs, 0, stubs, &iterator )); |
| |
| type = CV_MAT_TYPE(iterator.hdr[0]->type); |
| depth = CV_MAT_DEPTH(type); |
| iterator.size.width *= CV_MAT_CN(type); |
| |
| pass_hint = normType != 0 && (depth == CV_32F); |
| |
| if( !mat2 || is_relative ) |
| { |
| if( !pass_hint ) |
| { |
| CvFunc2D_1A1P func; |
| |
| CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]); |
| |
| do |
| { |
| double temp = 0; |
| IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, |
| iterator.size, &temp )); |
| norm += temp; |
| } |
| while( cvNextNArraySlice( &iterator )); |
| } |
| else |
| { |
| CvFunc2D_1A1P1I func; |
| |
| CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]); |
| |
| do |
| { |
| double temp = 0; |
| IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, |
| iterator.size, &temp, cvAlgHintAccurate )); |
| norm += temp; |
| } |
| while( cvNextNArraySlice( &iterator )); |
| } |
| } |
| |
| if( mat2 ) |
| { |
| if( !pass_hint ) |
| { |
| CvFunc2D_2A1P func; |
| CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]); |
| |
| do |
| { |
| double temp = 0; |
| IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, |
| iterator.ptr[1], CV_STUB_STEP, |
| iterator.size, &temp )); |
| norm_diff += temp; |
| } |
| while( cvNextNArraySlice( &iterator )); |
| } |
| else |
| { |
| CvFunc2D_2A1P1I func; |
| CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]); |
| |
| do |
| { |
| double temp = 0; |
| IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, |
| iterator.ptr[1], CV_STUB_STEP, |
| iterator.size, &temp, cvAlgHintAccurate )); |
| norm_diff += temp; |
| } |
| while( cvNextNArraySlice( &iterator )); |
| } |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| EXIT; |
| } |
| |
| if( !inittab ) |
| { |
| icvInitNormTabs( norm_tab, normmask_tab ); |
| inittab = 1; |
| } |
| |
| if( !mask ) |
| { |
| if( cn == 1 || coi == 0 ) |
| { |
| int pass_hint = depth == CV_32F && normType != 0; |
| size.width *= cn; |
| |
| if( !mat2 || is_relative ) |
| { |
| if( !pass_hint ) |
| { |
| CvFunc2D_1A1P func; |
| CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm )); |
| } |
| else |
| { |
| CvFunc2D_1A1P1I func; |
| CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm, cvAlgHintAccurate )); |
| } |
| } |
| |
| if( mat2 ) |
| { |
| if( !pass_hint ) |
| { |
| CvFunc2D_2A1P func; |
| CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, |
| size, &norm_diff )); |
| } |
| else |
| { |
| CvFunc2D_2A1P1I func; |
| CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, |
| size, &norm_diff, cvAlgHintAccurate )); |
| } |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| } |
| else |
| { |
| if( !mat2 || is_relative ) |
| { |
| CvFunc2DnC_1A1P func; |
| CV_GET_FUNC_PTR( func, (CvFunc2DnC_1A1P)norm_tab[6 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, size, cn, coi, &norm )); |
| } |
| |
| if( mat2 ) |
| { |
| CvFunc2DnC_2A1P func; |
| CV_GET_FUNC_PTR( func, (CvFunc2DnC_2A1P)norm_tab[9 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, |
| size, cn, coi, &norm_diff )); |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| } |
| } |
| else |
| { |
| CvMat maskstub, *matmask = (CvMat*)mask; |
| |
| if( CV_MAT_CN(type) > 1 && coi == 0 ) |
| CV_ERROR( CV_StsBadArg, "" ); |
| |
| CV_CALL( matmask = cvGetMat( matmask, &maskstub )); |
| |
| if( !CV_IS_MASK_ARR( matmask )) |
| CV_ERROR( CV_StsBadMask, "" ); |
| |
| if( !CV_ARE_SIZES_EQ( mat1, matmask )) |
| CV_ERROR( CV_StsUnmatchedSizes, "" ); |
| |
| mask_step = matmask->step; |
| |
| if( CV_IS_MAT_CONT( mat1->type & mat2_flag & matmask->type )) |
| { |
| size.width *= size.height; |
| size.height = 1; |
| mat1_step = mat2_step = mask_step = CV_STUB_STEP; |
| } |
| |
| if( CV_MAT_CN(type) == 1 || coi == 0 ) |
| { |
| if( !mat2 || is_relative ) |
| { |
| CvFunc2D_2A1P func; |
| CV_GET_FUNC_PTR( func, |
| (CvFunc2D_2A1P)normmask_tab[normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, |
| matmask->data.ptr, mask_step, size, &norm )); |
| } |
| |
| if( mat2 ) |
| { |
| CvFunc2D_3A1P func; |
| CV_GET_FUNC_PTR( func, |
| (CvFunc2D_3A1P)normmask_tab[3 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, |
| matmask->data.ptr, mask_step, size, &norm_diff )); |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| } |
| else |
| { |
| if( !mat2 || is_relative ) |
| { |
| CvFunc2DnC_2A1P func; |
| CV_GET_FUNC_PTR( func, |
| (CvFunc2DnC_2A1P)normmask_tab[6 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, |
| matmask->data.ptr, mask_step, |
| size, cn, coi, &norm )); |
| } |
| |
| if( mat2 ) |
| { |
| CvFunc2DnC_3A1P func; |
| CV_GET_FUNC_PTR( func, |
| (CvFunc2DnC_3A1P)normmask_tab[9 + normType].fn_2d[depth]); |
| |
| IPPI_CALL( func( mat1->data.ptr, mat1_step, |
| mat2->data.ptr, mat2_step, |
| matmask->data.ptr, mask_step, |
| size, cn, coi, &norm_diff )); |
| |
| if( is_relative ) |
| norm = norm_diff/(norm + DBL_EPSILON); |
| else |
| norm = norm_diff; |
| } |
| } |
| } |
| |
| __END__; |
| |
| return norm; |
| } |
| |
| /* End of file. */ |