roiTracker.cpp

00001 /* Copyright (c) 2009       Maxim Makhinya
00002  *
00003  * This library is free software; you can redistribute it and/or modify it under
00004  * the terms of the GNU Lesser General Public License version 2.1 as published
00005  * by the Free Software Foundation.
00006  *  
00007  * This library is distributed in the hope that it will be useful, but WITHOUT
00008  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00010  * details.
00011  * 
00012  * You should have received a copy of the GNU Lesser General Public License
00013  * along with this library; if not, write to the Free Software Foundation, Inc.,
00014  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00015  */
00016 
00017 #include "roiTracker.h"
00018 
00019 namespace eq
00020 {
00021 
00022 ROITracker::Area::Area( const PixelViewport& pvp_,
00023                               uint32_t       lastSkip_,
00024                               uint32_t       skip_ )
00025     :pvp(      pvp_      )
00026     ,lastSkip( lastSkip_ )
00027     ,skip(     skip_     )
00028 {
00029 }
00030 
00031 
00032 ROITracker::ROITracker()
00033     : _needsUpdate( false )
00034 {
00035     _ticket   = reinterpret_cast< uint8_t* >( this );
00036     _prvFrame = new stde::hash_map< uint32_t, Stage >;
00037     _curFrame = new stde::hash_map< uint32_t, Stage >;
00038 }
00039 
00040 
00041 ROITracker::~ROITracker()
00042 {
00043     delete _prvFrame;
00044     delete _curFrame;
00045     _prvFrame = 0;
00046     _curFrame = 0;
00047 }
00048 
00049 
00050 bool ROITracker::_returnPositive( uint8_t*& ticket )
00051 {
00052     ticket = ++_ticket;
00053     _needsUpdate = true;
00054     return true;
00055 }
00056 
00057 bool ROITracker::useROIFinder( const PixelViewport& pvp,
00058                                const uint32_t       stage,
00059                                const uint32_t       frameID,
00060                                      uint8_t*&      ticket )
00061 {
00062     EQASSERT( !_needsUpdate );
00063     ticket = 0;
00064 
00065     const uint32_t pvpArea = pvp.getArea();
00066     if( pvpArea < 100 )
00067         return false;
00068 
00069     if( _lastFrameID != frameID ) // new frame
00070     {
00071         stde::hash_map< uint32_t, Stage >* tmp = _prvFrame;
00072         _prvFrame = _curFrame;
00073         _curFrame = tmp;
00074         _curFrame->clear();
00075         _lastFrameID = frameID;
00076     }
00077 
00078     _lastStage = stage;
00079 
00080     Stage& curStage = (*_curFrame)[ stage ];
00081 
00082     // check if proper stage is avaliable
00083     if( _prvFrame->find( stage ) == _prvFrame->end( )) // new stage
00084     {
00085         curStage.areas.push_back( Area( pvp ));
00086         return _returnPositive( ticket );
00087     }
00088     //else existing stage, try to find matching area
00089 
00090     const Area*    match     = 0;
00091           uint32_t bestArea  = 0;
00092     const Stage&   prvStage  = (*_prvFrame)[ stage ];
00093     for( uint32_t i = 0; i < prvStage.areas.size(); i++ )
00094     {
00095         PixelViewport tmp = prvStage.areas[i].pvp;
00096         tmp.intersect( pvp );
00097         const uint32_t area = tmp.getArea();
00098         if( area > bestArea )
00099         {
00100             bestArea = area;
00101             match    = &prvStage.areas[i];
00102             if( area == pvpArea ) // full match
00103                 break;
00104         }
00105     }
00106 
00107     if( bestArea < pvpArea*2/3 ) // no proper match found, new area
00108     {
00109         curStage.areas.push_back( Area( pvp ));
00110         return _returnPositive( ticket );
00111     }
00112     // else good match
00113 
00114     if( match->skip == 0 ) // don't skip frame
00115     {
00116         curStage.areas.push_back( Area( pvp, match->lastSkip ));
00117         return _returnPositive( ticket );
00118     }
00119     //else skip frame
00120 
00121     curStage.areas.push_back( Area( pvp, match->lastSkip, match->skip-1 ));
00122     return false;
00123 }
00124 
00125 
00126 void ROITracker::updateDelay( const PixelViewportVector& pvps,
00127                               const uint8_t*             ticket )
00128 {
00129     EQASSERT( _needsUpdate );
00130     EQASSERTINFO( ticket == _ticket, "Wrong ticket" );
00131 
00132     if( ticket != _ticket )
00133     {
00134         EQERROR << "Wrong ticket" << std::endl;
00135         return;
00136     }
00137 
00138     uint32_t totalAreaFound = 0;
00139     for( uint32_t i = 0; i < pvps.size(); i++ )
00140         totalAreaFound += pvps[ i ].getArea();
00141 
00142     Area& area = (*_curFrame)[ _lastStage ].areas.back();
00143     if( totalAreaFound < area.pvp.getArea()*4/5 )
00144     {
00145         // ROI cutted enough, reset failure statistics
00146         area.lastSkip = 0;
00147     }else
00148     {
00149         // disable ROI for next frames, if it was failing before, 
00150         // increase number of frames to skip
00151         area.lastSkip = EQ_MIN( area.lastSkip*2 + 1, 64 );
00152         area.skip     = area.lastSkip;
00153     }
00154     _needsUpdate = false;
00155 }
00156 
00157 }
00158 
00159 
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8