Commit 88bae7be authored by jaco's avatar jaco

SuBSENSE porting: compiling errors fixed

parent 00d9ef42
set(the_description "Saliency API") set(the_description "Saliency API")
ocv_define_module(saliency opencv_imgproc opencv_highgui) ocv_define_module(saliency opencv_imgproc opencv_highgui opencv_features2d)
...@@ -81,11 +81,11 @@ class CV_EXPORTS_W StaticSaliencySpectralResidual : public StaticSaliency ...@@ -81,11 +81,11 @@ class CV_EXPORTS_W StaticSaliencySpectralResidual : public StaticSaliency
StaticSaliencySpectralResidual(); StaticSaliencySpectralResidual();
~StaticSaliencySpectralResidual(); ~StaticSaliencySpectralResidual();
typedef Ptr<Size> (cv::Algorithm::*SizeGetter)(); typedef Ptr<Size> (Algorithm::*SizeGetter)();
typedef void (cv::Algorithm::*SizeSetter)( const cv::Ptr<Size> & ); typedef void (Algorithm::*SizeSetter)( const Ptr<Size> & );
Ptr<Size> getWsize(); Ptr<Size> getWsize();
void setWsize( const cv::Ptr<Size> &arrPtr ); void setWsize( const Ptr<Size> &arrPtr );
void read( const FileNode& fn ); void read( const FileNode& fn );
void write( FileStorage& fs ) const; void write( FileStorage& fs ) const;
...@@ -99,28 +99,6 @@ class CV_EXPORTS_W StaticSaliencySpectralResidual : public StaticSaliency ...@@ -99,28 +99,6 @@ class CV_EXPORTS_W StaticSaliencySpectralResidual : public StaticSaliency
/************************************ Specific Motion Saliency Specialized Classes ************************************/ /************************************ Specific Motion Saliency Specialized Classes ************************************/
/**
* \brief Saliency based on algorithms described in [2]
* [2] Hofmann, Martin, Philipp Tiefenbacher, and Gerhard Rigoll. "Background segmentation with feedback: The pixel-based adaptive segmenter."
* Computer Vision and Pattern Recognition Workshops (CVPRW), 2012 IEEE Computer Society Conference on. IEEE, 2012.
*/
class CV_EXPORTS_W MotionSaliencyPBAS : public MotionSaliency
{
public:
//MotionSaliencyPBAS( const MotionSaliencyPBAS::Params &parameters = MotionSaliencyPBAS::Params() );
MotionSaliencyPBAS();
~MotionSaliencyPBAS();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
protected:
bool computeSaliencyImpl( const InputArray src, OutputArray dst );
AlgorithmInfo* info() const;
};
/*! /*!
Self-Balanced Sensitivity segmenTER (SuBSENSE) foreground-background segmentation algorithm. Self-Balanced Sensitivity segmenTER (SuBSENSE) foreground-background segmentation algorithm.
...@@ -147,13 +125,13 @@ class CV_EXPORTS_W MotionSaliencySuBSENSE : public BackgroundSubtractorLBSP, pub ...@@ -147,13 +125,13 @@ class CV_EXPORTS_W MotionSaliencySuBSENSE : public BackgroundSubtractorLBSP, pub
virtual ~MotionSaliencySuBSENSE(); virtual ~MotionSaliencySuBSENSE();
//! (re)initiaization method; needs to be called before starting background subtraction (note: also reinitializes the keypoints vector) //! (re)initiaization method; needs to be called before starting background subtraction (note: also reinitializes the keypoints vector)
virtual void initialize( const cv::Mat& oInitImg, const std::vector<cv::KeyPoint>& voKeyPoints ); virtual void initialize( const Mat& oInitImg, const std::vector<KeyPoint>& voKeyPoints );
//! refreshes all samples based on the last analyzed frame //! refreshes all samples based on the last analyzed frame
virtual void refreshModel( float fSamplesRefreshFrac ); virtual void refreshModel( float fSamplesRefreshFrac );
//! primary model update function; the learning param is used to override the internal learning thresholds (ignored when <= 0) //! primary model update function; the learning param is used to override the internal learning thresholds (ignored when <= 0)
virtual void operator()( cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = 0 ); virtual void operator()( InputArray image, OutputArray fgmask, double learningRateOverride = 0 );
//! returns a copy of the latest reconstructed background image //! returns a copy of the latest reconstructed background image
void getBackgroundImage( cv::OutputArray backgroundImage ) const; void getBackgroundImage( OutputArray backgroundImage ) const;
//! turns automatic model reset on or off //! turns automatic model reset on or off
void setAutomaticModelReset( bool ); void setAutomaticModelReset( bool );
...@@ -195,43 +173,43 @@ class CV_EXPORTS_W MotionSaliencySuBSENSE : public BackgroundSubtractorLBSP, pub ...@@ -195,43 +173,43 @@ class CV_EXPORTS_W MotionSaliencySuBSENSE : public BackgroundSubtractorLBSP, pub
std::vector<Mat> m_voBGColorSamples; std::vector<Mat> m_voBGColorSamples;
//! per-pixel update rates ('T(x)' in PBAS, which contains pixel-level 'sigmas', as referred to in ViBe) //! per-pixel update rates ('T(x)' in PBAS, which contains pixel-level 'sigmas', as referred to in ViBe)
cv::Mat m_oUpdateRateFrame; Mat m_oUpdateRateFrame;
//! per-pixel distance thresholds (equivalent to 'R(x)' in PBAS, but used as a relative value to determine both intensity and descriptor variation thresholds) //! per-pixel distance thresholds (equivalent to 'R(x)' in PBAS, but used as a relative value to determine both intensity and descriptor variation thresholds)
cv::Mat m_oDistThresholdFrame; Mat m_oDistThresholdFrame;
//! per-pixel distance variation modulators ('v(x)', relative value used to modulate 'R(x)' and 'T(x)' variations) //! per-pixel distance variation modulators ('v(x)', relative value used to modulate 'R(x)' and 'T(x)' variations)
cv::Mat m_oVariationModulatorFrame; Mat m_oVariationModulatorFrame;
//! per-pixel mean distances between consecutive frames ('D_last(x)', used to detect ghosts and high variation regions in the sequence) //! per-pixel mean distances between consecutive frames ('D_last(x)', used to detect ghosts and high variation regions in the sequence)
cv::Mat m_oMeanLastDistFrame; Mat m_oMeanLastDistFrame;
//! per-pixel mean minimal distances from the model ('D_min(x)' in PBAS, used to control variation magnitude and direction of 'T(x)' and 'R(x)') //! per-pixel mean minimal distances from the model ('D_min(x)' in PBAS, used to control variation magnitude and direction of 'T(x)' and 'R(x)')
cv::Mat m_oMeanMinDistFrame_LT, m_oMeanMinDistFrame_ST; Mat m_oMeanMinDistFrame_LT, m_oMeanMinDistFrame_ST;
//! per-pixel mean downsampled distances between consecutive frames (used to analyze camera movement and control max learning rates globally) //! per-pixel mean downsampled distances between consecutive frames (used to analyze camera movement and control max learning rates globally)
cv::Mat m_oMeanDownSampledLastDistFrame_LT, m_oMeanDownSampledLastDistFrame_ST; Mat m_oMeanDownSampledLastDistFrame_LT, m_oMeanDownSampledLastDistFrame_ST;
//! per-pixel mean raw segmentation results //! per-pixel mean raw segmentation results
cv::Mat m_oMeanRawSegmResFrame_LT, m_oMeanRawSegmResFrame_ST; Mat m_oMeanRawSegmResFrame_LT, m_oMeanRawSegmResFrame_ST;
//! per-pixel mean final segmentation results //! per-pixel mean final segmentation results
cv::Mat m_oMeanFinalSegmResFrame_LT, m_oMeanFinalSegmResFrame_ST; Mat m_oMeanFinalSegmResFrame_LT, m_oMeanFinalSegmResFrame_ST;
//! a lookup map used to keep track of unstable regions (based on segm. noise & local dist. thresholds) //! a lookup map used to keep track of unstable regions (based on segm. noise & local dist. thresholds)
cv::Mat m_oUnstableRegionMask; Mat m_oUnstableRegionMask;
//! per-pixel blink detection results ('Z(x)') //! per-pixel blink detection results ('Z(x)')
cv::Mat m_oBlinksFrame; Mat m_oBlinksFrame;
//! pre-allocated matrix used to downsample (1/8) the input frame when needed //! pre-allocated matrix used to downsample (1/8) the input frame when needed
cv::Mat m_oDownSampledColorFrame; Mat m_oDownSampledColorFrame;
//! copy of previously used pixel intensities used to calculate 'D_last(x)' //! copy of previously used pixel intensities used to calculate 'D_last(x)'
cv::Mat m_oLastColorFrame; Mat m_oLastColorFrame;
//! copy of previously used descriptors used to calculate 'D_last(x)' //! copy of previously used descriptors used to calculate 'D_last(x)'
cv::Mat m_oLastDescFrame; Mat m_oLastDescFrame;
//! the foreground mask generated by the method at [t-1] (without post-proc, used for blinking px detection) //! the foreground mask generated by the method at [t-1] (without post-proc, used for blinking px detection)
cv::Mat m_oRawFGMask_last; Mat m_oRawFGMask_last;
//! the foreground mask generated by the method at [t-1] (with post-proc) //! the foreground mask generated by the method at [t-1] (with post-proc)
cv::Mat m_oFGMask_last; Mat m_oFGMask_last;
//! pre-allocated CV_8UC1 matrices used to speed up morph ops //! pre-allocated CV_8UC1 matrices used to speed up morph ops
cv::Mat m_oFGMask_PreFlood; Mat m_oFGMask_PreFlood;
cv::Mat m_oFGMask_FloodedHoles; Mat m_oFGMask_FloodedHoles;
cv::Mat m_oFGMask_last_dilated; Mat m_oFGMask_last_dilated;
cv::Mat m_oFGMask_last_dilated_inverted; Mat m_oFGMask_last_dilated_inverted;
cv::Mat m_oRawFGBlinkMask_curr; Mat m_oRawFGBlinkMask_curr;
cv::Mat m_oRawFGBlinkMask_last; Mat m_oRawFGBlinkMask_last;
}; };
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
This algorithm is currently NOT thread-safe. This algorithm is currently NOT thread-safe.
*/ */
class BackgroundSubtractorLBSP : public cv::BackgroundSubtractor { class BackgroundSubtractorLBSP /* : public cv::BackgroundSubtractor */ {
public: public:
//! full constructor //! full constructor
BackgroundSubtractorLBSP(float fRelLBSPThreshold, size_t nDescDistThreshold, size_t nLBSPThresholdOffset=0); BackgroundSubtractorLBSP(float fRelLBSPThreshold, size_t nDescDistThreshold, size_t nLBSPThresholdOffset=0);
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
// local define used for debug purposes only // local define used for debug purposes only
#define DISPLAY_SUBSENSE_DEBUG_INFO 0 #define DISPLAY_SUBSENSE_DEBUG_INFO 0
// local define used to specify the default internal frame size // local define used to specify the default internal frame size
#define DEFAULT_FRAME_SIZE cv::Size(320,240) #define DEFAULT_FRAME_SIZE Size(320,240)
// local define used to specify the color dist threshold offset used for unstable regions // local define used to specify the color dist threshold offset used for unstable regions
#define STAB_COLOR_DIST_OFFSET m_nMinColorDistThreshold/5 #define STAB_COLOR_DIST_OFFSET m_nMinColorDistThreshold/5
// local define used to specify the desc dist threshold offset used for unstable regions // local define used to specify the desc dist threshold offset used for unstable regions
...@@ -94,48 +94,51 @@ ...@@ -94,48 +94,51 @@
#define DEFAULT_MEDIAN_BLUR_KERNEL_SIZE (9) #define DEFAULT_MEDIAN_BLUR_KERNEL_SIZE (9)
static const size_t s_nColorMaxDataRange_1ch = UCHAR_MAX; static const size_t s_nColorMaxDataRange_1ch = UCHAR_MAX;
static const size_t s_nDescMaxDataRange_1ch = LBSP::DESC_SIZE*8; static const size_t s_nDescMaxDataRange_1ch = LBSP::DESC_SIZE * 8;
static const size_t s_nColorMaxDataRange_3ch = s_nColorMaxDataRange_1ch*3; static const size_t s_nColorMaxDataRange_3ch = s_nColorMaxDataRange_1ch * 3;
static const size_t s_nDescMaxDataRange_3ch = s_nDescMaxDataRange_1ch*3; static const size_t s_nDescMaxDataRange_3ch = s_nDescMaxDataRange_1ch * 3;
namespace cv namespace cv
{ {
MotionSaliencySuBSENSE::MotionSaliencySuBSENSE( float fRelLBSPThreshold, size_t nMinDescDistThreshold, size_t nMinColorDistThreshold,
size_t nBGSamples, size_t nRequiredBGSamples, size_t nSamplesForMovingAvgs )
:
MotionSaliencySuBSENSE::MotionSaliencySuBSENSE(float fRelLBSPThreshold BackgroundSubtractorLBSP( fRelLBSPThreshold, nMinDescDistThreshold ),
,size_t nMinDescDistThreshold m_bInitializedInternalStructs( false ),
,size_t nMinColorDistThreshold m_nMinColorDistThreshold( nMinColorDistThreshold ),
,size_t nBGSamples m_nBGSamples( nBGSamples ),
,size_t nRequiredBGSamples m_nRequiredBGSamples( nRequiredBGSamples ),
,size_t nSamplesForMovingAvgs) m_nSamplesForMovingAvgs( nSamplesForMovingAvgs ),
m_nFrameIndex( SIZE_MAX ),
: BackgroundSubtractorLBSP(fRelLBSPThreshold,nMinDescDistThreshold) m_nFramesSinceLastReset( 0 ),
,m_bInitializedInternalStructs(false) m_nModelResetCooldown( 0 ),
,m_nMinColorDistThreshold(nMinColorDistThreshold) m_fLastNonZeroDescRatio( 0.0f ),
,m_nBGSamples(nBGSamples) m_bAutoModelResetEnabled( true ),
,m_nRequiredBGSamples(nRequiredBGSamples) m_bLearningRateScalingEnabled( true ),
,m_nSamplesForMovingAvgs(nSamplesForMovingAvgs) m_fCurrLearningRateLowerCap( FEEDBACK_T_LOWER ),
,m_nFrameIndex(SIZE_MAX) m_fCurrLearningRateUpperCap( FEEDBACK_T_UPPER ),
,m_nFramesSinceLastReset(0) m_nMedianBlurKernelSize( DEFAULT_MEDIAN_BLUR_KERNEL_SIZE ),
,m_nModelResetCooldown(0) m_bUse3x3Spread( true )
,m_fLastNonZeroDescRatio(0.0f) {
,m_bAutoModelResetEnabled(true) CV_Assert( m_nBGSamples > 0 && m_nRequiredBGSamples <= m_nBGSamples );
,m_bLearningRateScalingEnabled(true) CV_Assert( m_nMinColorDistThreshold>=STAB_COLOR_DIST_OFFSET );
,m_fCurrLearningRateLowerCap(FEEDBACK_T_LOWER)
,m_fCurrLearningRateUpperCap(FEEDBACK_T_UPPER)
,m_nMedianBlurKernelSize(DEFAULT_MEDIAN_BLUR_KERNEL_SIZE)
,m_bUse3x3Spread(true) {
CV_Assert(m_nBGSamples>0 && m_nRequiredBGSamples<=m_nBGSamples);
CV_Assert(m_nMinColorDistThreshold>=STAB_COLOR_DIST_OFFSET);
className = "PBAS"; className = "PBAS";
} }
MotionSaliencySuBSENSE::~MotionSaliencySuBSENSE() MotionSaliencySuBSENSE::~MotionSaliencySuBSENSE() {}
{
void MotionSaliencySuBSENSE::read( const cv::FileNode& /*fn*/ )
{
//params.read( fn );
} }
void MotionSaliencySuBSENSE::write( cv::FileStorage& /*fs*/ ) const
{
//params.write( fs );
}
bool MotionSaliencySuBSENSE::computeSaliencyImpl( const InputArray /*src*/, OutputArray /*dst*/) bool MotionSaliencySuBSENSE::computeSaliencyImpl( const InputArray /*src*/, OutputArray /*dst*/)
{ {
...@@ -143,30 +146,35 @@ bool MotionSaliencySuBSENSE::computeSaliencyImpl( const InputArray /*src*/, Outp ...@@ -143,30 +146,35 @@ bool MotionSaliencySuBSENSE::computeSaliencyImpl( const InputArray /*src*/, Outp
return true; return true;
} }
void MotionSaliencySuBSENSE::initialize(const cv::Mat& oInitImg, const std::vector<cv::KeyPoint>& voKeyPoints) { void MotionSaliencySuBSENSE::initialize( const Mat& oInitImg, const std::vector<KeyPoint>& voKeyPoints )
{
// == init // == init
CV_Assert(!oInitImg.empty() && oInitImg.cols>0 && oInitImg.rows>0); CV_Assert( !oInitImg.empty() && oInitImg.cols > 0 && oInitImg.rows > 0 );
CV_Assert(oInitImg.type()==CV_8UC3 || oInitImg.type()==CV_8UC1); CV_Assert( oInitImg.type()==CV_8UC3 || oInitImg.type()==CV_8UC1 );
if(oInitImg.type()==CV_8UC3) { if( oInitImg.type() == CV_8UC3 )
std::vector<cv::Mat> voInitImgChannels; {
cv::split(oInitImg,voInitImgChannels); std::vector<Mat> voInitImgChannels;
bool eq = std::equal(voInitImgChannels[0].begin<uchar>(), voInitImgChannels[0].end<uchar>(), voInitImgChannels[1].begin<uchar>()) split( oInitImg, voInitImgChannels );
&& std::equal(voInitImgChannels[1].begin<uchar>(), voInitImgChannels[1].end<uchar>(), voInitImgChannels[2].begin<uchar>()); /* bool eq = std::equal( voInitImgChannels[0].begin<uchar>(), voInitImgChannels[0].end<uchar>(), voInitImgChannels[1].begin<uchar>() )
if(eq) && std::equal( voInitImgChannels[1].begin<uchar>(), voInitImgChannels[1].end<uchar>(), voInitImgChannels[2].begin<uchar>() );
std::cout << std::endl << "\tMotionSaliencySuBSENSE : Warning, grayscale images should always be passed in CV_8UC1 format for optimal performance." << std::endl; if( eq )
} std::cout << std::endl
std::vector<cv::KeyPoint> voNewKeyPoints; << "\tMotionSaliencySuBSENSE : Warning, grayscale images should always be passed in CV_8UC1 format for optimal performance."
if(voKeyPoints.empty()) { << std::endl; */
cv::DenseFeatureDetector oKPDDetector(1.f, 1, 1.f, 1, 0, true, false); }
voNewKeyPoints.reserve(oInitImg.rows*oInitImg.cols); std::vector<KeyPoint> voNewKeyPoints;
oKPDDetector.detect(cv::Mat(oInitImg.size(),oInitImg.type()),voNewKeyPoints); if( voKeyPoints.empty() )
{
DenseFeatureDetector oKPDDetector( 1.f, 1, 1.f, 1, 0, true, false );
voNewKeyPoints.reserve( oInitImg.rows * oInitImg.cols );
oKPDDetector.detect( Mat( oInitImg.size(), oInitImg.type() ), voNewKeyPoints );
} }
else else
voNewKeyPoints = voKeyPoints; voNewKeyPoints = voKeyPoints;
const size_t nOrigKeyPointsCount = voNewKeyPoints.size(); const size_t nOrigKeyPointsCount = voNewKeyPoints.size();
CV_Assert(nOrigKeyPointsCount>0); CV_Assert( nOrigKeyPointsCount > 0 );
LBSP::validateKeyPoints(voNewKeyPoints,oInitImg.size()); LBSP::validateKeyPoints( voNewKeyPoints, oInitImg.size() );
CV_Assert(!voNewKeyPoints.empty()); CV_Assert( !voNewKeyPoints.empty() );
m_voKeyPoints = voNewKeyPoints; m_voKeyPoints = voNewKeyPoints;
m_nKeyPoints = m_voKeyPoints.size(); m_nKeyPoints = m_voKeyPoints.size();
m_oImgSize = oInitImg.size(); m_oImgSize = oInitImg.size();
...@@ -176,164 +184,183 @@ void MotionSaliencySuBSENSE::initialize(const cv::Mat& oInitImg, const std::vect ...@@ -176,164 +184,183 @@ void MotionSaliencySuBSENSE::initialize(const cv::Mat& oInitImg, const std::vect
m_nFramesSinceLastReset = 0; m_nFramesSinceLastReset = 0;
m_nModelResetCooldown = 0; m_nModelResetCooldown = 0;
m_fLastNonZeroDescRatio = 0.0f; m_fLastNonZeroDescRatio = 0.0f;
const int nTotImgPixels = m_oImgSize.height*m_oImgSize.width; const int nTotImgPixels = m_oImgSize.height * m_oImgSize.width;
if((int)nOrigKeyPointsCount>=nTotImgPixels/2 && nTotImgPixels>=DEFAULT_FRAME_SIZE.area()) { if( (int) nOrigKeyPointsCount >= nTotImgPixels / 2 && nTotImgPixels >= DEFAULT_FRAME_SIZE.area() )
{
m_bLearningRateScalingEnabled = true; m_bLearningRateScalingEnabled = true;
m_bAutoModelResetEnabled = true; m_bAutoModelResetEnabled = true;
m_bUse3x3Spread = !(nTotImgPixels>DEFAULT_FRAME_SIZE.area()*2); m_bUse3x3Spread = ! ( nTotImgPixels > DEFAULT_FRAME_SIZE.area() * 2 );
const int nRawMedianBlurKernelSize = std::min((int)floor((float)nTotImgPixels/DEFAULT_FRAME_SIZE.area()+0.5f)+DEFAULT_MEDIAN_BLUR_KERNEL_SIZE,14); const int nRawMedianBlurKernelSize = std::min(
m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize%2)?nRawMedianBlurKernelSize:nRawMedianBlurKernelSize-1; (int) floor( (float) nTotImgPixels / DEFAULT_FRAME_SIZE.area() + 0.5f ) + DEFAULT_MEDIAN_BLUR_KERNEL_SIZE, 14 );
m_nMedianBlurKernelSize = ( nRawMedianBlurKernelSize % 2 ) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER; m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER;
m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER; m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER;
} }
else { else
{
m_bLearningRateScalingEnabled = false; m_bLearningRateScalingEnabled = false;
m_bAutoModelResetEnabled = false; m_bAutoModelResetEnabled = false;
m_bUse3x3Spread = true; m_bUse3x3Spread = true;
m_nMedianBlurKernelSize = DEFAULT_MEDIAN_BLUR_KERNEL_SIZE; m_nMedianBlurKernelSize = DEFAULT_MEDIAN_BLUR_KERNEL_SIZE;
m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER*2; m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER * 2;
m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER*2; m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER * 2;
} }
//std::cout << m_oImgSize << " => m_nMedianBlurKernelSize=" << m_nMedianBlurKernelSize << ", with 3x3Spread=" << m_bUse3x3Spread << ", with Tscaling=" << m_bLearningRateScalingEnabled << std::endl; //std::cout << m_oImgSize << " => m_nMedianBlurKernelSize=" << m_nMedianBlurKernelSize << ", with 3x3Spread=" << m_bUse3x3Spread << ", with Tscaling=" << m_bLearningRateScalingEnabled << std::endl;
m_oUpdateRateFrame.create(m_oImgSize,CV_32FC1); m_oUpdateRateFrame.create( m_oImgSize, CV_32FC1 );
m_oUpdateRateFrame = cv::Scalar(m_fCurrLearningRateLowerCap); m_oUpdateRateFrame = Scalar( m_fCurrLearningRateLowerCap );
m_oDistThresholdFrame.create(m_oImgSize,CV_32FC1); m_oDistThresholdFrame.create( m_oImgSize, CV_32FC1 );
m_oDistThresholdFrame = cv::Scalar(1.0f); m_oDistThresholdFrame = Scalar( 1.0f );
m_oVariationModulatorFrame.create(m_oImgSize,CV_32FC1); m_oVariationModulatorFrame.create( m_oImgSize, CV_32FC1 );
m_oVariationModulatorFrame = cv::Scalar(10.0f); // should always be >= FEEDBACK_V_DECR m_oVariationModulatorFrame = Scalar( 10.0f ); // should always be >= FEEDBACK_V_DECR
m_oMeanLastDistFrame.create(m_oImgSize,CV_32FC1); m_oMeanLastDistFrame.create( m_oImgSize, CV_32FC1 );
m_oMeanLastDistFrame = cv::Scalar(0.0f); m_oMeanLastDistFrame = Scalar( 0.0f );
m_oMeanMinDistFrame_LT.create(m_oImgSize,CV_32FC1); m_oMeanMinDistFrame_LT.create( m_oImgSize, CV_32FC1 );
m_oMeanMinDistFrame_LT = cv::Scalar(0.0f); m_oMeanMinDistFrame_LT = Scalar( 0.0f );
m_oMeanMinDistFrame_ST.create(m_oImgSize,CV_32FC1); m_oMeanMinDistFrame_ST.create( m_oImgSize, CV_32FC1 );
m_oMeanMinDistFrame_ST = cv::Scalar(0.0f); m_oMeanMinDistFrame_ST = Scalar( 0.0f );
m_oDownSampledFrameSize = cv::Size(m_oImgSize.width/FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO,m_oImgSize.height/FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO); m_oDownSampledFrameSize = Size( m_oImgSize.width / FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO, m_oImgSize.height / FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO );
m_oMeanDownSampledLastDistFrame_LT.create(m_oDownSampledFrameSize,CV_32FC((int)m_nImgChannels)); m_oMeanDownSampledLastDistFrame_LT.create( m_oDownSampledFrameSize, CV_32FC( (int )m_nImgChannels ) );
m_oMeanDownSampledLastDistFrame_LT = cv::Scalar(0.0f); m_oMeanDownSampledLastDistFrame_LT = Scalar( 0.0f );
m_oMeanDownSampledLastDistFrame_ST.create(m_oDownSampledFrameSize,CV_32FC((int)m_nImgChannels)); m_oMeanDownSampledLastDistFrame_ST.create( m_oDownSampledFrameSize, CV_32FC( (int )m_nImgChannels ) );
m_oMeanDownSampledLastDistFrame_ST = cv::Scalar(0.0f); m_oMeanDownSampledLastDistFrame_ST = Scalar( 0.0f );
m_oMeanRawSegmResFrame_LT.create(m_oImgSize,CV_32FC1); m_oMeanRawSegmResFrame_LT.create( m_oImgSize, CV_32FC1 );
m_oMeanRawSegmResFrame_LT = cv::Scalar(0.0f); m_oMeanRawSegmResFrame_LT = Scalar( 0.0f );
m_oMeanRawSegmResFrame_ST.create(m_oImgSize,CV_32FC1); m_oMeanRawSegmResFrame_ST.create( m_oImgSize, CV_32FC1 );
m_oMeanRawSegmResFrame_ST = cv::Scalar(0.0f); m_oMeanRawSegmResFrame_ST = Scalar( 0.0f );
m_oMeanFinalSegmResFrame_LT.create(m_oImgSize,CV_32FC1); m_oMeanFinalSegmResFrame_LT.create( m_oImgSize, CV_32FC1 );
m_oMeanFinalSegmResFrame_LT = cv::Scalar(0.0f); m_oMeanFinalSegmResFrame_LT = Scalar( 0.0f );
m_oMeanFinalSegmResFrame_ST.create(m_oImgSize,CV_32FC1); m_oMeanFinalSegmResFrame_ST.create( m_oImgSize, CV_32FC1 );
m_oMeanFinalSegmResFrame_ST = cv::Scalar(0.0f); m_oMeanFinalSegmResFrame_ST = Scalar( 0.0f );
m_oUnstableRegionMask.create(m_oImgSize,CV_8UC1); m_oUnstableRegionMask.create( m_oImgSize, CV_8UC1 );
m_oUnstableRegionMask = cv::Scalar_<uchar>(0); m_oUnstableRegionMask = Scalar_<uchar>( 0 );
m_oBlinksFrame.create(m_oImgSize,CV_8UC1); m_oBlinksFrame.create( m_oImgSize, CV_8UC1 );
m_oBlinksFrame = cv::Scalar_<uchar>(0); m_oBlinksFrame = Scalar_<uchar>( 0 );
m_oDownSampledColorFrame.create(m_oDownSampledFrameSize,CV_8UC((int)m_nImgChannels)); m_oDownSampledColorFrame.create( m_oDownSampledFrameSize, CV_8UC( (int )m_nImgChannels ) );
m_oDownSampledColorFrame = cv::Scalar_<uchar>::all(0); m_oDownSampledColorFrame = Scalar_<uchar>::all( 0 );
m_oLastColorFrame.create(m_oImgSize,CV_8UC((int)m_nImgChannels)); m_oLastColorFrame.create( m_oImgSize, CV_8UC( (int )m_nImgChannels ) );
m_oLastColorFrame = cv::Scalar_<uchar>::all(0); m_oLastColorFrame = Scalar_<uchar>::all( 0 );
m_oLastDescFrame.create(m_oImgSize,CV_16UC((int)m_nImgChannels)); m_oLastDescFrame.create( m_oImgSize, CV_16UC( (int )m_nImgChannels ) );
m_oLastDescFrame = cv::Scalar_<ushort>::all(0); m_oLastDescFrame = Scalar_<ushort>::all( 0 );
m_oRawFGMask_last.create(m_oImgSize,CV_8UC1); m_oRawFGMask_last.create( m_oImgSize, CV_8UC1 );
m_oRawFGMask_last = cv::Scalar_<uchar>(0); m_oRawFGMask_last = Scalar_<uchar>( 0 );
m_oFGMask_last.create(m_oImgSize,CV_8UC1); m_oFGMask_last.create( m_oImgSize, CV_8UC1 );
m_oFGMask_last = cv::Scalar_<uchar>(0); m_oFGMask_last = Scalar_<uchar>( 0 );
m_oFGMask_last_dilated.create(m_oImgSize,CV_8UC1); m_oFGMask_last_dilated.create( m_oImgSize, CV_8UC1 );
m_oFGMask_last_dilated = cv::Scalar_<uchar>(0); m_oFGMask_last_dilated = Scalar_<uchar>( 0 );
m_oFGMask_last_dilated_inverted.create(m_oImgSize,CV_8UC1); m_oFGMask_last_dilated_inverted.create( m_oImgSize, CV_8UC1 );
m_oFGMask_last_dilated_inverted = cv::Scalar_<uchar>(0); m_oFGMask_last_dilated_inverted = Scalar_<uchar>( 0 );
m_oFGMask_FloodedHoles.create(m_oImgSize,CV_8UC1); m_oFGMask_FloodedHoles.create( m_oImgSize, CV_8UC1 );
m_oFGMask_FloodedHoles = cv::Scalar_<uchar>(0); m_oFGMask_FloodedHoles = Scalar_<uchar>( 0 );
m_oFGMask_PreFlood.create(m_oImgSize,CV_8UC1); m_oFGMask_PreFlood.create( m_oImgSize, CV_8UC1 );
m_oFGMask_PreFlood = cv::Scalar_<uchar>(0); m_oFGMask_PreFlood = Scalar_<uchar>( 0 );
m_oRawFGBlinkMask_curr.create(m_oImgSize,CV_8UC1); m_oRawFGBlinkMask_curr.create( m_oImgSize, CV_8UC1 );
m_oRawFGBlinkMask_curr = cv::Scalar_<uchar>(0); m_oRawFGBlinkMask_curr = Scalar_<uchar>( 0 );
m_oRawFGBlinkMask_last.create(m_oImgSize,CV_8UC1); m_oRawFGBlinkMask_last.create( m_oImgSize, CV_8UC1 );
m_oRawFGBlinkMask_last = cv::Scalar_<uchar>(0); m_oRawFGBlinkMask_last = Scalar_<uchar>( 0 );
m_voBGColorSamples.resize(m_nBGSamples); m_voBGColorSamples.resize( m_nBGSamples );
m_voBGDescSamples.resize(m_nBGSamples); m_voBGDescSamples.resize( m_nBGSamples );
for(size_t s=0; s<m_nBGSamples; ++s) { for ( size_t s = 0; s < m_nBGSamples; ++s )
m_voBGColorSamples[s].create(m_oImgSize,CV_8UC((int)m_nImgChannels)); {
m_voBGColorSamples[s] = cv::Scalar_<uchar>::all(0); m_voBGColorSamples[s].create( m_oImgSize, CV_8UC( (int )m_nImgChannels ) );
m_voBGDescSamples[s].create(m_oImgSize,CV_16UC((int)m_nImgChannels)); m_voBGColorSamples[s] = Scalar_<uchar>::all( 0 );
m_voBGDescSamples[s] = cv::Scalar_<ushort>::all(0); m_voBGDescSamples[s].create( m_oImgSize, CV_16UC( (int )m_nImgChannels ) );
} m_voBGDescSamples[s] = Scalar_<ushort>::all( 0 );
if(m_nImgChannels==1) { }
for(size_t t=0; t<=UCHAR_MAX; ++t) if( m_nImgChannels == 1 )
m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>((m_nLBSPThresholdOffset+t*m_fRelLBSPThreshold)/3); {
for(size_t k=0; k<m_nKeyPoints; ++k) { for ( size_t t = 0; t <= UCHAR_MAX; ++t )
const int y_orig = (int)m_voKeyPoints[k].pt.y; m_anLBSPThreshold_8bitLUT[t] = saturate_cast<uchar>( ( m_nLBSPThresholdOffset + t * m_fRelLBSPThreshold ) / 3 );
const int x_orig = (int)m_voKeyPoints[k].pt.x; for ( size_t k = 0; k < m_nKeyPoints; ++k )
{
const int y_orig = (int) m_voKeyPoints[k].pt.y;
const int x_orig = (int) m_voKeyPoints[k].pt.x;
CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols && m_oLastColorFrame.step.p[1]==1); CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols && m_oLastColorFrame.step.p[1]==1);
const size_t idx_color = m_oLastColorFrame.cols*y_orig + x_orig; const size_t idx_color = m_oLastColorFrame.cols * y_orig + x_orig;
CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2); CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2);
const size_t idx_desc = idx_color*2; const size_t idx_desc = idx_color * 2;
m_oLastColorFrame.data[idx_color] = oInitImg.data[idx_color]; m_oLastColorFrame.data[idx_color] = oInitImg.data[idx_color];
LBSP::computeGrayscaleDescriptor(oInitImg,oInitImg.data[idx_color],x_orig,y_orig,m_anLBSPThreshold_8bitLUT[oInitImg.data[idx_color]],*((ushort*)(m_oLastDescFrame.data+idx_desc))); LBSP::computeGrayscaleDescriptor( oInitImg, oInitImg.data[idx_color], x_orig, y_orig, m_anLBSPThreshold_8bitLUT[oInitImg.data[idx_color]],
* ( (ushort*) ( m_oLastDescFrame.data + idx_desc ) ) );
} }
} }
else { //m_nImgChannels==3 else
for(size_t t=0; t<=UCHAR_MAX; ++t) { //m_nImgChannels==3
m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>(m_nLBSPThresholdOffset+t*m_fRelLBSPThreshold); for ( size_t t = 0; t <= UCHAR_MAX; ++t )
for(size_t k=0; k<m_nKeyPoints; ++k) { m_anLBSPThreshold_8bitLUT[t] = saturate_cast<uchar>( m_nLBSPThresholdOffset + t * m_fRelLBSPThreshold );
const int y_orig = (int)m_voKeyPoints[k].pt.y; for ( size_t k = 0; k < m_nKeyPoints; ++k )
const int x_orig = (int)m_voKeyPoints[k].pt.x; {
const int y_orig = (int) m_voKeyPoints[k].pt.y;
const int x_orig = (int) m_voKeyPoints[k].pt.x;
CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols*3 && m_oLastColorFrame.step.p[1]==3); CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols*3 && m_oLastColorFrame.step.p[1]==3);
const size_t idx_color = 3*(m_oLastColorFrame.cols*y_orig + x_orig); const size_t idx_color = 3 * ( m_oLastColorFrame.cols * y_orig + x_orig );
CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2); CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2);
const size_t idx_desc = idx_color*2; const size_t idx_desc = idx_color * 2;
for(size_t c=0; c<3; ++c) { for ( size_t c = 0; c < 3; ++c )
const uchar nCurrBGInitColor = oInitImg.data[idx_color+c]; {
m_oLastColorFrame.data[idx_color+c] = nCurrBGInitColor; const uchar nCurrBGInitColor = oInitImg.data[idx_color + c];
LBSP::computeSingleRGBDescriptor(oInitImg,nCurrBGInitColor,x_orig,y_orig,c,m_anLBSPThreshold_8bitLUT[nCurrBGInitColor],((ushort*)(m_oLastDescFrame.data+idx_desc))[c]); m_oLastColorFrame.data[idx_color + c] = nCurrBGInitColor;
LBSP::computeSingleRGBDescriptor( oInitImg, nCurrBGInitColor, x_orig, y_orig, c, m_anLBSPThreshold_8bitLUT[nCurrBGInitColor],
( (ushort*) ( m_oLastDescFrame.data + idx_desc ) )[c] );
} }
} }
} }
m_bInitializedInternalStructs = true; m_bInitializedInternalStructs = true;
refreshModel(1.0f); refreshModel( 1.0f );
m_bInitialized = true; m_bInitialized = true;
} }
void MotionSaliencySuBSENSE::refreshModel(float fSamplesRefreshFrac) { void MotionSaliencySuBSENSE::refreshModel( float fSamplesRefreshFrac )
{
// == refresh // == refresh
CV_Assert(m_bInitializedInternalStructs); CV_Assert( m_bInitializedInternalStructs );
CV_Assert(fSamplesRefreshFrac>0.0f && fSamplesRefreshFrac<=1.0f); CV_Assert( fSamplesRefreshFrac > 0.0f && fSamplesRefreshFrac <= 1.0f );
const size_t nBGSamplesToRefresh = fSamplesRefreshFrac<1.0f?(size_t)(fSamplesRefreshFrac*m_nBGSamples):m_nBGSamples; const size_t nBGSamplesToRefresh = fSamplesRefreshFrac < 1.0f ? (size_t) ( fSamplesRefreshFrac * m_nBGSamples ) : m_nBGSamples;
const size_t nRefreshStartPos = fSamplesRefreshFrac<1.0f?rand()%m_nBGSamples:0; const size_t nRefreshStartPos = fSamplesRefreshFrac < 1.0f ? rand() % m_nBGSamples : 0;
if(m_nImgChannels==1) { if( m_nImgChannels == 1 )
for(size_t k=0; k<m_nKeyPoints; ++k) { {
const int y_orig = (int)m_voKeyPoints[k].pt.y; for ( size_t k = 0; k < m_nKeyPoints; ++k )
const int x_orig = (int)m_voKeyPoints[k].pt.x; {
const int y_orig = (int) m_voKeyPoints[k].pt.y;
const int x_orig = (int) m_voKeyPoints[k].pt.x;
CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols && m_oLastColorFrame.step.p[1]==1); CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols && m_oLastColorFrame.step.p[1]==1);
const size_t idx_orig_color = m_oLastColorFrame.cols*y_orig + x_orig; const size_t idx_orig_color = m_oLastColorFrame.cols * y_orig + x_orig;
CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2); CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2);
const size_t idx_orig_desc = idx_orig_color*2; const size_t idx_orig_desc = idx_orig_color * 2;
for(size_t s=nRefreshStartPos; s<nRefreshStartPos+nBGSamplesToRefresh; ++s) { for ( size_t s = nRefreshStartPos; s < nRefreshStartPos + nBGSamplesToRefresh; ++s )
{
int y_sample, x_sample; int y_sample, x_sample;
getRandSamplePosition(x_sample,y_sample,x_orig,y_orig,LBSP::PATCH_SIZE/2,m_oImgSize); getRandSamplePosition( x_sample, y_sample, x_orig, y_orig, LBSP::PATCH_SIZE / 2, m_oImgSize );
const size_t idx_sample_color = m_oLastColorFrame.cols*y_sample + x_sample; const size_t idx_sample_color = m_oLastColorFrame.cols * y_sample + x_sample;
const size_t idx_sample_desc = idx_sample_color*2; const size_t idx_sample_desc = idx_sample_color * 2;
const size_t idx_sample = s%m_nBGSamples; const size_t idx_sample = s % m_nBGSamples;
m_voBGColorSamples[idx_sample].data[idx_orig_color] = m_oLastColorFrame.data[idx_sample_color]; m_voBGColorSamples[idx_sample].data[idx_orig_color] = m_oLastColorFrame.data[idx_sample_color];
*((ushort*)(m_voBGDescSamples[idx_sample].data+idx_orig_desc)) = *((ushort*)(m_oLastDescFrame.data+idx_sample_desc)); * ( (ushort*) ( m_voBGDescSamples[idx_sample].data + idx_orig_desc ) ) = * ( (ushort*) ( m_oLastDescFrame.data + idx_sample_desc ) );
} }
} }
} }
else { //m_nImgChannels==3 else
for(size_t k=0; k<m_nKeyPoints; ++k) { { //m_nImgChannels==3
const int y_orig = (int)m_voKeyPoints[k].pt.y; for ( size_t k = 0; k < m_nKeyPoints; ++k )
const int x_orig = (int)m_voKeyPoints[k].pt.x; {
const int y_orig = (int) m_voKeyPoints[k].pt.y;
const int x_orig = (int) m_voKeyPoints[k].pt.x;
CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols*3 && m_oLastColorFrame.step.p[1]==3); CV_DbgAssert(m_oLastColorFrame.step.p[0]==(size_t)m_oLastColorFrame.cols*3 && m_oLastColorFrame.step.p[1]==3);
const size_t idx_orig_color = 3*(m_oLastColorFrame.cols*y_orig + x_orig); const size_t idx_orig_color = 3 * ( m_oLastColorFrame.cols * y_orig + x_orig );
CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2); CV_DbgAssert(m_oLastDescFrame.step.p[0]==m_oLastColorFrame.step.p[0]*2 && m_oLastDescFrame.step.p[1]==m_oLastColorFrame.step.p[1]*2);
const size_t idx_orig_desc = idx_orig_color*2; const size_t idx_orig_desc = idx_orig_color * 2;
for(size_t s=nRefreshStartPos; s<nRefreshStartPos+nBGSamplesToRefresh; ++s) { for ( size_t s = nRefreshStartPos; s < nRefreshStartPos + nBGSamplesToRefresh; ++s )
{
int y_sample, x_sample; int y_sample, x_sample;
getRandSamplePosition(x_sample,y_sample,x_orig,y_orig,LBSP::PATCH_SIZE/2,m_oImgSize); getRandSamplePosition( x_sample, y_sample, x_orig, y_orig, LBSP::PATCH_SIZE / 2, m_oImgSize );
const size_t idx_sample_color = 3*(m_oLastColorFrame.cols*y_sample + x_sample); const size_t idx_sample_color = 3 * ( m_oLastColorFrame.cols * y_sample + x_sample );
const size_t idx_sample_desc = idx_sample_color*2; const size_t idx_sample_desc = idx_sample_color * 2;
const size_t idx_sample = s%m_nBGSamples; const size_t idx_sample = s % m_nBGSamples;
uchar* bg_color_ptr = m_voBGColorSamples[idx_sample].data+idx_orig_color; uchar* bg_color_ptr = m_voBGColorSamples[idx_sample].data + idx_orig_color;
ushort* bg_desc_ptr = (ushort*)(m_voBGDescSamples[idx_sample].data+idx_orig_desc); ushort* bg_desc_ptr = (ushort*) ( m_voBGDescSamples[idx_sample].data + idx_orig_desc );
const uchar* const init_color_ptr = m_oLastColorFrame.data+idx_sample_color; const uchar* const init_color_ptr = m_oLastColorFrame.data + idx_sample_color;
const ushort* const init_desc_ptr = (ushort*)(m_oLastDescFrame.data+idx_sample_desc); const ushort* const init_desc_ptr = (ushort*) ( m_oLastDescFrame.data + idx_sample_desc );
for(size_t c=0; c<3; ++c) { for ( size_t c = 0; c < 3; ++c )
{
bg_color_ptr[c] = init_color_ptr[c]; bg_color_ptr[c] = init_color_ptr[c];
bg_desc_ptr[c] = init_desc_ptr[c]; bg_desc_ptr[c] = init_desc_ptr[c];
} }
...@@ -342,292 +369,346 @@ void MotionSaliencySuBSENSE::refreshModel(float fSamplesRefreshFrac) { ...@@ -342,292 +369,346 @@ void MotionSaliencySuBSENSE::refreshModel(float fSamplesRefreshFrac) {
} }
} }
void MotionSaliencySuBSENSE::operator()(cv::InputArray _image, cv::OutputArray _fgmask, double learningRateOverride) { void MotionSaliencySuBSENSE::operator()( InputArray _image, OutputArray _fgmask, double learningRateOverride )
{
// == process // == process
CV_DbgAssert(m_bInitialized); CV_DbgAssert(m_bInitialized);
cv::Mat oInputImg = _image.getMat(); Mat oInputImg = _image.getMat();
CV_DbgAssert(oInputImg.type()==m_nImgType && oInputImg.size()==m_oImgSize); CV_DbgAssert(oInputImg.type()==m_nImgType && oInputImg.size()==m_oImgSize);
_fgmask.create(m_oImgSize,CV_8UC1); _fgmask.create( m_oImgSize, CV_8UC1 );
cv::Mat oCurrFGMask = _fgmask.getMat(); Mat oCurrFGMask = _fgmask.getMat();
memset(oCurrFGMask.data,0,oCurrFGMask.cols*oCurrFGMask.rows); memset( oCurrFGMask.data, 0, oCurrFGMask.cols * oCurrFGMask.rows );
size_t nNonZeroDescCount = 0; size_t nNonZeroDescCount = 0;
const float fRollAvgFactor_LT = 1.0f/std::min(++m_nFrameIndex,m_nSamplesForMovingAvgs*4); const float fRollAvgFactor_LT = 1.0f / std::min( ++m_nFrameIndex, m_nSamplesForMovingAvgs * 4 );
const float fRollAvgFactor_ST = 1.0f/std::min(m_nFrameIndex,m_nSamplesForMovingAvgs); const float fRollAvgFactor_ST = 1.0f / std::min( m_nFrameIndex, m_nSamplesForMovingAvgs );
if(m_nImgChannels==1) { if( m_nImgChannels == 1 )
for(size_t k=0; k<m_nKeyPoints; ++k) { {
const int x = (int)m_voKeyPoints[k].pt.x; for ( size_t k = 0; k < m_nKeyPoints; ++k )
const int y = (int)m_voKeyPoints[k].pt.y; {
const size_t idx_uchar = m_oImgSize.width*y + x; const int x = (int) m_voKeyPoints[k].pt.x;
const size_t idx_ushrt = idx_uchar*2; const int y = (int) m_voKeyPoints[k].pt.y;
const size_t idx_flt32 = idx_uchar*4; const size_t idx_uchar = m_oImgSize.width * y + x;
const size_t idx_ushrt = idx_uchar * 2;
const size_t idx_flt32 = idx_uchar * 4;
const uchar nCurrColor = oInputImg.data[idx_uchar]; const uchar nCurrColor = oInputImg.data[idx_uchar];
size_t nMinDescDist = s_nDescMaxDataRange_1ch; size_t nMinDescDist = s_nDescMaxDataRange_1ch;
size_t nMinSumDist = s_nColorMaxDataRange_1ch; size_t nMinSumDist = s_nColorMaxDataRange_1ch;
float* pfCurrDistThresholdFactor = (float*)(m_oDistThresholdFrame.data+idx_flt32); float* pfCurrDistThresholdFactor = (float*) ( m_oDistThresholdFrame.data + idx_flt32 );
float* pfCurrVariationFactor = (float*)(m_oVariationModulatorFrame.data+idx_flt32); float* pfCurrVariationFactor = (float*) ( m_oVariationModulatorFrame.data + idx_flt32 );
float* pfCurrLearningRate = ((float*)(m_oUpdateRateFrame.data+idx_flt32)); float* pfCurrLearningRate = ( (float*) ( m_oUpdateRateFrame.data + idx_flt32 ) );
float* pfCurrMeanLastDist = ((float*)(m_oMeanLastDistFrame.data+idx_flt32)); float* pfCurrMeanLastDist = ( (float*) ( m_oMeanLastDistFrame.data + idx_flt32 ) );
float* pfCurrMeanMinDist_LT = ((float*)(m_oMeanMinDistFrame_LT.data+idx_flt32)); float* pfCurrMeanMinDist_LT = ( (float*) ( m_oMeanMinDistFrame_LT.data + idx_flt32 ) );
float* pfCurrMeanMinDist_ST = ((float*)(m_oMeanMinDistFrame_ST.data+idx_flt32)); float* pfCurrMeanMinDist_ST = ( (float*) ( m_oMeanMinDistFrame_ST.data + idx_flt32 ) );
float* pfCurrMeanRawSegmRes_LT = ((float*)(m_oMeanRawSegmResFrame_LT.data+idx_flt32)); float* pfCurrMeanRawSegmRes_LT = ( (float*) ( m_oMeanRawSegmResFrame_LT.data + idx_flt32 ) );
float* pfCurrMeanRawSegmRes_ST = ((float*)(m_oMeanRawSegmResFrame_ST.data+idx_flt32)); float* pfCurrMeanRawSegmRes_ST = ( (float*) ( m_oMeanRawSegmResFrame_ST.data + idx_flt32 ) );
float* pfCurrMeanFinalSegmRes_LT = ((float*)(m_oMeanFinalSegmResFrame_LT.data+idx_flt32)); float* pfCurrMeanFinalSegmRes_LT = ( (float*) ( m_oMeanFinalSegmResFrame_LT.data + idx_flt32 ) );
float* pfCurrMeanFinalSegmRes_ST = ((float*)(m_oMeanFinalSegmResFrame_ST.data+idx_flt32)); float* pfCurrMeanFinalSegmRes_ST = ( (float*) ( m_oMeanFinalSegmResFrame_ST.data + idx_flt32 ) );
ushort& nLastIntraDesc = *((ushort*)(m_oLastDescFrame.data+idx_ushrt)); ushort& nLastIntraDesc = * ( (ushort*) ( m_oLastDescFrame.data + idx_ushrt ) );
uchar& nLastColor = m_oLastColorFrame.data[idx_uchar]; uchar& nLastColor = m_oLastColorFrame.data[idx_uchar];
const size_t nCurrColorDistThreshold = (size_t)(((*pfCurrDistThresholdFactor)*m_nMinColorDistThreshold)-((!m_oUnstableRegionMask.data[idx_uchar])*STAB_COLOR_DIST_OFFSET))/2; const size_t nCurrColorDistThreshold = (size_t) ( ( ( *pfCurrDistThresholdFactor ) * m_nMinColorDistThreshold )
const size_t nCurrDescDistThreshold = ((size_t)1<<((size_t)floor(*pfCurrDistThresholdFactor+0.5f)))+m_nDescDistThreshold+(m_oUnstableRegionMask.data[idx_uchar]*UNSTAB_DESC_DIST_OFFSET); - ( ( !m_oUnstableRegionMask.data[idx_uchar] ) * STAB_COLOR_DIST_OFFSET ) ) / 2;
const size_t nCurrDescDistThreshold = ( (size_t) 1 << ( (size_t) floor( *pfCurrDistThresholdFactor + 0.5f ) ) ) + m_nDescDistThreshold
+ ( m_oUnstableRegionMask.data[idx_uchar] * UNSTAB_DESC_DIST_OFFSET );
ushort nCurrInterDesc, nCurrIntraDesc; ushort nCurrInterDesc, nCurrIntraDesc;
LBSP::computeGrayscaleDescriptor(oInputImg,nCurrColor,x,y,m_anLBSPThreshold_8bitLUT[nCurrColor],nCurrIntraDesc); LBSP::computeGrayscaleDescriptor( oInputImg, nCurrColor, x, y, m_anLBSPThreshold_8bitLUT[nCurrColor], nCurrIntraDesc );
m_oUnstableRegionMask.data[idx_uchar] = ((*pfCurrDistThresholdFactor)>UNSTABLE_REG_RDIST_MIN || (*pfCurrMeanRawSegmRes_LT-*pfCurrMeanFinalSegmRes_LT)>UNSTABLE_REG_RATIO_MIN || (*pfCurrMeanRawSegmRes_ST-*pfCurrMeanFinalSegmRes_ST)>UNSTABLE_REG_RATIO_MIN)?1:0; m_oUnstableRegionMask.data[idx_uchar] =
size_t nGoodSamplesCount=0, nSampleIdx=0; ( ( *pfCurrDistThresholdFactor ) > UNSTABLE_REG_RDIST_MIN
while(nGoodSamplesCount<m_nRequiredBGSamples && nSampleIdx<m_nBGSamples) { || ( *pfCurrMeanRawSegmRes_LT - *pfCurrMeanFinalSegmRes_LT ) > UNSTABLE_REG_RATIO_MIN
|| ( *pfCurrMeanRawSegmRes_ST - *pfCurrMeanFinalSegmRes_ST ) > UNSTABLE_REG_RATIO_MIN ) ? 1 : 0;
size_t nGoodSamplesCount = 0, nSampleIdx = 0;
while ( nGoodSamplesCount < m_nRequiredBGSamples && nSampleIdx < m_nBGSamples )
{
const uchar& nBGColor = m_voBGColorSamples[nSampleIdx].data[idx_uchar]; const uchar& nBGColor = m_voBGColorSamples[nSampleIdx].data[idx_uchar];
{ {
const size_t nColorDist = absdiff_uchar(nCurrColor,nBGColor); const size_t nColorDist = absdiff_uchar( nCurrColor, nBGColor );
if(nColorDist>nCurrColorDistThreshold) if( nColorDist > nCurrColorDistThreshold )
goto failedcheck1ch; goto failedcheck1ch;
const ushort& nBGIntraDesc = *((ushort*)(m_voBGDescSamples[nSampleIdx].data+idx_ushrt)); const ushort& nBGIntraDesc = * ( (ushort*) ( m_voBGDescSamples[nSampleIdx].data + idx_ushrt ) );
const size_t nIntraDescDist = hdist_ushort_8bitLUT(nCurrIntraDesc,nBGIntraDesc); const size_t nIntraDescDist = hdist_ushort_8bitLUT( nCurrIntraDesc, nBGIntraDesc );
LBSP::computeGrayscaleDescriptor(oInputImg,nBGColor,x,y,m_anLBSPThreshold_8bitLUT[nBGColor],nCurrInterDesc); LBSP::computeGrayscaleDescriptor( oInputImg, nBGColor, x, y, m_anLBSPThreshold_8bitLUT[nBGColor], nCurrInterDesc );
const size_t nInterDescDist = hdist_ushort_8bitLUT(nCurrInterDesc,nBGIntraDesc); const size_t nInterDescDist = hdist_ushort_8bitLUT( nCurrInterDesc, nBGIntraDesc );
const size_t nDescDist = (nIntraDescDist+nInterDescDist)/2; const size_t nDescDist = ( nIntraDescDist + nInterDescDist ) / 2;
if(nDescDist>nCurrDescDistThreshold) if( nDescDist > nCurrDescDistThreshold )
goto failedcheck1ch; goto failedcheck1ch;
const size_t nSumDist = std::min((nDescDist/4)*(s_nColorMaxDataRange_1ch/s_nDescMaxDataRange_1ch)+nColorDist,s_nColorMaxDataRange_1ch); const size_t nSumDist = std::min( ( nDescDist / 4 ) * ( s_nColorMaxDataRange_1ch / s_nDescMaxDataRange_1ch ) + nColorDist,
if(nSumDist>nCurrColorDistThreshold) s_nColorMaxDataRange_1ch );
if( nSumDist > nCurrColorDistThreshold )
goto failedcheck1ch; goto failedcheck1ch;
if(nMinDescDist>nDescDist) if( nMinDescDist > nDescDist )
nMinDescDist = nDescDist; nMinDescDist = nDescDist;
if(nMinSumDist>nSumDist) if( nMinSumDist > nSumDist )
nMinSumDist = nSumDist; nMinSumDist = nSumDist;
nGoodSamplesCount++; nGoodSamplesCount++;
} }
failedcheck1ch: failedcheck1ch : nSampleIdx++;
nSampleIdx++;
} }
const float fNormalizedLastDist = ((float)absdiff_uchar(nLastColor,nCurrColor)/s_nColorMaxDataRange_1ch+(float)hdist_ushort_8bitLUT(nLastIntraDesc,nCurrIntraDesc)/s_nDescMaxDataRange_1ch)/2; const float fNormalizedLastDist = ( (float) absdiff_uchar( nLastColor, nCurrColor ) / s_nColorMaxDataRange_1ch
*pfCurrMeanLastDist = (*pfCurrMeanLastDist)*(1.0f-fRollAvgFactor_ST) + fNormalizedLastDist*fRollAvgFactor_ST; + (float) hdist_ushort_8bitLUT( nLastIntraDesc, nCurrIntraDesc ) / s_nDescMaxDataRange_1ch ) / 2;
if(nGoodSamplesCount<m_nRequiredBGSamples) { *pfCurrMeanLastDist = ( *pfCurrMeanLastDist ) * ( 1.0f - fRollAvgFactor_ST ) + fNormalizedLastDist * fRollAvgFactor_ST;
if( nGoodSamplesCount < m_nRequiredBGSamples )
{
// == foreground // == foreground
const float fNormalizedMinDist = std::min(1.0f,((float)nMinSumDist/s_nColorMaxDataRange_1ch+(float)nMinDescDist/s_nDescMaxDataRange_1ch)/2 + (float)(m_nRequiredBGSamples-nGoodSamplesCount)/m_nRequiredBGSamples); const float fNormalizedMinDist = std::min(
*pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f-fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT; 1.0f,
*pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f-fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST; ( (float) nMinSumDist / s_nColorMaxDataRange_1ch + (float) nMinDescDist / s_nDescMaxDataRange_1ch ) / 2
*pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f-fRollAvgFactor_LT) + fRollAvgFactor_LT; + (float) ( m_nRequiredBGSamples - nGoodSamplesCount ) / m_nRequiredBGSamples );
*pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f-fRollAvgFactor_ST) + fRollAvgFactor_ST; *pfCurrMeanMinDist_LT = ( *pfCurrMeanMinDist_LT ) * ( 1.0f - fRollAvgFactor_LT ) + fNormalizedMinDist * fRollAvgFactor_LT;
*pfCurrMeanMinDist_ST = ( *pfCurrMeanMinDist_ST ) * ( 1.0f - fRollAvgFactor_ST ) + fNormalizedMinDist * fRollAvgFactor_ST;
*pfCurrMeanRawSegmRes_LT = ( *pfCurrMeanRawSegmRes_LT ) * ( 1.0f - fRollAvgFactor_LT ) + fRollAvgFactor_LT;
*pfCurrMeanRawSegmRes_ST = ( *pfCurrMeanRawSegmRes_ST ) * ( 1.0f - fRollAvgFactor_ST ) + fRollAvgFactor_ST;
oCurrFGMask.data[idx_uchar] = UCHAR_MAX; oCurrFGMask.data[idx_uchar] = UCHAR_MAX;
if(m_nModelResetCooldown && (rand()%(size_t)FEEDBACK_T_LOWER)==0) { if( m_nModelResetCooldown && ( rand() % (size_t) FEEDBACK_T_LOWER ) == 0 )
const size_t s_rand = rand()%m_nBGSamples; {
*((ushort*)(m_voBGDescSamples[s_rand].data+idx_ushrt)) = nCurrIntraDesc; const size_t s_rand = rand() % m_nBGSamples;
* ( (ushort*) ( m_voBGDescSamples[s_rand].data + idx_ushrt ) ) = nCurrIntraDesc;
m_voBGColorSamples[s_rand].data[idx_uchar] = nCurrColor; m_voBGColorSamples[s_rand].data[idx_uchar] = nCurrColor;
} }
} }
else { else
{
// == background // == background
const float fNormalizedMinDist = ((float)nMinSumDist/s_nColorMaxDataRange_1ch+(float)nMinDescDist/s_nDescMaxDataRange_1ch)/2; const float fNormalizedMinDist = ( (float) nMinSumDist / s_nColorMaxDataRange_1ch + (float) nMinDescDist / s_nDescMaxDataRange_1ch ) / 2;
*pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f-fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT; *pfCurrMeanMinDist_LT = ( *pfCurrMeanMinDist_LT ) * ( 1.0f - fRollAvgFactor_LT ) + fNormalizedMinDist * fRollAvgFactor_LT;
*pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f-fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST; *pfCurrMeanMinDist_ST = ( *pfCurrMeanMinDist_ST ) * ( 1.0f - fRollAvgFactor_ST ) + fNormalizedMinDist * fRollAvgFactor_ST;
*pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f-fRollAvgFactor_LT); *pfCurrMeanRawSegmRes_LT = ( *pfCurrMeanRawSegmRes_LT ) * ( 1.0f - fRollAvgFactor_LT );
*pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f-fRollAvgFactor_ST); *pfCurrMeanRawSegmRes_ST = ( *pfCurrMeanRawSegmRes_ST ) * ( 1.0f - fRollAvgFactor_ST );
const size_t nLearningRate = learningRateOverride>0?(size_t)ceil(learningRateOverride):(size_t)ceil(*pfCurrLearningRate); const size_t nLearningRate = learningRateOverride > 0 ? (size_t) ceil( learningRateOverride ) : (size_t) ceil( *pfCurrLearningRate );
if((rand()%nLearningRate)==0) { if( ( rand() % nLearningRate ) == 0 )
const size_t s_rand = rand()%m_nBGSamples; {
*((ushort*)(m_voBGDescSamples[s_rand].data+idx_ushrt)) = nCurrIntraDesc; const size_t s_rand = rand() % m_nBGSamples;
* ( (ushort*) ( m_voBGDescSamples[s_rand].data + idx_ushrt ) ) = nCurrIntraDesc;
m_voBGColorSamples[s_rand].data[idx_uchar] = nCurrColor; m_voBGColorSamples[s_rand].data[idx_uchar] = nCurrColor;
} }
int x_rand,y_rand; int x_rand, y_rand;
const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[idx_uchar]; const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[idx_uchar];
if(bCurrUsing3x3Spread) if( bCurrUsing3x3Spread )
getRandNeighborPosition_3x3(x_rand,y_rand,x,y,LBSP::PATCH_SIZE/2,m_oImgSize); getRandNeighborPosition_3x3( x_rand, y_rand, x, y, LBSP::PATCH_SIZE / 2, m_oImgSize );
else else
getRandNeighborPosition_5x5(x_rand,y_rand,x,y,LBSP::PATCH_SIZE/2,m_oImgSize); getRandNeighborPosition_5x5( x_rand, y_rand, x, y, LBSP::PATCH_SIZE / 2, m_oImgSize );
const size_t n_rand = rand(); const size_t n_rand = rand();
const size_t idx_rand_uchar = m_oImgSize.width*y_rand + x_rand; const size_t idx_rand_uchar = m_oImgSize.width * y_rand + x_rand;
const size_t idx_rand_flt32 = idx_rand_uchar*4; const size_t idx_rand_flt32 = idx_rand_uchar * 4;
const float fRandMeanLastDist = *((float*)(m_oMeanLastDistFrame.data+idx_rand_flt32)); const float fRandMeanLastDist = * ( (float*) ( m_oMeanLastDistFrame.data + idx_rand_flt32 ) );
const float fRandMeanRawSegmRes = *((float*)(m_oMeanRawSegmResFrame_ST.data+idx_rand_flt32)); const float fRandMeanRawSegmRes = * ( (float*) ( m_oMeanRawSegmResFrame_ST.data + idx_rand_flt32 ) );
if((n_rand%(bCurrUsing3x3Spread?nLearningRate:(nLearningRate/2+1)))==0 if( ( n_rand % ( bCurrUsing3x3Spread ? nLearningRate : ( nLearningRate / 2 + 1 ) ) ) == 0
|| (fRandMeanRawSegmRes>GHOSTDET_S_MIN && fRandMeanLastDist<GHOSTDET_D_MAX && (n_rand%((size_t)m_fCurrLearningRateLowerCap))==0)) { || ( fRandMeanRawSegmRes > GHOSTDET_S_MIN && fRandMeanLastDist < GHOSTDET_D_MAX
const size_t idx_rand_ushrt = idx_rand_uchar*2; && ( n_rand % ( (size_t) m_fCurrLearningRateLowerCap ) ) == 0 ) )
const size_t s_rand = rand()%m_nBGSamples; {
*((ushort*)(m_voBGDescSamples[s_rand].data+idx_rand_ushrt)) = nCurrIntraDesc; const size_t idx_rand_ushrt = idx_rand_uchar * 2;
const size_t s_rand = rand() % m_nBGSamples;
* ( (ushort*) ( m_voBGDescSamples[s_rand].data + idx_rand_ushrt ) ) = nCurrIntraDesc;
m_voBGColorSamples[s_rand].data[idx_rand_uchar] = nCurrColor; m_voBGColorSamples[s_rand].data[idx_rand_uchar] = nCurrColor;
} }
} }
if(m_oFGMask_last.data[idx_uchar] || (std::min(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)<UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[idx_uchar])) { if( m_oFGMask_last.data[idx_uchar]
if((*pfCurrLearningRate)<m_fCurrLearningRateUpperCap) || ( std::min( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) < UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[idx_uchar] ) )
*pfCurrLearningRate += FEEDBACK_T_INCR/(std::max(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)*(*pfCurrVariationFactor)); {
if( ( *pfCurrLearningRate ) < m_fCurrLearningRateUpperCap )
*pfCurrLearningRate += FEEDBACK_T_INCR / ( std::max( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) * ( *pfCurrVariationFactor ) );
} }
else if((*pfCurrLearningRate)>m_fCurrLearningRateLowerCap) else if( ( *pfCurrLearningRate ) > m_fCurrLearningRateLowerCap )
*pfCurrLearningRate -= FEEDBACK_T_DECR*(*pfCurrVariationFactor)/std::max(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST); *pfCurrLearningRate -= FEEDBACK_T_DECR * ( *pfCurrVariationFactor ) / std::max( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST );
if((*pfCurrLearningRate)<m_fCurrLearningRateLowerCap) if( ( *pfCurrLearningRate ) < m_fCurrLearningRateLowerCap )
*pfCurrLearningRate = m_fCurrLearningRateLowerCap; *pfCurrLearningRate = m_fCurrLearningRateLowerCap;
else if((*pfCurrLearningRate)>m_fCurrLearningRateUpperCap) else if( ( *pfCurrLearningRate ) > m_fCurrLearningRateUpperCap )
*pfCurrLearningRate = m_fCurrLearningRateUpperCap; *pfCurrLearningRate = m_fCurrLearningRateUpperCap;
if(std::max(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)>UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[idx_uchar]) if( std::max( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[idx_uchar] )
(*pfCurrVariationFactor) += FEEDBACK_V_INCR; ( *pfCurrVariationFactor ) += FEEDBACK_V_INCR;
else if((*pfCurrVariationFactor)>FEEDBACK_V_DECR) { else if( ( *pfCurrVariationFactor ) > FEEDBACK_V_DECR )
(*pfCurrVariationFactor) -= m_oFGMask_last.data[idx_uchar]?FEEDBACK_V_DECR/4:m_oUnstableRegionMask.data[idx_uchar]?FEEDBACK_V_DECR/2:FEEDBACK_V_DECR; {
if((*pfCurrVariationFactor)<FEEDBACK_V_DECR) ( *pfCurrVariationFactor ) -= m_oFGMask_last.data[idx_uchar] ? FEEDBACK_V_DECR / 4 :
(*pfCurrVariationFactor) = FEEDBACK_V_DECR; m_oUnstableRegionMask.data[idx_uchar] ? FEEDBACK_V_DECR / 2 : FEEDBACK_V_DECR;
} if( ( *pfCurrVariationFactor ) < FEEDBACK_V_DECR )
if((*pfCurrDistThresholdFactor)<std::pow(1.0f+std::min(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)*2,2)) ( *pfCurrVariationFactor ) = FEEDBACK_V_DECR;
(*pfCurrDistThresholdFactor) += FEEDBACK_R_VAR*(*pfCurrVariationFactor-FEEDBACK_V_DECR); }
else { if( ( *pfCurrDistThresholdFactor ) < std::pow( 1.0f + std::min( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) * 2, 2 ) )
(*pfCurrDistThresholdFactor) -= FEEDBACK_R_VAR/(*pfCurrVariationFactor); ( *pfCurrDistThresholdFactor ) += FEEDBACK_R_VAR * ( *pfCurrVariationFactor - FEEDBACK_V_DECR );
if((*pfCurrDistThresholdFactor)<1.0f) else
(*pfCurrDistThresholdFactor) = 1.0f; {
} ( *pfCurrDistThresholdFactor ) -= FEEDBACK_R_VAR / ( *pfCurrVariationFactor );
if(popcount_ushort_8bitsLUT(nCurrIntraDesc)>=2) if( ( *pfCurrDistThresholdFactor ) < 1.0f )
( *pfCurrDistThresholdFactor ) = 1.0f;
}
if( popcount_ushort_8bitsLUT( nCurrIntraDesc ) >= 2 )
++nNonZeroDescCount; ++nNonZeroDescCount;
nLastIntraDesc = nCurrIntraDesc; nLastIntraDesc = nCurrIntraDesc;
nLastColor = nCurrColor; nLastColor = nCurrColor;
} }
} }
else { //m_nImgChannels==3 else
for(size_t k=0; k<m_nKeyPoints; ++k) { { //m_nImgChannels==3
const int x = (int)m_voKeyPoints[k].pt.x; for ( size_t k = 0; k < m_nKeyPoints; ++k )
const int y = (int)m_voKeyPoints[k].pt.y; {
const size_t idx_uchar = m_oImgSize.width*y + x; const int x = (int) m_voKeyPoints[k].pt.x;
const size_t idx_flt32 = idx_uchar*4; const int y = (int) m_voKeyPoints[k].pt.y;
const size_t idx_uchar_rgb = idx_uchar*3; const size_t idx_uchar = m_oImgSize.width * y + x;
const size_t idx_ushrt_rgb = idx_uchar_rgb*2; const size_t idx_flt32 = idx_uchar * 4;
const uchar* const anCurrColor = oInputImg.data+idx_uchar_rgb; const size_t idx_uchar_rgb = idx_uchar * 3;
size_t nMinTotDescDist=s_nDescMaxDataRange_3ch; const size_t idx_ushrt_rgb = idx_uchar_rgb * 2;
size_t nMinTotSumDist=s_nColorMaxDataRange_3ch; const uchar* const anCurrColor = oInputImg.data + idx_uchar_rgb;
float* pfCurrDistThresholdFactor = (float*)(m_oDistThresholdFrame.data+idx_flt32); size_t nMinTotDescDist = s_nDescMaxDataRange_3ch;
float* pfCurrVariationFactor = (float*)(m_oVariationModulatorFrame.data+idx_flt32); size_t nMinTotSumDist = s_nColorMaxDataRange_3ch;
float* pfCurrLearningRate = ((float*)(m_oUpdateRateFrame.data+idx_flt32)); float* pfCurrDistThresholdFactor = (float*) ( m_oDistThresholdFrame.data + idx_flt32 );
float* pfCurrMeanLastDist = ((float*)(m_oMeanLastDistFrame.data+idx_flt32)); float* pfCurrVariationFactor = (float*) ( m_oVariationModulatorFrame.data + idx_flt32 );
float* pfCurrMeanMinDist_LT = ((float*)(m_oMeanMinDistFrame_LT.data+idx_flt32)); float* pfCurrLearningRate = ( (float*) ( m_oUpdateRateFrame.data + idx_flt32 ) );
float* pfCurrMeanMinDist_ST = ((float*)(m_oMeanMinDistFrame_ST.data+idx_flt32)); float* pfCurrMeanLastDist = ( (float*) ( m_oMeanLastDistFrame.data + idx_flt32 ) );
float* pfCurrMeanRawSegmRes_LT = ((float*)(m_oMeanRawSegmResFrame_LT.data+idx_flt32)); float* pfCurrMeanMinDist_LT = ( (float*) ( m_oMeanMinDistFrame_LT.data + idx_flt32 ) );
float* pfCurrMeanRawSegmRes_ST = ((float*)(m_oMeanRawSegmResFrame_ST.data+idx_flt32)); float* pfCurrMeanMinDist_ST = ( (float*) ( m_oMeanMinDistFrame_ST.data + idx_flt32 ) );
float* pfCurrMeanFinalSegmRes_LT = ((float*)(m_oMeanFinalSegmResFrame_LT.data+idx_flt32)); float* pfCurrMeanRawSegmRes_LT = ( (float*) ( m_oMeanRawSegmResFrame_LT.data + idx_flt32 ) );
float* pfCurrMeanFinalSegmRes_ST = ((float*)(m_oMeanFinalSegmResFrame_ST.data+idx_flt32)); float* pfCurrMeanRawSegmRes_ST = ( (float*) ( m_oMeanRawSegmResFrame_ST.data + idx_flt32 ) );
ushort* anLastIntraDesc = ((ushort*)(m_oLastDescFrame.data+idx_ushrt_rgb)); float* pfCurrMeanFinalSegmRes_LT = ( (float*) ( m_oMeanFinalSegmResFrame_LT.data + idx_flt32 ) );
uchar* anLastColor = m_oLastColorFrame.data+idx_uchar_rgb; float* pfCurrMeanFinalSegmRes_ST = ( (float*) ( m_oMeanFinalSegmResFrame_ST.data + idx_flt32 ) );
const size_t nCurrColorDistThreshold = (size_t)(((*pfCurrDistThresholdFactor)*m_nMinColorDistThreshold)-((!m_oUnstableRegionMask.data[idx_uchar])*STAB_COLOR_DIST_OFFSET)); ushort* anLastIntraDesc = ( (ushort*) ( m_oLastDescFrame.data + idx_ushrt_rgb ) );
const size_t nCurrDescDistThreshold = ((size_t)1<<((size_t)floor(*pfCurrDistThresholdFactor+0.5f)))+m_nDescDistThreshold+(m_oUnstableRegionMask.data[idx_uchar]*UNSTAB_DESC_DIST_OFFSET); uchar* anLastColor = m_oLastColorFrame.data + idx_uchar_rgb;
const size_t nCurrTotColorDistThreshold = nCurrColorDistThreshold*3; const size_t nCurrColorDistThreshold = (size_t) ( ( ( *pfCurrDistThresholdFactor ) * m_nMinColorDistThreshold )
const size_t nCurrTotDescDistThreshold = nCurrDescDistThreshold*3; - ( ( !m_oUnstableRegionMask.data[idx_uchar] ) * STAB_COLOR_DIST_OFFSET ) );
const size_t nCurrSCColorDistThreshold = nCurrTotColorDistThreshold/2; const size_t nCurrDescDistThreshold = ( (size_t) 1 << ( (size_t) floor( *pfCurrDistThresholdFactor + 0.5f ) ) ) + m_nDescDistThreshold
+ ( m_oUnstableRegionMask.data[idx_uchar] * UNSTAB_DESC_DIST_OFFSET );
const size_t nCurrTotColorDistThreshold = nCurrColorDistThreshold * 3;
const size_t nCurrTotDescDistThreshold = nCurrDescDistThreshold * 3;
const size_t nCurrSCColorDistThreshold = nCurrTotColorDistThreshold / 2;
ushort anCurrInterDesc[3], anCurrIntraDesc[3]; ushort anCurrInterDesc[3], anCurrIntraDesc[3];
const size_t anCurrIntraLBSPThresholds[3] = {m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]]}; const size_t anCurrIntraLBSPThresholds[3] =
LBSP::computeRGBDescriptor(oInputImg,anCurrColor,x,y,anCurrIntraLBSPThresholds,anCurrIntraDesc); { m_anLBSPThreshold_8bitLUT[anCurrColor[0]], m_anLBSPThreshold_8bitLUT[anCurrColor[1]], m_anLBSPThreshold_8bitLUT[anCurrColor[2]] };
m_oUnstableRegionMask.data[idx_uchar] = ((*pfCurrDistThresholdFactor)>UNSTABLE_REG_RDIST_MIN || (*pfCurrMeanRawSegmRes_LT-*pfCurrMeanFinalSegmRes_LT)>UNSTABLE_REG_RATIO_MIN || (*pfCurrMeanRawSegmRes_ST-*pfCurrMeanFinalSegmRes_ST)>UNSTABLE_REG_RATIO_MIN)?1:0; LBSP::computeRGBDescriptor( oInputImg, anCurrColor, x, y, anCurrIntraLBSPThresholds, anCurrIntraDesc );
size_t nGoodSamplesCount=0, nSampleIdx=0; m_oUnstableRegionMask.data[idx_uchar] =
while(nGoodSamplesCount<m_nRequiredBGSamples && nSampleIdx<m_nBGSamples) { ( ( *pfCurrDistThresholdFactor ) > UNSTABLE_REG_RDIST_MIN
const ushort* const anBGIntraDesc = (ushort*)(m_voBGDescSamples[nSampleIdx].data+idx_ushrt_rgb); || ( *pfCurrMeanRawSegmRes_LT - *pfCurrMeanFinalSegmRes_LT ) > UNSTABLE_REG_RATIO_MIN
const uchar* const anBGColor = m_voBGColorSamples[nSampleIdx].data+idx_uchar_rgb; || ( *pfCurrMeanRawSegmRes_ST - *pfCurrMeanFinalSegmRes_ST ) > UNSTABLE_REG_RATIO_MIN ) ? 1 : 0;
size_t nGoodSamplesCount = 0, nSampleIdx = 0;
while ( nGoodSamplesCount < m_nRequiredBGSamples && nSampleIdx < m_nBGSamples )
{
const ushort* const anBGIntraDesc = (ushort*) ( m_voBGDescSamples[nSampleIdx].data + idx_ushrt_rgb );
const uchar* const anBGColor = m_voBGColorSamples[nSampleIdx].data + idx_uchar_rgb;
size_t nTotDescDist = 0; size_t nTotDescDist = 0;
size_t nTotSumDist = 0; size_t nTotSumDist = 0;
for(size_t c=0;c<3; ++c) { for ( size_t c = 0; c < 3; ++c )
const size_t nColorDist = absdiff_uchar(anCurrColor[c],anBGColor[c]); {
if(nColorDist>nCurrSCColorDistThreshold) const size_t nColorDist = absdiff_uchar( anCurrColor[c], anBGColor[c] );
if( nColorDist > nCurrSCColorDistThreshold )
goto failedcheck3ch; goto failedcheck3ch;
size_t nIntraDescDist = hdist_ushort_8bitLUT(anCurrIntraDesc[c],anBGIntraDesc[c]); size_t nIntraDescDist = hdist_ushort_8bitLUT( anCurrIntraDesc[c], anBGIntraDesc[c] );
LBSP::computeSingleRGBDescriptor(oInputImg,anBGColor[c],x,y,c,m_anLBSPThreshold_8bitLUT[anBGColor[c]],anCurrInterDesc[c]); LBSP::computeSingleRGBDescriptor( oInputImg, anBGColor[c], x, y, c, m_anLBSPThreshold_8bitLUT[anBGColor[c]], anCurrInterDesc[c] );
size_t nInterDescDist = hdist_ushort_8bitLUT(anCurrInterDesc[c],anBGIntraDesc[c]); size_t nInterDescDist = hdist_ushort_8bitLUT( anCurrInterDesc[c], anBGIntraDesc[c] );
const size_t nDescDist = (nIntraDescDist+nInterDescDist)/2; const size_t nDescDist = ( nIntraDescDist + nInterDescDist ) / 2;
const size_t nSumDist = std::min((nDescDist/2)*(s_nColorMaxDataRange_1ch/s_nDescMaxDataRange_1ch)+nColorDist,s_nColorMaxDataRange_1ch); const size_t nSumDist = std::min( ( nDescDist / 2 ) * ( s_nColorMaxDataRange_1ch / s_nDescMaxDataRange_1ch ) + nColorDist,
if(nSumDist>nCurrSCColorDistThreshold) s_nColorMaxDataRange_1ch );
if( nSumDist > nCurrSCColorDistThreshold )
goto failedcheck3ch; goto failedcheck3ch;
nTotDescDist += nDescDist; nTotDescDist += nDescDist;
nTotSumDist += nSumDist; nTotSumDist += nSumDist;
} }
if(nTotDescDist>nCurrTotDescDistThreshold || nTotSumDist>nCurrTotColorDistThreshold) if( nTotDescDist > nCurrTotDescDistThreshold || nTotSumDist > nCurrTotColorDistThreshold )
goto failedcheck3ch; goto failedcheck3ch;
if(nMinTotDescDist>nTotDescDist) if( nMinTotDescDist > nTotDescDist )
nMinTotDescDist = nTotDescDist; nMinTotDescDist = nTotDescDist;
if(nMinTotSumDist>nTotSumDist) if( nMinTotSumDist > nTotSumDist )
nMinTotSumDist = nTotSumDist; nMinTotSumDist = nTotSumDist;
nGoodSamplesCount++; nGoodSamplesCount++;
failedcheck3ch: failedcheck3ch : nSampleIdx++;
nSampleIdx++;
} }
const float fNormalizedLastDist = ((float)L1dist_uchar(anLastColor,anCurrColor)/s_nColorMaxDataRange_3ch+(float)hdist_ushort_8bitLUT(anLastIntraDesc,anCurrIntraDesc)/s_nDescMaxDataRange_3ch)/2; const float fNormalizedLastDist = ( (float) L1dist_uchar( anLastColor, anCurrColor ) / s_nColorMaxDataRange_3ch
*pfCurrMeanLastDist = (*pfCurrMeanLastDist)*(1.0f-fRollAvgFactor_ST) + fNormalizedLastDist*fRollAvgFactor_ST; + (float) hdist_ushort_8bitLUT( anLastIntraDesc, anCurrIntraDesc ) / s_nDescMaxDataRange_3ch ) / 2;
if(nGoodSamplesCount<m_nRequiredBGSamples) { *pfCurrMeanLastDist = ( *pfCurrMeanLastDist ) * ( 1.0f - fRollAvgFactor_ST ) + fNormalizedLastDist * fRollAvgFactor_ST;
if( nGoodSamplesCount < m_nRequiredBGSamples )
{
// == foreground // == foreground
const float fNormalizedMinDist = std::min(1.0f,((float)nMinTotSumDist/s_nColorMaxDataRange_3ch+(float)nMinTotDescDist/s_nDescMaxDataRange_3ch)/2 + (float)(m_nRequiredBGSamples-nGoodSamplesCount)/m_nRequiredBGSamples); const float fNormalizedMinDist = std::min(
*pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f-fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT; 1.0f,
*pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f-fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST; ( (float) nMinTotSumDist / s_nColorMaxDataRange_3ch + (float) nMinTotDescDist / s_nDescMaxDataRange_3ch ) / 2
*pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f-fRollAvgFactor_LT) + fRollAvgFactor_LT; + (float) ( m_nRequiredBGSamples - nGoodSamplesCount ) / m_nRequiredBGSamples );
*pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f-fRollAvgFactor_ST) + fRollAvgFactor_ST; *pfCurrMeanMinDist_LT = ( *pfCurrMeanMinDist_LT ) * ( 1.0f - fRollAvgFactor_LT ) + fNormalizedMinDist * fRollAvgFactor_LT;
*pfCurrMeanMinDist_ST = ( *pfCurrMeanMinDist_ST ) * ( 1.0f - fRollAvgFactor_ST ) + fNormalizedMinDist * fRollAvgFactor_ST;
*pfCurrMeanRawSegmRes_LT = ( *pfCurrMeanRawSegmRes_LT ) * ( 1.0f - fRollAvgFactor_LT ) + fRollAvgFactor_LT;
*pfCurrMeanRawSegmRes_ST = ( *pfCurrMeanRawSegmRes_ST ) * ( 1.0f - fRollAvgFactor_ST ) + fRollAvgFactor_ST;
oCurrFGMask.data[idx_uchar] = UCHAR_MAX; oCurrFGMask.data[idx_uchar] = UCHAR_MAX;
if(m_nModelResetCooldown && (rand()%(size_t)FEEDBACK_T_LOWER)==0) { if( m_nModelResetCooldown && ( rand() % (size_t) FEEDBACK_T_LOWER ) == 0 )
const size_t s_rand = rand()%m_nBGSamples; {
for(size_t c=0; c<3; ++c) { const size_t s_rand = rand() % m_nBGSamples;
*((ushort*)(m_voBGDescSamples[s_rand].data+idx_ushrt_rgb+2*c)) = anCurrIntraDesc[c]; for ( size_t c = 0; c < 3; ++c )
*(m_voBGColorSamples[s_rand].data+idx_uchar_rgb+c) = anCurrColor[c]; {
* ( (ushort*) ( m_voBGDescSamples[s_rand].data + idx_ushrt_rgb + 2 * c ) ) = anCurrIntraDesc[c];
* ( m_voBGColorSamples[s_rand].data + idx_uchar_rgb + c ) = anCurrColor[c];
} }
} }
} }
else { else
{
// == background // == background
const float fNormalizedMinDist = ((float)nMinTotSumDist/s_nColorMaxDataRange_3ch+(float)nMinTotDescDist/s_nDescMaxDataRange_3ch)/2; const float fNormalizedMinDist = ( (float) nMinTotSumDist / s_nColorMaxDataRange_3ch + (float) nMinTotDescDist / s_nDescMaxDataRange_3ch )
*pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f-fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT; / 2;
*pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f-fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST; *pfCurrMeanMinDist_LT = ( *pfCurrMeanMinDist_LT ) * ( 1.0f - fRollAvgFactor_LT ) + fNormalizedMinDist * fRollAvgFactor_LT;
*pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f-fRollAvgFactor_LT); *pfCurrMeanMinDist_ST = ( *pfCurrMeanMinDist_ST ) * ( 1.0f - fRollAvgFactor_ST ) + fNormalizedMinDist * fRollAvgFactor_ST;
*pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f-fRollAvgFactor_ST); *pfCurrMeanRawSegmRes_LT = ( *pfCurrMeanRawSegmRes_LT ) * ( 1.0f - fRollAvgFactor_LT );
const size_t nLearningRate = learningRateOverride>0?(size_t)ceil(learningRateOverride):(size_t)ceil(*pfCurrLearningRate); *pfCurrMeanRawSegmRes_ST = ( *pfCurrMeanRawSegmRes_ST ) * ( 1.0f - fRollAvgFactor_ST );
if((rand()%nLearningRate)==0) { const size_t nLearningRate = learningRateOverride > 0 ? (size_t) ceil( learningRateOverride ) : (size_t) ceil( *pfCurrLearningRate );
const size_t s_rand = rand()%m_nBGSamples; if( ( rand() % nLearningRate ) == 0 )
for(size_t c=0; c<3; ++c) { {
*((ushort*)(m_voBGDescSamples[s_rand].data+idx_ushrt_rgb+2*c)) = anCurrIntraDesc[c]; const size_t s_rand = rand() % m_nBGSamples;
*(m_voBGColorSamples[s_rand].data+idx_uchar_rgb+c) = anCurrColor[c]; for ( size_t c = 0; c < 3; ++c )
} {
} * ( (ushort*) ( m_voBGDescSamples[s_rand].data + idx_ushrt_rgb + 2 * c ) ) = anCurrIntraDesc[c];
int x_rand,y_rand; * ( m_voBGColorSamples[s_rand].data + idx_uchar_rgb + c ) = anCurrColor[c];
}
}
int x_rand, y_rand;
const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[idx_uchar]; const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[idx_uchar];
if(bCurrUsing3x3Spread) if( bCurrUsing3x3Spread )
getRandNeighborPosition_3x3(x_rand,y_rand,x,y,LBSP::PATCH_SIZE/2,m_oImgSize); getRandNeighborPosition_3x3( x_rand, y_rand, x, y, LBSP::PATCH_SIZE / 2, m_oImgSize );
else else
getRandNeighborPosition_5x5(x_rand,y_rand,x,y,LBSP::PATCH_SIZE/2,m_oImgSize); getRandNeighborPosition_5x5( x_rand, y_rand, x, y, LBSP::PATCH_SIZE / 2, m_oImgSize );
const size_t n_rand = rand(); const size_t n_rand = rand();
const size_t idx_rand_uchar = m_oImgSize.width*y_rand + x_rand; const size_t idx_rand_uchar = m_oImgSize.width * y_rand + x_rand;
const size_t idx_rand_flt32 = idx_rand_uchar*4; const size_t idx_rand_flt32 = idx_rand_uchar * 4;
const float fRandMeanLastDist = *((float*)(m_oMeanLastDistFrame.data+idx_rand_flt32)); const float fRandMeanLastDist = * ( (float*) ( m_oMeanLastDistFrame.data + idx_rand_flt32 ) );
const float fRandMeanRawSegmRes = *((float*)(m_oMeanRawSegmResFrame_ST.data+idx_rand_flt32)); const float fRandMeanRawSegmRes = * ( (float*) ( m_oMeanRawSegmResFrame_ST.data + idx_rand_flt32 ) );
if((n_rand%(bCurrUsing3x3Spread?nLearningRate:(nLearningRate/2+1)))==0 if( ( n_rand % ( bCurrUsing3x3Spread ? nLearningRate : ( nLearningRate / 2 + 1 ) ) ) == 0
|| (fRandMeanRawSegmRes>GHOSTDET_S_MIN && fRandMeanLastDist<GHOSTDET_D_MAX && (n_rand%((size_t)m_fCurrLearningRateLowerCap))==0)) { || ( fRandMeanRawSegmRes > GHOSTDET_S_MIN && fRandMeanLastDist < GHOSTDET_D_MAX
const size_t idx_rand_uchar_rgb = idx_rand_uchar*3; && ( n_rand % ( (size_t) m_fCurrLearningRateLowerCap ) ) == 0 ) )
const size_t idx_rand_ushrt_rgb = idx_rand_uchar_rgb*2; {
const size_t s_rand = rand()%m_nBGSamples; const size_t idx_rand_uchar_rgb = idx_rand_uchar * 3;
for(size_t c=0; c<3; ++c) { const size_t idx_rand_ushrt_rgb = idx_rand_uchar_rgb * 2;
*((ushort*)(m_voBGDescSamples[s_rand].data+idx_rand_ushrt_rgb+2*c)) = anCurrIntraDesc[c]; const size_t s_rand = rand() % m_nBGSamples;
*(m_voBGColorSamples[s_rand].data+idx_rand_uchar_rgb+c) = anCurrColor[c]; for ( size_t c = 0; c < 3; ++c )
} {
} * ( (ushort*) ( m_voBGDescSamples[s_rand].data + idx_rand_ushrt_rgb + 2 * c ) ) = anCurrIntraDesc[c];
} * ( m_voBGColorSamples[s_rand].data + idx_rand_uchar_rgb + c ) = anCurrColor[c];
if(m_oFGMask_last.data[idx_uchar] || (std::min(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)<UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[idx_uchar])) { }
if((*pfCurrLearningRate)<m_fCurrLearningRateUpperCap) }
*pfCurrLearningRate += FEEDBACK_T_INCR/(std::max(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)*(*pfCurrVariationFactor)); }
} if( m_oFGMask_last.data[idx_uchar]
else if((*pfCurrLearningRate)>m_fCurrLearningRateLowerCap) || ( std::min( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) < UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[idx_uchar] ) )
*pfCurrLearningRate -= FEEDBACK_T_DECR*(*pfCurrVariationFactor)/std::max(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST); {
if((*pfCurrLearningRate)<m_fCurrLearningRateLowerCap) if( ( *pfCurrLearningRate ) < m_fCurrLearningRateUpperCap )
*pfCurrLearningRate += FEEDBACK_T_INCR / ( std::max( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) * ( *pfCurrVariationFactor ) );
}
else if( ( *pfCurrLearningRate ) > m_fCurrLearningRateLowerCap )
*pfCurrLearningRate -= FEEDBACK_T_DECR * ( *pfCurrVariationFactor ) / std::max( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST );
if( ( *pfCurrLearningRate ) < m_fCurrLearningRateLowerCap )
*pfCurrLearningRate = m_fCurrLearningRateLowerCap; *pfCurrLearningRate = m_fCurrLearningRateLowerCap;
else if((*pfCurrLearningRate)>m_fCurrLearningRateUpperCap) else if( ( *pfCurrLearningRate ) > m_fCurrLearningRateUpperCap )
*pfCurrLearningRate = m_fCurrLearningRateUpperCap; *pfCurrLearningRate = m_fCurrLearningRateUpperCap;
if(std::max(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)>UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[idx_uchar]) if( std::max( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[idx_uchar] )
(*pfCurrVariationFactor) += FEEDBACK_V_INCR; ( *pfCurrVariationFactor ) += FEEDBACK_V_INCR;
else if((*pfCurrVariationFactor)>FEEDBACK_V_DECR) { else if( ( *pfCurrVariationFactor ) > FEEDBACK_V_DECR )
(*pfCurrVariationFactor) -= m_oFGMask_last.data[idx_uchar]?FEEDBACK_V_DECR/4:m_oUnstableRegionMask.data[idx_uchar]?FEEDBACK_V_DECR/2:FEEDBACK_V_DECR; {
if((*pfCurrVariationFactor)<FEEDBACK_V_DECR) ( *pfCurrVariationFactor ) -= m_oFGMask_last.data[idx_uchar] ? FEEDBACK_V_DECR / 4 :
(*pfCurrVariationFactor) = FEEDBACK_V_DECR; m_oUnstableRegionMask.data[idx_uchar] ? FEEDBACK_V_DECR / 2 : FEEDBACK_V_DECR;
} if( ( *pfCurrVariationFactor ) < FEEDBACK_V_DECR )
if((*pfCurrDistThresholdFactor)<std::pow(1.0f+std::min(*pfCurrMeanMinDist_LT,*pfCurrMeanMinDist_ST)*2,2)) ( *pfCurrVariationFactor ) = FEEDBACK_V_DECR;
(*pfCurrDistThresholdFactor) += FEEDBACK_R_VAR*(*pfCurrVariationFactor-FEEDBACK_V_DECR); }
else { if( ( *pfCurrDistThresholdFactor ) < std::pow( 1.0f + std::min( *pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST ) * 2, 2 ) )
(*pfCurrDistThresholdFactor) -= FEEDBACK_R_VAR/(*pfCurrVariationFactor); ( *pfCurrDistThresholdFactor ) += FEEDBACK_R_VAR * ( *pfCurrVariationFactor - FEEDBACK_V_DECR );
if((*pfCurrDistThresholdFactor)<1.0f) else
(*pfCurrDistThresholdFactor) = 1.0f; {
} ( *pfCurrDistThresholdFactor ) -= FEEDBACK_R_VAR / ( *pfCurrVariationFactor );
if(popcount_ushort_8bitsLUT(anCurrIntraDesc)>=4) if( ( *pfCurrDistThresholdFactor ) < 1.0f )
( *pfCurrDistThresholdFactor ) = 1.0f;
}
if( popcount_ushort_8bitsLUT( anCurrIntraDesc ) >= 4 )
++nNonZeroDescCount; ++nNonZeroDescCount;
for(size_t c=0; c<3; ++c) { for ( size_t c = 0; c < 3; ++c )
{
anLastIntraDesc[c] = anCurrIntraDesc[c]; anLastIntraDesc[c] = anCurrIntraDesc[c];
anLastColor[c] = anCurrColor[c]; anLastColor[c] = anCurrColor[c];
} }
...@@ -635,140 +716,167 @@ void MotionSaliencySuBSENSE::operator()(cv::InputArray _image, cv::OutputArray _ ...@@ -635,140 +716,167 @@ void MotionSaliencySuBSENSE::operator()(cv::InputArray _image, cv::OutputArray _
} }
#if DISPLAY_SUBSENSE_DEBUG_INFO #if DISPLAY_SUBSENSE_DEBUG_INFO
std::cout << std::endl; std::cout << std::endl;
cv::Point dbgpt(nDebugCoordX,nDebugCoordY); Point dbgpt(nDebugCoordX,nDebugCoordY);
cv::Mat oMeanMinDistFrameNormalized; m_oMeanMinDistFrame_ST.copyTo(oMeanMinDistFrameNormalized); Mat oMeanMinDistFrameNormalized; m_oMeanMinDistFrame_ST.copyTo(oMeanMinDistFrameNormalized);
cv::circle(oMeanMinDistFrameNormalized,dbgpt,5,cv::Scalar(1.0f)); circle(oMeanMinDistFrameNormalized,dbgpt,5,Scalar(1.0f));
cv::resize(oMeanMinDistFrameNormalized,oMeanMinDistFrameNormalized,DEFAULT_FRAME_SIZE); resize(oMeanMinDistFrameNormalized,oMeanMinDistFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("d_min(x)",oMeanMinDistFrameNormalized); imshow("d_min(x)",oMeanMinDistFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " d_min(" << dbgpt << ") = " << m_oMeanMinDistFrame_ST.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " d_min(" << dbgpt << ") = " << m_oMeanMinDistFrame_ST.at<float>(dbgpt) << std::endl;
cv::Mat oMeanLastDistFrameNormalized; m_oMeanLastDistFrame.copyTo(oMeanLastDistFrameNormalized); Mat oMeanLastDistFrameNormalized; m_oMeanLastDistFrame.copyTo(oMeanLastDistFrameNormalized);
cv::circle(oMeanLastDistFrameNormalized,dbgpt,5,cv::Scalar(1.0f)); circle(oMeanLastDistFrameNormalized,dbgpt,5,Scalar(1.0f));
cv::resize(oMeanLastDistFrameNormalized,oMeanLastDistFrameNormalized,DEFAULT_FRAME_SIZE); resize(oMeanLastDistFrameNormalized,oMeanLastDistFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("d_last(x)",oMeanLastDistFrameNormalized); imshow("d_last(x)",oMeanLastDistFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " d_last(" << dbgpt << ") = " << m_oMeanLastDistFrame.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " d_last(" << dbgpt << ") = " << m_oMeanLastDistFrame.at<float>(dbgpt) << std::endl;
cv::Mat oMeanRawSegmResFrameNormalized; m_oMeanRawSegmResFrame_ST.copyTo(oMeanRawSegmResFrameNormalized); Mat oMeanRawSegmResFrameNormalized; m_oMeanRawSegmResFrame_ST.copyTo(oMeanRawSegmResFrameNormalized);
cv::circle(oMeanRawSegmResFrameNormalized,dbgpt,5,cv::Scalar(1.0f)); circle(oMeanRawSegmResFrameNormalized,dbgpt,5,Scalar(1.0f));
cv::resize(oMeanRawSegmResFrameNormalized,oMeanRawSegmResFrameNormalized,DEFAULT_FRAME_SIZE); resize(oMeanRawSegmResFrameNormalized,oMeanRawSegmResFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("s_avg(x)",oMeanRawSegmResFrameNormalized); imshow("s_avg(x)",oMeanRawSegmResFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " s_avg(" << dbgpt << ") = " << m_oMeanRawSegmResFrame_ST.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " s_avg(" << dbgpt << ") = " << m_oMeanRawSegmResFrame_ST.at<float>(dbgpt) << std::endl;
cv::Mat oMeanFinalSegmResFrameNormalized; m_oMeanFinalSegmResFrame_ST.copyTo(oMeanFinalSegmResFrameNormalized); Mat oMeanFinalSegmResFrameNormalized; m_oMeanFinalSegmResFrame_ST.copyTo(oMeanFinalSegmResFrameNormalized);
cv::circle(oMeanFinalSegmResFrameNormalized,dbgpt,5,cv::Scalar(1.0f)); circle(oMeanFinalSegmResFrameNormalized,dbgpt,5,Scalar(1.0f));
cv::resize(oMeanFinalSegmResFrameNormalized,oMeanFinalSegmResFrameNormalized,DEFAULT_FRAME_SIZE); resize(oMeanFinalSegmResFrameNormalized,oMeanFinalSegmResFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("z_avg(x)",oMeanFinalSegmResFrameNormalized); imshow("z_avg(x)",oMeanFinalSegmResFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " z_avg(" << dbgpt << ") = " << m_oMeanFinalSegmResFrame_ST.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " z_avg(" << dbgpt << ") = " << m_oMeanFinalSegmResFrame_ST.at<float>(dbgpt) << std::endl;
cv::Mat oDistThresholdFrameNormalized; m_oDistThresholdFrame.convertTo(oDistThresholdFrameNormalized,CV_32FC1,0.25f,-0.25f); Mat oDistThresholdFrameNormalized; m_oDistThresholdFrame.convertTo(oDistThresholdFrameNormalized,CV_32FC1,0.25f,-0.25f);
cv::circle(oDistThresholdFrameNormalized,dbgpt,5,cv::Scalar(1.0f)); circle(oDistThresholdFrameNormalized,dbgpt,5,Scalar(1.0f));
cv::resize(oDistThresholdFrameNormalized,oDistThresholdFrameNormalized,DEFAULT_FRAME_SIZE); resize(oDistThresholdFrameNormalized,oDistThresholdFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("r(x)",oDistThresholdFrameNormalized); imshow("r(x)",oDistThresholdFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " r(" << dbgpt << ") = " << m_oDistThresholdFrame.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " r(" << dbgpt << ") = " << m_oDistThresholdFrame.at<float>(dbgpt) << std::endl;
cv::Mat oVariationModulatorFrameNormalized; cv::normalize(m_oVariationModulatorFrame,oVariationModulatorFrameNormalized,0,255,cv::NORM_MINMAX,CV_8UC1); Mat oVariationModulatorFrameNormalized; normalize(m_oVariationModulatorFrame,oVariationModulatorFrameNormalized,0,255,NORM_MINMAX,CV_8UC1);
cv::circle(oVariationModulatorFrameNormalized,dbgpt,5,cv::Scalar(255)); circle(oVariationModulatorFrameNormalized,dbgpt,5,Scalar(255));
cv::resize(oVariationModulatorFrameNormalized,oVariationModulatorFrameNormalized,DEFAULT_FRAME_SIZE); resize(oVariationModulatorFrameNormalized,oVariationModulatorFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("v(x)",oVariationModulatorFrameNormalized); imshow("v(x)",oVariationModulatorFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " v(" << dbgpt << ") = " << m_oVariationModulatorFrame.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " v(" << dbgpt << ") = " << m_oVariationModulatorFrame.at<float>(dbgpt) << std::endl;
cv::Mat oUpdateRateFrameNormalized; m_oUpdateRateFrame.convertTo(oUpdateRateFrameNormalized,CV_32FC1,1.0f/FEEDBACK_T_UPPER,-FEEDBACK_T_LOWER/FEEDBACK_T_UPPER); Mat oUpdateRateFrameNormalized; m_oUpdateRateFrame.convertTo(oUpdateRateFrameNormalized,CV_32FC1,1.0f/FEEDBACK_T_UPPER,-FEEDBACK_T_LOWER/FEEDBACK_T_UPPER);
cv::circle(oUpdateRateFrameNormalized,dbgpt,5,cv::Scalar(1.0f)); circle(oUpdateRateFrameNormalized,dbgpt,5,Scalar(1.0f));
cv::resize(oUpdateRateFrameNormalized,oUpdateRateFrameNormalized,DEFAULT_FRAME_SIZE); resize(oUpdateRateFrameNormalized,oUpdateRateFrameNormalized,DEFAULT_FRAME_SIZE);
cv::imshow("t(x)",oUpdateRateFrameNormalized); imshow("t(x)",oUpdateRateFrameNormalized);
std::cout << std::fixed << std::setprecision(5) << " t(" << dbgpt << ") = " << m_oUpdateRateFrame.at<float>(dbgpt) << std::endl; std::cout << std::fixed << std::setprecision(5) << " t(" << dbgpt << ") = " << m_oUpdateRateFrame.at<float>(dbgpt) << std::endl;
#endif //DISPLAY_SUBSENSE_DEBUG_INFO #endif //DISPLAY_SUBSENSE_DEBUG_INFO
cv::bitwise_xor(oCurrFGMask,m_oRawFGMask_last,m_oRawFGBlinkMask_curr); bitwise_xor( oCurrFGMask, m_oRawFGMask_last, m_oRawFGBlinkMask_curr );
cv::bitwise_or(m_oRawFGBlinkMask_curr,m_oRawFGBlinkMask_last,m_oBlinksFrame); bitwise_or( m_oRawFGBlinkMask_curr, m_oRawFGBlinkMask_last, m_oBlinksFrame );
m_oRawFGBlinkMask_curr.copyTo(m_oRawFGBlinkMask_last); m_oRawFGBlinkMask_curr.copyTo( m_oRawFGBlinkMask_last );
oCurrFGMask.copyTo(m_oRawFGMask_last); oCurrFGMask.copyTo( m_oRawFGMask_last );
cv::morphologyEx(oCurrFGMask,m_oFGMask_PreFlood,cv::MORPH_CLOSE,cv::Mat()); morphologyEx( oCurrFGMask, m_oFGMask_PreFlood, MORPH_CLOSE, Mat() );
m_oFGMask_PreFlood.copyTo(m_oFGMask_FloodedHoles); m_oFGMask_PreFlood.copyTo( m_oFGMask_FloodedHoles );
cv::floodFill(m_oFGMask_FloodedHoles,cv::Point(0,0),UCHAR_MAX); floodFill( m_oFGMask_FloodedHoles, Point( 0, 0 ), UCHAR_MAX );
cv::bitwise_not(m_oFGMask_FloodedHoles,m_oFGMask_FloodedHoles); bitwise_not( m_oFGMask_FloodedHoles, m_oFGMask_FloodedHoles );
cv::erode(m_oFGMask_PreFlood,m_oFGMask_PreFlood,cv::Mat(),cv::Point(-1,-1),3); erode( m_oFGMask_PreFlood, m_oFGMask_PreFlood, Mat(), Point( -1, -1 ), 3 );
cv::bitwise_or(oCurrFGMask,m_oFGMask_FloodedHoles,oCurrFGMask); bitwise_or( oCurrFGMask, m_oFGMask_FloodedHoles, oCurrFGMask );
cv::bitwise_or(oCurrFGMask,m_oFGMask_PreFlood,oCurrFGMask); bitwise_or( oCurrFGMask, m_oFGMask_PreFlood, oCurrFGMask );
cv::medianBlur(oCurrFGMask,m_oFGMask_last,m_nMedianBlurKernelSize); medianBlur( oCurrFGMask, m_oFGMask_last, m_nMedianBlurKernelSize );
cv::dilate(m_oFGMask_last,m_oFGMask_last_dilated,cv::Mat(),cv::Point(-1,-1),3); dilate( m_oFGMask_last, m_oFGMask_last_dilated, Mat(), Point( -1, -1 ), 3 );
cv::bitwise_and(m_oBlinksFrame,m_oFGMask_last_dilated_inverted,m_oBlinksFrame); bitwise_and( m_oBlinksFrame, m_oFGMask_last_dilated_inverted, m_oBlinksFrame );
cv::bitwise_not(m_oFGMask_last_dilated,m_oFGMask_last_dilated_inverted); bitwise_not( m_oFGMask_last_dilated, m_oFGMask_last_dilated_inverted );
cv::bitwise_and(m_oBlinksFrame,m_oFGMask_last_dilated_inverted,m_oBlinksFrame); bitwise_and( m_oBlinksFrame, m_oFGMask_last_dilated_inverted, m_oBlinksFrame );
m_oFGMask_last.copyTo(oCurrFGMask); m_oFGMask_last.copyTo( oCurrFGMask );
cv::addWeighted(m_oMeanFinalSegmResFrame_LT,(1.0f-fRollAvgFactor_LT),m_oFGMask_last,(1.0/UCHAR_MAX)*fRollAvgFactor_LT,0,m_oMeanFinalSegmResFrame_LT,CV_32F); addWeighted( m_oMeanFinalSegmResFrame_LT, ( 1.0f - fRollAvgFactor_LT ), m_oFGMask_last, ( 1.0 / UCHAR_MAX ) * fRollAvgFactor_LT, 0,
cv::addWeighted(m_oMeanFinalSegmResFrame_ST,(1.0f-fRollAvgFactor_ST),m_oFGMask_last,(1.0/UCHAR_MAX)*fRollAvgFactor_ST,0,m_oMeanFinalSegmResFrame_ST,CV_32F); m_oMeanFinalSegmResFrame_LT, CV_32F );
const float fCurrNonZeroDescRatio = (float)nNonZeroDescCount/m_nKeyPoints; addWeighted( m_oMeanFinalSegmResFrame_ST, ( 1.0f - fRollAvgFactor_ST ), m_oFGMask_last, ( 1.0 / UCHAR_MAX ) * fRollAvgFactor_ST, 0,
if(fCurrNonZeroDescRatio<LBSPDESC_NONZERO_RATIO_MIN && m_fLastNonZeroDescRatio<LBSPDESC_NONZERO_RATIO_MIN) { m_oMeanFinalSegmResFrame_ST, CV_32F );
for(size_t t=0; t<=UCHAR_MAX; ++t) const float fCurrNonZeroDescRatio = (float) nNonZeroDescCount / m_nKeyPoints;
if(m_anLBSPThreshold_8bitLUT[t]>cv::saturate_cast<uchar>(m_nLBSPThresholdOffset+ceil(t*m_fRelLBSPThreshold/4))) if( fCurrNonZeroDescRatio < LBSPDESC_NONZERO_RATIO_MIN && m_fLastNonZeroDescRatio < LBSPDESC_NONZERO_RATIO_MIN )
{
for ( size_t t = 0; t <= UCHAR_MAX; ++t )
if( m_anLBSPThreshold_8bitLUT[t] > saturate_cast<uchar>( m_nLBSPThresholdOffset + ceil( t * m_fRelLBSPThreshold / 4 ) ) )
--m_anLBSPThreshold_8bitLUT[t]; --m_anLBSPThreshold_8bitLUT[t];
} }
else if(fCurrNonZeroDescRatio>LBSPDESC_NONZERO_RATIO_MAX && m_fLastNonZeroDescRatio>LBSPDESC_NONZERO_RATIO_MAX) { else if( fCurrNonZeroDescRatio > LBSPDESC_NONZERO_RATIO_MAX && m_fLastNonZeroDescRatio > LBSPDESC_NONZERO_RATIO_MAX )
for(size_t t=0; t<=UCHAR_MAX; ++t) {
if(m_anLBSPThreshold_8bitLUT[t]<cv::saturate_cast<uchar>(m_nLBSPThresholdOffset+UCHAR_MAX*m_fRelLBSPThreshold)) for ( size_t t = 0; t <= UCHAR_MAX; ++t )
if( m_anLBSPThreshold_8bitLUT[t] < saturate_cast<uchar>( m_nLBSPThresholdOffset + UCHAR_MAX * m_fRelLBSPThreshold ) )
++m_anLBSPThreshold_8bitLUT[t]; ++m_anLBSPThreshold_8bitLUT[t];
} }
m_fLastNonZeroDescRatio = fCurrNonZeroDescRatio; m_fLastNonZeroDescRatio = fCurrNonZeroDescRatio;
if(m_bLearningRateScalingEnabled) { if( m_bLearningRateScalingEnabled )
cv::resize(oInputImg,m_oDownSampledColorFrame,m_oDownSampledFrameSize,0,0,cv::INTER_AREA); {
cv::accumulateWeighted(m_oDownSampledColorFrame,m_oMeanDownSampledLastDistFrame_LT,fRollAvgFactor_LT); resize( oInputImg, m_oDownSampledColorFrame, m_oDownSampledFrameSize, 0, 0, INTER_AREA );
cv::accumulateWeighted(m_oDownSampledColorFrame,m_oMeanDownSampledLastDistFrame_ST,fRollAvgFactor_ST); accumulateWeighted( m_oDownSampledColorFrame, m_oMeanDownSampledLastDistFrame_LT, fRollAvgFactor_LT );
accumulateWeighted( m_oDownSampledColorFrame, m_oMeanDownSampledLastDistFrame_ST, fRollAvgFactor_ST );
size_t nTotColorDiff = 0; size_t nTotColorDiff = 0;
for(int i=0; i<m_oMeanDownSampledLastDistFrame_ST.rows; ++i) { for ( int i = 0; i < m_oMeanDownSampledLastDistFrame_ST.rows; ++i )
const size_t idx1 = m_oMeanDownSampledLastDistFrame_ST.step.p[0]*i; {
for(int j=0; j<m_oMeanDownSampledLastDistFrame_ST.cols; ++j) { const size_t idx1 = m_oMeanDownSampledLastDistFrame_ST.step.p[0] * i;
const size_t idx2 = idx1+m_oMeanDownSampledLastDistFrame_ST.step.p[1]*j; for ( int j = 0; j < m_oMeanDownSampledLastDistFrame_ST.cols; ++j )
nTotColorDiff += (m_nImgChannels==1)? {
(size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data+idx2))-(*(float*)(m_oMeanDownSampledLastDistFrame_LT.data+idx2)))/2 const size_t idx2 = idx1 + m_oMeanDownSampledLastDistFrame_ST.step.p[1] * j;
: //(m_nImgChannels==3) nTotColorDiff +=
std::max((size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data+idx2))-(*(float*)(m_oMeanDownSampledLastDistFrame_LT.data+idx2))), ( m_nImgChannels == 1 ) ?
std::max((size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data+idx2+4))-(*(float*)(m_oMeanDownSampledLastDistFrame_LT.data+idx2+4))), (size_t) fabs(
(size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data+idx2+8))-(*(float*)(m_oMeanDownSampledLastDistFrame_LT.data+idx2+8))))); ( *(float*) ( m_oMeanDownSampledLastDistFrame_ST.data + idx2 ) )
} - ( *(float*) ( m_oMeanDownSampledLastDistFrame_LT.data + idx2 ) ) ) / 2 : //(m_nImgChannels==3)
} std::max(
const float fCurrColorDiffRatio = (float)nTotColorDiff/(m_oMeanDownSampledLastDistFrame_ST.rows*m_oMeanDownSampledLastDistFrame_ST.cols); (size_t) fabs(
if(m_bAutoModelResetEnabled) { ( *(float*) ( m_oMeanDownSampledLastDistFrame_ST.data + idx2 ) )
if(m_nFramesSinceLastReset>1000) - ( *(float*) ( m_oMeanDownSampledLastDistFrame_LT.data + idx2 ) ) ),
std::max(
(size_t) fabs(
( *(float*) ( m_oMeanDownSampledLastDistFrame_ST.data + idx2 + 4 ) )
- ( *(float*) ( m_oMeanDownSampledLastDistFrame_LT.data + idx2 + 4 ) ) ),
(size_t) fabs(
( *(float*) ( m_oMeanDownSampledLastDistFrame_ST.data + idx2 + 8 ) )
- ( *(float*) ( m_oMeanDownSampledLastDistFrame_LT.data + idx2 + 8 ) ) ) ) );
}
}
const float fCurrColorDiffRatio = (float) nTotColorDiff / ( m_oMeanDownSampledLastDistFrame_ST.rows * m_oMeanDownSampledLastDistFrame_ST.cols );
if( m_bAutoModelResetEnabled )
{
if( m_nFramesSinceLastReset > 1000 )
m_bAutoModelResetEnabled = false; m_bAutoModelResetEnabled = false;
else if(fCurrColorDiffRatio>=FRAMELEVEL_COLOR_DIFF_RESET_THRESHOLD && m_nModelResetCooldown==0) { else if( fCurrColorDiffRatio >= FRAMELEVEL_COLOR_DIFF_RESET_THRESHOLD && m_nModelResetCooldown == 0 )
{
m_nFramesSinceLastReset = 0; m_nFramesSinceLastReset = 0;
refreshModel(0.1f); // reset 10% of the bg model refreshModel( 0.1f ); // reset 10% of the bg model
m_nModelResetCooldown = m_nSamplesForMovingAvgs; m_nModelResetCooldown = m_nSamplesForMovingAvgs;
m_oUpdateRateFrame = cv::Scalar(1.0f); m_oUpdateRateFrame = Scalar( 1.0f );
} }
else else
++m_nFramesSinceLastReset; ++m_nFramesSinceLastReset;
} }
else if(fCurrColorDiffRatio>=FRAMELEVEL_COLOR_DIFF_RESET_THRESHOLD*2) { else if( fCurrColorDiffRatio >= FRAMELEVEL_COLOR_DIFF_RESET_THRESHOLD * 2 )
{
m_nFramesSinceLastReset = 0; m_nFramesSinceLastReset = 0;
m_bAutoModelResetEnabled = true; m_bAutoModelResetEnabled = true;
} }
if(fCurrColorDiffRatio>=FRAMELEVEL_COLOR_DIFF_RESET_THRESHOLD/2) { if( fCurrColorDiffRatio >= FRAMELEVEL_COLOR_DIFF_RESET_THRESHOLD / 2 )
m_fCurrLearningRateLowerCap = (float)std::max((int)FEEDBACK_T_LOWER>>(int)(fCurrColorDiffRatio/2),1); {
m_fCurrLearningRateUpperCap = (float)std::max((int)FEEDBACK_T_UPPER>>(int)(fCurrColorDiffRatio/2),1); m_fCurrLearningRateLowerCap = (float) std::max( (int) FEEDBACK_T_LOWER >> (int) ( fCurrColorDiffRatio / 2 ), 1 );
m_fCurrLearningRateUpperCap = (float) std::max( (int) FEEDBACK_T_UPPER >> (int) ( fCurrColorDiffRatio / 2 ), 1 );
} }
else { else
{
m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER; m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER;
m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER; m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER;
} }
if(m_nModelResetCooldown>0) if( m_nModelResetCooldown > 0 )
--m_nModelResetCooldown; --m_nModelResetCooldown;
} }
} }
void MotionSaliencySuBSENSE::getBackgroundImage(cv::OutputArray backgroundImage) const { void MotionSaliencySuBSENSE::getBackgroundImage( OutputArray backgroundImage ) const
CV_Assert(m_bInitialized); {
cv::Mat oAvgBGImg = cv::Mat::zeros(m_oImgSize,CV_32FC((int)m_nImgChannels)); CV_Assert( m_bInitialized );
for(size_t s=0; s<m_nBGSamples; ++s) { Mat oAvgBGImg = Mat::zeros( m_oImgSize, CV_32FC( (int )m_nImgChannels ) );
for(int y=0; y<m_oImgSize.height; ++y) { for ( size_t s = 0; s < m_nBGSamples; ++s )
for(int x=0; x<m_oImgSize.width; ++x) { {
const size_t idx_nimg = m_voBGColorSamples[s].step.p[0]*y + m_voBGColorSamples[s].step.p[1]*x; for ( int y = 0; y < m_oImgSize.height; ++y )
const size_t idx_flt32 = idx_nimg*4; {
float* oAvgBgImgPtr = (float*)(oAvgBGImg.data+idx_flt32); for ( int x = 0; x < m_oImgSize.width; ++x )
const uchar* const oBGImgPtr = m_voBGColorSamples[s].data+idx_nimg; {
for(size_t c=0; c<m_nImgChannels; ++c) const size_t idx_nimg = m_voBGColorSamples[s].step.p[0] * y + m_voBGColorSamples[s].step.p[1] * x;
oAvgBgImgPtr[c] += ((float)oBGImgPtr[c])/m_nBGSamples; const size_t idx_flt32 = idx_nimg * 4;
} float* oAvgBgImgPtr = (float*) ( oAvgBGImg.data + idx_flt32 );
} const uchar* const oBGImgPtr = m_voBGColorSamples[s].data + idx_nimg;
} for ( size_t c = 0; c < m_nImgChannels; ++c )
oAvgBGImg.convertTo(backgroundImage,CV_8U); oAvgBgImgPtr[c] += ( (float) oBGImgPtr[c] ) / m_nBGSamples;
}
}
}
oAvgBGImg.convertTo( backgroundImage, CV_8U );
} }
void MotionSaliencySuBSENSE::setAutomaticModelReset(bool b) { void MotionSaliencySuBSENSE::setAutomaticModelReset( bool b )
{
m_bAutoModelResetEnabled = b; m_bAutoModelResetEnabled = b;
} }
......
...@@ -52,7 +52,7 @@ CV_INIT_ALGORITHM( ...@@ -52,7 +52,7 @@ CV_INIT_ALGORITHM(
reinterpret_cast<SizeGetter>( &StaticSaliencySpectralResidual::getWsize ), reinterpret_cast<SizeGetter>( &StaticSaliencySpectralResidual::getWsize ),
reinterpret_cast<SizeSetter>( &StaticSaliencySpectralResidual::setWsize ) ) ); reinterpret_cast<SizeSetter>( &StaticSaliencySpectralResidual::setWsize ) ) );
CV_INIT_ALGORITHM( MotionSaliencyPBAS, "SALIENCY.PBAS", ); CV_INIT_ALGORITHM( MotionSaliencySuBSENSE, "SALIENCY.SuBSENSE", );
CV_INIT_ALGORITHM( CV_INIT_ALGORITHM(
ObjectnessBING, "SALIENCY.BING", ObjectnessBING, "SALIENCY.BING",
...@@ -62,7 +62,7 @@ bool initModule_saliency( void ) ...@@ -62,7 +62,7 @@ bool initModule_saliency( void )
{ {
bool all = true; bool all = true;
all &= !StaticSaliencySpectralResidual_info_auto.name().empty(); all &= !StaticSaliencySpectralResidual_info_auto.name().empty();
all &= !MotionSaliencyPBAS_info_auto.name().empty(); all &= !MotionSaliencySuBSENSE_info_auto.name().empty();
all &= !ObjectnessBING_info_auto.name().empty(); all &= !ObjectnessBING_info_auto.name().empty();
return all; return all;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment