Home | History | Annotate | Download | only in src
      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*
     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 {
    109     int operator()(float a) const { return cvRound(a*(1 << SUBPIX_SHIFT)); }
    110 };
    111 
    112 struct cast_8u
    113 {
    114     uchar operator()(int a) const { return (uchar)((a + (1 << (SUBPIX_SHIFT-1))) >> SUBPIX_SHIFT); }
    115 };
    116 
    117 struct cast_flt_8u
    118 {
    119     uchar operator()(float a) const { return (uchar)cvRound(a); }
    120 };
    121 
    122 template<typename _Tp>
    123 struct nop
    124 {
    125     _Tp operator()(_Tp a) const { return a; }
    126 };
    127 
    128 
    129 template<typename _Tp, typename _DTp, typename _WTp, class ScaleOp, class CastOp>
    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 
    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
    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 
    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
    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
    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
    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