static void cvTsMHIGradient( const CvMat* mhi, CvMat* mask, CvMat* orientation,
                             double delta1, double delta2, int aperture_size )
{
    CvPoint anchor = { aperture_size/2, aperture_size/2 };
    CvMat* src = cvCreateMat( mhi->rows + aperture_size - 1, mhi->cols + aperture_size - 1, CV_32FC1 );
    CvMat* kernel = cvCreateMat( aperture_size, aperture_size, CV_32FC1 );
    CvMat* dx = cvCreateMat( mhi->rows, mhi->cols, CV_32FC1 );
    CvMat* dy = cvCreateMat( mhi->rows, mhi->cols, CV_32FC1 );
    CvMat* min_mhi = cvCreateMat( mhi->rows, mhi->cols, CV_32FC1 );
    CvMat* max_mhi = cvCreateMat( mhi->rows, mhi->cols, CV_32FC1 );
    IplConvKernel* element = cvCreateStructuringElementEx( aperture_size, aperture_size,
                                        aperture_size/2, aperture_size/2, CV_SHAPE_RECT );
    int i, j;
    double limit = 1e-4*aperture_size*aperture_size;
    
    cvTsPrepareToFilter( mhi, src, anchor );
    cvTsCalcSobelKernel2D( 1, 0, aperture_size, 0, kernel );
    cvTsConvolve2D( src, dx, kernel, anchor );
    cvTsCalcSobelKernel2D( 0, 1, aperture_size, 0, kernel );
    cvTsConvolve2D( src, dy, kernel, anchor );
    cvReleaseMat( &kernel );

    cvTsMinMaxFilter( src, min_mhi, element, CV_TS_MIN );
    cvTsMinMaxFilter( src, max_mhi, element, CV_TS_MAX );
    cvReleaseStructuringElement( &element );

    if( delta1 > delta2 )
    {
        double t;
        CV_SWAP( delta1, delta2, t );
    }

    for( i = 0; i < mhi->rows; i++ )
    {
        uchar* mask_row = mask->data.ptr + i*mask->step;
        float* orient_row = (float*)(orientation->data.ptr + i*orientation->step);
        const float* dx_row = (float*)(dx->data.ptr + i*dx->step);
        const float* dy_row = (float*)(dy->data.ptr + i*dy->step);
        const float* min_row = (float*)(min_mhi->data.ptr + i*min_mhi->step);
        const float* max_row = (float*)(max_mhi->data.ptr + i*max_mhi->step);

        for( j = 0; j < mhi->cols; j++ )
        {
            double delta = max_row[j] - min_row[j];
            double _dx = dx_row[j], _dy = dy_row[j];

            if( delta1 <= delta && delta <= delta2 &&
                (fabs(_dx) > limit || fabs(_dy) > limit) )
            {
                mask_row[j] = 1;
                double angle = atan2( _dy, _dx ) * (180/CV_PI);
                if( angle < 0 )
                    angle += 360.;
                orient_row[j] = (float)angle;
            }
            else
            {
                mask_row[j] = 0;
                orient_row[j] = 0.f;
            }
        }
    }

    cvReleaseMat( &dx );
    cvReleaseMat( &dy );
    cvReleaseMat( &min_mhi );
    cvReleaseMat( &max_mhi );
}
Ejemplo n.º 2
0
static void
icvTsCanny( const CvMat* src, CvMat* dst,
            double threshold1, double threshold2,
            int aperture_size, int use_true_gradient )
{
    int m = aperture_size;
    CvMat* _src = cvCreateMat( src->rows + m - 1, src->cols + m - 1, CV_16S );
    CvMat* dx = cvCreateMat( src->rows, src->cols, CV_16S );
    CvMat* dy = cvCreateMat( src->rows, src->cols, CV_16S );
    CvMat* kernel = cvCreateMat( m, m, CV_32F );
    CvPoint anchor = {m/2, m/2};
    CvMat* mag = cvCreateMat( src->rows, src->cols, CV_32F );
    const double tan_pi_8 = tan(CV_PI/8.);
    const double tan_3pi_8 = tan(CV_PI*3/8);
    float lowThreshold = (float)MIN(threshold1, threshold2);
    float highThreshold = (float)MAX(threshold1, threshold2);

    int x, y, width = src->cols, height = src->rows;

    cvTsConvert( src, dx );
    cvTsPrepareToFilter( dx, _src, anchor, CV_TS_BORDER_REPLICATE );
    cvTsCalcSobelKernel2D( 1, 0, m, 0, kernel );
    cvTsConvolve2D( _src, dx, kernel, anchor );
    cvTsCalcSobelKernel2D( 0, 1, m, 0, kernel );
    cvTsConvolve2D( _src, dy, kernel, anchor );

    /* estimate magnitude and angle */
    for( y = 0; y < height; y++ )
    {
        const short* _dx = (short*)(dx->data.ptr + dx->step*y);
        const short* _dy = (short*)(dy->data.ptr + dy->step*y);
        float* _mag = (float*)(mag->data.ptr + mag->step*y);

        for( x = 0; x < width; x++ )
        {
            float mval = use_true_gradient ?
                (float)sqrt((double)(_dx[x]*_dx[x] + _dy[x]*_dy[x])) :
                (float)(abs(_dx[x]) + abs(_dy[x]));
            _mag[x] = mval;
        }
    }

    /* nonmaxima suppression */
    for( y = 0; y < height; y++ )
    {
        const short* _dx = (short*)(dx->data.ptr + dx->step*y);
        const short* _dy = (short*)(dy->data.ptr + dy->step*y);
        float* _mag = (float*)(mag->data.ptr + mag->step*y);

        for( x = 0; x < width; x++ )
        {
            int y1 = 0, y2 = 0, x1 = 0, x2 = 0;
            double tg;
            float a = _mag[x], b = 0, c = 0;

            if( a <= lowThreshold )
                continue;

            if( _dx[x] )
                tg = (double)_dy[x]/_dx[x];
            else
                tg = DBL_MAX*CV_SIGN(_dy[x]);

            if( fabs(tg) < tan_pi_8 )
            {
                y1 = y2 = y; x1 = x + 1; x2 = x - 1;
            }
            else if( tan_pi_8 <= tg && tg <= tan_3pi_8 )
            {
                y1 = y + 1; y2 = y - 1; x1 = x + 1; x2 = x - 1;
            }
            else if( -tan_3pi_8 <= tg && tg <= -tan_pi_8 )
            {
                y1 = y - 1; y2 = y + 1; x1 = x + 1; x2 = x - 1;
            }
            else
            {
                assert( fabs(tg) > tan_3pi_8 );
                x1 = x2 = x; y1 = y + 1; y2 = y - 1;
            }

            if( (unsigned)y1 < (unsigned)height && (unsigned)x1 < (unsigned)width )
                b = (float)fabs((double)mag->data.fl[y1*width+x1]);

            if( (unsigned)y2 < (unsigned)height && (unsigned)x2 < (unsigned)width )
                c = (float)fabs((double)mag->data.fl[y2*width+x2]);

            if( (a > b || (a == b && ((x1 == x+1 && y1 == y) || (x1 == x && y1 == y+1)))) && a > c )
                ;
            else
                _mag[x] = -a;
        }
    }

    cvTsZero( dst );

    /* hysteresis threshold */
    for( y = 0; y < height; y++ )
    {
        const float* _mag = (float*)(mag->data.ptr + mag->step*y);
        uchar* _dst = dst->data.ptr + dst->step*y;

        for( x = 0; x < width; x++ )
            if( _mag[x] > highThreshold && !_dst[x] )
                icvTsCannyFollow( x, y, lowThreshold, mag, dst );
    }

    cvReleaseMat( &_src );
    cvReleaseMat( &dx );
    cvReleaseMat( &dy );
    cvReleaseMat( &kernel );
    cvReleaseMat( &mag );
}