1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
42 /* ////////////////////////////////////////////////////////////////////
44 // Geometrical transforms on images and matrices: rotation, zoom etc.
51 /************** interpolation constants and tables ***************/
53 #define ICV_WARP_MUL_ONE_8U(x) ((x) << ICV_WARP_SHIFT)
54 #define ICV_WARP_DESCALE_8U(x) CV_DESCALE((x), ICV_WARP_SHIFT*2)
55 #define ICV_WARP_CLIP_X(x) ((unsigned)(x) < (unsigned)ssize.width ? \
56 (x) : (x) < 0 ? 0 : ssize.width - 1)
57 #define ICV_WARP_CLIP_Y(y) ((unsigned)(y) < (unsigned)ssize.height ? \
58 (y) : (y) < 0 ? 0 : ssize.height - 1)
60 float icvLinearCoeffs[(ICV_LINEAR_TAB_SIZE+1)*2];
62 void icvInitLinearCoeffTab()
64 static int inittab = 0;
67 for( int i = 0; i <= ICV_LINEAR_TAB_SIZE; i++ )
69 float x = (float)i/ICV_LINEAR_TAB_SIZE;
70 icvLinearCoeffs[i*2] = x;
71 icvLinearCoeffs[i*2+1] = 1.f - x;
79 float icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE+1)*2];
81 void icvInitCubicCoeffTab()
83 static int inittab = 0;
87 // classical Mitchell-Netravali filter
88 const double B = 1./3;
89 const double C = 1./3;
90 const double p0 = (6 - 2*B)/6.;
91 const double p2 = (-18 + 12*B + 6*C)/6.;
92 const double p3 = (12 - 9*B - 6*C)/6.;
93 const double q0 = (8*B + 24*C)/6.;
94 const double q1 = (-12*B - 48*C)/6.;
95 const double q2 = (6*B + 30*C)/6.;
96 const double q3 = (-B - 6*C)/6.;
98 #define ICV_CUBIC_1(x) (((x)*p3 + p2)*(x)*(x) + p0)
99 #define ICV_CUBIC_2(x) ((((x)*q3 + q2)*(x) + q1)*(x) + q0)
101 // alternative "sharp" filter
102 const double A = -0.75;
103 #define ICV_CUBIC_1(x) (((A + 2)*(x) - (A + 3))*(x)*(x) + 1)
104 #define ICV_CUBIC_2(x) (((A*(x) - 5*A)*(x) + 8*A)*(x) - 4*A)
106 for( int i = 0; i <= ICV_CUBIC_TAB_SIZE; i++ )
108 float x = (float)i/ICV_CUBIC_TAB_SIZE;
109 icvCubicCoeffs[i*2] = (float)ICV_CUBIC_1(x);
111 icvCubicCoeffs[i*2+1] = (float)ICV_CUBIC_2(x);
119 /****************************************************************************************\
121 \****************************************************************************************/
123 static CvStatus CV_STDCALL
124 icvResize_NN_8u_C1R( const uchar* src, int srcstep, CvSize ssize,
125 uchar* dst, int dststep, CvSize dsize, int pix_size )
127 int* x_ofs = (int*)cvStackAlloc( dsize.width * sizeof(x_ofs[0]) );
128 int pix_size4 = pix_size / sizeof(int);
131 for( x = 0; x < dsize.width; x++ )
133 t = (ssize.width*x*2 + MIN(ssize.width, dsize.width) - 1)/(dsize.width*2);
134 t -= t >= ssize.width;
135 x_ofs[x] = t*pix_size;
138 for( y = 0; y < dsize.height; y++, dst += dststep )
141 t = (ssize.height*y*2 + MIN(ssize.height, dsize.height) - 1)/(dsize.height*2);
142 t -= t >= ssize.height;
143 tsrc = src + srcstep*t;
148 for( x = 0; x <= dsize.width - 2; x += 2 )
150 uchar t0 = tsrc[x_ofs[x]];
151 uchar t1 = tsrc[x_ofs[x+1]];
157 for( ; x < dsize.width; x++ )
158 dst[x] = tsrc[x_ofs[x]];
161 for( x = 0; x < dsize.width; x++ )
162 *(ushort*)(dst + x*2) = *(ushort*)(tsrc + x_ofs[x]);
165 for( x = 0; x < dsize.width; x++ )
167 const uchar* _tsrc = tsrc + x_ofs[x];
168 dst[x*3] = _tsrc[0]; dst[x*3+1] = _tsrc[1]; dst[x*3+2] = _tsrc[2];
172 for( x = 0; x < dsize.width; x++ )
173 *(int*)(dst + x*4) = *(int*)(tsrc + x_ofs[x]);
176 for( x = 0; x < dsize.width; x++ )
178 const ushort* _tsrc = (const ushort*)(tsrc + x_ofs[x]);
179 ushort* _tdst = (ushort*)(dst + x*6);
180 _tdst[0] = _tsrc[0]; _tdst[1] = _tsrc[1]; _tdst[2] = _tsrc[2];
184 for( x = 0; x < dsize.width; x++ )
185 CV_MEMCPY_INT( dst + x*pix_size, tsrc + x_ofs[x], pix_size4 );
193 typedef struct CvResizeAlpha
205 #define ICV_DEF_RESIZE_BILINEAR_FUNC( flavor, arrtype, worktype, alpha_field, \
206 mul_one_macro, descale_macro ) \
207 static CvStatus CV_STDCALL \
208 icvResize_Bilinear_##flavor##_CnR( const arrtype* src, int srcstep, CvSize ssize,\
209 arrtype* dst, int dststep, CvSize dsize, \
211 const CvResizeAlpha* xofs, \
212 const CvResizeAlpha* yofs, \
213 worktype* buf0, worktype* buf1 ) \
215 int prev_sy0 = -1, prev_sy1 = -1; \
218 srcstep /= sizeof(src[0]); \
219 dststep /= sizeof(dst[0]); \
223 for( dy = 0; dy < dsize.height; dy++, dst += dststep ) \
225 worktype fy = yofs[dy].alpha_field, *swap_t; \
226 int sy0 = yofs[dy].idx, sy1 = sy0 + (fy > 0 && sy0 < ssize.height-1); \
228 if( sy0 == prev_sy0 && sy1 == prev_sy1 ) \
230 else if( sy0 == prev_sy1 ) \
232 CV_SWAP( buf0, buf1, swap_t ); \
238 for( ; k < 2; k++ ) \
240 worktype* _buf = k == 0 ? buf0 : buf1; \
241 const arrtype* _src; \
242 int sy = k == 0 ? sy0 : sy1; \
243 if( k == 1 && sy1 == sy0 ) \
245 memcpy( buf1, buf0, dsize.width*sizeof(buf0[0]) ); \
249 _src = src + sy*srcstep; \
250 for( dx = 0; dx < xmax; dx++ ) \
252 int sx = xofs[dx].idx; \
253 worktype fx = xofs[dx].alpha_field; \
254 worktype t = _src[sx]; \
255 _buf[dx] = mul_one_macro(t) + fx*(_src[sx+cn] - t); \
258 for( ; dx < dsize.width; dx++ ) \
259 _buf[dx] = mul_one_macro(_src[xofs[dx].idx]); \
266 for( dx = 0; dx < dsize.width; dx++ ) \
267 dst[dx] = (arrtype)descale_macro( mul_one_macro(buf0[dx])); \
269 for( dx = 0; dx < dsize.width; dx++ ) \
270 dst[dx] = (arrtype)descale_macro( mul_one_macro(buf0[dx]) + \
271 fy*(buf1[dx] - buf0[dx])); \
278 typedef struct CvDecimateAlpha
286 #define ICV_DEF_RESIZE_AREA_FAST_FUNC( flavor, arrtype, worktype, cast_macro ) \
287 static CvStatus CV_STDCALL \
288 icvResize_AreaFast_##flavor##_CnR( const arrtype* src, int srcstep, CvSize ssize,\
289 arrtype* dst, int dststep, CvSize dsize, int cn, \
290 const int* ofs, const int* xofs ) \
293 int scale_x = ssize.width/dsize.width; \
294 int scale_y = ssize.height/dsize.height; \
295 int area = scale_x*scale_y; \
296 float scale = 1.f/(scale_x*scale_y); \
298 srcstep /= sizeof(src[0]); \
299 dststep /= sizeof(dst[0]); \
302 for( dy = 0; dy < dsize.height; dy++, dst += dststep ) \
303 for( dx = 0; dx < dsize.width; dx++ ) \
305 const arrtype* _src = src + dy*scale_y*srcstep + xofs[dx]; \
308 for( k = 0; k <= area - 4; k += 4 ) \
309 sum += _src[ofs[k]] + _src[ofs[k+1]] + \
310 _src[ofs[k+2]] + _src[ofs[k+3]]; \
312 for( ; k < area; k++ ) \
313 sum += _src[ofs[k]]; \
315 dst[dx] = (arrtype)cast_macro( sum*scale ); \
322 #define ICV_DEF_RESIZE_AREA_FUNC( flavor, arrtype, load_macro, cast_macro ) \
323 static CvStatus CV_STDCALL \
324 icvResize_Area_##flavor##_CnR( const arrtype* src, int srcstep, CvSize ssize, \
325 arrtype* dst, int dststep, CvSize dsize, \
326 int cn, const CvDecimateAlpha* xofs, \
327 int xofs_count, float* buf, float* sum ) \
329 int k, sy, dx, cur_dy = 0; \
330 float scale_y = (float)ssize.height/dsize.height; \
332 srcstep /= sizeof(src[0]); \
333 dststep /= sizeof(dst[0]); \
336 for( sy = 0; sy < ssize.height; sy++, src += srcstep ) \
339 for( k = 0; k < xofs_count; k++ ) \
341 int dxn = xofs[k].di; \
342 float alpha = xofs[k].alpha; \
343 buf[dxn] = buf[dxn] + load_macro(src[xofs[k].si])*alpha; \
346 for( k = 0; k < xofs_count; k++ ) \
348 int sxn = xofs[k].si; \
349 int dxn = xofs[k].di; \
350 float alpha = xofs[k].alpha; \
351 float t0 = buf[dxn] + load_macro(src[sxn])*alpha; \
352 float t1 = buf[dxn+1] + load_macro(src[sxn+1])*alpha; \
353 buf[dxn] = t0; buf[dxn+1] = t1; \
356 for( k = 0; k < xofs_count; k++ ) \
358 int sxn = xofs[k].si; \
359 int dxn = xofs[k].di; \
360 float alpha = xofs[k].alpha; \
361 float t0 = buf[dxn] + load_macro(src[sxn])*alpha; \
362 float t1 = buf[dxn+1] + load_macro(src[sxn+1])*alpha; \
363 float t2 = buf[dxn+2] + load_macro(src[sxn+2])*alpha; \
364 buf[dxn] = t0; buf[dxn+1] = t1; buf[dxn+2] = t2; \
367 for( k = 0; k < xofs_count; k++ ) \
369 int sxn = xofs[k].si; \
370 int dxn = xofs[k].di; \
371 float alpha = xofs[k].alpha; \
372 float t0 = buf[dxn] + load_macro(src[sxn])*alpha; \
373 float t1 = buf[dxn+1] + load_macro(src[sxn+1])*alpha; \
374 buf[dxn] = t0; buf[dxn+1] = t1; \
375 t0 = buf[dxn+2] + load_macro(src[sxn+2])*alpha; \
376 t1 = buf[dxn+3] + load_macro(src[sxn+3])*alpha; \
377 buf[dxn+2] = t0; buf[dxn+3] = t1; \
380 if( (cur_dy + 1)*scale_y <= sy + 1 || sy == ssize.height - 1 ) \
382 float beta = sy + 1 - (cur_dy+1)*scale_y, beta1; \
383 beta = MAX( beta, 0 ); \
385 if( fabs(beta) < 1e-3 ) \
386 for( dx = 0; dx < dsize.width; dx++ ) \
388 dst[dx] = (arrtype)cast_macro(sum[dx] + buf[dx]); \
389 sum[dx] = buf[dx] = 0; \
392 for( dx = 0; dx < dsize.width; dx++ ) \
394 dst[dx] = (arrtype)cast_macro(sum[dx] + buf[dx]*beta1); \
395 sum[dx] = buf[dx]*beta; \
402 for( dx = 0; dx < dsize.width; dx += 2 ) \
404 float t0 = sum[dx] + buf[dx]; \
405 float t1 = sum[dx+1] + buf[dx+1]; \
406 sum[dx] = t0; sum[dx+1] = t1; \
407 buf[dx] = buf[dx+1] = 0; \
415 #define ICV_DEF_RESIZE_BICUBIC_FUNC( flavor, arrtype, worktype, load_macro, \
416 cast_macro1, cast_macro2 ) \
417 static CvStatus CV_STDCALL \
418 icvResize_Bicubic_##flavor##_CnR( const arrtype* src, int srcstep, CvSize ssize,\
419 arrtype* dst, int dststep, CvSize dsize, \
420 int cn, int xmin, int xmax, \
421 const CvResizeAlpha* xofs, float** buf ) \
423 float scale_y = (float)ssize.height/dsize.height; \
424 int dx, dy, sx, sy, sy2, ify; \
427 xmin *= cn; xmax *= cn; \
430 srcstep /= sizeof(src[0]); \
431 dststep /= sizeof(dst[0]); \
433 for( dy = 0; dy < dsize.height; dy++, dst += dststep ) \
435 float w0, w1, w2, w3; \
437 float *row, *row0, *row1, *row2, *row3; \
443 ify = cvRound(fy*ICV_CUBIC_TAB_SIZE); \
446 if( sy2 > prev_sy2 ) \
448 int delta = prev_sy2 - sy + 2; \
449 for( k = 0; k < delta; k++ ) \
450 CV_SWAP( buf[k], buf[k+4-delta], row ); \
453 for( sy += k - 1; k < 4; k++, sy++ ) \
455 const arrtype* _src = src + sy*srcstep; \
460 if( sy >= ssize.height ) \
463 memcpy( row, buf[k-1], dsize.width*sizeof(row[0]) ); \
467 for( dx = 0; dx < xmin; dx++ ) \
469 int ifx = xofs[dx].ialpha, sx0 = xofs[dx].idx; \
471 while( sx >= ssize.width ) \
473 x = load_macro(_src[sx]); \
474 sum = x*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE - ifx)*2 + 1]; \
475 if( (unsigned)(sx = sx0 + cn) < (unsigned)ssize.width ) \
476 x = load_macro(_src[sx]); \
477 sum += x*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE - ifx)*2]; \
478 if( (unsigned)(sx = sx0) < (unsigned)ssize.width ) \
479 x = load_macro(_src[sx]); \
480 sum += x*icvCubicCoeffs[ifx*2]; \
481 if( (unsigned)(sx = sx0 - cn) < (unsigned)ssize.width ) \
482 x = load_macro(_src[sx]); \
483 row[dx] = sum + x*icvCubicCoeffs[ifx*2 + 1]; \
486 for( ; dx < xmax; dx++ ) \
488 int ifx = xofs[dx].ialpha; \
489 int sx0 = xofs[dx].idx; \
490 row[dx] = _src[sx0 - cn]*icvCubicCoeffs[ifx*2 + 1] + \
491 _src[sx0]*icvCubicCoeffs[ifx*2] + \
492 _src[sx0 + cn]*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2] + \
493 _src[sx0 + cn*2]*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2+1];\
496 for( ; dx < dsize.width; dx++ ) \
498 int ifx = xofs[dx].ialpha, sx0 = xofs[dx].idx; \
499 x = load_macro(_src[sx0 - cn]); \
500 sum = x*icvCubicCoeffs[ifx*2 + 1]; \
501 if( (unsigned)(sx = sx0) < (unsigned)ssize.width ) \
502 x = load_macro(_src[sx]); \
503 sum += x*icvCubicCoeffs[ifx*2]; \
504 if( (unsigned)(sx = sx0 + cn) < (unsigned)ssize.width ) \
505 x = load_macro(_src[sx]); \
506 sum += x*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE - ifx)*2]; \
507 if( (unsigned)(sx = sx0 + cn*2) < (unsigned)ssize.width ) \
508 x = load_macro(_src[sx]); \
509 row[dx] = sum + x*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2+1]; \
513 for( k1 = 0; k1 < k; k1++ ) \
514 memcpy( buf[k1], row, dsize.width*sizeof(row[0])); \
519 row0 = buf[0]; row1 = buf[1]; \
520 row2 = buf[2]; row3 = buf[3]; \
522 w0 = icvCubicCoeffs[ify*2+1]; \
523 w1 = icvCubicCoeffs[ify*2]; \
524 w2 = icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE - ify)*2]; \
525 w3 = icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE - ify)*2 + 1]; \
527 for( dx = 0; dx < dsize.width; dx++ ) \
529 worktype val = cast_macro1( row0[dx]*w0 + row1[dx]*w1 + \
530 row2[dx]*w2 + row3[dx]*w3 ); \
531 dst[dx] = cast_macro2(val); \
539 ICV_DEF_RESIZE_BILINEAR_FUNC( 8u, uchar, int, ialpha,
540 ICV_WARP_MUL_ONE_8U, ICV_WARP_DESCALE_8U )
541 ICV_DEF_RESIZE_BILINEAR_FUNC( 16u, ushort, float, alpha, CV_NOP, cvRound )
542 ICV_DEF_RESIZE_BILINEAR_FUNC( 32f, float, float, alpha, CV_NOP, CV_NOP )
544 ICV_DEF_RESIZE_BICUBIC_FUNC( 8u, uchar, int, CV_8TO32F, cvRound, CV_CAST_8U )
545 ICV_DEF_RESIZE_BICUBIC_FUNC( 16u, ushort, int, CV_NOP, cvRound, CV_CAST_16U )
546 ICV_DEF_RESIZE_BICUBIC_FUNC( 32f, float, float, CV_NOP, CV_NOP, CV_NOP )
548 ICV_DEF_RESIZE_AREA_FAST_FUNC( 8u, uchar, int, cvRound )
549 ICV_DEF_RESIZE_AREA_FAST_FUNC( 16u, ushort, int, cvRound )
550 ICV_DEF_RESIZE_AREA_FAST_FUNC( 32f, float, float, CV_NOP )
552 ICV_DEF_RESIZE_AREA_FUNC( 8u, uchar, CV_8TO32F, cvRound )
553 ICV_DEF_RESIZE_AREA_FUNC( 16u, ushort, CV_NOP, cvRound )
554 ICV_DEF_RESIZE_AREA_FUNC( 32f, float, CV_NOP, CV_NOP )
557 static void icvInitResizeTab( CvFuncTable* bilin_tab,
558 CvFuncTable* bicube_tab,
559 CvFuncTable* areafast_tab,
560 CvFuncTable* area_tab )
562 bilin_tab->fn_2d[CV_8U] = (void*)icvResize_Bilinear_8u_CnR;
563 bilin_tab->fn_2d[CV_16U] = (void*)icvResize_Bilinear_16u_CnR;
564 bilin_tab->fn_2d[CV_32F] = (void*)icvResize_Bilinear_32f_CnR;
566 bicube_tab->fn_2d[CV_8U] = (void*)icvResize_Bicubic_8u_CnR;
567 bicube_tab->fn_2d[CV_16U] = (void*)icvResize_Bicubic_16u_CnR;
568 bicube_tab->fn_2d[CV_32F] = (void*)icvResize_Bicubic_32f_CnR;
570 areafast_tab->fn_2d[CV_8U] = (void*)icvResize_AreaFast_8u_CnR;
571 areafast_tab->fn_2d[CV_16U] = (void*)icvResize_AreaFast_16u_CnR;
572 areafast_tab->fn_2d[CV_32F] = (void*)icvResize_AreaFast_32f_CnR;
574 area_tab->fn_2d[CV_8U] = (void*)icvResize_Area_8u_CnR;
575 area_tab->fn_2d[CV_16U] = (void*)icvResize_Area_16u_CnR;
576 area_tab->fn_2d[CV_32F] = (void*)icvResize_Area_32f_CnR;
580 typedef CvStatus (CV_STDCALL * CvResizeBilinearFunc)
581 ( const void* src, int srcstep, CvSize ssize,
582 void* dst, int dststep, CvSize dsize,
583 int cn, int xmax, const CvResizeAlpha* xofs,
584 const CvResizeAlpha* yofs, float* buf0, float* buf1 );
586 typedef CvStatus (CV_STDCALL * CvResizeBicubicFunc)
587 ( const void* src, int srcstep, CvSize ssize,
588 void* dst, int dststep, CvSize dsize,
589 int cn, int xmin, int xmax,
590 const CvResizeAlpha* xofs, float** buf );
592 typedef CvStatus (CV_STDCALL * CvResizeAreaFastFunc)
593 ( const void* src, int srcstep, CvSize ssize,
594 void* dst, int dststep, CvSize dsize,
595 int cn, const int* ofs, const int *xofs );
597 typedef CvStatus (CV_STDCALL * CvResizeAreaFunc)
598 ( const void* src, int srcstep, CvSize ssize,
599 void* dst, int dststep, CvSize dsize,
600 int cn, const CvDecimateAlpha* xofs,
601 int xofs_count, float* buf, float* sum );
604 ////////////////////////////////// IPP resize functions //////////////////////////////////
606 icvResize_8u_C1R_t icvResize_8u_C1R_p = 0;
607 icvResize_8u_C3R_t icvResize_8u_C3R_p = 0;
608 icvResize_8u_C4R_t icvResize_8u_C4R_p = 0;
609 icvResize_16u_C1R_t icvResize_16u_C1R_p = 0;
610 icvResize_16u_C3R_t icvResize_16u_C3R_p = 0;
611 icvResize_16u_C4R_t icvResize_16u_C4R_p = 0;
612 icvResize_32f_C1R_t icvResize_32f_C1R_p = 0;
613 icvResize_32f_C3R_t icvResize_32f_C3R_p = 0;
614 icvResize_32f_C4R_t icvResize_32f_C4R_p = 0;
616 typedef CvStatus (CV_STDCALL * CvResizeIPPFunc)
617 ( const void* src, CvSize srcsize, int srcstep, CvRect srcroi,
618 void* dst, int dststep, CvSize dstroi,
619 double xfactor, double yfactor, int interpolation );
621 //////////////////////////////////////////////////////////////////////////////////////////
624 cvResize( const CvArr* srcarr, CvArr* dstarr, int method )
626 static CvFuncTable bilin_tab, bicube_tab, areafast_tab, area_tab;
627 static int inittab = 0;
630 CV_FUNCNAME( "cvResize" );
634 CvMat srcstub, *src = (CvMat*)srcarr;
635 CvMat dststub, *dst = (CvMat*)dstarr;
637 float scale_x, scale_y;
638 int k, sx, sy, dx, dy;
641 CV_CALL( src = cvGetMat( srcarr, &srcstub ));
642 CV_CALL( dst = cvGetMat( dstarr, &dststub ));
644 if( CV_ARE_SIZES_EQ( src, dst ))
646 CV_CALL( cvCopy( src, dst ));
650 if( !CV_ARE_TYPES_EQ( src, dst ))
651 CV_ERROR( CV_StsUnmatchedFormats, "" );
655 icvInitResizeTab( &bilin_tab, &bicube_tab, &areafast_tab, &area_tab );
659 ssize = cvGetMatSize( src );
660 dsize = cvGetMatSize( dst );
661 type = CV_MAT_TYPE(src->type);
662 depth = CV_MAT_DEPTH(type);
663 cn = CV_MAT_CN(type);
664 scale_x = (float)ssize.width/dsize.width;
665 scale_y = (float)ssize.height/dsize.height;
667 if( method == CV_INTER_CUBIC &&
668 (MIN(ssize.width, dsize.width) <= 4 ||
669 MIN(ssize.height, dsize.height) <= 4) )
670 method = CV_INTER_LINEAR;
672 if( icvResize_8u_C1R_p &&
673 MIN(ssize.width, dsize.width) > 4 &&
674 MIN(ssize.height, dsize.height) > 4 )
676 CvResizeIPPFunc ipp_func =
677 type == CV_8UC1 ? icvResize_8u_C1R_p :
678 type == CV_8UC3 ? icvResize_8u_C3R_p :
679 type == CV_8UC4 ? icvResize_8u_C4R_p :
680 type == CV_16UC1 ? icvResize_16u_C1R_p :
681 type == CV_16UC3 ? icvResize_16u_C3R_p :
682 type == CV_16UC4 ? icvResize_16u_C4R_p :
683 type == CV_32FC1 ? icvResize_32f_C1R_p :
684 type == CV_32FC3 ? icvResize_32f_C3R_p :
685 type == CV_32FC4 ? icvResize_32f_C4R_p : 0;
686 if( ipp_func && (CV_INTER_NN < method && method < CV_INTER_AREA))
688 int srcstep = src->step ? src->step : CV_STUB_STEP;
689 int dststep = dst->step ? dst->step : CV_STUB_STEP;
690 IPPI_CALL( ipp_func( src->data.ptr, ssize, srcstep,
691 cvRect(0,0,ssize.width,ssize.height),
692 dst->data.ptr, dststep, dsize,
693 (double)dsize.width/ssize.width,
694 (double)dsize.height/ssize.height, 1 << method ));
699 if( method == CV_INTER_NN )
701 IPPI_CALL( icvResize_NN_8u_C1R( src->data.ptr, src->step, ssize,
702 dst->data.ptr, dst->step, dsize,
703 CV_ELEM_SIZE(src->type)));
705 else if( method == CV_INTER_LINEAR || method == CV_INTER_AREA )
707 if( method == CV_INTER_AREA &&
708 ssize.width >= dsize.width && ssize.height >= dsize.height )
710 // "area" method for (scale_x > 1 & scale_y > 1)
711 int iscale_x = cvRound(scale_x);
712 int iscale_y = cvRound(scale_y);
714 if( fabs(scale_x - iscale_x) < DBL_EPSILON &&
715 fabs(scale_y - iscale_y) < DBL_EPSILON )
717 int area = iscale_x*iscale_y;
718 int srcstep = src->step / CV_ELEM_SIZE(depth);
719 int* ofs = (int*)cvStackAlloc( (area + dsize.width*cn)*sizeof(int) );
720 int* xofs = ofs + area;
721 CvResizeAreaFastFunc func = (CvResizeAreaFastFunc)areafast_tab.fn_2d[depth];
724 CV_ERROR( CV_StsUnsupportedFormat, "" );
726 for( sy = 0, k = 0; sy < iscale_y; sy++ )
727 for( sx = 0; sx < iscale_x; sx++ )
728 ofs[k++] = sy*srcstep + sx*cn;
730 for( dx = 0; dx < dsize.width; dx++ )
733 for( k = 0; k < cn; k++ )
734 xofs[dx*cn + k] = sx + k;
737 IPPI_CALL( func( src->data.ptr, src->step, ssize, dst->data.ptr,
738 dst->step, dsize, cn, ofs, xofs ));
742 int buf_len = dsize.width*cn + 4, buf_size, xofs_count = 0;
743 float scale = 1.f/(scale_x*scale_y);
745 CvDecimateAlpha* xofs;
746 CvResizeAreaFunc func = (CvResizeAreaFunc)area_tab.fn_2d[depth];
748 if( !func || cn > 4 )
749 CV_ERROR( CV_StsUnsupportedFormat, "" );
751 buf_size = buf_len*2*sizeof(float) + ssize.width*2*sizeof(CvDecimateAlpha);
752 if( buf_size < CV_MAX_LOCAL_SIZE )
753 buf = (float*)cvStackAlloc(buf_size);
755 CV_CALL( temp_buf = buf = (float*)cvAlloc(buf_size));
757 xofs = (CvDecimateAlpha*)(sum + buf_len);
759 for( dx = 0, k = 0; dx < dsize.width; dx++ )
761 float fsx1 = dx*scale_x, fsx2 = fsx1 + scale_x;
762 int sx1 = cvCeil(fsx1), sx2 = cvFloor(fsx2);
764 assert( (unsigned)sx1 < (unsigned)ssize.width );
768 assert( k < ssize.width*2 );
770 xofs[k].si = (sx1-1)*cn;
771 xofs[k++].alpha = (sx1 - fsx1)*scale;
774 for( sx = sx1; sx < sx2; sx++ )
776 assert( k < ssize.width*2 );
779 xofs[k++].alpha = scale;
782 if( fsx2 - sx2 > 1e-3 )
784 assert( k < ssize.width*2 );
785 assert((unsigned)sx2 < (unsigned)ssize.width );
788 xofs[k++].alpha = (fsx2 - sx2)*scale;
793 memset( sum, 0, buf_len*sizeof(float) );
794 memset( buf, 0, buf_len*sizeof(float) );
796 IPPI_CALL( func( src->data.ptr, src->step, ssize, dst->data.ptr,
797 dst->step, dsize, cn, xofs, xofs_count, buf, sum ));
800 else // true "area" method for the cases (scale_x > 1 & scale_y < 1) and
801 // (scale_x < 1 & scale_y > 1) is not implemented.
802 // instead, it is emulated via some variant of bilinear interpolation.
804 float inv_scale_x = (float)dsize.width/ssize.width;
805 float inv_scale_y = (float)dsize.height/ssize.height;
806 int xmax = dsize.width, width = dsize.width*cn, buf_size;
808 CvResizeAlpha *xofs, *yofs;
809 int area_mode = method == CV_INTER_AREA;
811 CvResizeBilinearFunc func = (CvResizeBilinearFunc)bilin_tab.fn_2d[depth];
814 CV_ERROR( CV_StsUnsupportedFormat, "" );
816 buf_size = width*2*sizeof(float) + (width + dsize.height)*sizeof(CvResizeAlpha);
817 if( buf_size < CV_MAX_LOCAL_SIZE )
818 buf0 = (float*)cvStackAlloc(buf_size);
820 CV_CALL( temp_buf = buf0 = (float*)cvAlloc(buf_size));
822 xofs = (CvResizeAlpha*)(buf1 + width);
825 for( dx = 0; dx < dsize.width; dx++ )
829 fx = (float)((dx+0.5)*scale_x - 0.5);
835 sx = cvFloor(dx*scale_x);
836 fx = (dx+1) - (sx+1)*inv_scale_x;
837 fx = fx <= 0 ? 0.f : fx - cvFloor(fx);
843 if( sx >= ssize.width-1 )
845 fx = 0, sx = ssize.width-1;
846 if( xmax >= dsize.width )
851 for( k = 0, sx *= cn; k < cn; k++ )
852 xofs[dx*cn + k].idx = sx + k, xofs[dx*cn + k].alpha = fx;
854 for( k = 0, sx *= cn; k < cn; k++ )
855 xofs[dx*cn + k].idx = sx + k,
856 xofs[dx*cn + k].ialpha = CV_FLT_TO_FIX(fx, ICV_WARP_SHIFT);
859 for( dy = 0; dy < dsize.height; dy++ )
863 fy = (float)((dy+0.5)*scale_y - 0.5);
871 sy = cvFloor(dy*scale_y);
872 fy = (dy+1) - (sy+1)*inv_scale_y;
873 fy = fy <= 0 ? 0.f : fy - cvFloor(fy);
880 yofs[dy].ialpha = CV_FLT_TO_FIX(fy, ICV_WARP_SHIFT);
883 IPPI_CALL( func( src->data.ptr, src->step, ssize, dst->data.ptr,
884 dst->step, dsize, cn, xmax, xofs, yofs, buf0, buf1 ));
887 else if( method == CV_INTER_CUBIC )
889 int width = dsize.width*cn, buf_size;
890 int xmin = dsize.width, xmax = -1;
893 CvResizeBicubicFunc func = (CvResizeBicubicFunc)bicube_tab.fn_2d[depth];
896 CV_ERROR( CV_StsUnsupportedFormat, "" );
898 buf_size = width*(4*sizeof(float) + sizeof(xofs[0]));
899 if( buf_size < CV_MAX_LOCAL_SIZE )
900 buf[0] = (float*)cvStackAlloc(buf_size);
902 CV_CALL( temp_buf = buf[0] = (float*)cvAlloc(buf_size));
904 for( k = 1; k < 4; k++ )
905 buf[k] = buf[k-1] + width;
906 xofs = (CvResizeAlpha*)(buf[3] + width);
908 icvInitCubicCoeffTab();
910 for( dx = 0; dx < dsize.width; dx++ )
912 float fx = dx*scale_x;
915 int ifx = cvRound(fx*ICV_CUBIC_TAB_SIZE);
916 if( sx-1 >= 0 && xmin > dx )
918 if( sx+2 < ssize.width )
921 // at least one of 4 points should be within the image - to
922 // be able to set other points to the same value. see the loops
923 // for( dx = 0; dx < xmin; dx++ ) ... and for( ; dx < width; dx++ ) ...
926 else if( sx > ssize.width )
929 for( k = 0; k < cn; k++ )
931 xofs[dx*cn + k].idx = sx*cn + k;
932 xofs[dx*cn + k].ialpha = ifx;
936 IPPI_CALL( func( src->data.ptr, src->step, ssize, dst->data.ptr,
937 dst->step, dsize, cn, xmin, xmax, xofs, buf ));
940 CV_ERROR( CV_StsBadFlag, "Unknown/unsupported interpolation method" );
948 /****************************************************************************************\
950 \****************************************************************************************/
952 #define ICV_DEF_WARP_AFFINE_BILINEAR_FUNC( flavor, arrtype, worktype, \
953 scale_alpha_macro, mul_one_macro, descale_macro, cast_macro ) \
954 static CvStatus CV_STDCALL \
955 icvWarpAffine_Bilinear_##flavor##_CnR( \
956 const arrtype* src, int step, CvSize ssize, \
957 arrtype* dst, int dststep, CvSize dsize, \
958 const double* matrix, int cn, \
959 const arrtype* fillval, const int* ofs ) \
962 double A12 = matrix[1], b1 = matrix[2]; \
963 double A22 = matrix[4], b2 = matrix[5]; \
965 step /= sizeof(src[0]); \
966 dststep /= sizeof(dst[0]); \
968 for( y = 0; y < dsize.height; y++, dst += dststep ) \
970 int xs = CV_FLT_TO_FIX( A12*y + b1, ICV_WARP_SHIFT ); \
971 int ys = CV_FLT_TO_FIX( A22*y + b2, ICV_WARP_SHIFT ); \
973 for( x = 0; x < dsize.width; x++ ) \
975 int ixs = xs + ofs[x*2]; \
976 int iys = ys + ofs[x*2+1]; \
977 worktype a = scale_alpha_macro( ixs & ICV_WARP_MASK ); \
978 worktype b = scale_alpha_macro( iys & ICV_WARP_MASK ); \
980 ixs >>= ICV_WARP_SHIFT; \
981 iys >>= ICV_WARP_SHIFT; \
983 if( (unsigned)ixs < (unsigned)(ssize.width - 1) && \
984 (unsigned)iys < (unsigned)(ssize.height - 1) ) \
986 const arrtype* ptr = src + step*iys + ixs*cn; \
988 for( k = 0; k < cn; k++ ) \
990 p0 = mul_one_macro(ptr[k]) + \
991 a * (ptr[k+cn] - ptr[k]); \
992 p1 = mul_one_macro(ptr[k+step]) + \
993 a * (ptr[k+cn+step] - ptr[k+step]); \
994 p0 = descale_macro(mul_one_macro(p0) + b*(p1 - p0)); \
995 dst[x*cn+k] = (arrtype)cast_macro(p0); \
998 else if( (unsigned)(ixs+1) < (unsigned)(ssize.width+1) && \
999 (unsigned)(iys+1) < (unsigned)(ssize.height+1)) \
1001 int x0 = ICV_WARP_CLIP_X( ixs ); \
1002 int y0 = ICV_WARP_CLIP_Y( iys ); \
1003 int x1 = ICV_WARP_CLIP_X( ixs + 1 ); \
1004 int y1 = ICV_WARP_CLIP_Y( iys + 1 ); \
1005 const arrtype* ptr0, *ptr1, *ptr2, *ptr3; \
1007 ptr0 = src + y0*step + x0*cn; \
1008 ptr1 = src + y0*step + x1*cn; \
1009 ptr2 = src + y1*step + x0*cn; \
1010 ptr3 = src + y1*step + x1*cn; \
1012 for( k = 0; k < cn; k++ ) \
1014 p0 = mul_one_macro(ptr0[k]) + a * (ptr1[k] - ptr0[k]); \
1015 p1 = mul_one_macro(ptr2[k]) + a * (ptr3[k] - ptr2[k]); \
1016 p0 = descale_macro( mul_one_macro(p0) + b*(p1 - p0) ); \
1017 dst[x*cn+k] = (arrtype)cast_macro(p0); \
1020 else if( fillval ) \
1021 for( k = 0; k < cn; k++ ) \
1022 dst[x*cn+k] = fillval[k]; \
1030 #define ICV_WARP_SCALE_ALPHA(x) ((x)*(1./(ICV_WARP_MASK+1)))
1032 ICV_DEF_WARP_AFFINE_BILINEAR_FUNC( 8u, uchar, int, CV_NOP, ICV_WARP_MUL_ONE_8U,
1033 ICV_WARP_DESCALE_8U, CV_NOP )
1034 //ICV_DEF_WARP_AFFINE_BILINEAR_FUNC( 8u, uchar, double, ICV_WARP_SCALE_ALPHA, CV_NOP,
1035 // CV_NOP, ICV_WARP_CAST_8U )
1036 ICV_DEF_WARP_AFFINE_BILINEAR_FUNC( 16u, ushort, double, ICV_WARP_SCALE_ALPHA, CV_NOP,
1038 ICV_DEF_WARP_AFFINE_BILINEAR_FUNC( 32f, float, double, ICV_WARP_SCALE_ALPHA, CV_NOP,
1042 typedef CvStatus (CV_STDCALL * CvWarpAffineFunc)(
1043 const void* src, int srcstep, CvSize ssize,
1044 void* dst, int dststep, CvSize dsize,
1045 const double* matrix, int cn,
1046 const void* fillval, const int* ofs );
1048 static void icvInitWarpAffineTab( CvFuncTable* bilin_tab )
1050 bilin_tab->fn_2d[CV_8U] = (void*)icvWarpAffine_Bilinear_8u_CnR;
1051 bilin_tab->fn_2d[CV_16U] = (void*)icvWarpAffine_Bilinear_16u_CnR;
1052 bilin_tab->fn_2d[CV_32F] = (void*)icvWarpAffine_Bilinear_32f_CnR;
1056 /////////////////////////////// IPP warpaffine functions /////////////////////////////////
1058 icvWarpAffineBack_8u_C1R_t icvWarpAffineBack_8u_C1R_p = 0;
1059 icvWarpAffineBack_8u_C3R_t icvWarpAffineBack_8u_C3R_p = 0;
1060 icvWarpAffineBack_8u_C4R_t icvWarpAffineBack_8u_C4R_p = 0;
1061 icvWarpAffineBack_32f_C1R_t icvWarpAffineBack_32f_C1R_p = 0;
1062 icvWarpAffineBack_32f_C3R_t icvWarpAffineBack_32f_C3R_p = 0;
1063 icvWarpAffineBack_32f_C4R_t icvWarpAffineBack_32f_C4R_p = 0;
1065 typedef CvStatus (CV_STDCALL * CvWarpAffineBackIPPFunc)
1066 ( const void* src, CvSize srcsize, int srcstep, CvRect srcroi,
1067 void* dst, int dststep, CvRect dstroi,
1068 const double* coeffs, int interpolation );
1070 //////////////////////////////////////////////////////////////////////////////////////////
1073 cvWarpAffine( const CvArr* srcarr, CvArr* dstarr, const CvMat* matrix,
1074 int flags, CvScalar fillval )
1076 static CvFuncTable bilin_tab;
1077 static int inittab = 0;
1079 CV_FUNCNAME( "cvWarpAffine" );
1083 CvMat srcstub, *src = (CvMat*)srcarr;
1084 CvMat dststub, *dst = (CvMat*)dstarr;
1085 int k, type, depth, cn, *ofs = 0;
1086 double src_matrix[6], dst_matrix[6];
1088 int method = flags & 3;
1089 CvMat srcAb = cvMat( 2, 3, CV_64F, src_matrix ),
1090 dstAb = cvMat( 2, 3, CV_64F, dst_matrix ),
1092 CvWarpAffineFunc func;
1093 CvSize ssize, dsize;
1097 icvInitWarpAffineTab( &bilin_tab );
1101 CV_CALL( src = cvGetMat( srcarr, &srcstub ));
1102 CV_CALL( dst = cvGetMat( dstarr, &dststub ));
1104 if( !CV_ARE_TYPES_EQ( src, dst ))
1105 CV_ERROR( CV_StsUnmatchedFormats, "" );
1107 if( !CV_IS_MAT(matrix) || CV_MAT_CN(matrix->type) != 1 ||
1108 CV_MAT_DEPTH(matrix->type) < CV_32F || matrix->rows != 2 || matrix->cols != 3 )
1109 CV_ERROR( CV_StsBadArg,
1110 "Transformation matrix should be 2x3 floating-point single-channel matrix" );
1112 if( flags & CV_WARP_INVERSE_MAP )
1113 cvConvertScale( matrix, &dstAb );
1116 // [R|t] -> [R^-1 | -(R^-1)*t]
1117 cvConvertScale( matrix, &srcAb );
1118 cvGetCols( &srcAb, &A, 0, 2 );
1119 cvGetCol( &srcAb, &b, 2 );
1120 cvGetCols( &dstAb, &invA, 0, 2 );
1121 cvGetCol( &dstAb, &invAb, 2 );
1122 cvInvert( &A, &invA, CV_SVD );
1123 cvGEMM( &invA, &b, -1, 0, 0, &invAb );
1126 type = CV_MAT_TYPE(src->type);
1127 depth = CV_MAT_DEPTH(type);
1128 cn = CV_MAT_CN(type);
1130 CV_ERROR( CV_BadNumChannels, "" );
1132 ssize = cvGetMatSize(src);
1133 dsize = cvGetMatSize(dst);
1135 if( icvWarpAffineBack_8u_C1R_p && MIN( ssize.width, dsize.width ) >= 4 &&
1136 MIN( ssize.height, dsize.height ) >= 4 )
1138 CvWarpAffineBackIPPFunc ipp_func =
1139 type == CV_8UC1 ? icvWarpAffineBack_8u_C1R_p :
1140 type == CV_8UC3 ? icvWarpAffineBack_8u_C3R_p :
1141 type == CV_8UC4 ? icvWarpAffineBack_8u_C4R_p :
1142 type == CV_32FC1 ? icvWarpAffineBack_32f_C1R_p :
1143 type == CV_32FC3 ? icvWarpAffineBack_32f_C3R_p :
1144 type == CV_32FC4 ? icvWarpAffineBack_32f_C4R_p : 0;
1146 if( ipp_func && CV_INTER_NN <= method && method <= CV_INTER_AREA )
1148 int srcstep = src->step ? src->step : CV_STUB_STEP;
1149 int dststep = dst->step ? dst->step : CV_STUB_STEP;
1150 CvRect srcroi = {0, 0, ssize.width, ssize.height};
1151 CvRect dstroi = {0, 0, dsize.width, dsize.height};
1153 // this is not the most efficient way to fill outliers
1154 if( flags & CV_WARP_FILL_OUTLIERS )
1155 cvSet( dst, fillval );
1157 if( ipp_func( src->data.ptr, ssize, srcstep, srcroi,
1158 dst->data.ptr, dststep, dstroi,
1159 dstAb.data.db, 1 << method ) >= 0 )
1164 cvScalarToRawData( &fillval, fillbuf, CV_MAT_TYPE(src->type), 0 );
1165 ofs = (int*)cvStackAlloc( dst->cols*2*sizeof(ofs[0]) );
1166 for( k = 0; k < dst->cols; k++ )
1168 ofs[2*k] = CV_FLT_TO_FIX( dst_matrix[0]*k, ICV_WARP_SHIFT );
1169 ofs[2*k+1] = CV_FLT_TO_FIX( dst_matrix[3]*k, ICV_WARP_SHIFT );
1172 /*if( method == CV_INTER_LINEAR )*/
1174 func = (CvWarpAffineFunc)bilin_tab.fn_2d[depth];
1176 CV_ERROR( CV_StsUnsupportedFormat, "" );
1178 IPPI_CALL( func( src->data.ptr, src->step, ssize, dst->data.ptr,
1179 dst->step, dsize, dst_matrix, cn,
1180 flags & CV_WARP_FILL_OUTLIERS ? fillbuf : 0, ofs ));
1188 cv2DRotationMatrix( CvPoint2D32f center, double angle,
1189 double scale, CvMat* matrix )
1191 CV_FUNCNAME( "cvGetRotationMatrix" );
1196 CvMat M = cvMat( 2, 3, CV_64FC1, m );
1200 CV_ERROR( CV_StsNullPtr, "" );
1203 alpha = cos(angle)*scale;
1204 beta = sin(angle)*scale;
1208 m[0][2] = (1-alpha)*center.x - beta*center.y;
1211 m[1][2] = beta*center.x + (1-alpha)*center.y;
1213 cvConvert( &M, matrix );
1221 /****************************************************************************************\
1223 \****************************************************************************************/
1225 #define ICV_DEF_WARP_PERSPECTIVE_BILINEAR_FUNC( flavor, arrtype, load_macro, cast_macro )\
1226 static CvStatus CV_STDCALL \
1227 icvWarpPerspective_Bilinear_##flavor##_CnR( \
1228 const arrtype* src, int step, CvSize ssize, \
1229 arrtype* dst, int dststep, CvSize dsize, \
1230 const double* matrix, int cn, \
1231 const arrtype* fillval ) \
1234 float A11 = (float)matrix[0], A12 = (float)matrix[1], A13 = (float)matrix[2];\
1235 float A21 = (float)matrix[3], A22 = (float)matrix[4], A23 = (float)matrix[5];\
1236 float A31 = (float)matrix[6], A32 = (float)matrix[7], A33 = (float)matrix[8];\
1238 step /= sizeof(src[0]); \
1239 dststep /= sizeof(dst[0]); \
1241 for( y = 0; y < dsize.height; y++, dst += dststep ) \
1243 float xs0 = A12*y + A13; \
1244 float ys0 = A22*y + A23; \
1245 float ws = A32*y + A33; \
1247 for( x = 0; x < dsize.width; x++, xs0 += A11, ys0 += A21, ws += A31 )\
1249 float inv_ws = 1.f/ws; \
1250 float xs = xs0*inv_ws; \
1251 float ys = ys0*inv_ws; \
1252 int ixs = cvFloor(xs); \
1253 int iys = cvFloor(ys); \
1254 float a = xs - ixs; \
1255 float b = ys - iys; \
1258 if( (unsigned)ixs < (unsigned)(ssize.width - 1) && \
1259 (unsigned)iys < (unsigned)(ssize.height - 1) ) \
1261 const arrtype* ptr = src + step*iys + ixs*cn; \
1263 for( k = 0; k < cn; k++ ) \
1265 p0 = load_macro(ptr[k]) + \
1266 a * (load_macro(ptr[k+cn]) - load_macro(ptr[k])); \
1267 p1 = load_macro(ptr[k+step]) + \
1268 a * (load_macro(ptr[k+cn+step]) - \
1269 load_macro(ptr[k+step])); \
1270 dst[x*cn+k] = (arrtype)cast_macro(p0 + b*(p1 - p0)); \
1273 else if( (unsigned)(ixs+1) < (unsigned)(ssize.width+1) && \
1274 (unsigned)(iys+1) < (unsigned)(ssize.height+1)) \
1276 int x0 = ICV_WARP_CLIP_X( ixs ); \
1277 int y0 = ICV_WARP_CLIP_Y( iys ); \
1278 int x1 = ICV_WARP_CLIP_X( ixs + 1 ); \
1279 int y1 = ICV_WARP_CLIP_Y( iys + 1 ); \
1280 const arrtype* ptr0, *ptr1, *ptr2, *ptr3; \
1282 ptr0 = src + y0*step + x0*cn; \
1283 ptr1 = src + y0*step + x1*cn; \
1284 ptr2 = src + y1*step + x0*cn; \
1285 ptr3 = src + y1*step + x1*cn; \
1287 for( k = 0; k < cn; k++ ) \
1289 p0 = load_macro(ptr0[k]) + \
1290 a * (load_macro(ptr1[k]) - load_macro(ptr0[k])); \
1291 p1 = load_macro(ptr2[k]) + \
1292 a * (load_macro(ptr3[k]) - load_macro(ptr2[k])); \
1293 dst[x*cn+k] = (arrtype)cast_macro(p0 + b*(p1 - p0)); \
1296 else if( fillval ) \
1297 for( k = 0; k < cn; k++ ) \
1298 dst[x*cn+k] = fillval[k]; \
1306 #define ICV_WARP_SCALE_ALPHA(x) ((x)*(1./(ICV_WARP_MASK+1)))
1308 ICV_DEF_WARP_PERSPECTIVE_BILINEAR_FUNC( 8u, uchar, CV_8TO32F, cvRound )
1309 ICV_DEF_WARP_PERSPECTIVE_BILINEAR_FUNC( 16u, ushort, CV_NOP, cvRound )
1310 ICV_DEF_WARP_PERSPECTIVE_BILINEAR_FUNC( 32f, float, CV_NOP, CV_NOP )
1312 typedef CvStatus (CV_STDCALL * CvWarpPerspectiveFunc)(
1313 const void* src, int srcstep, CvSize ssize,
1314 void* dst, int dststep, CvSize dsize,
1315 const double* matrix, int cn, const void* fillval );
1317 static void icvInitWarpPerspectiveTab( CvFuncTable* bilin_tab )
1319 bilin_tab->fn_2d[CV_8U] = (void*)icvWarpPerspective_Bilinear_8u_CnR;
1320 bilin_tab->fn_2d[CV_16U] = (void*)icvWarpPerspective_Bilinear_16u_CnR;
1321 bilin_tab->fn_2d[CV_32F] = (void*)icvWarpPerspective_Bilinear_32f_CnR;
1325 /////////////////////////// IPP warpperspective functions ////////////////////////////////
1327 icvWarpPerspectiveBack_8u_C1R_t icvWarpPerspectiveBack_8u_C1R_p = 0;
1328 icvWarpPerspectiveBack_8u_C3R_t icvWarpPerspectiveBack_8u_C3R_p = 0;
1329 icvWarpPerspectiveBack_8u_C4R_t icvWarpPerspectiveBack_8u_C4R_p = 0;
1330 icvWarpPerspectiveBack_32f_C1R_t icvWarpPerspectiveBack_32f_C1R_p = 0;
1331 icvWarpPerspectiveBack_32f_C3R_t icvWarpPerspectiveBack_32f_C3R_p = 0;
1332 icvWarpPerspectiveBack_32f_C4R_t icvWarpPerspectiveBack_32f_C4R_p = 0;
1334 icvWarpPerspective_8u_C1R_t icvWarpPerspective_8u_C1R_p = 0;
1335 icvWarpPerspective_8u_C3R_t icvWarpPerspective_8u_C3R_p = 0;
1336 icvWarpPerspective_8u_C4R_t icvWarpPerspective_8u_C4R_p = 0;
1337 icvWarpPerspective_32f_C1R_t icvWarpPerspective_32f_C1R_p = 0;
1338 icvWarpPerspective_32f_C3R_t icvWarpPerspective_32f_C3R_p = 0;
1339 icvWarpPerspective_32f_C4R_t icvWarpPerspective_32f_C4R_p = 0;
1341 typedef CvStatus (CV_STDCALL * CvWarpPerspectiveBackIPPFunc)
1342 ( const void* src, CvSize srcsize, int srcstep, CvRect srcroi,
1343 void* dst, int dststep, CvRect dstroi,
1344 const double* coeffs, int interpolation );
1346 //////////////////////////////////////////////////////////////////////////////////////////
1349 cvWarpPerspective( const CvArr* srcarr, CvArr* dstarr,
1350 const CvMat* matrix, int flags, CvScalar fillval )
1352 static CvFuncTable bilin_tab;
1353 static int inittab = 0;
1355 CV_FUNCNAME( "cvWarpPerspective" );
1359 CvMat srcstub, *src = (CvMat*)srcarr;
1360 CvMat dststub, *dst = (CvMat*)dstarr;
1361 int type, depth, cn;
1362 int method = flags & 3;
1363 double src_matrix[9], dst_matrix[9];
1365 CvMat A = cvMat( 3, 3, CV_64F, src_matrix ),
1366 invA = cvMat( 3, 3, CV_64F, dst_matrix );
1367 CvWarpPerspectiveFunc func;
1368 CvSize ssize, dsize;
1370 if( method == CV_INTER_NN || method == CV_INTER_AREA )
1371 method = CV_INTER_LINEAR;
1375 icvInitWarpPerspectiveTab( &bilin_tab );
1379 CV_CALL( src = cvGetMat( srcarr, &srcstub ));
1380 CV_CALL( dst = cvGetMat( dstarr, &dststub ));
1382 if( !CV_ARE_TYPES_EQ( src, dst ))
1383 CV_ERROR( CV_StsUnmatchedFormats, "" );
1385 if( !CV_IS_MAT(matrix) || CV_MAT_CN(matrix->type) != 1 ||
1386 CV_MAT_DEPTH(matrix->type) < CV_32F || matrix->rows != 3 || matrix->cols != 3 )
1387 CV_ERROR( CV_StsBadArg,
1388 "Transformation matrix should be 3x3 floating-point single-channel matrix" );
1390 if( flags & CV_WARP_INVERSE_MAP )
1391 cvConvertScale( matrix, &invA );
1394 cvConvertScale( matrix, &A );
1395 cvInvert( &A, &invA, CV_SVD );
1398 type = CV_MAT_TYPE(src->type);
1399 depth = CV_MAT_DEPTH(type);
1400 cn = CV_MAT_CN(type);
1402 CV_ERROR( CV_BadNumChannels, "" );
1404 ssize = cvGetMatSize(src);
1405 dsize = cvGetMatSize(dst);
1407 if( icvWarpPerspectiveBack_8u_C1R_p )
1409 CvWarpPerspectiveBackIPPFunc ipp_func =
1410 type == CV_8UC1 ? icvWarpPerspectiveBack_8u_C1R_p :
1411 type == CV_8UC3 ? icvWarpPerspectiveBack_8u_C3R_p :
1412 type == CV_8UC4 ? icvWarpPerspectiveBack_8u_C4R_p :
1413 type == CV_32FC1 ? icvWarpPerspectiveBack_32f_C1R_p :
1414 type == CV_32FC3 ? icvWarpPerspectiveBack_32f_C3R_p :
1415 type == CV_32FC4 ? icvWarpPerspectiveBack_32f_C4R_p : 0;
1417 if( ipp_func && CV_INTER_NN <= method && method <= CV_INTER_AREA &&
1418 MIN(ssize.width,ssize.height) >= 4 && MIN(dsize.width,dsize.height) >= 4 )
1420 int srcstep = src->step ? src->step : CV_STUB_STEP;
1421 int dststep = dst->step ? dst->step : CV_STUB_STEP;
1423 CvRect srcroi = {0, 0, ssize.width, ssize.height};
1424 CvRect dstroi = {0, 0, dsize.width, dsize.height};
1426 // this is not the most efficient way to fill outliers
1427 if( flags & CV_WARP_FILL_OUTLIERS )
1428 cvSet( dst, fillval );
1430 status = ipp_func( src->data.ptr, ssize, srcstep, srcroi,
1431 dst->data.ptr, dststep, dstroi,
1432 invA.data.db, 1 << method );
1436 ipp_func = type == CV_8UC1 ? icvWarpPerspective_8u_C1R_p :
1437 type == CV_8UC3 ? icvWarpPerspective_8u_C3R_p :
1438 type == CV_8UC4 ? icvWarpPerspective_8u_C4R_p :
1439 type == CV_32FC1 ? icvWarpPerspective_32f_C1R_p :
1440 type == CV_32FC3 ? icvWarpPerspective_32f_C3R_p :
1441 type == CV_32FC4 ? icvWarpPerspective_32f_C4R_p : 0;
1445 if( flags & CV_WARP_INVERSE_MAP )
1446 cvInvert( &invA, &A, CV_SVD );
1448 status = ipp_func( src->data.ptr, ssize, srcstep, srcroi,
1449 dst->data.ptr, dststep, dstroi,
1450 A.data.db, 1 << method );
1457 cvScalarToRawData( &fillval, fillbuf, CV_MAT_TYPE(src->type), 0 );
1459 /*if( method == CV_INTER_LINEAR )*/
1461 func = (CvWarpPerspectiveFunc)bilin_tab.fn_2d[depth];
1463 CV_ERROR( CV_StsUnsupportedFormat, "" );
1465 IPPI_CALL( func( src->data.ptr, src->step, ssize, dst->data.ptr,
1466 dst->step, dsize, dst_matrix, cn,
1467 flags & CV_WARP_FILL_OUTLIERS ? fillbuf : 0 ));
1474 /* Calculates coefficients of perspective transformation
1475 * which maps (xi,yi) to (ui,vi), (i=1,2,3,4):
1477 * c00*xi + c01*yi + c02
1478 * ui = ---------------------
1479 * c20*xi + c21*yi + c22
1481 * c10*xi + c11*yi + c12
1482 * vi = ---------------------
1483 * c20*xi + c21*yi + c22
1485 * Coefficients are calculated by solving linear system:
1486 * / x0 y0 1 0 0 0 -x0*u0 -y0*u0 \ /c00\ /u0\
1487 * | x1 y1 1 0 0 0 -x1*u1 -y1*u1 | |c01| |u1|
1488 * | x2 y2 1 0 0 0 -x2*u2 -y2*u2 | |c02| |u2|
1489 * | x3 y3 1 0 0 0 -x3*u3 -y3*u3 |.|c10|=|u3|,
1490 * | 0 0 0 x0 y0 1 -x0*v0 -y0*v0 | |c11| |v0|
1491 * | 0 0 0 x1 y1 1 -x1*v1 -y1*v1 | |c12| |v1|
1492 * | 0 0 0 x2 y2 1 -x2*v2 -y2*v2 | |c20| |v2|
1493 * \ 0 0 0 x3 y3 1 -x3*v3 -y3*v3 / \c21/ \v3/
1496 * cij - matrix coefficients, c22 = 1
1499 cvGetPerspectiveTransform( const CvPoint2D32f* src,
1500 const CvPoint2D32f* dst,
1503 CV_FUNCNAME( "cvGetPerspectiveTransform" );
1510 CvMat A = cvMat( 8, 8, CV_64FC1, a );
1511 CvMat B = cvMat( 8, 1, CV_64FC1, b );
1512 CvMat X = cvMat( 8, 1, CV_64FC1, x );
1516 if( !src || !dst || !matrix )
1517 CV_ERROR( CV_StsNullPtr, "" );
1519 for( i = 0; i < 4; ++i )
1521 a[i][0] = a[i+4][3] = src[i].x;
1522 a[i][1] = a[i+4][4] = src[i].y;
1523 a[i][2] = a[i+4][5] = 1;
1524 a[i][3] = a[i][4] = a[i][5] =
1525 a[i+4][0] = a[i+4][1] = a[i+4][2] = 0;
1526 a[i][6] = -src[i].x*dst[i].x;
1527 a[i][7] = -src[i].y*dst[i].x;
1528 a[i+4][6] = -src[i].x*dst[i].y;
1529 a[i+4][7] = -src[i].y*dst[i].y;
1534 cvSolve( &A, &B, &X, CV_SVD );
1537 X = cvMat( 3, 3, CV_64FC1, x );
1538 cvConvert( &X, matrix );
1545 /* Calculates coefficients of affine transformation
1546 * which maps (xi,yi) to (ui,vi), (i=1,2,3):
1548 * ui = c00*xi + c01*yi + c02
1550 * vi = c10*xi + c11*yi + c12
1552 * Coefficients are calculated by solving linear system:
1553 * / x0 y0 1 0 0 0 \ /c00\ /u0\
1554 * | x1 y1 1 0 0 0 | |c01| |u1|
1555 * | x2 y2 1 0 0 0 | |c02| |u2|
1556 * | 0 0 0 x0 y0 1 | |c10| |v0|
1557 * | 0 0 0 x1 y1 1 | |c11| |v1|
1558 * \ 0 0 0 x2 y2 1 / |c12| |v2|
1561 * cij - matrix coefficients
1564 cvGetAffineTransform( const CvPoint2D32f * src, const CvPoint2D32f * dst, CvMat * map_matrix )
1566 CV_FUNCNAME( "cvGetAffineTransform" );
1576 cvInitMatHeader(&mA, 6, 6, CV_64F, A);
1577 cvInitMatHeader(&mB, 6, 1, CV_64F, B);
1578 cvInitMatHeader(&mX, 6, 1, CV_64F, x);
1580 if( !src || !dst || !map_matrix )
1581 CV_ERROR( CV_StsNullPtr, "" );
1583 for( i = 0; i < 3; i++ )
1587 A[j] = A[k+3] = src[i].x;
1588 A[j+1] = A[k+4] = src[i].y;
1589 A[j+2] = A[k+5] = 1;
1590 A[j+3] = A[j+4] = A[j+5] = 0;
1591 A[k] = A[k+1] = A[k+2] = 0;
1593 B[i*2+1] = dst[i].y;
1595 cvSolve(&mA, &mB, &mX);
1597 mX = cvMat( 2, 3, CV_64FC1, x );
1598 cvConvert( &mX, map_matrix );
1604 /****************************************************************************************\
1605 * Generic Geometric Transformation: Remap *
1606 \****************************************************************************************/
1608 #define ICV_DEF_REMAP_BILINEAR_FUNC( flavor, arrtype, load_macro, cast_macro ) \
1609 static CvStatus CV_STDCALL \
1610 icvRemap_Bilinear_##flavor##_CnR( const arrtype* src, int srcstep, CvSize ssize,\
1611 arrtype* dst, int dststep, CvSize dsize, \
1612 const float* mapx, int mxstep, \
1613 const float* mapy, int mystep, \
1614 int cn, const arrtype* fillval ) \
1620 srcstep /= sizeof(src[0]); \
1621 dststep /= sizeof(dst[0]); \
1622 mxstep /= sizeof(mapx[0]); \
1623 mystep /= sizeof(mapy[0]); \
1625 for( i = 0; i < dsize.height; i++, dst += dststep, \
1626 mapx += mxstep, mapy += mystep ) \
1628 for( j = 0; j < dsize.width; j++ ) \
1630 int ix = cvRound(mapx[j]*(1 << ICV_WARP_SHIFT)); \
1631 int iy = cvRound(mapy[j]*(1 << ICV_WARP_SHIFT)); \
1632 int ifx = ix & ICV_WARP_MASK; \
1633 int ify = iy & ICV_WARP_MASK; \
1634 ix >>= ICV_WARP_SHIFT; \
1635 iy >>= ICV_WARP_SHIFT; \
1637 float x0 = icvLinearCoeffs[ifx*2]; \
1638 float x1 = icvLinearCoeffs[ifx*2 + 1]; \
1639 float y0 = icvLinearCoeffs[ify*2]; \
1640 float y1 = icvLinearCoeffs[ify*2 + 1]; \
1642 if( (unsigned)ix < (unsigned)ssize.width && \
1643 (unsigned)iy < (unsigned)ssize.height ) \
1645 const arrtype* s = src + iy*srcstep + ix*cn; \
1646 for( k = 0; k < cn; k++, s++ ) \
1648 float t0 = x1*load_macro(s[0]) + x0*load_macro(s[cn]); \
1649 float t1 = x1*load_macro(s[srcstep]) + \
1650 x0*load_macro(s[srcstep + cn]); \
1651 dst[j*cn + k] = (arrtype)cast_macro(y1*t0 + y0*t1); \
1654 else if( fillval ) \
1655 for( k = 0; k < cn; k++ ) \
1656 dst[j*cn + k] = fillval[k]; \
1664 #define ICV_DEF_REMAP_BICUBIC_FUNC( flavor, arrtype, worktype, \
1665 load_macro, cast_macro1, cast_macro2 ) \
1666 static CvStatus CV_STDCALL \
1667 icvRemap_Bicubic_##flavor##_CnR( const arrtype* src, int srcstep, CvSize ssize, \
1668 arrtype* dst, int dststep, CvSize dsize, \
1669 const float* mapx, int mxstep, \
1670 const float* mapy, int mystep, \
1671 int cn, const arrtype* fillval ) \
1674 ssize.width = MAX( ssize.width - 3, 0 ); \
1675 ssize.height = MAX( ssize.height - 3, 0 ); \
1677 srcstep /= sizeof(src[0]); \
1678 dststep /= sizeof(dst[0]); \
1679 mxstep /= sizeof(mapx[0]); \
1680 mystep /= sizeof(mapy[0]); \
1682 for( i = 0; i < dsize.height; i++, dst += dststep, \
1683 mapx += mxstep, mapy += mystep ) \
1685 for( j = 0; j < dsize.width; j++ ) \
1687 int ix = cvRound(mapx[j]*(1 << ICV_WARP_SHIFT)); \
1688 int iy = cvRound(mapy[j]*(1 << ICV_WARP_SHIFT)); \
1689 int ifx = ix & ICV_WARP_MASK; \
1690 int ify = iy & ICV_WARP_MASK; \
1691 ix >>= ICV_WARP_SHIFT; \
1692 iy >>= ICV_WARP_SHIFT; \
1694 if( (unsigned)(ix-1) < (unsigned)ssize.width && \
1695 (unsigned)(iy-1) < (unsigned)ssize.height ) \
1697 for( k = 0; k < cn; k++ ) \
1699 const arrtype* s = src + (iy-1)*srcstep + ix*cn + k; \
1701 float t0 = load_macro(s[-cn])*icvCubicCoeffs[ifx*2 + 1] + \
1702 load_macro(s[0])*icvCubicCoeffs[ifx*2] + \
1703 load_macro(s[cn])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2] +\
1704 load_macro(s[cn*2])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2+1];\
1708 float t1 = load_macro(s[-cn])*icvCubicCoeffs[ifx*2 + 1] + \
1709 load_macro(s[0])*icvCubicCoeffs[ifx*2] + \
1710 load_macro(s[cn])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2] +\
1711 load_macro(s[cn*2])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2+1];\
1715 float t2 = load_macro(s[-cn])*icvCubicCoeffs[ifx*2 + 1] + \
1716 load_macro(s[0])*icvCubicCoeffs[ifx*2] + \
1717 load_macro(s[cn])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2] +\
1718 load_macro(s[cn*2])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2+1];\
1722 float t3 = load_macro(s[-cn])*icvCubicCoeffs[ifx*2 + 1] + \
1723 load_macro(s[0])*icvCubicCoeffs[ifx*2] + \
1724 load_macro(s[cn])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2] +\
1725 load_macro(s[cn*2])*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ifx)*2+1];\
1727 worktype t = cast_macro1( t0*icvCubicCoeffs[ify*2 + 1] + \
1728 t1*icvCubicCoeffs[ify*2] + \
1729 t2*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ify)*2] + \
1730 t3*icvCubicCoeffs[(ICV_CUBIC_TAB_SIZE-ify)*2+1] );\
1732 dst[j*cn + k] = cast_macro2(t); \
1735 else if( fillval ) \
1736 for( k = 0; k < cn; k++ ) \
1737 dst[j*cn + k] = fillval[k]; \
1745 ICV_DEF_REMAP_BILINEAR_FUNC( 8u, uchar, CV_8TO32F, cvRound )
1746 ICV_DEF_REMAP_BILINEAR_FUNC( 16u, ushort, CV_NOP, cvRound )
1747 ICV_DEF_REMAP_BILINEAR_FUNC( 32f, float, CV_NOP, CV_NOP )
1749 ICV_DEF_REMAP_BICUBIC_FUNC( 8u, uchar, int, CV_8TO32F, cvRound, CV_FAST_CAST_8U )
1750 ICV_DEF_REMAP_BICUBIC_FUNC( 16u, ushort, int, CV_NOP, cvRound, CV_CAST_16U )
1751 ICV_DEF_REMAP_BICUBIC_FUNC( 32f, float, float, CV_NOP, CV_NOP, CV_NOP )
1753 typedef CvStatus (CV_STDCALL * CvRemapFunc)(
1754 const void* src, int srcstep, CvSize ssize,
1755 void* dst, int dststep, CvSize dsize,
1756 const float* mapx, int mxstep,
1757 const float* mapy, int mystep,
1758 int cn, const void* fillval );
1760 static void icvInitRemapTab( CvFuncTable* bilinear_tab, CvFuncTable* bicubic_tab )
1762 bilinear_tab->fn_2d[CV_8U] = (void*)icvRemap_Bilinear_8u_CnR;
1763 bilinear_tab->fn_2d[CV_16U] = (void*)icvRemap_Bilinear_16u_CnR;
1764 bilinear_tab->fn_2d[CV_32F] = (void*)icvRemap_Bilinear_32f_CnR;
1766 bicubic_tab->fn_2d[CV_8U] = (void*)icvRemap_Bicubic_8u_CnR;
1767 bicubic_tab->fn_2d[CV_16U] = (void*)icvRemap_Bicubic_16u_CnR;
1768 bicubic_tab->fn_2d[CV_32F] = (void*)icvRemap_Bicubic_32f_CnR;
1772 /******************** IPP remap functions *********************/
1774 typedef CvStatus (CV_STDCALL * CvRemapIPPFunc)(
1775 const void* src, CvSize srcsize, int srcstep, CvRect srcroi,
1776 const float* xmap, int xmapstep, const float* ymap, int ymapstep,
1777 void* dst, int dststep, CvSize dstsize, int interpolation );
1779 icvRemap_8u_C1R_t icvRemap_8u_C1R_p = 0;
1780 icvRemap_8u_C3R_t icvRemap_8u_C3R_p = 0;
1781 icvRemap_8u_C4R_t icvRemap_8u_C4R_p = 0;
1783 icvRemap_32f_C1R_t icvRemap_32f_C1R_p = 0;
1784 icvRemap_32f_C3R_t icvRemap_32f_C3R_p = 0;
1785 icvRemap_32f_C4R_t icvRemap_32f_C4R_p = 0;
1787 /**************************************************************/
1790 cvRemap( const CvArr* srcarr, CvArr* dstarr,
1791 const CvArr* _mapx, const CvArr* _mapy,
1792 int flags, CvScalar fillval )
1794 static CvFuncTable bilinear_tab;
1795 static CvFuncTable bicubic_tab;
1796 static int inittab = 0;
1798 CV_FUNCNAME( "cvRemap" );
1802 CvMat srcstub, *src = (CvMat*)srcarr;
1803 CvMat dststub, *dst = (CvMat*)dstarr;
1804 CvMat mxstub, *mapx = (CvMat*)_mapx;
1805 CvMat mystub, *mapy = (CvMat*)_mapy;
1806 int type, depth, cn;
1807 int method = flags & 3;
1809 CvSize ssize, dsize;
1813 icvInitRemapTab( &bilinear_tab, &bicubic_tab );
1814 icvInitLinearCoeffTab();
1815 icvInitCubicCoeffTab();
1819 CV_CALL( src = cvGetMat( srcarr, &srcstub ));
1820 CV_CALL( dst = cvGetMat( dstarr, &dststub ));
1821 CV_CALL( mapx = cvGetMat( mapx, &mxstub ));
1822 CV_CALL( mapy = cvGetMat( mapy, &mystub ));
1824 if( !CV_ARE_TYPES_EQ( src, dst ))
1825 CV_ERROR( CV_StsUnmatchedFormats, "" );
1827 if( !CV_ARE_TYPES_EQ( mapx, mapy ) || CV_MAT_TYPE( mapx->type ) != CV_32FC1 )
1828 CV_ERROR( CV_StsUnmatchedFormats, "Both map arrays must have 32fC1 type" );
1830 if( !CV_ARE_SIZES_EQ( mapx, mapy ) || !CV_ARE_SIZES_EQ( mapx, dst ))
1831 CV_ERROR( CV_StsUnmatchedSizes,
1832 "Both map arrays and the destination array must have the same size" );
1834 type = CV_MAT_TYPE(src->type);
1835 depth = CV_MAT_DEPTH(type);
1836 cn = CV_MAT_CN(type);
1838 CV_ERROR( CV_BadNumChannels, "" );
1840 ssize = cvGetMatSize(src);
1841 dsize = cvGetMatSize(dst);
1843 if( icvRemap_8u_C1R_p )
1845 CvRemapIPPFunc ipp_func =
1846 type == CV_8UC1 ? icvRemap_8u_C1R_p :
1847 type == CV_8UC3 ? icvRemap_8u_C3R_p :
1848 type == CV_8UC4 ? icvRemap_8u_C4R_p :
1849 type == CV_32FC1 ? icvRemap_32f_C1R_p :
1850 type == CV_32FC3 ? icvRemap_32f_C3R_p :
1851 type == CV_32FC4 ? icvRemap_32f_C4R_p : 0;
1855 int srcstep = src->step ? src->step : CV_STUB_STEP;
1856 int dststep = dst->step ? dst->step : CV_STUB_STEP;
1857 int mxstep = mapx->step ? mapx->step : CV_STUB_STEP;
1858 int mystep = mapy->step ? mapy->step : CV_STUB_STEP;
1860 CvRect srcroi = {0, 0, ssize.width, ssize.height};
1862 // this is not the most efficient way to fill outliers
1863 if( flags & CV_WARP_FILL_OUTLIERS )
1864 cvSet( dst, fillval );
1866 status = ipp_func( src->data.ptr, ssize, srcstep, srcroi,
1867 mapx->data.fl, mxstep, mapy->data.fl, mystep,
1868 dst->data.ptr, dststep, dsize,
1869 1 << (method == CV_INTER_NN || method == CV_INTER_LINEAR ||
1870 method == CV_INTER_CUBIC ? method : CV_INTER_LINEAR) );
1876 cvScalarToRawData( &fillval, fillbuf, CV_MAT_TYPE(src->type), 0 );
1879 CvRemapFunc func = method == CV_INTER_CUBIC ?
1880 (CvRemapFunc)bicubic_tab.fn_2d[depth] :
1881 (CvRemapFunc)bilinear_tab.fn_2d[depth];
1884 CV_ERROR( CV_StsUnsupportedFormat, "" );
1886 func( src->data.ptr, src->step, ssize, dst->data.ptr, dst->step, dsize,
1887 mapx->data.fl, mapx->step, mapy->data.fl, mapy->step,
1888 cn, flags & CV_WARP_FILL_OUTLIERS ? fillbuf : 0 );
1895 /****************************************************************************************\
1896 * Log-Polar Transform *
1897 \****************************************************************************************/
1899 /* now it is done via Remap; more correct implementation should use
1900 some super-sampling technique outside of the "fovea" circle */
1902 cvLogPolar( const CvArr* srcarr, CvArr* dstarr,
1903 CvPoint2D32f center, double M, int flags )
1907 double* exp_tab = 0;
1910 CV_FUNCNAME( "cvLogPolar" );
1914 CvMat srcstub, *src = (CvMat*)srcarr;
1915 CvMat dststub, *dst = (CvMat*)dstarr;
1916 CvSize ssize, dsize;
1918 CV_CALL( src = cvGetMat( srcarr, &srcstub ));
1919 CV_CALL( dst = cvGetMat( dstarr, &dststub ));
1921 if( !CV_ARE_TYPES_EQ( src, dst ))
1922 CV_ERROR( CV_StsUnmatchedFormats, "" );
1925 CV_ERROR( CV_StsOutOfRange, "M should be >0" );
1927 ssize = cvGetMatSize(src);
1928 dsize = cvGetMatSize(dst);
1930 CV_CALL( mapx = cvCreateMat( dsize.height, dsize.width, CV_32F ));
1931 CV_CALL( mapy = cvCreateMat( dsize.height, dsize.width, CV_32F ));
1933 if( !(flags & CV_WARP_INVERSE_MAP) )
1937 CV_CALL( exp_tab = (double*)cvAlloc( dsize.width*sizeof(exp_tab[0])) );
1939 for( rho = 0; rho < dst->width; rho++ )
1940 exp_tab[rho] = exp(rho/M);
1942 for( phi = 0; phi < dsize.height; phi++ )
1944 double cp = cos(phi*2*CV_PI/dsize.height);
1945 double sp = sin(phi*2*CV_PI/dsize.height);
1946 float* mx = (float*)(mapx->data.ptr + phi*mapx->step);
1947 float* my = (float*)(mapy->data.ptr + phi*mapy->step);
1949 for( rho = 0; rho < dsize.width; rho++ )
1951 double r = exp_tab[rho];
1952 double x = r*cp + center.x;
1953 double y = r*sp + center.y;
1963 CvMat bufx, bufy, bufp, bufa;
1964 double ascale = (ssize.width-1)/(2*CV_PI);
1966 CV_CALL( buf = (float*)cvAlloc( 4*dsize.width*sizeof(buf[0]) ));
1968 bufx = cvMat( 1, dsize.width, CV_32F, buf );
1969 bufy = cvMat( 1, dsize.width, CV_32F, buf + dsize.width );
1970 bufp = cvMat( 1, dsize.width, CV_32F, buf + dsize.width*2 );
1971 bufa = cvMat( 1, dsize.width, CV_32F, buf + dsize.width*3 );
1973 for( x = 0; x < dsize.width; x++ )
1974 bufx.data.fl[x] = (float)x - center.x;
1976 for( y = 0; y < dsize.height; y++ )
1978 float* mx = (float*)(mapx->data.ptr + y*mapx->step);
1979 float* my = (float*)(mapy->data.ptr + y*mapy->step);
1981 for( x = 0; x < dsize.width; x++ )
1982 bufy.data.fl[x] = (float)y - center.y;
1985 cvCartToPolar( &bufx, &bufy, &bufp, &bufa );
1987 for( x = 0; x < dsize.width; x++ )
1988 bufp.data.fl[x] += 1.f;
1990 cvLog( &bufp, &bufp );
1992 for( x = 0; x < dsize.width; x++ )
1994 double rho = bufp.data.fl[x]*M;
1995 double phi = bufa.data.fl[x]*ascale;
2001 for( x = 0; x < dsize.width; x++ )
2003 double xx = bufx.data.fl[x];
2004 double yy = bufy.data.fl[x];
2006 double p = log(sqrt(xx*xx + yy*yy) + 1.)*M;
2007 double a = atan2(yy,xx);
2019 cvRemap( src, dst, mapx, mapy, flags, cvScalarAll(0) );
2025 cvReleaseMat( &mapx );
2026 cvReleaseMat( &mapy );