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
CV_IMPLEMENT_QSORT(icvSortFeatures,int *,cmp_features)45 static CV_IMPLEMENT_QSORT( icvSortFeatures, int *, cmp_features )
46
47 CV_IMPL void
48 cvGoodFeaturesToTrack( 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