www.pudn.com > OpenCV-Intel.zip > cvcanny.cpp


/*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 "_cv.h" 
 
IPCVAPI_IMPL( CvStatus, icvCannyGetSize, ( CvSize roi, int *bufsize ), (roi, bufsize)) 
{ 
    if( (roi.width <= 0) && (roi.height <= 0) ) 
        return CV_BADSIZE_ERR; 
    if( !bufsize ) 
        return CV_NULLPTR_ERR; 
    *bufsize = (roi.height + 2)*(roi.width + 2)*(sizeof(int) + sizeof(uchar) + sizeof(void*)*2); 
    return CV_NO_ERR; 
} 
 
 
IPCVAPI_IMPL( CvStatus, 
icvCanny_16s8u_C1R, ( const short *dx, int dxstep, const short *dy, int dystep, 
                      uchar *dst, int dststep, CvSize roi, float low_threshold, 
                      float high_threshold, void *buffer ), 
    (dx, dxstep, dy, dystep, dst, dststep, roi, low_threshold, high_threshold, buffer )) 
 
{ 
    static const int sec_tab[] = { 1, 3, 0, 0, 2, 2, 2, 2 }; 
    int stack_count = 0; 
    int low = cvRound( low_threshold ); 
    int high = cvRound( high_threshold ); 
    uchar* sector = (uchar*)buffer; 
    int sectorstep = roi.width; 
    int* mag = (int*)(sector + roi.width * roi.height); 
    int magstep = roi.width + 2; 
    void** stack = (void**)(mag + magstep*(roi.height + 2)); 
    int i, j; 
 
    /* Check Bad Arguments */ 
    if( !dx || !dy || !dst || !stack  ) 
        return CV_NULLPTR_ERR; 
 
    if( (roi.width <= 0) || (roi.height <= 0) ) 
        return CV_BADSIZE_ERR; 
 
    memset( mag, 0, magstep * sizeof(mag[0])); 
    memset( mag + magstep * (roi.height + 1), 0, magstep * sizeof(mag[0])); 
    mag += magstep + 1; 
 
    dxstep /= sizeof(dx[0]); 
    dystep /= sizeof(dy[0]); 
 
    /* sector numbers  
       (Top-Left Origin) 
 
        1   2   3 
         *  *  *  
          * * *   
        0*******0 
          * * *   
         *  *  *  
        3   2   1 
    */ 
 
    /* ///////////////////// calculate magnitude and angle of gradient ///////////////// */ 
    for( i = 0; i < roi.height; i++, dx += dxstep, dy += dystep, 
                                     sector += sectorstep, mag += magstep ) 
    { 
        mag[-1] = mag[roi.width] = 0; 
 
        for( j = 0; j < roi.width; j++ ) 
        { 
            int x = dx[j]; 
            int y = dy[j]; 
            int s = x ^ y; 
 
            x = abs(x); 
            y = abs(y); 
 
            int m = x + y; 
 
            /* estimating sector and magnitude */ 
            if( m > low ) 
            { 
                #define CANNY_SHIFT 12 
                #define TG22  (int)(0.4142135623730950488016887242097*(1< tg67x)*4 + (y < tg22x)*2 + (s < 0)]; 
 
                #undef CANNY_SHIFT 
                #undef TG22 
            } 
            else 
            { 
                mag[j] = 0; 
                sector[j] = 0; 
            } 
        } 
    } 
 
    mag -= magstep * roi.height; 
    sector -= sectorstep * roi.height; 
 
    #define PUSH2(d,m)                      \ 
    {                                       \ 
        stack[stack_count] = (void*)(d);    \ 
        stack[stack_count+1] = (void*)(m);  \ 
        stack_count += 2;                   \ 
    } 
 
    #define POP2(d,m)                       \ 
    {                                       \ 
        stack_count -= 2;                   \ 
        (d) = (uchar*)stack[stack_count];   \ 
        (m) = (int*)stack[stack_count+1];   \ 
    } 
 
    /* /////////////////////////// non-maxima suppresion ///////////////////////// */ 
    { 
        /* arrays for neighborhood indexing */ 
        int mshift[4]; 
         
        mshift[0] = 1; 
        mshift[1] = magstep + 1; 
        mshift[2] = magstep; 
        mshift[3] = magstep - 1; 
 
        for( i = 0; i < roi.height; i++, sector += sectorstep, 
                               mag += magstep, dst += dststep ) 
        { 
            memset( dst, 0, roi.width ); 
        
            for( j = 0; j < roi.width; j++ ) 
            { 
                int* center = mag + j; 
                int val = *center; 
             
                if( val ) 
                { 
                    int sec = sector[j]; 
                    int delta = mshift[sec]; 
                    int b = center[delta]; 
                    int c = center[-delta] & INT_MAX; 
                     
                    if( val > c && (val > b || 
                        sec == 0 && val == b || 
                        sec == 2 && val == b) ) 
                    { 
                        if( val > high ) 
                            PUSH2( dst + j, mag + j ); 
                    } 
                    else 
                    { 
                        *center = val | INT_MIN; 
                    } 
                } 
            } 
        } 
 
        ///////////////////////  Hysteresis thresholding ///////////////////// 
        while( stack_count ) 
        { 
            uchar* d; 
            int* m; 
 
            POP2( d, m ); 
         
            if( *d == 0 ) 
            { 
                *d = 255; 
 
                if( m[-1] > low && d[-1] == 0 ) 
                    PUSH2( d - 1, m - 1 ); 
                if( m[1] > low && d[1] == 0 ) 
                    PUSH2( d + 1, m + 1 ); 
                if( m[-magstep-1] > low && d[-dststep-1] == 0 ) 
                    PUSH2( d - dststep - 1, m - magstep - 1 ); 
                if( m[-magstep] > low && d[-dststep] == 0 ) 
                    PUSH2( d - dststep, m - magstep ); 
                if( m[-magstep+1] > low && d[-dststep+1] == 0 ) 
                    PUSH2( d - dststep + 1, m - magstep + 1 ); 
                if( m[magstep-1] > low && d[dststep-1] == 0 ) 
                    PUSH2( d + dststep - 1, m + magstep - 1 ); 
                if( m[magstep] > low && d[dststep] == 0 ) 
                    PUSH2( d + dststep, m + magstep ); 
                if( m[magstep+1] > low && d[dststep+1] == 0 ) 
                    PUSH2( d + dststep + 1, m + magstep + 1 ); 
            } 
        } 
    } 
    #undef PUSH2 
    #undef POP2 
 
    return CV_OK; 
} 
 
