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#include "_cv.h" 42 43#define cmp_features( f1, f2 ) (*(f1) > *(f2)) 44 45static CV_IMPLEMENT_QSORT( icvSortFeatures, int *, cmp_features ) 46 47CV_IMPL void 48cvGoodFeaturesToTrack( const void* image, void* eigImage, void* tempImage, 49 CvPoint2D32f* corners, int *corner_count, 50 double quality_level, double min_distance, 51 const void* maskImage, int block_size, 52 int use_harris, double harris_k ) 53{ 54 CvMat* _eigImg = 0; 55 CvMat* _tmpImg = 0; 56 57 CV_FUNCNAME( "cvGoodFeaturesToTrack" ); 58 59 __BEGIN__; 60 61 double max_val = 0; 62 int max_count = 0; 63 int count = 0; 64 int x, y, i, k = 0; 65 int min_dist; 66 int eig_step, tmp_step; 67 68 /* when selecting points, use integer coordinates */ 69 CvPoint *ptr = (CvPoint *) corners; 70 71 /* process floating-point images using integer arithmetics */ 72 int *eig_data = 0; 73 int *tmp_data = 0; 74 int **ptr_data = 0; 75 uchar *mask_data = 0; 76 int mask_step = 0; 77 CvSize size; 78 79 int coi1 = 0, coi2 = 0, coi3 = 0; 80 CvMat stub, *img = (CvMat*)image; 81 CvMat eig_stub, *eig = (CvMat*)eigImage; 82 CvMat tmp_stub, *tmp = (CvMat*)tempImage; 83 CvMat mask_stub, *mask = (CvMat*)maskImage; 84 85 if( corner_count ) 86 { 87 max_count = *corner_count; 88 *corner_count = 0; 89 } 90 91 CV_CALL( img = cvGetMat( img, &stub, &coi1 )); 92 if( eig ) 93 { 94 CV_CALL( eig = cvGetMat( eig, &eig_stub, &coi2 )); 95 } 96 else 97 { 98 CV_CALL( _eigImg = cvCreateMat( img->rows, img->cols, CV_32FC1 )); 99 eig = _eigImg; 100 } 101 102 if( tmp ) 103 { 104 CV_CALL( tmp = cvGetMat( tmp, &tmp_stub, &coi3 )); 105 } 106 else 107 { 108 CV_CALL( _tmpImg = cvCreateMat( img->rows, img->cols, CV_32FC1 )); 109 tmp = _tmpImg; 110 } 111 112 if( mask ) 113 { 114 CV_CALL( mask = cvGetMat( mask, &mask_stub )); 115 if( !CV_IS_MASK_ARR( mask )) 116 { 117 CV_ERROR( CV_StsBadMask, "" ); 118 } 119 } 120 121 if( coi1 != 0 || coi2 != 0 || coi3 != 0 ) 122 CV_ERROR( CV_BadCOI, "" ); 123 124 if( CV_MAT_CN(img->type) != 1 || 125 CV_MAT_CN(eig->type) != 1 || 126 CV_MAT_CN(tmp->type) != 1 ) 127 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 128 129 if( CV_MAT_DEPTH(tmp->type) != CV_32F || 130 CV_MAT_DEPTH(eig->type) != CV_32F ) 131 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 132 133 if( !corners || !corner_count ) 134 CV_ERROR( CV_StsNullPtr, "" ); 135 136 if( max_count <= 0 ) 137 CV_ERROR( CV_StsBadArg, "maximal corners number is non positive" ); 138 139 if( quality_level <= 0 || min_distance < 0 ) 140 CV_ERROR( CV_StsBadArg, "quality level or min distance are non positive" ); 141 142 if( use_harris ) 143 { 144 CV_CALL( cvCornerHarris( img, eig, block_size, 3, harris_k )); 145 } 146 else 147 { 148 CV_CALL( cvCornerMinEigenVal( img, eig, block_size, 3 )); 149 } 150 CV_CALL( cvMinMaxLoc( eig, 0, &max_val, 0, 0, mask )); 151 CV_CALL( cvThreshold( eig, eig, max_val * quality_level, 152 0, CV_THRESH_TOZERO )); 153 CV_CALL( cvDilate( eig, tmp )); 154 155 min_dist = cvRound( min_distance * min_distance ); 156 157 size = cvGetMatSize( img ); 158 ptr_data = (int**)(tmp->data.ptr); 159 eig_data = (int*)(eig->data.ptr); 160 tmp_data = (int*)(tmp->data.ptr); 161 if( mask ) 162 { 163 mask_data = (uchar*)(mask->data.ptr); 164 mask_step = mask->step; 165 } 166 167 eig_step = eig->step / sizeof(eig_data[0]); 168 tmp_step = tmp->step / sizeof(tmp_data[0]); 169 170 /* collect list of pointers to features - put them into temporary image */ 171 for( y = 1, k = 0; y < size.height - 1; y++ ) 172 { 173 eig_data += eig_step; 174 tmp_data += tmp_step; 175 mask_data += mask_step; 176 177 for( x = 1; x < size.width - 1; x++ ) 178 { 179 int val = eig_data[x]; 180 if( val != 0 && val == tmp_data[x] && (!mask || mask_data[x]) ) 181 ptr_data[k++] = eig_data + x; 182 } 183 } 184 185 icvSortFeatures( ptr_data, k, 0 ); 186 187 /* select the strongest features */ 188 for( i = 0; i < k; i++ ) 189 { 190 int j = count, ofs = (int)((uchar*)(ptr_data[i]) - eig->data.ptr); 191 y = ofs / eig->step; 192 x = (ofs - y * eig->step)/sizeof(float); 193 194 if( min_dist != 0 ) 195 { 196 for( j = 0; j < count; j++ ) 197 { 198 int dx = x - ptr[j].x; 199 int dy = y - ptr[j].y; 200 int dist = dx * dx + dy * dy; 201 202 if( dist < min_dist ) 203 break; 204 } 205 } 206 207 if( j == count ) 208 { 209 ptr[count].x = x; 210 ptr[count].y = y; 211 if( ++count >= max_count ) 212 break; 213 } 214 } 215 216 /* convert points to floating-point format */ 217 for( i = 0; i < count; i++ ) 218 { 219 assert( (unsigned)ptr[i].x < (unsigned)size.width && 220 (unsigned)ptr[i].y < (unsigned)size.height ); 221 222 corners[i].x = (float)ptr[i].x; 223 corners[i].y = (float)ptr[i].y; 224 } 225 226 *corner_count = count; 227 228 __END__; 229 230 cvReleaseMat( &_eigImg ); 231 cvReleaseMat( &_tmpImg ); 232} 233 234/* End of file. */ 235