www.pudn.com > OpenCV-Intel.zip > cvfeatureselect.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" 
 
#define  cmp_features( f1, f2 )  (*(f1) > *(f2)) 
 
static CV_IMPLEMENT_QSORT( icvSortFeatures, int *, cmp_features ) 
 
CV_IMPL void 
cvGoodFeaturesToTrack( const void* image, void* eigImage, void* tempImage, 
                       CvPoint2D32f* corners, int *corner_count, 
                       double quality_level, double min_distance, 
                       const void* maskImage, int block_size, 
                       int use_harris, double harris_k ) 
{ 
    CvMat* _eigImg = 0; 
    CvMat* _tmpImg = 0; 
     
    CV_FUNCNAME( "cvGoodFeaturesToTrack" ); 
 
    __BEGIN__; 
 
    double max_val = 0; 
    int max_count = 0; 
    int count = 0; 
    int x, y, i, k = 0; 
    int min_dist; 
 
    /* when selecting points, use integer coordinates */ 
    CvPoint *ptr = (CvPoint *) corners; 
 
    /* process floating-point images using integer arithmetics */ 
    int *eig_data = 0; 
    int *tmp_data = 0; 
    int **ptr_data = 0; 
    uchar *mask_data = 0; 
    int  mask_step = 0; 
    CvSize size; 
 
    int    coi1 = 0, coi2 = 0, coi3 = 0; 
    CvMat  stub, *img = (CvMat*)image; 
    CvMat  eig_stub, *eig = (CvMat*)eigImage; 
    CvMat  tmp_stub, *tmp = (CvMat*)tempImage; 
    CvMat  mask_stub, *mask = (CvMat*)maskImage; 
 
    if( corner_count ) 
    { 
        max_count = *corner_count; 
        *corner_count = 0; 
    } 
 
    CV_CALL( img = cvGetMat( img, &stub, &coi1 )); 
    if( eig ) 
    { 
        CV_CALL( eig = cvGetMat( eig, &eig_stub, &coi2 )); 
    } 
    else 
    { 
        CV_CALL( _eigImg = cvCreateMat( img->rows, img->cols, CV_32FC1 )); 
        eig = _eigImg; 
    } 
 
    if( tmp ) 
    { 
        CV_CALL( tmp = cvGetMat( tmp, &tmp_stub, &coi3 )); 
    } 
    else 
    { 
        CV_CALL( _tmpImg = cvCreateMat( img->rows, img->cols, CV_32FC1 )); 
        tmp = _tmpImg; 
    } 
 
    if( mask ) 
    { 
        CV_CALL( mask = cvGetMat( mask, &mask_stub )); 
        if( !CV_IS_MASK_ARR( mask )) 
        { 
            CV_ERROR( CV_StsBadMask, "" ); 
        } 
    } 
 
    if( coi1 != 0 || coi2 != 0 || coi3 != 0 ) 
        CV_ERROR( CV_BadCOI, "" ); 
 
    if( CV_MAT_CN(img->type) != 1 || 
        CV_MAT_CN(eig->type) != 1 || 
        CV_MAT_CN(tmp->type) != 1 ) 
        CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 
 
    if( CV_MAT_DEPTH(tmp->type) != CV_32F || 
        CV_MAT_DEPTH(eig->type) != CV_32F ) 
        CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 
 
    if( !corners || !corner_count ) 
        CV_ERROR( CV_StsNullPtr, "" ); 
 
    if( max_count <= 0 ) 
        CV_ERROR( CV_StsBadArg, "maximal corners number is non positive" ); 
 
    if( quality_level <= 0 || min_distance < 0 ) 
        CV_ERROR( CV_StsBadArg, "quality level or min distance are non positive" ); 
 
    if( use_harris ) 
    { 
        CV_CALL( cvCornerHarris( img, eig, block_size, 3, harris_k )); 
    } 
    else 
    { 
        CV_CALL( cvCornerMinEigenVal( img, eig, block_size, 3 )); 
    } 
    CV_CALL( cvMinMaxLoc( eig, 0, &max_val, 0, 0, mask )); 
    CV_CALL( cvThreshold( eig, eig, max_val * quality_level, 
                          0, CV_THRESH_TOZERO )); 
    CV_CALL( cvDilate( eig, tmp )); 
 
    min_dist = cvRound( min_distance * min_distance ); 
 
    size = cvGetMatSize( img ); 
    ptr_data = (int**)(tmp->data.ptr); 
    eig_data = (int*)(eig->data.ptr); 
    tmp_data = (int*)(tmp->data.ptr); 
    if( mask ) 
    { 
        mask_data = (uchar*)(mask->data.ptr); 
        mask_step = mask->step; 
    } 
 
    /* collect list of pointers to features - put them into temporary image */ 
    for( y = 1, k = 0; y < size.height - 1; y++ ) 
    { 
        (char*&)eig_data += eig->step; 
        (char*&)tmp_data += tmp->step; 
        mask_data += mask_step; 
 
        for( x = 1; x < size.width - 1; x++ ) 
        { 
            int val = eig_data[x]; 
            if( val != 0 && val == tmp_data[x] && (!mask || mask_data[x]) ) 
                ptr_data[k++] = eig_data + x; 
        } 
    } 
 
    icvSortFeatures( ptr_data, k, 0 ); 
 
    /* select the strongest features */ 
    for( i = 0; i < k; i++ ) 
    { 
        int j = count, ofs = (int)((uchar*)(ptr_data[i]) - eig->data.ptr); 
        y = ofs / eig->step; 
        x = (ofs - y * eig->step)/sizeof(float); 
 
        if( min_dist != 0 ) 
        { 
            for( j = 0; j < count; j++ ) 
            { 
                int dx = x - ptr[j].x; 
                int dy = y - ptr[j].y; 
                int dist = dx * dx + dy * dy; 
 
                if( dist < min_dist ) 
                    break; 
            } 
        } 
 
        if( j == count ) 
        { 
            ptr[count].x = x; 
            ptr[count].y = y; 
            if( ++count >= max_count ) 
                break; 
        } 
    } 
     
    /* convert points to floating-point format */ 
    for( i = 0; i < count; i++ ) 
    { 
        assert( (unsigned)ptr[i].x < (unsigned)size.width && 
                (unsigned)ptr[i].y < (unsigned)size.height ); 
 
        corners[i].x = (float)ptr[i].x; 
        corners[i].y = (float)ptr[i].y; 
    } 
 
    *corner_count = count; 
 
    __END__; 
 
    cvReleaseMat( &_eigImg ); 
    cvReleaseMat( &_tmpImg ); 
} 
 
/* End of file. */