CV_IMPL void 
cvCanny( const void* srcarr, void* dstarr, 
         double low_thresh, double high_thresh, int aperture_size ) 
{ 
    CvMat *dx = 0, *dy = 0; 
    void *buffer = 0; 
 
    CV_FUNCNAME( "cvCanny" ); 
 
    __BEGIN__; 
 
    CvMat srcstub, *src = (CvMat*)srcarr; 
    CvMat dststub, *dst = (CvMat*)dstarr; 
    CvSize src_size; 
    int buf_size = 0, origin = 0; 
 
    CV_CALL( src = cvGetMat( src, &srcstub )); 
    CV_CALL( dst = cvGetMat( dst, &dststub )); 
 
    if( CV_IS_IMAGE_HDR( srcarr )) 
        origin = ((IplImage*)srcarr)->origin; 
 
    if( CV_MAT_TYPE( src->type ) != CV_8UC1 || 
        CV_MAT_TYPE( dst->type ) != CV_8UC1 ) 
        CV_ERROR( CV_StsUnsupportedFormat, "" ); 
 
    if( !CV_ARE_SIZES_EQ( src, dst )) 
        CV_ERROR( CV_StsUnmatchedSizes, "" ); 
 
    if( low_thresh > high_thresh ) 
    { 
        double t; 
        CV_SWAP( low_thresh, high_thresh, t ); 
    } 
 
    if( (aperture_size & 1) == 0 || aperture_size < 3 || aperture_size > 7 ) 
        CV_ERROR( CV_StsBadFlag, "" ); 
 
    src_size = cvGetMatSize( src ); 
 
    dx = cvCreateMat( src_size.height, src_size.width, CV_16SC1 ); 
    dy = cvCreateMat( src_size.height, src_size.width, CV_16SC1 ); 
 
    IPPI_CALL( icvCannyGetSize( src_size, &buf_size )); 
    CV_CALL( buffer = cvAlloc( buf_size )); 
 
    cvSobel( src, dx, 1, 0, aperture_size ); 
    cvSobel( src, dy, 0, 1, aperture_size ); 
 
    if( origin ) 
        cvSubRS( dy, cvScalarAll(0), dy ); 
 
    IPPI_CALL( icvCanny_16s8u_C1R( (short*)dx->data.ptr, dx->step, 
                                   (short*)dy->data.ptr, dy->step, 
                                   dst->data.ptr, dst->step, 
                                   src_size, (float)low_thresh, 
                                   (float)high_thresh, buffer )); 
 
    __END__; 
 
    cvReleaseMat( &dx ); 
    cvReleaseMat( &dy ); 
    cvFree( &buffer ); 
} 
 
 
/* End of file. */