16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h"
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennIPCVAPI_IMPL( CvStatus, icvUpdateMotionHistory_8u32f_C1IR,
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (const uchar * silIm, int silStep, float *mhiIm, int mhiStep,
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     CvSize size, float timestamp, float mhi_duration),
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     (silIm, silStep, mhiIm, mhiStep, size, timestamp, mhi_duration) )
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int x, y;
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* function processes floating-point images using integer arithmetics */
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Cv32suf v;
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ts, delbound;
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int *mhi = (int *) mhiIm;
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    v.f = timestamp;
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ts = v.i;
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !silIm || !mhiIm )
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return CV_NULLPTR_ERR;
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( size.height <= 0 || size.width <= 0 ||
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        silStep < size.width || mhiStep < size.width * CV_SIZEOF_FLOAT ||
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (mhiStep & (CV_SIZEOF_FLOAT - 1)) != 0 )
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return CV_BADSIZE_ERR;
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( mhi_duration < 0 )
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return CV_BADFACTOR_ERR;
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    mhi_duration = timestamp - mhi_duration;
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    v.f = mhi_duration;
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delbound = CV_TOGGLE_FLT( v.i );
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    mhiStep /= sizeof(mhi[0]);
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( mhiStep == size.width && silStep == size.width )
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.width *= size.height;
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.height = 1;
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( delbound > 0 )
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( y = 0; y < size.height; y++, silIm += silStep, mhi += mhiStep )
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = 0; x < size.width; x++ )
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int val = mhi[x];
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* val = silIm[x] ? ts : val < delbound ? 0 : val; */
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                val &= (val < delbound) - 1;
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                val ^= (ts ^ val) & ((silIm[x] == 0) - 1);
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mhi[x] = val;
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( y = 0; y < size.height; y++, silIm += silStep, mhi += mhiStep )
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = 0; x < size.width; x++ )
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int val = mhi[x];
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* val = silIm[x] ? ts : val < delbound ? 0 : val; */
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                val &= (CV_TOGGLE_FLT( val ) < delbound) - 1;
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                val ^= (ts ^ val) & ((silIm[x] == 0) - 1);
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mhi[x] = val;
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_OK;
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* motion templates */
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvUpdateMotionHistory( const void* silhouette, void* mhimg,
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       double timestamp, double mhi_duration )
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  silhstub, *silh = (CvMat*)silhouette;
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  mhistub, *mhi = (CvMat*)mhimg;
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int mhi_step, silh_step;
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvUpdateMHIByTime" );
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( silh = cvGetMat( silh, &silhstub ));
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mhi = cvGetMat( mhi, &mhistub ));
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MASK_ARR( silh ))
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadMask, "" );
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_CN( mhi->type ) > 1 )
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadNumChannels, "" );
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_DEPTH( mhi->type ) != CV_32F )
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadDepth, "" );
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ( mhi, silh ))
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "" );
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvGetMatSize( mhi );
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    mhi_step = mhi->step;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    silh_step = silh->step;
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_IS_MAT_CONT( mhi->type & silh->type ))
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.width *= size.height;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mhi_step = silh_step = CV_STUB_STEP;
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.height = 1;
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    IPPI_CALL( icvUpdateMotionHistory_8u32f_C1IR( (const uchar*)(silh->data.ptr), silh_step,
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                  mhi->data.fl, mhi_step, size,
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                  (float)timestamp, (float)mhi_duration ));
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCalcMotionGradient( const CvArr* mhiimg, CvArr* maskimg,
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      CvArr* orientation,
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      double delta1, double delta2,
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      int aperture_size )
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat *dX_min = 0, *dY_max = 0;
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    IplConvKernel* el = 0;
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCalcMotionGradient" );
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  mhistub, *mhi = (CvMat*)mhiimg;
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  maskstub, *mask = (CvMat*)maskimg;
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  orientstub, *orient = (CvMat*)orientation;
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  dX_min_row, dY_max_row, orient_row, mask_row;
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int x, y;
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float  gradient_epsilon = 1e-4f * aperture_size * aperture_size;
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float  min_delta, max_delta;
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mhi = cvGetMat( mhi, &mhistub ));
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mask = cvGetMat( mask, &maskstub ));
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( orient = cvGetMat( orient, &orientstub ));
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MASK_ARR( mask ))
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadMask, "" );
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( aperture_size < 3 || aperture_size > 7 || (aperture_size & 1) == 0 )
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "aperture_size must be 3, 5 or 7" );
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( delta1 <= 0 || delta2 <= 0 )
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "both delta's must be positive" );
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_TYPE( mhi->type ) != CV_32FC1 || CV_MAT_TYPE( orient->type ) != CV_32FC1 )
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat,
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "MHI and orientation must be single-channel floating-point images" );
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ( mhi, mask ) || !CV_ARE_SIZES_EQ( orient, mhi ))
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "" );
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( orient->data.ptr == mhi->data.ptr )
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsInplaceNotSupported, "orientation image must be different from MHI" );
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( delta1 > delta2 )
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double t;
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP( delta1, delta2, t );
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvGetMatSize( mhi );
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_delta = (float)delta1;
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_delta = (float)delta2;
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dX_min = cvCreateMat( mhi->rows, mhi->cols, CV_32F ));
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dY_max = cvCreateMat( mhi->rows, mhi->cols, CV_32F ));
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* calc Dx and Dy */
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvSobel( mhi, dX_min, 1, 0, aperture_size ));
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvSobel( mhi, dY_max, 0, 1, aperture_size ));
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( dX_min, &dX_min_row, 0 );
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( dY_max, &dY_max_row, 0 );
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( orient, &orient_row, 0 );
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( mask, &mask_row, 0 );
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* calc gradient */
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < size.height; y++ )
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dX_min_row.data.ptr = dX_min->data.ptr + y*dX_min->step;
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dY_max_row.data.ptr = dY_max->data.ptr + y*dY_max->step;
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        orient_row.data.ptr = orient->data.ptr + y*orient->step;
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mask_row.data.ptr = mask->data.ptr + y*mask->step;
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvCartToPolar( &dX_min_row, &dY_max_row, 0, &orient_row, 1 );
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* make orientation zero where the gradient is very small */
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < size.width; x++ )
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            float dY = dY_max_row.data.fl[x];
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            float dX = dX_min_row.data.fl[x];
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fabs(dX) < gradient_epsilon && fabs(dY) < gradient_epsilon )
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mask_row.data.ptr[x] = 0;
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                orient_row.data.i[x] = 0;
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mask_row.data.ptr[x] = 1;
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( el = cvCreateStructuringElementEx( aperture_size, aperture_size,
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            aperture_size/2, aperture_size/2, CV_SHAPE_RECT ));
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvErode( mhi, dX_min, el );
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvDilate( mhi, dY_max, el );
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* mask off pixels which have little motion difference in their neighborhood */
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < size.height; y++ )
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dX_min_row.data.ptr = dX_min->data.ptr + y*dX_min->step;
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dY_max_row.data.ptr = dY_max->data.ptr + y*dY_max->step;
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mask_row.data.ptr = mask->data.ptr + y*mask->step;
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        orient_row.data.ptr = orient->data.ptr + y*orient->step;
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < size.width; x++ )
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            float d0 = dY_max_row.data.fl[x] - dX_min_row.data.fl[x];
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( mask_row.data.ptr[x] == 0 || d0 < min_delta || max_delta < d0 )
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mask_row.data.ptr[x] = 0;
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                orient_row.data.i[x] = 0;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &dX_min );
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &dY_max );
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseStructuringElement( &el );
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL double
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCalcGlobalOrientation( const void* orientation, const void* maskimg, const void* mhiimg,
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                         double curr_mhi_timestamp, double mhi_duration )
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double  angle = 0;
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int hist_size = 12;
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvHistogram* hist = 0;
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCalcGlobalOrientation" );
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  mhistub, *mhi = (CvMat*)mhiimg;
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  maskstub, *mask = (CvMat*)maskimg;
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  orientstub, *orient = (CvMat*)orientation;
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void*  _orient;
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float _ranges[] = { 0, 360 };
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* ranges = _ranges;
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int base_orient;
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double shift_orient = 0, shift_weight = 0, fbase_orient;
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double a, b;
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float delbound;
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat mhi_row, mask_row, orient_row;
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int x, y, mhi_rows, mhi_cols;
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mhi = cvGetMat( mhi, &mhistub ));
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mask = cvGetMat( mask, &maskstub ));
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( orient = cvGetMat( orient, &orientstub ));
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MASK_ARR( mask ))
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadMask, "" );
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_TYPE( mhi->type ) != CV_32FC1 || CV_MAT_TYPE( orient->type ) != CV_32FC1 )
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat,
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "MHI and orientation must be single-channel floating-point images" );
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ( mhi, mask ) || !CV_ARE_SIZES_EQ( orient, mhi ))
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "" );
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( mhi_duration <= 0 )
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "MHI duration must be positive" );
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( orient->data.ptr == mhi->data.ptr )
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsInplaceNotSupported, "orientation image must be different from MHI" );
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // calculate histogram of different orientation values
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( hist = cvCreateHist( 1, &hist_size, CV_HIST_ARRAY, &ranges ));
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _orient = orient;
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvCalcArrHist( &_orient, hist, 0, mask );
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // find the maximum index (the dominant orientation)
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetMinMaxHistValue( hist, 0, 0, 0, &base_orient );
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    base_orient *= 360/hist_size;
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // override timestamp with the maximum value in MHI
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvMinMaxLoc( mhi, 0, &curr_mhi_timestamp, 0, 0, mask );
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // find the shift relative to the dominant orientation as weighted sum of relative angles
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    a = 254. / 255. / mhi_duration;
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    b = 1. - curr_mhi_timestamp * a;
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fbase_orient = base_orient;
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delbound = (float)(curr_mhi_timestamp - mhi_duration);
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    mhi_rows = mhi->rows;
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    mhi_cols = mhi->cols;
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_IS_MAT_CONT( mhi->type & mask->type & orient->type ))
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mhi_cols *= mhi_rows;
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mhi_rows = 1;
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( mhi, &mhi_row, 0 );
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( mask, &mask_row, 0 );
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetRow( orient, &orient_row, 0 );
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       a = 254/(255*dt)
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       b = 1 - t*a = 1 - 254*t/(255*dur) =
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       (255*dt - 254*t)/(255*dt) =
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       (dt - (t - dt)*254)/(255*dt);
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       --------------------------------------------------------
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       ax + b = 254*x/(255*dt) + (dt - (t - dt)*254)/(255*dt) =
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       (254*x + dt - (t - dt)*254)/(255*dt) =
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       ((x - (t - dt))*254 + dt)/(255*dt) =
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       (((x - (t - dt))/dt)*254 + 1)/255 = (((x - low_time)/dt)*254 + 1)/255
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     */
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < mhi_rows; y++ )
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mhi_row.data.ptr = mhi->data.ptr + mhi->step*y;
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mask_row.data.ptr = mask->data.ptr + mask->step*y;
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        orient_row.data.ptr = orient->data.ptr + orient->step*y;
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < mhi_cols; x++ )
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( mask_row.data.ptr[x] != 0 && mhi_row.data.fl[x] > delbound )
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /*
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   orient in 0..360, base_orient in 0..360
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   -> (rel_angle = orient - base_orient) in -360..360.
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   rel_angle is translated to -180..180
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 */
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double weight = mhi_row.data.fl[x] * a + b;
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int rel_angle = cvRound( orient_row.data.fl[x] - fbase_orient );
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                rel_angle += (rel_angle < -180 ? 360 : 0);
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                rel_angle += (rel_angle > 180 ? -360 : 0);
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( abs(rel_angle) < 90 )
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    shift_orient += weight * rel_angle;
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    shift_weight += weight;
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // add the dominant orientation and the relative shift
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( shift_weight == 0 )
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        shift_weight = 0.01;
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    base_orient = base_orient + cvRound( shift_orient / shift_weight );
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    base_orient -= (base_orient < 360 ? 0 : 360);
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    base_orient += (base_orient >= 0 ? 0 : 360);
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    angle = base_orient;
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseHist( &hist );
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return angle;
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq*
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSegmentMotion( const CvArr* mhiimg, CvArr* segmask, CvMemStorage* storage,
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 double timestamp, double seg_thresh )
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* components = 0;
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* mask8u = 0;
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSegmentMotion" );
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  mhistub, *mhi = (CvMat*)mhiimg;
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat  maskstub, *mask = (CvMat*)segmask;
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Cv32suf v, comp_idx;
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int stub_val, ts;
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int x, y;
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL memory storage" );
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mhi = cvGetMat( mhi, &mhistub ));
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mask = cvGetMat( mask, &maskstub ));
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_TYPE( mhi->type ) != CV_32FC1 || CV_MAT_TYPE( mask->type ) != CV_32FC1 )
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadDepth, "Both MHI and the destination mask" );
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ( mhi, mask ))
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "" );
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mask8u = cvCreateMat( mhi->rows + 2, mhi->cols + 2, CV_8UC1 ));
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvZero( mask8u );
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvZero( mask );
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( components = cvCreateSeq( CV_SEQ_KIND_GENERIC, sizeof(CvSeq),
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       sizeof(CvConnectedComp), storage ));
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    v.f = (float)timestamp; ts = v.i;
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    v.f = FLT_MAX*0.1f; stub_val = v.i;
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    comp_idx.f = 1;
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < mhi->rows; y++ )
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* mhi_row = (int*)(mhi->data.ptr + y*mhi->step);
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < mhi->cols; x++ )
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( mhi_row[x] == 0 )
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mhi_row[x] = stub_val;
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < mhi->rows; y++ )
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* mhi_row = (int*)(mhi->data.ptr + y*mhi->step);
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* mask8u_row = mask8u->data.ptr + (y+1)*mask8u->step + 1;
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < mhi->cols; x++ )
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( mhi_row[x] == ts && mask8u_row[x] == 0 )
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvConnectedComp comp;
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int x1, y1;
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvScalar _seg_thresh = cvRealScalar(seg_thresh);
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvPoint seed = cvPoint(x,y);
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( cvFloodFill( mhi, seed, cvRealScalar(0), _seg_thresh, _seg_thresh,
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      &comp, CV_FLOODFILL_MASK_ONLY + 2*256 + 4, mask8u ));
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( y1 = 0; y1 < comp.rect.height; y1++ )
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int* mask_row1 = (int*)(mask->data.ptr +
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    (comp.rect.y + y1)*mask->step) + comp.rect.x;
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    uchar* mask8u_row1 = mask8u->data.ptr +
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    (comp.rect.y + y1+1)*mask8u->step + comp.rect.x+1;
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( x1 = 0; x1 < comp.rect.width; x1++ )
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( mask8u_row1[x1] > 1 )
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            mask8u_row1[x1] = 1;
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            mask_row1[x1] = comp_idx.i;
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                comp_idx.f++;
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvSeqPush( components, &comp );
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < mhi->rows; y++ )
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* mhi_row = (int*)(mhi->data.ptr + y*mhi->step);
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < mhi->cols; x++ )
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( mhi_row[x] == stub_val )
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mhi_row[x] = 0;
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &mask8u );
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return components;
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
518