1 /*M///////////////////////////////////////////////////////////////////////////////////////
\r
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
\r
5 // By downloading, copying, installing or using the software you agree to this license.
\r
6 // If you do not agree to this license, do not download, install,
\r
7 // copy or use the software.
\r
10 // Intel License Agreement
\r
11 // For Open Source Computer Vision Library
\r
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
\r
14 // Third party copyrights are property of their respective owners.
\r
16 // Redistribution and use in source and binary forms, with or without modification,
\r
17 // are permitted provided that the following conditions are met:
\r
19 // * Redistribution's of source code must retain the above copyright notice,
\r
20 // this list of conditions and the following disclaimer.
\r
22 // * Redistribution's in binary form must reproduce the above copyright notice,
\r
23 // this list of conditions and the following disclaimer in the documentation
\r
24 // and/or other materials provided with the distribution.
\r
26 // * The name of Intel Corporation may not be used to endorse or promote products
\r
27 // derived from this software without specific prior written permission.
\r
29 // This software is provided by the copyright holders and contributors "as is" and
\r
30 // any express or implied warranties, including, but not limited to, the implied
\r
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
\r
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
\r
33 // indirect, incidental, special, exemplary, or consequential damages
\r
34 // (including, but not limited to, procurement of substitute goods or services;
\r
35 // loss of use, data, or profits; or business interruption) however caused
\r
36 // and on any theory of liability, whether in contract, strict liability,
\r
37 // or tort (including negligence or otherwise) arising in any way out of
\r
38 // the use of this software, even if advised of the possibility of such damage.
\r
44 cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners,
\r
45 int count, CvSize win, CvSize zeroZone,
\r
46 CvTermCriteria criteria )
\r
50 CV_FUNCNAME( "cvFindCornerSubPix" );
\r
54 const int MAX_ITERS = 100;
\r
55 const float drv_x[] = { -1.f, 0.f, 1.f };
\r
56 const float drv_y[] = { 0.f, 0.5f, 0.f };
\r
63 int win_w = win.width * 2 + 1, win_h = win.height * 2 + 1;
\r
64 int win_rect_size = (win_w + 4) * (win_h + 4);
\r
66 CvSize size, src_buf_size;
\r
68 int max_iters, buffer_size;
\r
71 CvMat stub, *src = (CvMat*)srcarr;
\r
72 CV_CALL( src = cvGetMat( srcarr, &stub ));
\r
74 if( CV_MAT_TYPE( src->type ) != CV_8UC1 )
\r
75 CV_ERROR( CV_StsBadMask, "" );
\r
78 CV_ERROR( CV_StsNullPtr, "" );
\r
81 CV_ERROR( CV_StsBadSize, "" );
\r
86 if( win.width <= 0 || win.height <= 0 )
\r
87 CV_ERROR( CV_StsBadSize, "" );
\r
89 size = cvGetMatSize( src );
\r
91 if( size.width < win_w + 4 || size.height < win_h + 4 )
\r
92 CV_ERROR( CV_StsBadSize, "" );
\r
94 /* initialize variables, controlling loop termination */
\r
95 switch( criteria.type )
\r
97 case CV_TERMCRIT_ITER:
\r
99 max_iters = criteria.max_iter;
\r
101 case CV_TERMCRIT_EPS:
\r
102 eps = criteria.epsilon;
\r
103 max_iters = MAX_ITERS;
\r
105 case CV_TERMCRIT_ITER | CV_TERMCRIT_EPS:
\r
106 eps = criteria.epsilon;
\r
107 max_iters = criteria.max_iter;
\r
111 CV_ERROR( CV_StsBadFlag, "" );
\r
114 eps = MAX( eps, 0 );
\r
115 eps *= eps; /* use square of error in comparsion operations. */
\r
117 max_iters = MAX( max_iters, 1 );
\r
118 max_iters = MIN( max_iters, MAX_ITERS );
\r
121 buffer_size = (win_rect_size * 5 + win_w + win_h + 32) * sizeof(float);
\r
122 buffer = (float*)cvAlloc( buffer_size );
\r
124 /* assign pointers */
\r
126 maskY = maskX + win_w + 4;
\r
127 mask = maskY + win_h + 4;
\r
128 src_buffer = mask + win_w * win_h;
\r
129 gx_buffer = src_buffer + win_rect_size;
\r
130 gy_buffer = gx_buffer + win_rect_size;
\r
132 coeff = 1. / (win.width * win.width);
\r
134 /* calculate mask */
\r
135 for( i = -win.width, k = 0; i <= win.width; i++, k++ )
\r
137 maskX[k] = (float)exp( -i * i * coeff );
\r
140 if( win.width == win.height )
\r
146 coeff = 1. / (win.height * win.height);
\r
147 for( i = -win.height, k = 0; i <= win.height; i++, k++ )
\r
149 maskY[k] = (float) exp( -i * i * coeff );
\r
153 for( i = 0; i < win_h; i++ )
\r
155 for( j = 0; j < win_w; j++ )
\r
157 mask[i * win_w + j] = maskX[j] * maskY[i];
\r
162 /* make zero_zone */
\r
163 if( zeroZone.width >= 0 && zeroZone.height >= 0 &&
\r
164 zeroZone.width * 2 + 1 < win_w && zeroZone.height * 2 + 1 < win_h )
\r
166 for( i = win.height - zeroZone.height; i <= win.height + zeroZone.height; i++ )
\r
168 for( j = win.width - zeroZone.width; j <= win.width + zeroZone.width; j++ )
\r
170 mask[i * win_w + j] = 0;
\r
175 /* set sizes of image rectangles, used in convolutions */
\r
176 src_buf_size.width = win_w + 2;
\r
177 src_buf_size.height = win_h + 2;
\r
179 /* do optimization loop for all the points */
\r
180 for( pt_i = 0; pt_i < count; pt_i++ )
\r
182 CvPoint2D32f cT = corners[pt_i], cI = cT;
\r
189 double a, b, c, bb1, bb2;
\r
191 IPPI_CALL( icvGetRectSubPix_8u32f_C1R( (uchar*)src->data.ptr, src->step, size,
\r
192 src_buffer, (win_w + 2) * sizeof( src_buffer[0] ),
\r
193 cvSize( win_w + 2, win_h + 2 ), cI ));
\r
195 /* calc derivatives */
\r
196 icvSepConvSmall3_32f( src_buffer, src_buf_size.width * sizeof(src_buffer[0]),
\r
197 gx_buffer, win_w * sizeof(gx_buffer[0]),
\r
198 src_buf_size, drv_x, drv_y, buffer );
\r
200 icvSepConvSmall3_32f( src_buffer, src_buf_size.width * sizeof(src_buffer[0]),
\r
201 gy_buffer, win_w * sizeof(gy_buffer[0]),
\r
202 src_buf_size, drv_y, drv_x, buffer );
\r
204 a = b = c = bb1 = bb2 = 0;
\r
206 /* process gradient */
\r
207 for( i = 0, k = 0; i < win_h; i++ )
\r
209 double py = i - win.height;
\r
211 for( j = 0; j < win_w; j++, k++ )
\r
213 double m = mask[k];
\r
214 double tgx = gx_buffer[k];
\r
215 double tgy = gy_buffer[k];
\r
216 double gxx = tgx * tgx * m;
\r
217 double gxy = tgx * tgy * m;
\r
218 double gyy = tgy * tgy * m;
\r
219 double px = j - win.width;
\r
225 bb1 += gxx * px + gxy * py;
\r
226 bb2 += gxy * px + gyy * py;
\r
233 CvMat matA, matInvA;
\r
239 cvInitMatHeader( &matA, 2, 2, CV_64F, A );
\r
240 cvInitMatHeader( &matInvA, 2, 2, CV_64FC1, InvA );
\r
242 cvInvert( &matA, &matInvA, CV_SVD );
\r
243 cI2.x = (float)(cI.x + InvA[0]*bb1 + InvA[1]*bb2);
\r
244 cI2.y = (float)(cI.y + InvA[2]*bb1 + InvA[3]*bb2);
\r
247 err = (cI2.x - cI.x) * (cI2.x - cI.x) + (cI2.y - cI.y) * (cI2.y - cI.y);
\r
250 while( ++iter < max_iters && err > eps );
\r
252 /* if new point is too far from initial, it means poor convergence.
\r
253 leave initial point as the result */
\r
254 if( fabs( cI.x - cT.x ) > win.width || fabs( cI.y - cT.y ) > win.height )
\r
259 corners[pt_i] = cI; /* store result */
\r
268 void cv::cornerSubPix( const Mat& image, vector<Point2f>& corners,
\r
269 Size winSize, Size zeroZone,
\r
270 TermCriteria criteria )
\r
272 CvMat _image = image;
\r
273 cvFindCornerSubPix(&_image, (CvPoint2D32f*)&corners[0], (int)corners.size(),
\r
274 winSize, zeroZone, criteria );
\r