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 // License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
22 //
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
26 //
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "precomp.hpp"
44
45 namespace cv
46 {
47
48 static const uchar*
adjustRect(const uchar * src,size_t src_step,int pix_size,Size src_size,Size win_size,Point ip,Rect * pRect)49 adjustRect( const uchar* src, size_t src_step, int pix_size,
50 Size src_size, Size win_size,
51 Point ip, Rect* pRect )
52 {
53 Rect rect;
54
55 if( ip.x >= 0 )
56 {
57 src += ip.x*pix_size;
58 rect.x = 0;
59 }
60 else
61 {
62 rect.x = -ip.x;
63 if( rect.x > win_size.width )
64 rect.x = win_size.width;
65 }
66
67 if( ip.x < src_size.width - win_size.width )
68 rect.width = win_size.width;
69 else
70 {
71 rect.width = src_size.width - ip.x - 1;
72 if( rect.width < 0 )
73 {
74 src += rect.width*pix_size;
75 rect.width = 0;
76 }
77 assert( rect.width <= win_size.width );
78 }
79
80 if( ip.y >= 0 )
81 {
82 src += ip.y * src_step;
83 rect.y = 0;
84 }
85 else
86 rect.y = -ip.y;
87
88 if( ip.y < src_size.height - win_size.height )
89 rect.height = win_size.height;
90 else
91 {
92 rect.height = src_size.height - ip.y - 1;
93 if( rect.height < 0 )
94 {
95 src += rect.height*src_step;
96 rect.height = 0;
97 }
98 }
99
100 *pRect = rect;
101 return src - rect.x*pix_size;
102 }
103
104
105 enum { SUBPIX_SHIFT=16 };
106
107 struct scale_fixpt
108 {
operator ()cv::scale_fixpt109 int operator()(float a) const { return cvRound(a*(1 << SUBPIX_SHIFT)); }
110 };
111
112 struct cast_8u
113 {
operator ()cv::cast_8u114 uchar operator()(int a) const { return (uchar)((a + (1 << (SUBPIX_SHIFT-1))) >> SUBPIX_SHIFT); }
115 };
116
117 struct cast_flt_8u
118 {
operator ()cv::cast_flt_8u119 uchar operator()(float a) const { return (uchar)cvRound(a); }
120 };
121
122 template<typename _Tp>
123 struct nop
124 {
operator ()cv::nop125 _Tp operator()(_Tp a) const { return a; }
126 };
127
128
129 template<typename _Tp, typename _DTp, typename _WTp, class ScaleOp, class CastOp>
getRectSubPix_Cn_(const _Tp * src,size_t src_step,Size src_size,_DTp * dst,size_t dst_step,Size win_size,Point2f center,int cn)130 void getRectSubPix_Cn_(const _Tp* src, size_t src_step, Size src_size,
131 _DTp* dst, size_t dst_step, Size win_size, Point2f center, int cn )
132 {
133 ScaleOp scale_op;
134 CastOp cast_op;
135 Point ip;
136 _WTp a11, a12, a21, a22, b1, b2;
137 float a, b;
138 int i, j, c;
139
140 center.x -= (win_size.width-1)*0.5f;
141 center.y -= (win_size.height-1)*0.5f;
142
143 ip.x = cvFloor( center.x );
144 ip.y = cvFloor( center.y );
145
146 a = center.x - ip.x;
147 b = center.y - ip.y;
148 a11 = scale_op((1.f-a)*(1.f-b));
149 a12 = scale_op(a*(1.f-b));
150 a21 = scale_op((1.f-a)*b);
151 a22 = scale_op(a*b);
152 b1 = scale_op(1.f - b);
153 b2 = scale_op(b);
154
155 src_step /= sizeof(src[0]);
156 dst_step /= sizeof(dst[0]);
157
158 if( 0 <= ip.x && ip.x < src_size.width - win_size.width &&
159 0 <= ip.y && ip.y < src_size.height - win_size.height)
160 {
161 // extracted rectangle is totally inside the image
162 src += ip.y * src_step + ip.x*cn;
163 win_size.width *= cn;
164
165 for( i = 0; i < win_size.height; i++, src += src_step, dst += dst_step )
166 {
167 for( j = 0; j <= win_size.width - 2; j += 2 )
168 {
169 _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src[j+src_step]*a21 + src[j+src_step+cn]*a22;
170 _WTp s1 = src[j+1]*a11 + src[j+cn+1]*a12 + src[j+src_step+1]*a21 + src[j+src_step+cn+1]*a22;
171 dst[j] = cast_op(s0);
172 dst[j+1] = cast_op(s1);
173 }
174
175 for( ; j < win_size.width; j++ )
176 {
177 _WTp s0 = src[j]*a11 + src[j+cn]*a12 + src[j+src_step]*a21 + src[j+src_step+cn]*a22;
178 dst[j] = cast_op(s0);
179 }
180 }
181 }
182 else
183 {
184 Rect r;
185 src = (const _Tp*)adjustRect( (const uchar*)src, src_step*sizeof(*src),
186 sizeof(*src)*cn, src_size, win_size, ip, &r);
187
188 for( i = 0; i < win_size.height; i++, dst += dst_step )
189 {
190 const _Tp *src2 = src + src_step;
191 _WTp s0;
192
193 if( i < r.y || i >= r.height )
194 src2 -= src_step;
195
196 for( c = 0; c < cn; c++ )
197 {
198 s0 = src[r.x*cn + c]*b1 + src2[r.x*cn + c]*b2;
199 for( j = 0; j < r.x; j++ )
200 dst[j*cn + c] = cast_op(s0);
201 s0 = src[r.width*cn + c]*b1 + src2[r.width*cn + c]*b2;
202 for( j = r.width; j < win_size.width; j++ )
203 dst[j*cn + c] = cast_op(s0);
204 }
205
206 for( j = r.x*cn; j < r.width*cn; j++ )
207 {
208 s0 = src[j]*a11 + src[j+cn]*a12 + src2[j]*a21 + src2[j+cn]*a22;
209 dst[j] = cast_op(s0);
210 }
211
212 if( i < r.height )
213 src = src2;
214 }
215 }
216 }
217
218
getRectSubPix_8u32f(const uchar * src,size_t src_step,Size src_size,float * dst,size_t dst_step,Size win_size,Point2f center0,int cn)219 static void getRectSubPix_8u32f
220 ( const uchar* src, size_t src_step, Size src_size,
221 float* dst, size_t dst_step, Size win_size, Point2f center0, int cn )
222 {
223 Point2f center = center0;
224 Point ip;
225
226 center.x -= (win_size.width-1)*0.5f;
227 center.y -= (win_size.height-1)*0.5f;
228
229 ip.x = cvFloor( center.x );
230 ip.y = cvFloor( center.y );
231
232 if( cn == 1 &&
233 0 <= ip.x && ip.x + win_size.width < src_size.width &&
234 0 <= ip.y && ip.y + win_size.height < src_size.height &&
235 win_size.width > 0 && win_size.height > 0 )
236 {
237 float a = center.x - ip.x;
238 float b = center.y - ip.y;
239 a = MAX(a,0.0001f);
240 float a12 = a*(1.f-b);
241 float a22 = a*b;
242 float b1 = 1.f - b;
243 float b2 = b;
244 double s = (1. - a)/a;
245
246 src_step /= sizeof(src[0]);
247 dst_step /= sizeof(dst[0]);
248
249 // extracted rectangle is totally inside the image
250 src += ip.y * src_step + ip.x;
251
252 for( ; win_size.height--; src += src_step, dst += dst_step )
253 {
254 float prev = (1 - a)*(b1*src[0] + b2*src[src_step]);
255 for( int j = 0; j < win_size.width; j++ )
256 {
257 float t = a12*src[j+1] + a22*src[j+1+src_step];
258 dst[j] = prev + t;
259 prev = (float)(t*s);
260 }
261 }
262 }
263 else
264 {
265 getRectSubPix_Cn_<uchar, float, float, nop<float>, nop<float> >
266 (src, src_step, src_size, dst, dst_step, win_size, center0, cn );
267 }
268 }
269
270 static void
getQuadrangleSubPix_8u32f_CnR(const uchar * src,size_t src_step,Size src_size,float * dst,size_t dst_step,Size win_size,const double * matrix,int cn)271 getQuadrangleSubPix_8u32f_CnR( const uchar* src, size_t src_step, Size src_size,
272 float* dst, size_t dst_step, Size win_size,
273 const double *matrix, int cn )
274 {
275 int x, y, k;
276 double A11 = matrix[0], A12 = matrix[1], A13 = matrix[2];
277 double A21 = matrix[3], A22 = matrix[4], A23 = matrix[5];
278
279 src_step /= sizeof(src[0]);
280 dst_step /= sizeof(dst[0]);
281
282 for( y = 0; y < win_size.height; y++, dst += dst_step )
283 {
284 double xs = A12*y + A13;
285 double ys = A22*y + A23;
286 double xe = A11*(win_size.width-1) + A12*y + A13;
287 double ye = A21*(win_size.width-1) + A22*y + A23;
288
289 if( (unsigned)(cvFloor(xs)-1) < (unsigned)(src_size.width - 3) &&
290 (unsigned)(cvFloor(ys)-1) < (unsigned)(src_size.height - 3) &&
291 (unsigned)(cvFloor(xe)-1) < (unsigned)(src_size.width - 3) &&
292 (unsigned)(cvFloor(ye)-1) < (unsigned)(src_size.height - 3))
293 {
294 for( x = 0; x < win_size.width; x++ )
295 {
296 int ixs = cvFloor( xs );
297 int iys = cvFloor( ys );
298 const uchar *ptr = src + src_step*iys;
299 float a = (float)(xs - ixs), b = (float)(ys - iys), a1 = 1.f - a, b1 = 1.f - b;
300 float w00 = a1*b1, w01 = a*b1, w10 = a1*b, w11 = a*b;
301 xs += A11;
302 ys += A21;
303
304 if( cn == 1 )
305 {
306 ptr += ixs;
307 dst[x] = ptr[0]*w00 + ptr[1]*w01 + ptr[src_step]*w10 + ptr[src_step+1]*w11;
308 }
309 else if( cn == 3 )
310 {
311 ptr += ixs*3;
312 float t0 = ptr[0]*w00 + ptr[3]*w01 + ptr[src_step]*w10 + ptr[src_step+3]*w11;
313 float t1 = ptr[1]*w00 + ptr[4]*w01 + ptr[src_step+1]*w10 + ptr[src_step+4]*w11;
314 float t2 = ptr[2]*w00 + ptr[5]*w01 + ptr[src_step+2]*w10 + ptr[src_step+5]*w11;
315
316 dst[x*3] = t0;
317 dst[x*3+1] = t1;
318 dst[x*3+2] = t2;
319 }
320 else
321 {
322 ptr += ixs*cn;
323 for( k = 0; k < cn; k++ )
324 dst[x*cn+k] = ptr[k]*w00 + ptr[k+cn]*w01 +
325 ptr[src_step+k]*w10 + ptr[src_step+k+cn]*w11;
326 }
327 }
328 }
329 else
330 {
331 for( x = 0; x < win_size.width; x++ )
332 {
333 int ixs = cvFloor( xs ), iys = cvFloor( ys );
334 float a = (float)(xs - ixs), b = (float)(ys - iys), a1 = 1.f - a, b1 = 1.f - b;
335 float w00 = a1*b1, w01 = a*b1, w10 = a1*b, w11 = a*b;
336 const uchar *ptr0, *ptr1;
337 xs += A11; ys += A21;
338
339 if( (unsigned)iys < (unsigned)(src_size.height-1) )
340 ptr0 = src + src_step*iys, ptr1 = ptr0 + src_step;
341 else
342 ptr0 = ptr1 = src + (iys < 0 ? 0 : src_size.height-1)*src_step;
343
344 if( (unsigned)ixs < (unsigned)(src_size.width-1) )
345 {
346 ptr0 += ixs*cn; ptr1 += ixs*cn;
347 for( k = 0; k < cn; k++ )
348 dst[x*cn + k] = ptr0[k]*w00 + ptr0[k+cn]*w01 + ptr1[k]*w10 + ptr1[k+cn]*w11;
349 }
350 else
351 {
352 ixs = ixs < 0 ? 0 : src_size.width - 1;
353 ptr0 += ixs*cn; ptr1 += ixs*cn;
354 for( k = 0; k < cn; k++ )
355 dst[x*cn + k] = ptr0[k]*b1 + ptr1[k]*b;
356 }
357 }
358 }
359 }
360 }
361
362 }
363
364
getRectSubPix(InputArray _image,Size patchSize,Point2f center,OutputArray _patch,int patchType)365 void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center,
366 OutputArray _patch, int patchType )
367 {
368 Mat image = _image.getMat();
369 int depth = image.depth(), cn = image.channels();
370 int ddepth = patchType < 0 ? depth : CV_MAT_DEPTH(patchType);
371
372 CV_Assert( cn == 1 || cn == 3 );
373
374 _patch.create(patchSize, CV_MAKETYPE(ddepth, cn));
375 Mat patch = _patch.getMat();
376
377 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
378 CV_IPP_CHECK()
379 {
380 typedef IppStatus (CV_STDCALL *ippiGetRectSubPixFunc)( const void* src, int src_step,
381 IppiSize src_size, void* dst,
382 int dst_step, IppiSize win_size,
383 IppiPoint_32f center,
384 IppiPoint* minpt, IppiPoint* maxpt );
385
386 IppiPoint minpt={0,0}, maxpt={0,0};
387 IppiPoint_32f icenter = {center.x, center.y};
388 IppiSize src_size={image.cols, image.rows}, win_size={patch.cols, patch.rows};
389 int srctype = image.type();
390 ippiGetRectSubPixFunc ippfunc =
391 srctype == CV_8UC1 && ddepth == CV_8U ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_8u_C1R :
392 srctype == CV_8UC1 && ddepth == CV_32F ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_8u32f_C1R :
393 srctype == CV_32FC1 && ddepth == CV_32F ? (ippiGetRectSubPixFunc)ippiCopySubpixIntersect_32f_C1R : 0;
394
395 if( ippfunc)
396 {
397 if (ippfunc(image.ptr(), (int)image.step, src_size, patch.ptr(),
398 (int)patch.step, win_size, icenter, &minpt, &maxpt) >= 0 )
399 {
400 CV_IMPL_ADD(CV_IMPL_IPP);
401 return;
402 }
403 setIppErrorStatus();
404 }
405 }
406 #endif
407
408 if( depth == CV_8U && ddepth == CV_8U )
409 getRectSubPix_Cn_<uchar, uchar, int, scale_fixpt, cast_8u>
410 (image.ptr(), image.step, image.size(), patch.ptr(), patch.step, patch.size(), center, cn);
411 else if( depth == CV_8U && ddepth == CV_32F )
412 getRectSubPix_8u32f
413 (image.ptr(), image.step, image.size(), patch.ptr<float>(), patch.step, patch.size(), center, cn);
414 else if( depth == CV_32F && ddepth == CV_32F )
415 getRectSubPix_Cn_<float, float, float, nop<float>, nop<float> >
416 (image.ptr<float>(), image.step, image.size(), patch.ptr<float>(), patch.step, patch.size(), center, cn);
417 else
418 CV_Error( CV_StsUnsupportedFormat, "Unsupported combination of input and output formats");
419 }
420
421
422 CV_IMPL void
cvGetRectSubPix(const void * srcarr,void * dstarr,CvPoint2D32f center)423 cvGetRectSubPix( const void* srcarr, void* dstarr, CvPoint2D32f center )
424 {
425 cv::Mat src = cv::cvarrToMat(srcarr);
426 const cv::Mat dst = cv::cvarrToMat(dstarr);
427 CV_Assert( src.channels() == dst.channels() );
428
429 cv::getRectSubPix(src, dst.size(), center, dst, dst.type());
430 }
431
432
433 CV_IMPL void
cvGetQuadrangleSubPix(const void * srcarr,void * dstarr,const CvMat * mat)434 cvGetQuadrangleSubPix( const void* srcarr, void* dstarr, const CvMat* mat )
435 {
436 const cv::Mat src = cv::cvarrToMat(srcarr), m = cv::cvarrToMat(mat);
437 cv::Mat dst = cv::cvarrToMat(dstarr);
438
439 CV_Assert( src.channels() == dst.channels() );
440
441 cv::Size win_size = dst.size();
442 double matrix[6];
443 cv::Mat M(2, 3, CV_64F, matrix);
444 m.convertTo(M, CV_64F);
445 double dx = (win_size.width - 1)*0.5;
446 double dy = (win_size.height - 1)*0.5;
447 matrix[2] -= matrix[0]*dx + matrix[1]*dy;
448 matrix[5] -= matrix[3]*dx + matrix[4]*dy;
449
450 if( src.depth() == CV_8U && dst.depth() == CV_32F )
451 cv::getQuadrangleSubPix_8u32f_CnR( src.ptr(), src.step, src.size(),
452 dst.ptr<float>(), dst.step, dst.size(),
453 matrix, src.channels());
454 else
455 {
456 CV_Assert( src.depth() == dst.depth() );
457 cv::warpAffine(src, dst, M, dst.size(),
458 cv::INTER_LINEAR + cv::WARP_INVERSE_MAP,
459 cv::BORDER_REPLICATE);
460 }
461 }
462
463
464 CV_IMPL int
cvSampleLine(const void * _img,CvPoint pt1,CvPoint pt2,void * _buffer,int connectivity)465 cvSampleLine( const void* _img, CvPoint pt1, CvPoint pt2,
466 void* _buffer, int connectivity )
467 {
468 cv::Mat img = cv::cvarrToMat(_img);
469 cv::LineIterator li(img, pt1, pt2, connectivity, false);
470 uchar* buffer = (uchar*)_buffer;
471 size_t pixsize = img.elemSize();
472
473 if( !buffer )
474 CV_Error( CV_StsNullPtr, "" );
475
476 for( int i = 0; i < li.count; i++, ++li )
477 {
478 for( size_t k = 0; k < pixsize; k++ )
479 *buffer++ = li.ptr[k];
480 }
481
482 return li.count;
483 }
484
485
486 /* End of file. */
487