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 Intel Corporation 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 #include "precomp.hpp"
     43 
     44 int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria )
     45 {
     46     Size size;
     47     int cn;
     48     Mat mat;
     49     UMat umat;
     50     bool isUMat = _probImage.isUMat();
     51 
     52     if (isUMat)
     53         umat = _probImage.getUMat(), cn = umat.channels(), size = umat.size();
     54     else
     55         mat = _probImage.getMat(), cn = mat.channels(), size = mat.size();
     56 
     57     Rect cur_rect = window;
     58 
     59     CV_Assert( cn == 1 );
     60 
     61     if( window.height <= 0 || window.width <= 0 )
     62         CV_Error( Error::StsBadArg, "Input window has non-positive sizes" );
     63 
     64     window = window & Rect(0, 0, size.width, size.height);
     65 
     66     double eps = (criteria.type & TermCriteria::EPS) ? std::max(criteria.epsilon, 0.) : 1.;
     67     eps = cvRound(eps*eps);
     68     int i, niters = (criteria.type & TermCriteria::MAX_ITER) ? std::max(criteria.maxCount, 1) : 100;
     69 
     70     for( i = 0; i < niters; i++ )
     71     {
     72         cur_rect = cur_rect & Rect(0, 0, size.width, size.height);
     73         if( cur_rect == Rect() )
     74         {
     75             cur_rect.x = size.width/2;
     76             cur_rect.y = size.height/2;
     77         }
     78         cur_rect.width = std::max(cur_rect.width, 1);
     79         cur_rect.height = std::max(cur_rect.height, 1);
     80 
     81         Moments m = isUMat ? moments(umat(cur_rect)) : moments(mat(cur_rect));
     82 
     83         // Calculating center of mass
     84         if( fabs(m.m00) < DBL_EPSILON )
     85             break;
     86 
     87         int dx = cvRound( m.m10/m.m00 - window.width*0.5 );
     88         int dy = cvRound( m.m01/m.m00 - window.height*0.5 );
     89 
     90         int nx = std::min(std::max(cur_rect.x + dx, 0), size.width - cur_rect.width);
     91         int ny = std::min(std::max(cur_rect.y + dy, 0), size.height - cur_rect.height);
     92 
     93         dx = nx - cur_rect.x;
     94         dy = ny - cur_rect.y;
     95         cur_rect.x = nx;
     96         cur_rect.y = ny;
     97 
     98         // Check for coverage centers mass & window
     99         if( dx*dx + dy*dy < eps )
    100             break;
    101     }
    102 
    103     window = cur_rect;
    104     return i;
    105 }
    106 
    107 
    108 cv::RotatedRect cv::CamShift( InputArray _probImage, Rect& window,
    109                               TermCriteria criteria )
    110 {
    111     const int TOLERANCE = 10;
    112     Size size;
    113     Mat mat;
    114     UMat umat;
    115     bool isUMat = _probImage.isUMat();
    116 
    117     if (isUMat)
    118         umat = _probImage.getUMat(), size = umat.size();
    119     else
    120         mat = _probImage.getMat(), size = mat.size();
    121 
    122     meanShift( _probImage, window, criteria );
    123 
    124     window.x -= TOLERANCE;
    125     if( window.x < 0 )
    126         window.x = 0;
    127 
    128     window.y -= TOLERANCE;
    129     if( window.y < 0 )
    130         window.y = 0;
    131 
    132     window.width += 2 * TOLERANCE;
    133     if( window.x + window.width > size.width )
    134         window.width = size.width - window.x;
    135 
    136     window.height += 2 * TOLERANCE;
    137     if( window.y + window.height > size.height )
    138         window.height = size.height - window.y;
    139 
    140     // Calculating moments in new center mass
    141     Moments m = isUMat ? moments(umat(window)) : moments(mat(window));
    142 
    143     double m00 = m.m00, m10 = m.m10, m01 = m.m01;
    144     double mu11 = m.mu11, mu20 = m.mu20, mu02 = m.mu02;
    145 
    146     if( fabs(m00) < DBL_EPSILON )
    147         return RotatedRect();
    148 
    149     double inv_m00 = 1. / m00;
    150     int xc = cvRound( m10 * inv_m00 + window.x );
    151     int yc = cvRound( m01 * inv_m00 + window.y );
    152     double a = mu20 * inv_m00, b = mu11 * inv_m00, c = mu02 * inv_m00;
    153 
    154     // Calculating width & height
    155     double square = std::sqrt( 4 * b * b + (a - c) * (a - c) );
    156 
    157     // Calculating orientation
    158     double theta = atan2( 2 * b, a - c + square );
    159 
    160     // Calculating width & length of figure
    161     double cs = cos( theta );
    162     double sn = sin( theta );
    163 
    164     double rotate_a = cs * cs * mu20 + 2 * cs * sn * mu11 + sn * sn * mu02;
    165     double rotate_c = sn * sn * mu20 - 2 * cs * sn * mu11 + cs * cs * mu02;
    166     double length = std::sqrt( rotate_a * inv_m00 ) * 4;
    167     double width = std::sqrt( rotate_c * inv_m00 ) * 4;
    168 
    169     // In case, when tetta is 0 or 1.57... the Length & Width may be exchanged
    170     if( length < width )
    171     {
    172         std::swap( length, width );
    173         std::swap( cs, sn );
    174         theta = CV_PI*0.5 - theta;
    175     }
    176 
    177     // Saving results
    178     int _xc = cvRound( xc );
    179     int _yc = cvRound( yc );
    180 
    181     int t0 = cvRound( fabs( length * cs ));
    182     int t1 = cvRound( fabs( width * sn ));
    183 
    184     t0 = MAX( t0, t1 ) + 2;
    185     window.width = MIN( t0, (size.width - _xc) * 2 );
    186 
    187     t0 = cvRound( fabs( length * sn ));
    188     t1 = cvRound( fabs( width * cs ));
    189 
    190     t0 = MAX( t0, t1 ) + 2;
    191     window.height = MIN( t0, (size.height - _yc) * 2 );
    192 
    193     window.x = MAX( 0, _xc - window.width / 2 );
    194     window.y = MAX( 0, _yc - window.height / 2 );
    195 
    196     window.width = MIN( size.width - window.x, window.width );
    197     window.height = MIN( size.height - window.y, window.height );
    198 
    199     RotatedRect box;
    200     box.size.height = (float)length;
    201     box.size.width = (float)width;
    202     box.angle = (float)((CV_PI*0.5+theta)*180./CV_PI);
    203     while(box.angle < 0)
    204         box.angle += 360;
    205     while(box.angle >= 360)
    206         box.angle -= 360;
    207     if(box.angle >= 180)
    208         box.angle -= 180;
    209     box.center = Point2f( window.x + window.width*0.5f, window.y + window.height*0.5f);
    210 
    211     return box;
    212 }
    213 
    214 /* End of file. */
    215