feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake
1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试 2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程 3.重整权利声明文件,重整代码工程,确保最小化侵权风险 Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
12
3rdparty/opencv-4.5.4/modules/video/CMakeLists.txt
vendored
Normal file
12
3rdparty/opencv-4.5.4/modules/video/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
set(the_description "Video Analysis")
|
||||
ocv_define_module(video
|
||||
opencv_imgproc
|
||||
OPTIONAL
|
||||
opencv_calib3d
|
||||
opencv_dnn
|
||||
WRAP
|
||||
java
|
||||
objc
|
||||
python
|
||||
js
|
||||
)
|
||||
44
3rdparty/opencv-4.5.4/modules/video/doc/video.bib
vendored
Normal file
44
3rdparty/opencv-4.5.4/modules/video/doc/video.bib
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
@article{AAM,
|
||||
title={Adaptive appearance modeling for video tracking: survey and evaluation},
|
||||
author={Salti, Samuele and Cavallaro, Andrea and Di Stefano, Luigi},
|
||||
journal={Image Processing, IEEE Transactions on},
|
||||
volume={21},
|
||||
number={10},
|
||||
pages={4334--4348},
|
||||
year={2012},
|
||||
publisher={IEEE}
|
||||
}
|
||||
|
||||
@article{AMVOT,
|
||||
title={A survey of appearance models in visual object tracking},
|
||||
author={Li, Xi and Hu, Weiming and Shen, Chunhua and Zhang, Zhongfei and Dick, Anthony and Hengel, Anton Van Den},
|
||||
journal={ACM Transactions on Intelligent Systems and Technology (TIST)},
|
||||
volume={4},
|
||||
number={4},
|
||||
pages={58},
|
||||
year={2013},
|
||||
publisher={ACM}
|
||||
}
|
||||
|
||||
@inproceedings{GOTURN,
|
||||
title={Learning to Track at 100 FPS with Deep Regression Networks},
|
||||
author={Held, David and Thrun, Sebastian and Savarese, Silvio},
|
||||
booktitle={European Conference Computer Vision (ECCV)},
|
||||
year={2016}
|
||||
}
|
||||
|
||||
@inproceedings{Kroeger2016,
|
||||
author={Till Kroeger and Radu Timofte and Dengxin Dai and Luc Van Gool},
|
||||
title={Fast Optical Flow using Dense Inverse Search},
|
||||
booktitle={Proceedings of the European Conference on Computer Vision ({ECCV})},
|
||||
year={2016}
|
||||
}
|
||||
|
||||
@inproceedings{MIL,
|
||||
title={Visual tracking with online multiple instance learning},
|
||||
author={Babenko, Boris and Yang, Ming-Hsuan and Belongie, Serge},
|
||||
booktitle={Computer Vision and Pattern Recognition, 2009. CVPR 2009. IEEE Conference on},
|
||||
pages={983--990},
|
||||
year={2009},
|
||||
organization={IEEE}
|
||||
}
|
||||
59
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video.hpp
vendored
Normal file
59
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video.hpp
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_VIDEO_HPP
|
||||
#define OPENCV_VIDEO_HPP
|
||||
|
||||
/**
|
||||
@defgroup video Video Analysis
|
||||
@{
|
||||
@defgroup video_motion Motion Analysis
|
||||
@defgroup video_track Object Tracking
|
||||
@defgroup video_c C API
|
||||
@}
|
||||
*/
|
||||
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
#include "opencv2/video/background_segm.hpp"
|
||||
|
||||
#endif //OPENCV_VIDEO_HPP
|
||||
317
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/background_segm.hpp
vendored
Normal file
317
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/background_segm.hpp
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_BACKGROUND_SEGM_HPP
|
||||
#define OPENCV_BACKGROUND_SEGM_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup video_motion
|
||||
//! @{
|
||||
|
||||
/** @brief Base class for background/foreground segmentation. :
|
||||
|
||||
The class is only used to define the common interface for the whole family of background/foreground
|
||||
segmentation algorithms.
|
||||
*/
|
||||
class CV_EXPORTS_W BackgroundSubtractor : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Computes a foreground mask.
|
||||
|
||||
@param image Next video frame.
|
||||
@param fgmask The output foreground mask as an 8-bit binary image.
|
||||
@param learningRate The value between 0 and 1 that indicates how fast the background model is
|
||||
learnt. Negative parameter value makes the algorithm to use some automatically chosen learning
|
||||
rate. 0 means that the background model is not updated at all, 1 means that the background model
|
||||
is completely reinitialized from the last frame.
|
||||
*/
|
||||
CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) = 0;
|
||||
|
||||
/** @brief Computes a background image.
|
||||
|
||||
@param backgroundImage The output background image.
|
||||
|
||||
@note Sometimes the background image can be very blurry, as it contain the average background
|
||||
statistics.
|
||||
*/
|
||||
CV_WRAP virtual void getBackgroundImage(OutputArray backgroundImage) const = 0;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Gaussian Mixture-based Background/Foreground Segmentation Algorithm.
|
||||
|
||||
The class implements the Gaussian mixture model background subtraction described in @cite Zivkovic2004
|
||||
and @cite Zivkovic2006 .
|
||||
*/
|
||||
class CV_EXPORTS_W BackgroundSubtractorMOG2 : public BackgroundSubtractor
|
||||
{
|
||||
public:
|
||||
/** @brief Returns the number of last frames that affect the background model
|
||||
*/
|
||||
CV_WRAP virtual int getHistory() const = 0;
|
||||
/** @brief Sets the number of last frames that affect the background model
|
||||
*/
|
||||
CV_WRAP virtual void setHistory(int history) = 0;
|
||||
|
||||
/** @brief Returns the number of gaussian components in the background model
|
||||
*/
|
||||
CV_WRAP virtual int getNMixtures() const = 0;
|
||||
/** @brief Sets the number of gaussian components in the background model.
|
||||
|
||||
The model needs to be reinitalized to reserve memory.
|
||||
*/
|
||||
CV_WRAP virtual void setNMixtures(int nmixtures) = 0;//needs reinitialization!
|
||||
|
||||
/** @brief Returns the "background ratio" parameter of the algorithm
|
||||
|
||||
If a foreground pixel keeps semi-constant value for about backgroundRatio\*history frames, it's
|
||||
considered background and added to the model as a center of a new component. It corresponds to TB
|
||||
parameter in the paper.
|
||||
*/
|
||||
CV_WRAP virtual double getBackgroundRatio() const = 0;
|
||||
/** @brief Sets the "background ratio" parameter of the algorithm
|
||||
*/
|
||||
CV_WRAP virtual void setBackgroundRatio(double ratio) = 0;
|
||||
|
||||
/** @brief Returns the variance threshold for the pixel-model match
|
||||
|
||||
The main threshold on the squared Mahalanobis distance to decide if the sample is well described by
|
||||
the background model or not. Related to Cthr from the paper.
|
||||
*/
|
||||
CV_WRAP virtual double getVarThreshold() const = 0;
|
||||
/** @brief Sets the variance threshold for the pixel-model match
|
||||
*/
|
||||
CV_WRAP virtual void setVarThreshold(double varThreshold) = 0;
|
||||
|
||||
/** @brief Returns the variance threshold for the pixel-model match used for new mixture component generation
|
||||
|
||||
Threshold for the squared Mahalanobis distance that helps decide when a sample is close to the
|
||||
existing components (corresponds to Tg in the paper). If a pixel is not close to any component, it
|
||||
is considered foreground or added as a new component. 3 sigma =\> Tg=3\*3=9 is default. A smaller Tg
|
||||
value generates more components. A higher Tg value may result in a small number of components but
|
||||
they can grow too large.
|
||||
*/
|
||||
CV_WRAP virtual double getVarThresholdGen() const = 0;
|
||||
/** @brief Sets the variance threshold for the pixel-model match used for new mixture component generation
|
||||
*/
|
||||
CV_WRAP virtual void setVarThresholdGen(double varThresholdGen) = 0;
|
||||
|
||||
/** @brief Returns the initial variance of each gaussian component
|
||||
*/
|
||||
CV_WRAP virtual double getVarInit() const = 0;
|
||||
/** @brief Sets the initial variance of each gaussian component
|
||||
*/
|
||||
CV_WRAP virtual void setVarInit(double varInit) = 0;
|
||||
|
||||
CV_WRAP virtual double getVarMin() const = 0;
|
||||
CV_WRAP virtual void setVarMin(double varMin) = 0;
|
||||
|
||||
CV_WRAP virtual double getVarMax() const = 0;
|
||||
CV_WRAP virtual void setVarMax(double varMax) = 0;
|
||||
|
||||
/** @brief Returns the complexity reduction threshold
|
||||
|
||||
This parameter defines the number of samples needed to accept to prove the component exists. CT=0.05
|
||||
is a default value for all the samples. By setting CT=0 you get an algorithm very similar to the
|
||||
standard Stauffer&Grimson algorithm.
|
||||
*/
|
||||
CV_WRAP virtual double getComplexityReductionThreshold() const = 0;
|
||||
/** @brief Sets the complexity reduction threshold
|
||||
*/
|
||||
CV_WRAP virtual void setComplexityReductionThreshold(double ct) = 0;
|
||||
|
||||
/** @brief Returns the shadow detection flag
|
||||
|
||||
If true, the algorithm detects shadows and marks them. See createBackgroundSubtractorMOG2 for
|
||||
details.
|
||||
*/
|
||||
CV_WRAP virtual bool getDetectShadows() const = 0;
|
||||
/** @brief Enables or disables shadow detection
|
||||
*/
|
||||
CV_WRAP virtual void setDetectShadows(bool detectShadows) = 0;
|
||||
|
||||
/** @brief Returns the shadow value
|
||||
|
||||
Shadow value is the value used to mark shadows in the foreground mask. Default value is 127. Value 0
|
||||
in the mask always means background, 255 means foreground.
|
||||
*/
|
||||
CV_WRAP virtual int getShadowValue() const = 0;
|
||||
/** @brief Sets the shadow value
|
||||
*/
|
||||
CV_WRAP virtual void setShadowValue(int value) = 0;
|
||||
|
||||
/** @brief Returns the shadow threshold
|
||||
|
||||
A shadow is detected if pixel is a darker version of the background. The shadow threshold (Tau in
|
||||
the paper) is a threshold defining how much darker the shadow can be. Tau= 0.5 means that if a pixel
|
||||
is more than twice darker then it is not shadow. See Prati, Mikic, Trivedi and Cucchiara,
|
||||
*Detecting Moving Shadows...*, IEEE PAMI,2003.
|
||||
*/
|
||||
CV_WRAP virtual double getShadowThreshold() const = 0;
|
||||
/** @brief Sets the shadow threshold
|
||||
*/
|
||||
CV_WRAP virtual void setShadowThreshold(double threshold) = 0;
|
||||
|
||||
/** @brief Computes a foreground mask.
|
||||
|
||||
@param image Next video frame. Floating point frame will be used without scaling and should be in range \f$[0,255]\f$.
|
||||
@param fgmask The output foreground mask as an 8-bit binary image.
|
||||
@param learningRate The value between 0 and 1 that indicates how fast the background model is
|
||||
learnt. Negative parameter value makes the algorithm to use some automatically chosen learning
|
||||
rate. 0 means that the background model is not updated at all, 1 means that the background model
|
||||
is completely reinitialized from the last frame.
|
||||
*/
|
||||
CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) CV_OVERRIDE = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates MOG2 Background Subtractor
|
||||
|
||||
@param history Length of the history.
|
||||
@param varThreshold Threshold on the squared Mahalanobis distance between the pixel and the model
|
||||
to decide whether a pixel is well described by the background model. This parameter does not
|
||||
affect the background update.
|
||||
@param detectShadows If true, the algorithm will detect shadows and mark them. It decreases the
|
||||
speed a bit, so if you do not need this feature, set the parameter to false.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<BackgroundSubtractorMOG2>
|
||||
createBackgroundSubtractorMOG2(int history=500, double varThreshold=16,
|
||||
bool detectShadows=true);
|
||||
|
||||
/** @brief K-nearest neighbours - based Background/Foreground Segmentation Algorithm.
|
||||
|
||||
The class implements the K-nearest neighbours background subtraction described in @cite Zivkovic2006 .
|
||||
Very efficient if number of foreground pixels is low.
|
||||
*/
|
||||
class CV_EXPORTS_W BackgroundSubtractorKNN : public BackgroundSubtractor
|
||||
{
|
||||
public:
|
||||
/** @brief Returns the number of last frames that affect the background model
|
||||
*/
|
||||
CV_WRAP virtual int getHistory() const = 0;
|
||||
/** @brief Sets the number of last frames that affect the background model
|
||||
*/
|
||||
CV_WRAP virtual void setHistory(int history) = 0;
|
||||
|
||||
/** @brief Returns the number of data samples in the background model
|
||||
*/
|
||||
CV_WRAP virtual int getNSamples() const = 0;
|
||||
/** @brief Sets the number of data samples in the background model.
|
||||
|
||||
The model needs to be reinitalized to reserve memory.
|
||||
*/
|
||||
CV_WRAP virtual void setNSamples(int _nN) = 0;//needs reinitialization!
|
||||
|
||||
/** @brief Returns the threshold on the squared distance between the pixel and the sample
|
||||
|
||||
The threshold on the squared distance between the pixel and the sample to decide whether a pixel is
|
||||
close to a data sample.
|
||||
*/
|
||||
CV_WRAP virtual double getDist2Threshold() const = 0;
|
||||
/** @brief Sets the threshold on the squared distance
|
||||
*/
|
||||
CV_WRAP virtual void setDist2Threshold(double _dist2Threshold) = 0;
|
||||
|
||||
/** @brief Returns the number of neighbours, the k in the kNN.
|
||||
|
||||
K is the number of samples that need to be within dist2Threshold in order to decide that that
|
||||
pixel is matching the kNN background model.
|
||||
*/
|
||||
CV_WRAP virtual int getkNNSamples() const = 0;
|
||||
/** @brief Sets the k in the kNN. How many nearest neighbours need to match.
|
||||
*/
|
||||
CV_WRAP virtual void setkNNSamples(int _nkNN) = 0;
|
||||
|
||||
/** @brief Returns the shadow detection flag
|
||||
|
||||
If true, the algorithm detects shadows and marks them. See createBackgroundSubtractorKNN for
|
||||
details.
|
||||
*/
|
||||
CV_WRAP virtual bool getDetectShadows() const = 0;
|
||||
/** @brief Enables or disables shadow detection
|
||||
*/
|
||||
CV_WRAP virtual void setDetectShadows(bool detectShadows) = 0;
|
||||
|
||||
/** @brief Returns the shadow value
|
||||
|
||||
Shadow value is the value used to mark shadows in the foreground mask. Default value is 127. Value 0
|
||||
in the mask always means background, 255 means foreground.
|
||||
*/
|
||||
CV_WRAP virtual int getShadowValue() const = 0;
|
||||
/** @brief Sets the shadow value
|
||||
*/
|
||||
CV_WRAP virtual void setShadowValue(int value) = 0;
|
||||
|
||||
/** @brief Returns the shadow threshold
|
||||
|
||||
A shadow is detected if pixel is a darker version of the background. The shadow threshold (Tau in
|
||||
the paper) is a threshold defining how much darker the shadow can be. Tau= 0.5 means that if a pixel
|
||||
is more than twice darker then it is not shadow. See Prati, Mikic, Trivedi and Cucchiara,
|
||||
*Detecting Moving Shadows...*, IEEE PAMI,2003.
|
||||
*/
|
||||
CV_WRAP virtual double getShadowThreshold() const = 0;
|
||||
/** @brief Sets the shadow threshold
|
||||
*/
|
||||
CV_WRAP virtual void setShadowThreshold(double threshold) = 0;
|
||||
};
|
||||
|
||||
/** @brief Creates KNN Background Subtractor
|
||||
|
||||
@param history Length of the history.
|
||||
@param dist2Threshold Threshold on the squared distance between the pixel and the sample to decide
|
||||
whether a pixel is close to that sample. This parameter does not affect the background update.
|
||||
@param detectShadows If true, the algorithm will detect shadows and mark them. It decreases the
|
||||
speed a bit, so if you do not need this feature, set the parameter to false.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<BackgroundSubtractorKNN>
|
||||
createBackgroundSubtractorKNN(int history=500, double dist2Threshold=400.0,
|
||||
bool detectShadows=true);
|
||||
|
||||
//! @} video_motion
|
||||
|
||||
} // cv
|
||||
|
||||
#endif
|
||||
406
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/detail/tracking.detail.hpp
vendored
Normal file
406
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/detail/tracking.detail.hpp
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_VIDEO_DETAIL_TRACKING_HPP
|
||||
#define OPENCV_VIDEO_DETAIL_TRACKING_HPP
|
||||
|
||||
/*
|
||||
* Partially based on:
|
||||
* ====================================================================================================================
|
||||
* - [AAM] S. Salti, A. Cavallaro, L. Di Stefano, Adaptive Appearance Modeling for Video Tracking: Survey and Evaluation
|
||||
* - [AMVOT] X. Li, W. Hu, C. Shen, Z. Zhang, A. Dick, A. van den Hengel, A Survey of Appearance Models in Visual Object Tracking
|
||||
*
|
||||
* This Tracking API has been designed with PlantUML. If you modify this API please change UML files under modules/tracking/doc/uml
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
/** @addtogroup tracking_detail
|
||||
@{
|
||||
*/
|
||||
|
||||
/************************************ TrackerFeature Base Classes ************************************/
|
||||
|
||||
/** @brief Abstract base class for TrackerFeature that represents the feature.
|
||||
*/
|
||||
class CV_EXPORTS TrackerFeature
|
||||
{
|
||||
public:
|
||||
virtual ~TrackerFeature();
|
||||
|
||||
/** @brief Compute the features in the images collection
|
||||
@param images The images
|
||||
@param response The output response
|
||||
*/
|
||||
void compute(const std::vector<Mat>& images, Mat& response);
|
||||
|
||||
protected:
|
||||
virtual bool computeImpl(const std::vector<Mat>& images, Mat& response) = 0;
|
||||
};
|
||||
|
||||
/** @brief Class that manages the extraction and selection of features
|
||||
|
||||
@cite AAM Feature Extraction and Feature Set Refinement (Feature Processing and Feature Selection).
|
||||
See table I and section III C @cite AMVOT Appearance modelling -\> Visual representation (Table II,
|
||||
section 3.1 - 3.2)
|
||||
|
||||
TrackerFeatureSet is an aggregation of TrackerFeature
|
||||
|
||||
@sa
|
||||
TrackerFeature
|
||||
|
||||
*/
|
||||
class CV_EXPORTS TrackerFeatureSet
|
||||
{
|
||||
public:
|
||||
TrackerFeatureSet();
|
||||
|
||||
~TrackerFeatureSet();
|
||||
|
||||
/** @brief Extract features from the images collection
|
||||
@param images The input images
|
||||
*/
|
||||
void extraction(const std::vector<Mat>& images);
|
||||
|
||||
/** @brief Add TrackerFeature in the collection. Return true if TrackerFeature is added, false otherwise
|
||||
@param feature The TrackerFeature class
|
||||
*/
|
||||
bool addTrackerFeature(const Ptr<TrackerFeature>& feature);
|
||||
|
||||
/** @brief Get the TrackerFeature collection (TrackerFeature name, TrackerFeature pointer)
|
||||
*/
|
||||
const std::vector<Ptr<TrackerFeature>>& getTrackerFeatures() const;
|
||||
|
||||
/** @brief Get the responses
|
||||
@note Be sure to call extraction before getResponses Example TrackerFeatureSet::getResponses
|
||||
*/
|
||||
const std::vector<Mat>& getResponses() const;
|
||||
|
||||
private:
|
||||
void clearResponses();
|
||||
bool blockAddTrackerFeature;
|
||||
|
||||
std::vector<Ptr<TrackerFeature>> features; // list of features
|
||||
std::vector<Mat> responses; // list of response after compute
|
||||
};
|
||||
|
||||
/************************************ TrackerSampler Base Classes ************************************/
|
||||
|
||||
/** @brief Abstract base class for TrackerSamplerAlgorithm that represents the algorithm for the specific
|
||||
sampler.
|
||||
*/
|
||||
class CV_EXPORTS TrackerSamplerAlgorithm
|
||||
{
|
||||
public:
|
||||
virtual ~TrackerSamplerAlgorithm();
|
||||
|
||||
/** @brief Computes the regions starting from a position in an image.
|
||||
|
||||
Return true if samples are computed, false otherwise
|
||||
|
||||
@param image The current frame
|
||||
@param boundingBox The bounding box from which regions can be calculated
|
||||
|
||||
@param sample The computed samples @cite AAM Fig. 1 variable Sk
|
||||
*/
|
||||
virtual bool sampling(const Mat& image, const Rect& boundingBox, std::vector<Mat>& sample) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that manages the sampler in order to select regions for the update the model of the tracker
|
||||
* [AAM] Sampling e Labeling. See table I and section III B
|
||||
*/
|
||||
|
||||
/** @brief Class that manages the sampler in order to select regions for the update the model of the tracker
|
||||
|
||||
@cite AAM Sampling e Labeling. See table I and section III B
|
||||
|
||||
TrackerSampler is an aggregation of TrackerSamplerAlgorithm
|
||||
@sa
|
||||
TrackerSamplerAlgorithm
|
||||
*/
|
||||
class CV_EXPORTS TrackerSampler
|
||||
{
|
||||
public:
|
||||
TrackerSampler();
|
||||
|
||||
~TrackerSampler();
|
||||
|
||||
/** @brief Computes the regions starting from a position in an image
|
||||
@param image The current frame
|
||||
@param boundingBox The bounding box from which regions can be calculated
|
||||
*/
|
||||
void sampling(const Mat& image, Rect boundingBox);
|
||||
|
||||
/** @brief Return the collection of the TrackerSamplerAlgorithm
|
||||
*/
|
||||
const std::vector<Ptr<TrackerSamplerAlgorithm>>& getSamplers() const;
|
||||
|
||||
/** @brief Return the samples from all TrackerSamplerAlgorithm, @cite AAM Fig. 1 variable Sk
|
||||
*/
|
||||
const std::vector<Mat>& getSamples() const;
|
||||
|
||||
/** @brief Add TrackerSamplerAlgorithm in the collection. Return true if sampler is added, false otherwise
|
||||
@param sampler The TrackerSamplerAlgorithm
|
||||
*/
|
||||
bool addTrackerSamplerAlgorithm(const Ptr<TrackerSamplerAlgorithm>& sampler);
|
||||
|
||||
private:
|
||||
std::vector<Ptr<TrackerSamplerAlgorithm>> samplers;
|
||||
std::vector<Mat> samples;
|
||||
bool blockAddTrackerSampler;
|
||||
|
||||
void clearSamples();
|
||||
};
|
||||
|
||||
/************************************ TrackerModel Base Classes ************************************/
|
||||
|
||||
/** @brief Abstract base class for TrackerTargetState that represents a possible state of the target.
|
||||
|
||||
See @cite AAM \f$\hat{x}^{i}_{k}\f$ all the states candidates.
|
||||
|
||||
Inherits this class with your Target state, In own implementation you can add scale variation,
|
||||
width, height, orientation, etc.
|
||||
*/
|
||||
class CV_EXPORTS TrackerTargetState
|
||||
{
|
||||
public:
|
||||
virtual ~TrackerTargetState() {};
|
||||
/** @brief Get the position
|
||||
* @return The position
|
||||
*/
|
||||
Point2f getTargetPosition() const;
|
||||
|
||||
/** @brief Set the position
|
||||
* @param position The position
|
||||
*/
|
||||
void setTargetPosition(const Point2f& position);
|
||||
/** @brief Get the width of the target
|
||||
* @return The width of the target
|
||||
*/
|
||||
int getTargetWidth() const;
|
||||
|
||||
/** @brief Set the width of the target
|
||||
* @param width The width of the target
|
||||
*/
|
||||
void setTargetWidth(int width);
|
||||
/** @brief Get the height of the target
|
||||
* @return The height of the target
|
||||
*/
|
||||
int getTargetHeight() const;
|
||||
|
||||
/** @brief Set the height of the target
|
||||
* @param height The height of the target
|
||||
*/
|
||||
void setTargetHeight(int height);
|
||||
|
||||
protected:
|
||||
Point2f targetPosition;
|
||||
int targetWidth;
|
||||
int targetHeight;
|
||||
};
|
||||
|
||||
/** @brief Represents the model of the target at frame \f$k\f$ (all states and scores)
|
||||
|
||||
See @cite AAM The set of the pair \f$\langle \hat{x}^{i}_{k}, C^{i}_{k} \rangle\f$
|
||||
@sa TrackerTargetState
|
||||
*/
|
||||
typedef std::vector<std::pair<Ptr<TrackerTargetState>, float>> ConfidenceMap;
|
||||
|
||||
/** @brief Represents the estimate states for all frames
|
||||
|
||||
@cite AAM \f$x_{k}\f$ is the trajectory of the target up to time \f$k\f$
|
||||
|
||||
@sa TrackerTargetState
|
||||
*/
|
||||
typedef std::vector<Ptr<TrackerTargetState>> Trajectory;
|
||||
|
||||
/** @brief Abstract base class for TrackerStateEstimator that estimates the most likely target state.
|
||||
|
||||
See @cite AAM State estimator
|
||||
|
||||
See @cite AMVOT Statistical modeling (Fig. 3), Table III (generative) - IV (discriminative) - V (hybrid)
|
||||
*/
|
||||
class CV_EXPORTS TrackerStateEstimator
|
||||
{
|
||||
public:
|
||||
virtual ~TrackerStateEstimator();
|
||||
|
||||
/** @brief Estimate the most likely target state, return the estimated state
|
||||
@param confidenceMaps The overall appearance model as a list of :cConfidenceMap
|
||||
*/
|
||||
Ptr<TrackerTargetState> estimate(const std::vector<ConfidenceMap>& confidenceMaps);
|
||||
|
||||
/** @brief Update the ConfidenceMap with the scores
|
||||
@param confidenceMaps The overall appearance model as a list of :cConfidenceMap
|
||||
*/
|
||||
void update(std::vector<ConfidenceMap>& confidenceMaps);
|
||||
|
||||
/** @brief Create TrackerStateEstimator by tracker state estimator type
|
||||
@param trackeStateEstimatorType The TrackerStateEstimator name
|
||||
|
||||
The modes available now:
|
||||
|
||||
- "BOOSTING" -- Boosting-based discriminative appearance models. See @cite AMVOT section 4.4
|
||||
|
||||
The modes available soon:
|
||||
|
||||
- "SVM" -- SVM-based discriminative appearance models. See @cite AMVOT section 4.5
|
||||
*/
|
||||
static Ptr<TrackerStateEstimator> create(const String& trackeStateEstimatorType);
|
||||
|
||||
/** @brief Get the name of the specific TrackerStateEstimator
|
||||
*/
|
||||
String getClassName() const;
|
||||
|
||||
protected:
|
||||
virtual Ptr<TrackerTargetState> estimateImpl(const std::vector<ConfidenceMap>& confidenceMaps) = 0;
|
||||
virtual void updateImpl(std::vector<ConfidenceMap>& confidenceMaps) = 0;
|
||||
String className;
|
||||
};
|
||||
|
||||
/** @brief Abstract class that represents the model of the target.
|
||||
|
||||
It must be instantiated by specialized tracker
|
||||
|
||||
See @cite AAM Ak
|
||||
|
||||
Inherits this with your TrackerModel
|
||||
*/
|
||||
class CV_EXPORTS TrackerModel
|
||||
{
|
||||
public:
|
||||
TrackerModel();
|
||||
|
||||
virtual ~TrackerModel();
|
||||
|
||||
/** @brief Set TrackerEstimator, return true if the tracker state estimator is added, false otherwise
|
||||
@param trackerStateEstimator The TrackerStateEstimator
|
||||
@note You can add only one TrackerStateEstimator
|
||||
*/
|
||||
bool setTrackerStateEstimator(Ptr<TrackerStateEstimator> trackerStateEstimator);
|
||||
|
||||
/** @brief Estimate the most likely target location
|
||||
|
||||
@cite AAM ME, Model Estimation table I
|
||||
@param responses Features extracted from TrackerFeatureSet
|
||||
*/
|
||||
void modelEstimation(const std::vector<Mat>& responses);
|
||||
|
||||
/** @brief Update the model
|
||||
|
||||
@cite AAM MU, Model Update table I
|
||||
*/
|
||||
void modelUpdate();
|
||||
|
||||
/** @brief Run the TrackerStateEstimator, return true if is possible to estimate a new state, false otherwise
|
||||
*/
|
||||
bool runStateEstimator();
|
||||
|
||||
/** @brief Set the current TrackerTargetState in the Trajectory
|
||||
@param lastTargetState The current TrackerTargetState
|
||||
*/
|
||||
void setLastTargetState(const Ptr<TrackerTargetState>& lastTargetState);
|
||||
|
||||
/** @brief Get the last TrackerTargetState from Trajectory
|
||||
*/
|
||||
Ptr<TrackerTargetState> getLastTargetState() const;
|
||||
|
||||
/** @brief Get the list of the ConfidenceMap
|
||||
*/
|
||||
const std::vector<ConfidenceMap>& getConfidenceMaps() const;
|
||||
|
||||
/** @brief Get the last ConfidenceMap for the current frame
|
||||
*/
|
||||
const ConfidenceMap& getLastConfidenceMap() const;
|
||||
|
||||
/** @brief Get the TrackerStateEstimator
|
||||
*/
|
||||
Ptr<TrackerStateEstimator> getTrackerStateEstimator() const;
|
||||
|
||||
private:
|
||||
void clearCurrentConfidenceMap();
|
||||
|
||||
protected:
|
||||
std::vector<ConfidenceMap> confidenceMaps;
|
||||
Ptr<TrackerStateEstimator> stateEstimator;
|
||||
ConfidenceMap currentConfidenceMap;
|
||||
Trajectory trajectory;
|
||||
int maxCMLength;
|
||||
|
||||
virtual void modelEstimationImpl(const std::vector<Mat>& responses) = 0;
|
||||
virtual void modelUpdateImpl() = 0;
|
||||
};
|
||||
|
||||
/************************************ Specific TrackerStateEstimator Classes ************************************/
|
||||
|
||||
// None
|
||||
|
||||
/************************************ Specific TrackerSamplerAlgorithm Classes ************************************/
|
||||
|
||||
/** @brief TrackerSampler based on CSC (current state centered), used by MIL algorithm TrackerMIL
|
||||
*/
|
||||
class CV_EXPORTS TrackerSamplerCSC : public TrackerSamplerAlgorithm
|
||||
{
|
||||
public:
|
||||
~TrackerSamplerCSC();
|
||||
|
||||
enum MODE
|
||||
{
|
||||
MODE_INIT_POS = 1, //!< mode for init positive samples
|
||||
MODE_INIT_NEG = 2, //!< mode for init negative samples
|
||||
MODE_TRACK_POS = 3, //!< mode for update positive samples
|
||||
MODE_TRACK_NEG = 4, //!< mode for update negative samples
|
||||
MODE_DETECT = 5 //!< mode for detect samples
|
||||
};
|
||||
|
||||
struct CV_EXPORTS Params
|
||||
{
|
||||
Params();
|
||||
float initInRad; //!< radius for gathering positive instances during init
|
||||
float trackInPosRad; //!< radius for gathering positive instances during tracking
|
||||
float searchWinSize; //!< size of search window
|
||||
int initMaxNegNum; //!< # negative samples to use during init
|
||||
int trackMaxPosNum; //!< # positive samples to use during training
|
||||
int trackMaxNegNum; //!< # negative samples to use during training
|
||||
};
|
||||
|
||||
/** @brief Constructor
|
||||
@param parameters TrackerSamplerCSC parameters TrackerSamplerCSC::Params
|
||||
*/
|
||||
TrackerSamplerCSC(const TrackerSamplerCSC::Params& parameters = TrackerSamplerCSC::Params());
|
||||
|
||||
/** @brief Set the sampling mode of TrackerSamplerCSC
|
||||
@param samplingMode The sampling mode
|
||||
|
||||
The modes are:
|
||||
|
||||
- "MODE_INIT_POS = 1" -- for the positive sampling in initialization step
|
||||
- "MODE_INIT_NEG = 2" -- for the negative sampling in initialization step
|
||||
- "MODE_TRACK_POS = 3" -- for the positive sampling in update step
|
||||
- "MODE_TRACK_NEG = 4" -- for the negative sampling in update step
|
||||
- "MODE_DETECT = 5" -- for the sampling in detection step
|
||||
*/
|
||||
void setMode(int samplingMode);
|
||||
|
||||
bool sampling(const Mat& image, const Rect& boundingBox, std::vector<Mat>& sample) CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
Params params;
|
||||
int mode;
|
||||
RNG rng;
|
||||
|
||||
std::vector<Mat> sampleImage(const Mat& img, int x, int y, int w, int h, float inrad, float outrad = 0, int maxnum = 1000000);
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
|
||||
#endif // OPENCV_VIDEO_DETAIL_TRACKING_HPP
|
||||
16
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/legacy/constants_c.h
vendored
Normal file
16
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/legacy/constants_c.h
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_VIDEO_LEGACY_CONSTANTS_H
|
||||
#define OPENCV_VIDEO_LEGACY_CONSTANTS_H
|
||||
|
||||
enum
|
||||
{
|
||||
CV_LKFLOW_PYR_A_READY = 1,
|
||||
CV_LKFLOW_PYR_B_READY = 2,
|
||||
CV_LKFLOW_INITIAL_GUESSES = 4,
|
||||
CV_LKFLOW_GET_MIN_EIGENVALS = 8
|
||||
};
|
||||
|
||||
#endif // OPENCV_VIDEO_LEGACY_CONSTANTS_H
|
||||
857
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/tracking.hpp
vendored
Normal file
857
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/tracking.hpp
vendored
Normal file
@@ -0,0 +1,857 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_TRACKING_HPP
|
||||
#define OPENCV_TRACKING_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup video_track
|
||||
//! @{
|
||||
|
||||
enum { OPTFLOW_USE_INITIAL_FLOW = 4,
|
||||
OPTFLOW_LK_GET_MIN_EIGENVALS = 8,
|
||||
OPTFLOW_FARNEBACK_GAUSSIAN = 256
|
||||
};
|
||||
|
||||
/** @brief Finds an object center, size, and orientation.
|
||||
|
||||
@param probImage Back projection of the object histogram. See calcBackProject.
|
||||
@param window Initial search window.
|
||||
@param criteria Stop criteria for the underlying meanShift.
|
||||
returns
|
||||
(in old interfaces) Number of iterations CAMSHIFT took to converge
|
||||
The function implements the CAMSHIFT object tracking algorithm @cite Bradski98 . First, it finds an
|
||||
object center using meanShift and then adjusts the window size and finds the optimal rotation. The
|
||||
function returns the rotated rectangle structure that includes the object position, size, and
|
||||
orientation. The next position of the search window can be obtained with RotatedRect::boundingRect()
|
||||
|
||||
See the OpenCV sample camshiftdemo.c that tracks colored objects.
|
||||
|
||||
@note
|
||||
- (Python) A sample explaining the camshift tracking algorithm can be found at
|
||||
opencv_source_code/samples/python/camshift.py
|
||||
*/
|
||||
CV_EXPORTS_W RotatedRect CamShift( InputArray probImage, CV_IN_OUT Rect& window,
|
||||
TermCriteria criteria );
|
||||
/** @example samples/cpp/camshiftdemo.cpp
|
||||
An example using the mean-shift tracking algorithm
|
||||
*/
|
||||
|
||||
/** @brief Finds an object on a back projection image.
|
||||
|
||||
@param probImage Back projection of the object histogram. See calcBackProject for details.
|
||||
@param window Initial search window.
|
||||
@param criteria Stop criteria for the iterative search algorithm.
|
||||
returns
|
||||
: Number of iterations CAMSHIFT took to converge.
|
||||
The function implements the iterative object search algorithm. It takes the input back projection of
|
||||
an object and the initial position. The mass center in window of the back projection image is
|
||||
computed and the search window center shifts to the mass center. The procedure is repeated until the
|
||||
specified number of iterations criteria.maxCount is done or until the window center shifts by less
|
||||
than criteria.epsilon. The algorithm is used inside CamShift and, unlike CamShift , the search
|
||||
window size or orientation do not change during the search. You can simply pass the output of
|
||||
calcBackProject to this function. But better results can be obtained if you pre-filter the back
|
||||
projection and remove the noise. For example, you can do this by retrieving connected components
|
||||
with findContours , throwing away contours with small area ( contourArea ), and rendering the
|
||||
remaining contours with drawContours.
|
||||
|
||||
*/
|
||||
CV_EXPORTS_W int meanShift( InputArray probImage, CV_IN_OUT Rect& window, TermCriteria criteria );
|
||||
|
||||
/** @brief Constructs the image pyramid which can be passed to calcOpticalFlowPyrLK.
|
||||
|
||||
@param img 8-bit input image.
|
||||
@param pyramid output pyramid.
|
||||
@param winSize window size of optical flow algorithm. Must be not less than winSize argument of
|
||||
calcOpticalFlowPyrLK. It is needed to calculate required padding for pyramid levels.
|
||||
@param maxLevel 0-based maximal pyramid level number.
|
||||
@param withDerivatives set to precompute gradients for the every pyramid level. If pyramid is
|
||||
constructed without the gradients then calcOpticalFlowPyrLK will calculate them internally.
|
||||
@param pyrBorder the border mode for pyramid layers.
|
||||
@param derivBorder the border mode for gradients.
|
||||
@param tryReuseInputImage put ROI of input image into the pyramid if possible. You can pass false
|
||||
to force data copying.
|
||||
@return number of levels in constructed pyramid. Can be less than maxLevel.
|
||||
*/
|
||||
CV_EXPORTS_W int buildOpticalFlowPyramid( InputArray img, OutputArrayOfArrays pyramid,
|
||||
Size winSize, int maxLevel, bool withDerivatives = true,
|
||||
int pyrBorder = BORDER_REFLECT_101,
|
||||
int derivBorder = BORDER_CONSTANT,
|
||||
bool tryReuseInputImage = true );
|
||||
|
||||
/** @example samples/cpp/lkdemo.cpp
|
||||
An example using the Lucas-Kanade optical flow algorithm
|
||||
*/
|
||||
|
||||
/** @brief Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade method with
|
||||
pyramids.
|
||||
|
||||
@param prevImg first 8-bit input image or pyramid constructed by buildOpticalFlowPyramid.
|
||||
@param nextImg second input image or pyramid of the same size and the same type as prevImg.
|
||||
@param prevPts vector of 2D points for which the flow needs to be found; point coordinates must be
|
||||
single-precision floating-point numbers.
|
||||
@param nextPts output vector of 2D points (with single-precision floating-point coordinates)
|
||||
containing the calculated new positions of input features in the second image; when
|
||||
OPTFLOW_USE_INITIAL_FLOW flag is passed, the vector must have the same size as in the input.
|
||||
@param status output status vector (of unsigned chars); each element of the vector is set to 1 if
|
||||
the flow for the corresponding features has been found, otherwise, it is set to 0.
|
||||
@param err output vector of errors; each element of the vector is set to an error for the
|
||||
corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn't
|
||||
found then the error is not defined (use the status parameter to find such cases).
|
||||
@param winSize size of the search window at each pyramid level.
|
||||
@param maxLevel 0-based maximal pyramid level number; if set to 0, pyramids are not used (single
|
||||
level), if set to 1, two levels are used, and so on; if pyramids are passed to input then
|
||||
algorithm will use as many levels as pyramids have but no more than maxLevel.
|
||||
@param criteria parameter, specifying the termination criteria of the iterative search algorithm
|
||||
(after the specified maximum number of iterations criteria.maxCount or when the search window
|
||||
moves by less than criteria.epsilon.
|
||||
@param flags operation flags:
|
||||
- **OPTFLOW_USE_INITIAL_FLOW** uses initial estimations, stored in nextPts; if the flag is
|
||||
not set, then prevPts is copied to nextPts and is considered the initial estimate.
|
||||
- **OPTFLOW_LK_GET_MIN_EIGENVALS** use minimum eigen values as an error measure (see
|
||||
minEigThreshold description); if the flag is not set, then L1 distance between patches
|
||||
around the original and a moved point, divided by number of pixels in a window, is used as a
|
||||
error measure.
|
||||
@param minEigThreshold the algorithm calculates the minimum eigen value of a 2x2 normal matrix of
|
||||
optical flow equations (this matrix is called a spatial gradient matrix in @cite Bouguet00), divided
|
||||
by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding
|
||||
feature is filtered out and its flow is not processed, so it allows to remove bad points and get a
|
||||
performance boost.
|
||||
|
||||
The function implements a sparse iterative version of the Lucas-Kanade optical flow in pyramids. See
|
||||
@cite Bouguet00 . The function is parallelized with the TBB library.
|
||||
|
||||
@note
|
||||
|
||||
- An example using the Lucas-Kanade optical flow algorithm can be found at
|
||||
opencv_source_code/samples/cpp/lkdemo.cpp
|
||||
- (Python) An example using the Lucas-Kanade optical flow algorithm can be found at
|
||||
opencv_source_code/samples/python/lk_track.py
|
||||
- (Python) An example using the Lucas-Kanade tracker for homography matching can be found at
|
||||
opencv_source_code/samples/python/lk_homography.py
|
||||
*/
|
||||
CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
|
||||
InputArray prevPts, InputOutputArray nextPts,
|
||||
OutputArray status, OutputArray err,
|
||||
Size winSize = Size(21,21), int maxLevel = 3,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
|
||||
int flags = 0, double minEigThreshold = 1e-4 );
|
||||
|
||||
/** @brief Computes a dense optical flow using the Gunnar Farneback's algorithm.
|
||||
|
||||
@param prev first 8-bit single-channel input image.
|
||||
@param next second input image of the same size and the same type as prev.
|
||||
@param flow computed flow image that has the same size as prev and type CV_32FC2.
|
||||
@param pyr_scale parameter, specifying the image scale (\<1) to build pyramids for each image;
|
||||
pyr_scale=0.5 means a classical pyramid, where each next layer is twice smaller than the previous
|
||||
one.
|
||||
@param levels number of pyramid layers including the initial image; levels=1 means that no extra
|
||||
layers are created and only the original images are used.
|
||||
@param winsize averaging window size; larger values increase the algorithm robustness to image
|
||||
noise and give more chances for fast motion detection, but yield more blurred motion field.
|
||||
@param iterations number of iterations the algorithm does at each pyramid level.
|
||||
@param poly_n size of the pixel neighborhood used to find polynomial expansion in each pixel;
|
||||
larger values mean that the image will be approximated with smoother surfaces, yielding more
|
||||
robust algorithm and more blurred motion field, typically poly_n =5 or 7.
|
||||
@param poly_sigma standard deviation of the Gaussian that is used to smooth derivatives used as a
|
||||
basis for the polynomial expansion; for poly_n=5, you can set poly_sigma=1.1, for poly_n=7, a
|
||||
good value would be poly_sigma=1.5.
|
||||
@param flags operation flags that can be a combination of the following:
|
||||
- **OPTFLOW_USE_INITIAL_FLOW** uses the input flow as an initial flow approximation.
|
||||
- **OPTFLOW_FARNEBACK_GAUSSIAN** uses the Gaussian \f$\texttt{winsize}\times\texttt{winsize}\f$
|
||||
filter instead of a box filter of the same size for optical flow estimation; usually, this
|
||||
option gives z more accurate flow than with a box filter, at the cost of lower speed;
|
||||
normally, winsize for a Gaussian window should be set to a larger value to achieve the same
|
||||
level of robustness.
|
||||
|
||||
The function finds an optical flow for each prev pixel using the @cite Farneback2003 algorithm so that
|
||||
|
||||
\f[\texttt{prev} (y,x) \sim \texttt{next} ( y + \texttt{flow} (y,x)[1], x + \texttt{flow} (y,x)[0])\f]
|
||||
|
||||
@note
|
||||
|
||||
- An example using the optical flow algorithm described by Gunnar Farneback can be found at
|
||||
opencv_source_code/samples/cpp/fback.cpp
|
||||
- (Python) An example using the optical flow algorithm described by Gunnar Farneback can be
|
||||
found at opencv_source_code/samples/python/opt_flow.py
|
||||
*/
|
||||
CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next, InputOutputArray flow,
|
||||
double pyr_scale, int levels, int winsize,
|
||||
int iterations, int poly_n, double poly_sigma,
|
||||
int flags );
|
||||
|
||||
/** @brief Computes an optimal affine transformation between two 2D point sets.
|
||||
|
||||
@param src First input 2D point set stored in std::vector or Mat, or an image stored in Mat.
|
||||
@param dst Second input 2D point set of the same size and the same type as A, or another image.
|
||||
@param fullAffine If true, the function finds an optimal affine transformation with no additional
|
||||
restrictions (6 degrees of freedom). Otherwise, the class of transformations to choose from is
|
||||
limited to combinations of translation, rotation, and uniform scaling (4 degrees of freedom).
|
||||
|
||||
The function finds an optimal affine transform *[A|b]* (a 2 x 3 floating-point matrix) that
|
||||
approximates best the affine transformation between:
|
||||
|
||||
* Two point sets
|
||||
* Two raster images. In this case, the function first finds some features in the src image and
|
||||
finds the corresponding features in dst image. After that, the problem is reduced to the first
|
||||
case.
|
||||
In case of point sets, the problem is formulated as follows: you need to find a 2x2 matrix *A* and
|
||||
2x1 vector *b* so that:
|
||||
|
||||
\f[[A^*|b^*] = arg \min _{[A|b]} \sum _i \| \texttt{dst}[i] - A { \texttt{src}[i]}^T - b \| ^2\f]
|
||||
where src[i] and dst[i] are the i-th points in src and dst, respectively
|
||||
\f$[A|b]\f$ can be either arbitrary (when fullAffine=true ) or have a form of
|
||||
\f[\begin{bmatrix} a_{11} & a_{12} & b_1 \\ -a_{12} & a_{11} & b_2 \end{bmatrix}\f]
|
||||
when fullAffine=false.
|
||||
|
||||
@deprecated Use cv::estimateAffine2D, cv::estimateAffinePartial2D instead. If you are using this function
|
||||
with images, extract points using cv::calcOpticalFlowPyrLK and then use the estimation functions.
|
||||
|
||||
@sa
|
||||
estimateAffine2D, estimateAffinePartial2D, getAffineTransform, getPerspectiveTransform, findHomography
|
||||
*/
|
||||
CV_DEPRECATED CV_EXPORTS Mat estimateRigidTransform( InputArray src, InputArray dst, bool fullAffine );
|
||||
|
||||
enum
|
||||
{
|
||||
MOTION_TRANSLATION = 0,
|
||||
MOTION_EUCLIDEAN = 1,
|
||||
MOTION_AFFINE = 2,
|
||||
MOTION_HOMOGRAPHY = 3
|
||||
};
|
||||
|
||||
/** @brief Computes the Enhanced Correlation Coefficient value between two images @cite EP08 .
|
||||
|
||||
@param templateImage single-channel template image; CV_8U or CV_32F array.
|
||||
@param inputImage single-channel input image to be warped to provide an image similar to
|
||||
templateImage, same type as templateImage.
|
||||
@param inputMask An optional mask to indicate valid values of inputImage.
|
||||
|
||||
@sa
|
||||
findTransformECC
|
||||
*/
|
||||
|
||||
CV_EXPORTS_W double computeECC(InputArray templateImage, InputArray inputImage, InputArray inputMask = noArray());
|
||||
|
||||
/** @example samples/cpp/image_alignment.cpp
|
||||
An example using the image alignment ECC algorithm
|
||||
*/
|
||||
|
||||
/** @brief Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08 .
|
||||
|
||||
@param templateImage single-channel template image; CV_8U or CV_32F array.
|
||||
@param inputImage single-channel input image which should be warped with the final warpMatrix in
|
||||
order to provide an image similar to templateImage, same type as templateImage.
|
||||
@param warpMatrix floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp).
|
||||
@param motionType parameter, specifying the type of motion:
|
||||
- **MOTION_TRANSLATION** sets a translational motion model; warpMatrix is \f$2\times 3\f$ with
|
||||
the first \f$2\times 2\f$ part being the unity matrix and the rest two parameters being
|
||||
estimated.
|
||||
- **MOTION_EUCLIDEAN** sets a Euclidean (rigid) transformation as motion model; three
|
||||
parameters are estimated; warpMatrix is \f$2\times 3\f$.
|
||||
- **MOTION_AFFINE** sets an affine motion model (DEFAULT); six parameters are estimated;
|
||||
warpMatrix is \f$2\times 3\f$.
|
||||
- **MOTION_HOMOGRAPHY** sets a homography as a motion model; eight parameters are
|
||||
estimated;\`warpMatrix\` is \f$3\times 3\f$.
|
||||
@param criteria parameter, specifying the termination criteria of the ECC algorithm;
|
||||
criteria.epsilon defines the threshold of the increment in the correlation coefficient between two
|
||||
iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion).
|
||||
Default values are shown in the declaration above.
|
||||
@param inputMask An optional mask to indicate valid values of inputImage.
|
||||
@param gaussFiltSize An optional value indicating size of gaussian blur filter; (DEFAULT: 5)
|
||||
|
||||
The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion
|
||||
(@cite EP08), that is
|
||||
|
||||
\f[\texttt{warpMatrix} = \arg\max_{W} \texttt{ECC}(\texttt{templateImage}(x,y),\texttt{inputImage}(x',y'))\f]
|
||||
|
||||
where
|
||||
|
||||
\f[\begin{bmatrix} x' \\ y' \end{bmatrix} = W \cdot \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}\f]
|
||||
|
||||
(the equation holds with homogeneous coordinates for homography). It returns the final enhanced
|
||||
correlation coefficient, that is the correlation coefficient between the template image and the
|
||||
final warped input image. When a \f$3\times 3\f$ matrix is given with motionType =0, 1 or 2, the third
|
||||
row is ignored.
|
||||
|
||||
Unlike findHomography and estimateRigidTransform, the function findTransformECC implements an
|
||||
area-based alignment that builds on intensity similarities. In essence, the function updates the
|
||||
initial transformation that roughly aligns the images. If this information is missing, the identity
|
||||
warp (unity matrix) is used as an initialization. Note that if images undergo strong
|
||||
displacements/rotations, an initial transformation that roughly aligns the images is necessary
|
||||
(e.g., a simple euclidean/similarity transform that allows for the images showing the same image
|
||||
content approximately). Use inverse warping in the second image to take an image close to the first
|
||||
one, i.e. use the flag WARP_INVERSE_MAP with warpAffine or warpPerspective. See also the OpenCV
|
||||
sample image_alignment.cpp that demonstrates the use of the function. Note that the function throws
|
||||
an exception if algorithm does not converges.
|
||||
|
||||
@sa
|
||||
computeECC, estimateAffine2D, estimateAffinePartial2D, findHomography
|
||||
*/
|
||||
CV_EXPORTS_W double findTransformECC( InputArray templateImage, InputArray inputImage,
|
||||
InputOutputArray warpMatrix, int motionType,
|
||||
TermCriteria criteria,
|
||||
InputArray inputMask, int gaussFiltSize);
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W
|
||||
double findTransformECC(InputArray templateImage, InputArray inputImage,
|
||||
InputOutputArray warpMatrix, int motionType = MOTION_AFFINE,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001),
|
||||
InputArray inputMask = noArray());
|
||||
|
||||
/** @example samples/cpp/kalman.cpp
|
||||
An example using the standard Kalman filter
|
||||
*/
|
||||
|
||||
/** @brief Kalman filter class.
|
||||
|
||||
The class implements a standard Kalman filter <http://en.wikipedia.org/wiki/Kalman_filter>,
|
||||
@cite Welch95 . However, you can modify transitionMatrix, controlMatrix, and measurementMatrix to get
|
||||
an extended Kalman filter functionality.
|
||||
@note In C API when CvKalman\* kalmanFilter structure is not needed anymore, it should be released
|
||||
with cvReleaseKalman(&kalmanFilter)
|
||||
*/
|
||||
class CV_EXPORTS_W KalmanFilter
|
||||
{
|
||||
public:
|
||||
CV_WRAP KalmanFilter();
|
||||
/** @overload
|
||||
@param dynamParams Dimensionality of the state.
|
||||
@param measureParams Dimensionality of the measurement.
|
||||
@param controlParams Dimensionality of the control vector.
|
||||
@param type Type of the created matrices that should be CV_32F or CV_64F.
|
||||
*/
|
||||
CV_WRAP KalmanFilter( int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F );
|
||||
|
||||
/** @brief Re-initializes Kalman filter. The previous content is destroyed.
|
||||
|
||||
@param dynamParams Dimensionality of the state.
|
||||
@param measureParams Dimensionality of the measurement.
|
||||
@param controlParams Dimensionality of the control vector.
|
||||
@param type Type of the created matrices that should be CV_32F or CV_64F.
|
||||
*/
|
||||
void init( int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F );
|
||||
|
||||
/** @brief Computes a predicted state.
|
||||
|
||||
@param control The optional input control
|
||||
*/
|
||||
CV_WRAP const Mat& predict( const Mat& control = Mat() );
|
||||
|
||||
/** @brief Updates the predicted state from the measurement.
|
||||
|
||||
@param measurement The measured system parameters
|
||||
*/
|
||||
CV_WRAP const Mat& correct( const Mat& measurement );
|
||||
|
||||
CV_PROP_RW Mat statePre; //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k)
|
||||
CV_PROP_RW Mat statePost; //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k))
|
||||
CV_PROP_RW Mat transitionMatrix; //!< state transition matrix (A)
|
||||
CV_PROP_RW Mat controlMatrix; //!< control matrix (B) (not used if there is no control)
|
||||
CV_PROP_RW Mat measurementMatrix; //!< measurement matrix (H)
|
||||
CV_PROP_RW Mat processNoiseCov; //!< process noise covariance matrix (Q)
|
||||
CV_PROP_RW Mat measurementNoiseCov;//!< measurement noise covariance matrix (R)
|
||||
CV_PROP_RW Mat errorCovPre; //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/
|
||||
CV_PROP_RW Mat gain; //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)
|
||||
CV_PROP_RW Mat errorCovPost; //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k)
|
||||
|
||||
// temporary matrices
|
||||
Mat temp1;
|
||||
Mat temp2;
|
||||
Mat temp3;
|
||||
Mat temp4;
|
||||
Mat temp5;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Read a .flo file
|
||||
|
||||
@param path Path to the file to be loaded
|
||||
|
||||
The function readOpticalFlow loads a flow field from a file and returns it as a single matrix.
|
||||
Resulting Mat has a type CV_32FC2 - floating-point, 2-channel. First channel corresponds to the
|
||||
flow in the horizontal direction (u), second - vertical (v).
|
||||
*/
|
||||
CV_EXPORTS_W Mat readOpticalFlow( const String& path );
|
||||
/** @brief Write a .flo to disk
|
||||
|
||||
@param path Path to the file to be written
|
||||
@param flow Flow field to be stored
|
||||
|
||||
The function stores a flow field in a file, returns true on success, false otherwise.
|
||||
The flow field must be a 2-channel, floating-point matrix (CV_32FC2). First channel corresponds
|
||||
to the flow in the horizontal direction (u), second - vertical (v).
|
||||
*/
|
||||
CV_EXPORTS_W bool writeOpticalFlow( const String& path, InputArray flow );
|
||||
|
||||
/**
|
||||
Base class for dense optical flow algorithms
|
||||
*/
|
||||
class CV_EXPORTS_W DenseOpticalFlow : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Calculates an optical flow.
|
||||
|
||||
@param I0 first 8-bit single-channel input image.
|
||||
@param I1 second input image of the same size and the same type as prev.
|
||||
@param flow computed flow image that has the same size as prev and type CV_32FC2.
|
||||
*/
|
||||
CV_WRAP virtual void calc( InputArray I0, InputArray I1, InputOutputArray flow ) = 0;
|
||||
/** @brief Releases all inner buffers.
|
||||
*/
|
||||
CV_WRAP virtual void collectGarbage() = 0;
|
||||
};
|
||||
|
||||
/** @brief Base interface for sparse optical flow algorithms.
|
||||
*/
|
||||
class CV_EXPORTS_W SparseOpticalFlow : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Calculates a sparse optical flow.
|
||||
|
||||
@param prevImg First input image.
|
||||
@param nextImg Second input image of the same size and the same type as prevImg.
|
||||
@param prevPts Vector of 2D points for which the flow needs to be found.
|
||||
@param nextPts Output vector of 2D points containing the calculated new positions of input features in the second image.
|
||||
@param status Output status vector. Each element of the vector is set to 1 if the
|
||||
flow for the corresponding features has been found. Otherwise, it is set to 0.
|
||||
@param err Optional output vector that contains error response for each point (inverse confidence).
|
||||
*/
|
||||
CV_WRAP virtual void calc(InputArray prevImg, InputArray nextImg,
|
||||
InputArray prevPts, InputOutputArray nextPts,
|
||||
OutputArray status,
|
||||
OutputArray err = cv::noArray()) = 0;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Class computing a dense optical flow using the Gunnar Farneback's algorithm.
|
||||
*/
|
||||
class CV_EXPORTS_W FarnebackOpticalFlow : public DenseOpticalFlow
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual int getNumLevels() const = 0;
|
||||
CV_WRAP virtual void setNumLevels(int numLevels) = 0;
|
||||
|
||||
CV_WRAP virtual double getPyrScale() const = 0;
|
||||
CV_WRAP virtual void setPyrScale(double pyrScale) = 0;
|
||||
|
||||
CV_WRAP virtual bool getFastPyramids() const = 0;
|
||||
CV_WRAP virtual void setFastPyramids(bool fastPyramids) = 0;
|
||||
|
||||
CV_WRAP virtual int getWinSize() const = 0;
|
||||
CV_WRAP virtual void setWinSize(int winSize) = 0;
|
||||
|
||||
CV_WRAP virtual int getNumIters() const = 0;
|
||||
CV_WRAP virtual void setNumIters(int numIters) = 0;
|
||||
|
||||
CV_WRAP virtual int getPolyN() const = 0;
|
||||
CV_WRAP virtual void setPolyN(int polyN) = 0;
|
||||
|
||||
CV_WRAP virtual double getPolySigma() const = 0;
|
||||
CV_WRAP virtual void setPolySigma(double polySigma) = 0;
|
||||
|
||||
CV_WRAP virtual int getFlags() const = 0;
|
||||
CV_WRAP virtual void setFlags(int flags) = 0;
|
||||
|
||||
CV_WRAP static Ptr<FarnebackOpticalFlow> create(
|
||||
int numLevels = 5,
|
||||
double pyrScale = 0.5,
|
||||
bool fastPyramids = false,
|
||||
int winSize = 13,
|
||||
int numIters = 10,
|
||||
int polyN = 5,
|
||||
double polySigma = 1.1,
|
||||
int flags = 0);
|
||||
};
|
||||
|
||||
/** @brief Variational optical flow refinement
|
||||
|
||||
This class implements variational refinement of the input flow field, i.e.
|
||||
it uses input flow to initialize the minimization of the following functional:
|
||||
\f$E(U) = \int_{\Omega} \delta \Psi(E_I) + \gamma \Psi(E_G) + \alpha \Psi(E_S) \f$,
|
||||
where \f$E_I,E_G,E_S\f$ are color constancy, gradient constancy and smoothness terms
|
||||
respectively. \f$\Psi(s^2)=\sqrt{s^2+\epsilon^2}\f$ is a robust penalizer to limit the
|
||||
influence of outliers. A complete formulation and a description of the minimization
|
||||
procedure can be found in @cite Brox2004
|
||||
*/
|
||||
class CV_EXPORTS_W VariationalRefinement : public DenseOpticalFlow
|
||||
{
|
||||
public:
|
||||
/** @brief @ref calc function overload to handle separate horizontal (u) and vertical (v) flow components
|
||||
(to avoid extra splits/merges) */
|
||||
CV_WRAP virtual void calcUV(InputArray I0, InputArray I1, InputOutputArray flow_u, InputOutputArray flow_v) = 0;
|
||||
|
||||
/** @brief Number of outer (fixed-point) iterations in the minimization procedure.
|
||||
@see setFixedPointIterations */
|
||||
CV_WRAP virtual int getFixedPointIterations() const = 0;
|
||||
/** @copybrief getFixedPointIterations @see getFixedPointIterations */
|
||||
CV_WRAP virtual void setFixedPointIterations(int val) = 0;
|
||||
|
||||
/** @brief Number of inner successive over-relaxation (SOR) iterations
|
||||
in the minimization procedure to solve the respective linear system.
|
||||
@see setSorIterations */
|
||||
CV_WRAP virtual int getSorIterations() const = 0;
|
||||
/** @copybrief getSorIterations @see getSorIterations */
|
||||
CV_WRAP virtual void setSorIterations(int val) = 0;
|
||||
|
||||
/** @brief Relaxation factor in SOR
|
||||
@see setOmega */
|
||||
CV_WRAP virtual float getOmega() const = 0;
|
||||
/** @copybrief getOmega @see getOmega */
|
||||
CV_WRAP virtual void setOmega(float val) = 0;
|
||||
|
||||
/** @brief Weight of the smoothness term
|
||||
@see setAlpha */
|
||||
CV_WRAP virtual float getAlpha() const = 0;
|
||||
/** @copybrief getAlpha @see getAlpha */
|
||||
CV_WRAP virtual void setAlpha(float val) = 0;
|
||||
|
||||
/** @brief Weight of the color constancy term
|
||||
@see setDelta */
|
||||
CV_WRAP virtual float getDelta() const = 0;
|
||||
/** @copybrief getDelta @see getDelta */
|
||||
CV_WRAP virtual void setDelta(float val) = 0;
|
||||
|
||||
/** @brief Weight of the gradient constancy term
|
||||
@see setGamma */
|
||||
CV_WRAP virtual float getGamma() const = 0;
|
||||
/** @copybrief getGamma @see getGamma */
|
||||
CV_WRAP virtual void setGamma(float val) = 0;
|
||||
|
||||
/** @brief Creates an instance of VariationalRefinement
|
||||
*/
|
||||
CV_WRAP static Ptr<VariationalRefinement> create();
|
||||
};
|
||||
|
||||
/** @brief DIS optical flow algorithm.
|
||||
|
||||
This class implements the Dense Inverse Search (DIS) optical flow algorithm. More
|
||||
details about the algorithm can be found at @cite Kroeger2016 . Includes three presets with preselected
|
||||
parameters to provide reasonable trade-off between speed and quality. However, even the slowest preset is
|
||||
still relatively fast, use DeepFlow if you need better quality and don't care about speed.
|
||||
|
||||
This implementation includes several additional features compared to the algorithm described in the paper,
|
||||
including spatial propagation of flow vectors (@ref getUseSpatialPropagation), as well as an option to
|
||||
utilize an initial flow approximation passed to @ref calc (which is, essentially, temporal propagation,
|
||||
if the previous frame's flow field is passed).
|
||||
*/
|
||||
class CV_EXPORTS_W DISOpticalFlow : public DenseOpticalFlow
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
PRESET_ULTRAFAST = 0,
|
||||
PRESET_FAST = 1,
|
||||
PRESET_MEDIUM = 2
|
||||
};
|
||||
|
||||
/** @brief Finest level of the Gaussian pyramid on which the flow is computed (zero level
|
||||
corresponds to the original image resolution). The final flow is obtained by bilinear upscaling.
|
||||
@see setFinestScale */
|
||||
CV_WRAP virtual int getFinestScale() const = 0;
|
||||
/** @copybrief getFinestScale @see getFinestScale */
|
||||
CV_WRAP virtual void setFinestScale(int val) = 0;
|
||||
|
||||
/** @brief Size of an image patch for matching (in pixels). Normally, default 8x8 patches work well
|
||||
enough in most cases.
|
||||
@see setPatchSize */
|
||||
CV_WRAP virtual int getPatchSize() const = 0;
|
||||
/** @copybrief getPatchSize @see getPatchSize */
|
||||
CV_WRAP virtual void setPatchSize(int val) = 0;
|
||||
|
||||
/** @brief Stride between neighbor patches. Must be less than patch size. Lower values correspond
|
||||
to higher flow quality.
|
||||
@see setPatchStride */
|
||||
CV_WRAP virtual int getPatchStride() const = 0;
|
||||
/** @copybrief getPatchStride @see getPatchStride */
|
||||
CV_WRAP virtual void setPatchStride(int val) = 0;
|
||||
|
||||
/** @brief Maximum number of gradient descent iterations in the patch inverse search stage. Higher values
|
||||
may improve quality in some cases.
|
||||
@see setGradientDescentIterations */
|
||||
CV_WRAP virtual int getGradientDescentIterations() const = 0;
|
||||
/** @copybrief getGradientDescentIterations @see getGradientDescentIterations */
|
||||
CV_WRAP virtual void setGradientDescentIterations(int val) = 0;
|
||||
|
||||
/** @brief Number of fixed point iterations of variational refinement per scale. Set to zero to
|
||||
disable variational refinement completely. Higher values will typically result in more smooth and
|
||||
high-quality flow.
|
||||
@see setGradientDescentIterations */
|
||||
CV_WRAP virtual int getVariationalRefinementIterations() const = 0;
|
||||
/** @copybrief getGradientDescentIterations @see getGradientDescentIterations */
|
||||
CV_WRAP virtual void setVariationalRefinementIterations(int val) = 0;
|
||||
|
||||
/** @brief Weight of the smoothness term
|
||||
@see setVariationalRefinementAlpha */
|
||||
CV_WRAP virtual float getVariationalRefinementAlpha() const = 0;
|
||||
/** @copybrief getVariationalRefinementAlpha @see getVariationalRefinementAlpha */
|
||||
CV_WRAP virtual void setVariationalRefinementAlpha(float val) = 0;
|
||||
|
||||
/** @brief Weight of the color constancy term
|
||||
@see setVariationalRefinementDelta */
|
||||
CV_WRAP virtual float getVariationalRefinementDelta() const = 0;
|
||||
/** @copybrief getVariationalRefinementDelta @see getVariationalRefinementDelta */
|
||||
CV_WRAP virtual void setVariationalRefinementDelta(float val) = 0;
|
||||
|
||||
/** @brief Weight of the gradient constancy term
|
||||
@see setVariationalRefinementGamma */
|
||||
CV_WRAP virtual float getVariationalRefinementGamma() const = 0;
|
||||
/** @copybrief getVariationalRefinementGamma @see getVariationalRefinementGamma */
|
||||
CV_WRAP virtual void setVariationalRefinementGamma(float val) = 0;
|
||||
|
||||
|
||||
/** @brief Whether to use mean-normalization of patches when computing patch distance. It is turned on
|
||||
by default as it typically provides a noticeable quality boost because of increased robustness to
|
||||
illumination variations. Turn it off if you are certain that your sequence doesn't contain any changes
|
||||
in illumination.
|
||||
@see setUseMeanNormalization */
|
||||
CV_WRAP virtual bool getUseMeanNormalization() const = 0;
|
||||
/** @copybrief getUseMeanNormalization @see getUseMeanNormalization */
|
||||
CV_WRAP virtual void setUseMeanNormalization(bool val) = 0;
|
||||
|
||||
/** @brief Whether to use spatial propagation of good optical flow vectors. This option is turned on by
|
||||
default, as it tends to work better on average and can sometimes help recover from major errors
|
||||
introduced by the coarse-to-fine scheme employed by the DIS optical flow algorithm. Turning this
|
||||
option off can make the output flow field a bit smoother, however.
|
||||
@see setUseSpatialPropagation */
|
||||
CV_WRAP virtual bool getUseSpatialPropagation() const = 0;
|
||||
/** @copybrief getUseSpatialPropagation @see getUseSpatialPropagation */
|
||||
CV_WRAP virtual void setUseSpatialPropagation(bool val) = 0;
|
||||
|
||||
/** @brief Creates an instance of DISOpticalFlow
|
||||
|
||||
@param preset one of PRESET_ULTRAFAST, PRESET_FAST and PRESET_MEDIUM
|
||||
*/
|
||||
CV_WRAP static Ptr<DISOpticalFlow> create(int preset = DISOpticalFlow::PRESET_FAST);
|
||||
};
|
||||
|
||||
/** @brief Class used for calculating a sparse optical flow.
|
||||
|
||||
The class can calculate an optical flow for a sparse feature set using the
|
||||
iterative Lucas-Kanade method with pyramids.
|
||||
|
||||
@sa calcOpticalFlowPyrLK
|
||||
|
||||
*/
|
||||
class CV_EXPORTS_W SparsePyrLKOpticalFlow : public SparseOpticalFlow
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual Size getWinSize() const = 0;
|
||||
CV_WRAP virtual void setWinSize(Size winSize) = 0;
|
||||
|
||||
CV_WRAP virtual int getMaxLevel() const = 0;
|
||||
CV_WRAP virtual void setMaxLevel(int maxLevel) = 0;
|
||||
|
||||
CV_WRAP virtual TermCriteria getTermCriteria() const = 0;
|
||||
CV_WRAP virtual void setTermCriteria(TermCriteria& crit) = 0;
|
||||
|
||||
CV_WRAP virtual int getFlags() const = 0;
|
||||
CV_WRAP virtual void setFlags(int flags) = 0;
|
||||
|
||||
CV_WRAP virtual double getMinEigThreshold() const = 0;
|
||||
CV_WRAP virtual void setMinEigThreshold(double minEigThreshold) = 0;
|
||||
|
||||
CV_WRAP static Ptr<SparsePyrLKOpticalFlow> create(
|
||||
Size winSize = Size(21, 21),
|
||||
int maxLevel = 3, TermCriteria crit =
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
|
||||
int flags = 0,
|
||||
double minEigThreshold = 1e-4);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** @brief Base abstract class for the long-term tracker
|
||||
*/
|
||||
class CV_EXPORTS_W Tracker
|
||||
{
|
||||
protected:
|
||||
Tracker();
|
||||
public:
|
||||
virtual ~Tracker();
|
||||
|
||||
/** @brief Initialize the tracker with a known bounding box that surrounded the target
|
||||
@param image The initial frame
|
||||
@param boundingBox The initial bounding box
|
||||
*/
|
||||
CV_WRAP virtual
|
||||
void init(InputArray image, const Rect& boundingBox) = 0;
|
||||
|
||||
/** @brief Update the tracker, find the new most likely bounding box for the target
|
||||
@param image The current frame
|
||||
@param boundingBox The bounding box that represent the new target location, if true was returned, not
|
||||
modified otherwise
|
||||
|
||||
@return True means that target was located and false means that tracker cannot locate target in
|
||||
current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed
|
||||
missing from the frame (say, out of sight)
|
||||
*/
|
||||
CV_WRAP virtual
|
||||
bool update(InputArray image, CV_OUT Rect& boundingBox) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** @brief The MIL algorithm trains a classifier in an online manner to separate the object from the
|
||||
background.
|
||||
|
||||
Multiple Instance Learning avoids the drift problem for a robust tracking. The implementation is
|
||||
based on @cite MIL .
|
||||
|
||||
Original code can be found here <http://vision.ucsd.edu/~bbabenko/project_miltrack.shtml>
|
||||
*/
|
||||
class CV_EXPORTS_W TrackerMIL : public Tracker
|
||||
{
|
||||
protected:
|
||||
TrackerMIL(); // use ::create()
|
||||
public:
|
||||
virtual ~TrackerMIL() CV_OVERRIDE;
|
||||
|
||||
struct CV_EXPORTS_W_SIMPLE Params
|
||||
{
|
||||
CV_WRAP Params();
|
||||
//parameters for sampler
|
||||
CV_PROP_RW float samplerInitInRadius; //!< radius for gathering positive instances during init
|
||||
CV_PROP_RW int samplerInitMaxNegNum; //!< # negative samples to use during init
|
||||
CV_PROP_RW float samplerSearchWinSize; //!< size of search window
|
||||
CV_PROP_RW float samplerTrackInRadius; //!< radius for gathering positive instances during tracking
|
||||
CV_PROP_RW int samplerTrackMaxPosNum; //!< # positive samples to use during tracking
|
||||
CV_PROP_RW int samplerTrackMaxNegNum; //!< # negative samples to use during tracking
|
||||
CV_PROP_RW int featureSetNumFeatures; //!< # features
|
||||
};
|
||||
|
||||
/** @brief Create MIL tracker instance
|
||||
* @param parameters MIL parameters TrackerMIL::Params
|
||||
*/
|
||||
static CV_WRAP
|
||||
Ptr<TrackerMIL> create(const TrackerMIL::Params ¶meters = TrackerMIL::Params());
|
||||
|
||||
//void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE;
|
||||
//bool update(InputArray image, CV_OUT Rect& boundingBox) CV_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** @brief the GOTURN (Generic Object Tracking Using Regression Networks) tracker
|
||||
*
|
||||
* GOTURN (@cite GOTURN) is kind of trackers based on Convolutional Neural Networks (CNN). While taking all advantages of CNN trackers,
|
||||
* GOTURN is much faster due to offline training without online fine-tuning nature.
|
||||
* GOTURN tracker addresses the problem of single target tracking: given a bounding box label of an object in the first frame of the video,
|
||||
* we track that object through the rest of the video. NOTE: Current method of GOTURN does not handle occlusions; however, it is fairly
|
||||
* robust to viewpoint changes, lighting changes, and deformations.
|
||||
* Inputs of GOTURN are two RGB patches representing Target and Search patches resized to 227x227.
|
||||
* Outputs of GOTURN are predicted bounding box coordinates, relative to Search patch coordinate system, in format X1,Y1,X2,Y2.
|
||||
* Original paper is here: <http://davheld.github.io/GOTURN/GOTURN.pdf>
|
||||
* As long as original authors implementation: <https://github.com/davheld/GOTURN#train-the-tracker>
|
||||
* Implementation of training algorithm is placed in separately here due to 3d-party dependencies:
|
||||
* <https://github.com/Auron-X/GOTURN_Training_Toolkit>
|
||||
* GOTURN architecture goturn.prototxt and trained model goturn.caffemodel are accessible on opencv_extra GitHub repository.
|
||||
*/
|
||||
class CV_EXPORTS_W TrackerGOTURN : public Tracker
|
||||
{
|
||||
protected:
|
||||
TrackerGOTURN(); // use ::create()
|
||||
public:
|
||||
virtual ~TrackerGOTURN() CV_OVERRIDE;
|
||||
|
||||
struct CV_EXPORTS_W_SIMPLE Params
|
||||
{
|
||||
CV_WRAP Params();
|
||||
CV_PROP_RW std::string modelTxt;
|
||||
CV_PROP_RW std::string modelBin;
|
||||
};
|
||||
|
||||
/** @brief Constructor
|
||||
@param parameters GOTURN parameters TrackerGOTURN::Params
|
||||
*/
|
||||
static CV_WRAP
|
||||
Ptr<TrackerGOTURN> create(const TrackerGOTURN::Params& parameters = TrackerGOTURN::Params());
|
||||
|
||||
//void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE;
|
||||
//bool update(InputArray image, CV_OUT Rect& boundingBox) CV_OVERRIDE;
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W TrackerDaSiamRPN : public Tracker
|
||||
{
|
||||
protected:
|
||||
TrackerDaSiamRPN(); // use ::create()
|
||||
public:
|
||||
virtual ~TrackerDaSiamRPN() CV_OVERRIDE;
|
||||
|
||||
struct CV_EXPORTS_W_SIMPLE Params
|
||||
{
|
||||
CV_WRAP Params();
|
||||
CV_PROP_RW std::string model;
|
||||
CV_PROP_RW std::string kernel_cls1;
|
||||
CV_PROP_RW std::string kernel_r1;
|
||||
CV_PROP_RW int backend;
|
||||
CV_PROP_RW int target;
|
||||
};
|
||||
|
||||
/** @brief Constructor
|
||||
@param parameters DaSiamRPN parameters TrackerDaSiamRPN::Params
|
||||
*/
|
||||
static CV_WRAP
|
||||
Ptr<TrackerDaSiamRPN> create(const TrackerDaSiamRPN::Params& parameters = TrackerDaSiamRPN::Params());
|
||||
|
||||
/** @brief Return tracking score
|
||||
*/
|
||||
CV_WRAP virtual float getTrackingScore() = 0;
|
||||
|
||||
//void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE;
|
||||
//bool update(InputArray image, CV_OUT Rect& boundingBox) CV_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
//! @} video_track
|
||||
|
||||
} // cv
|
||||
|
||||
#endif
|
||||
48
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/video.hpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/video/include/opencv2/video/video.hpp
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifdef __OPENCV_BUILD
|
||||
#error this is a compatibility header which should not be used inside the OpenCV library
|
||||
#endif
|
||||
|
||||
#include "opencv2/video.hpp"
|
||||
16
3rdparty/opencv-4.5.4/modules/video/misc/java/gen_dict.json
vendored
Normal file
16
3rdparty/opencv-4.5.4/modules/video/misc/java/gen_dict.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"missing_consts": {
|
||||
"Video" : {
|
||||
"private" : [
|
||||
["CV_LKFLOW_INITIAL_GUESSES", 4 ],
|
||||
["CV_LKFLOW_GET_MIN_EIGENVALS", 8 ]
|
||||
]
|
||||
}
|
||||
},
|
||||
"func_arg_fix" : {
|
||||
"calcOpticalFlowPyrLK" : { "prevPts" : {"ctype" : "vector_Point2f"},
|
||||
"nextPts" : {"ctype" : "vector_Point2f"},
|
||||
"status" : {"ctype" : "vector_uchar"},
|
||||
"err" : {"ctype" : "vector_float"} }
|
||||
}
|
||||
}
|
||||
43
3rdparty/opencv-4.5.4/modules/video/misc/java/test/BackgroundSubtractorMOGTest.java
vendored
Normal file
43
3rdparty/opencv-4.5.4/modules/video/misc/java/test/BackgroundSubtractorMOGTest.java
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package org.opencv.test.video;
|
||||
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
public class BackgroundSubtractorMOGTest extends OpenCVTestCase {
|
||||
|
||||
public void testApplyMatMat() {
|
||||
fail("Not yet implemented");
|
||||
/*
|
||||
BackgroundSubtractorMOG backGroundSubtract = new BackgroundSubtractorMOG();
|
||||
|
||||
Point bottomRight = new Point(rgbLena.cols() / 2, rgbLena.rows() / 2);
|
||||
Point topLeft = new Point(0, 0);
|
||||
Scalar color = new Scalar(128);
|
||||
Mat mask = new Mat(rgbLena.size(), CvType.CV_16UC3, new Scalar(1));
|
||||
|
||||
Imgproc.rectangle(rgbLena, bottomRight, topLeft, color, Imgproc.FILLED);
|
||||
|
||||
backGroundSubtract.apply(rgbLena, mask);
|
||||
|
||||
Mat truth = new Mat(rgbLena.size(), rgbLena.type(), new Scalar(0));
|
||||
Imgproc.rectangle(truth, bottomRight, topLeft, color, Imgproc.FILLED);
|
||||
assertMatEqual(truth, rgbLena);
|
||||
*/
|
||||
}
|
||||
|
||||
public void testApplyMatMatDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testBackgroundSubtractorMOG() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testBackgroundSubtractorMOGIntIntDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testBackgroundSubtractorMOGIntIntDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
}
|
||||
38
3rdparty/opencv-4.5.4/modules/video/misc/java/test/KalmanFilterTest.java
vendored
Normal file
38
3rdparty/opencv-4.5.4/modules/video/misc/java/test/KalmanFilterTest.java
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package org.opencv.test.video;
|
||||
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
import org.opencv.video.KalmanFilter;
|
||||
|
||||
public class KalmanFilterTest extends OpenCVTestCase {
|
||||
|
||||
public void testCorrect() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testKalmanFilter() {
|
||||
KalmanFilter kf = new KalmanFilter();
|
||||
|
||||
assertNotNull(kf);
|
||||
}
|
||||
|
||||
public void testKalmanFilterIntInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testKalmanFilterIntIntInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testKalmanFilterIntIntIntInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testPredict() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testPredictMat() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
}
|
||||
39
3rdparty/opencv-4.5.4/modules/video/misc/java/test/TrackerCreateTest.java
vendored
Normal file
39
3rdparty/opencv-4.5.4/modules/video/misc/java/test/TrackerCreateTest.java
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package org.opencv.test.video;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.CvException;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Rect;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
|
||||
import org.opencv.video.Tracker;
|
||||
import org.opencv.video.TrackerGOTURN;
|
||||
import org.opencv.video.TrackerMIL;
|
||||
|
||||
public class TrackerCreateTest extends OpenCVTestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
|
||||
public void testCreateTrackerGOTURN() {
|
||||
try {
|
||||
Tracker tracker = TrackerGOTURN.create();
|
||||
assert(tracker != null);
|
||||
} catch (CvException e) {
|
||||
// expected, model files may be missing
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateTrackerMIL() {
|
||||
Tracker tracker = TrackerMIL.create();
|
||||
assert(tracker != null);
|
||||
Mat mat = new Mat(100, 100, CvType.CV_8UC1);
|
||||
Rect rect = new Rect(10, 10, 30, 30);
|
||||
tracker.init(mat, rect); // should not crash (https://github.com/opencv/opencv/issues/19915)
|
||||
}
|
||||
|
||||
}
|
||||
99
3rdparty/opencv-4.5.4/modules/video/misc/java/test/VideoTest.java
vendored
Normal file
99
3rdparty/opencv-4.5.4/modules/video/misc/java/test/VideoTest.java
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
package org.opencv.test.video;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.core.MatOfFloat;
|
||||
import org.opencv.core.MatOfPoint2f;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
import org.opencv.video.Video;
|
||||
|
||||
public class VideoTest extends OpenCVTestCase {
|
||||
|
||||
private MatOfFloat err = null;
|
||||
private int h;
|
||||
private MatOfPoint2f nextPts = null;
|
||||
private MatOfPoint2f prevPts = null;
|
||||
|
||||
private int shift1;
|
||||
private int shift2;
|
||||
|
||||
private MatOfByte status = null;
|
||||
private Mat subLena1 = null;
|
||||
private Mat subLena2 = null;
|
||||
private int w;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
shift1 = 10;
|
||||
shift2 = 17;
|
||||
w = (int)(rgbLena.cols() / 2);
|
||||
h = (int)(rgbLena.rows() / 2);
|
||||
|
||||
subLena1 = rgbLena.submat(shift1, h + shift1, shift1, w + shift1);
|
||||
subLena2 = rgbLena.submat(shift2, h + shift2, shift2, w + shift2);
|
||||
|
||||
prevPts = new MatOfPoint2f(new Point(11d, 8d), new Point(5d, 5d), new Point(10d, 10d));
|
||||
|
||||
nextPts = new MatOfPoint2f();
|
||||
status = new MatOfByte();
|
||||
err = new MatOfFloat();
|
||||
}
|
||||
|
||||
public void testCalcGlobalOrientation() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testCalcMotionGradientMatMatMatDoubleDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testCalcMotionGradientMatMatMatDoubleDoubleInt() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testCalcOpticalFlowFarneback() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testCalcOpticalFlowPyrLKMatMatListOfPointListOfPointListOfByteListOfFloat() {
|
||||
Video.calcOpticalFlowPyrLK(subLena1, subLena2, prevPts, nextPts, status, err);
|
||||
assertEquals(3, Core.countNonZero(status));
|
||||
}
|
||||
|
||||
public void testCalcOpticalFlowPyrLKMatMatListOfPointListOfPointListOfByteListOfFloatSize() {
|
||||
Size sz = new Size(3, 3);
|
||||
Video.calcOpticalFlowPyrLK(subLena1, subLena2, prevPts, nextPts, status, err, sz, 3);
|
||||
assertEquals(0, Core.countNonZero(status));
|
||||
}
|
||||
|
||||
|
||||
public void testCalcOpticalFlowPyrLKMatMatListOfPointListOfPointListOfByteListOfFloatSizeIntTermCriteriaDoubleIntDouble() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testCamShift() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testEstimateRigidTransform() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testMeanShift() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testSegmentMotion() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testUpdateMotionHistory() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
}
|
||||
5
3rdparty/opencv-4.5.4/modules/video/misc/python/pyopencv_video.hpp
vendored
Normal file
5
3rdparty/opencv-4.5.4/modules/video/misc/python/pyopencv_video.hpp
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#ifdef HAVE_OPENCV_VIDEO
|
||||
typedef TrackerMIL::Params TrackerMIL_Params;
|
||||
typedef TrackerGOTURN::Params TrackerGOTURN_Params;
|
||||
typedef TrackerDaSiamRPN::Params TrackerDaSiamRPN_Params;
|
||||
#endif
|
||||
100
3rdparty/opencv-4.5.4/modules/video/misc/python/test/test_lk_homography.py
vendored
Normal file
100
3rdparty/opencv-4.5.4/modules/video/misc/python/test/test_lk_homography.py
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Lucas-Kanade homography tracker test
|
||||
===============================
|
||||
Uses goodFeaturesToTrack for track initialization and back-tracking for match verification
|
||||
between frames. Finds homography between reference and current views.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
#local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
from tests_common import NewOpenCVTests, isPointInRect
|
||||
|
||||
lk_params = dict( winSize = (19, 19),
|
||||
maxLevel = 2,
|
||||
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
|
||||
feature_params = dict( maxCorners = 1000,
|
||||
qualityLevel = 0.01,
|
||||
minDistance = 8,
|
||||
blockSize = 19 )
|
||||
|
||||
def checkedTrace(img0, img1, p0, back_threshold = 1.0):
|
||||
p1, _st, _err = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
|
||||
p0r, _st, _err = cv.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
|
||||
d = abs(p0-p0r).reshape(-1, 2).max(-1)
|
||||
status = d < back_threshold
|
||||
return p1, status
|
||||
|
||||
class lk_homography_test(NewOpenCVTests):
|
||||
|
||||
render = None
|
||||
framesCounter = 0
|
||||
frame = frame0 = None
|
||||
p0 = None
|
||||
p1 = None
|
||||
gray0 = gray1 = None
|
||||
numFeaturesInRectOnStart = 0
|
||||
|
||||
def test_lk_homography(self):
|
||||
self.render = TestSceneRender(self.get_sample('samples/data/graf1.png'),
|
||||
self.get_sample('samples/data/box.png'), noise = 0.1, speed = 1.0)
|
||||
|
||||
frame = self.render.getNextFrame()
|
||||
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
|
||||
self.frame0 = frame.copy()
|
||||
self.p0 = cv.goodFeaturesToTrack(frame_gray, **feature_params)
|
||||
|
||||
isForegroundHomographyFound = False
|
||||
|
||||
if self.p0 is not None:
|
||||
self.p1 = self.p0
|
||||
self.gray0 = frame_gray
|
||||
self.gray1 = frame_gray
|
||||
currRect = self.render.getCurrentRect()
|
||||
for (x,y) in self.p0[:,0]:
|
||||
if isPointInRect((x,y), currRect):
|
||||
self.numFeaturesInRectOnStart += 1
|
||||
|
||||
while self.framesCounter < 200:
|
||||
self.framesCounter += 1
|
||||
frame = self.render.getNextFrame()
|
||||
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
|
||||
if self.p0 is not None:
|
||||
p2, trace_status = checkedTrace(self.gray1, frame_gray, self.p1)
|
||||
|
||||
self.p1 = p2[trace_status].copy()
|
||||
self.p0 = self.p0[trace_status].copy()
|
||||
self.gray1 = frame_gray
|
||||
|
||||
if len(self.p0) < 4:
|
||||
self.p0 = None
|
||||
continue
|
||||
_H, status = cv.findHomography(self.p0, self.p1, cv.RANSAC, 5.0)
|
||||
|
||||
goodPointsInRect = 0
|
||||
goodPointsOutsideRect = 0
|
||||
for (_x0, _y0), (x1, y1), good in zip(self.p0[:,0], self.p1[:,0], status[:,0]):
|
||||
if good:
|
||||
if isPointInRect((x1,y1), self.render.getCurrentRect()):
|
||||
goodPointsInRect += 1
|
||||
else: goodPointsOutsideRect += 1
|
||||
|
||||
if goodPointsOutsideRect < goodPointsInRect:
|
||||
isForegroundHomographyFound = True
|
||||
self.assertGreater(float(goodPointsInRect) / (self.numFeaturesInRectOnStart + 1), 0.6)
|
||||
else:
|
||||
self.p0 = cv.goodFeaturesToTrack(frame_gray, **feature_params)
|
||||
|
||||
self.assertEqual(isForegroundHomographyFound, True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
115
3rdparty/opencv-4.5.4/modules/video/misc/python/test/test_lk_track.py
vendored
Normal file
115
3rdparty/opencv-4.5.4/modules/video/misc/python/test/test_lk_track.py
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Lucas-Kanade tracker
|
||||
====================
|
||||
|
||||
Lucas-Kanade sparse optical flow demo. Uses goodFeaturesToTrack
|
||||
for track initialization and back-tracking for match verification
|
||||
between frames.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
#local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
from tests_common import NewOpenCVTests, intersectionRate, isPointInRect
|
||||
|
||||
lk_params = dict( winSize = (15, 15),
|
||||
maxLevel = 2,
|
||||
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
|
||||
feature_params = dict( maxCorners = 500,
|
||||
qualityLevel = 0.3,
|
||||
minDistance = 7,
|
||||
blockSize = 7 )
|
||||
|
||||
def getRectFromPoints(points):
|
||||
|
||||
distances = []
|
||||
for point in points:
|
||||
distances.append(cv.norm(point, cv.NORM_L2))
|
||||
|
||||
x0, y0 = points[np.argmin(distances)]
|
||||
x1, y1 = points[np.argmax(distances)]
|
||||
|
||||
return np.array([x0, y0, x1, y1])
|
||||
|
||||
|
||||
class lk_track_test(NewOpenCVTests):
|
||||
|
||||
track_len = 10
|
||||
detect_interval = 5
|
||||
tracks = []
|
||||
frame_idx = 0
|
||||
render = None
|
||||
|
||||
def test_lk_track(self):
|
||||
|
||||
self.render = TestSceneRender(self.get_sample('samples/data/graf1.png'), self.get_sample('samples/data/box.png'))
|
||||
self.runTracker()
|
||||
|
||||
def runTracker(self):
|
||||
foregroundPointsNum = 0
|
||||
|
||||
while True:
|
||||
frame = self.render.getNextFrame()
|
||||
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
|
||||
|
||||
if len(self.tracks) > 0:
|
||||
img0, img1 = self.prev_gray, frame_gray
|
||||
p0 = np.float32([tr[-1][0] for tr in self.tracks]).reshape(-1, 1, 2)
|
||||
p1, _st, _err = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
|
||||
p0r, _st, _err = cv.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
|
||||
d = abs(p0-p0r).reshape(-1, 2).max(-1)
|
||||
good = d < 1
|
||||
new_tracks = []
|
||||
for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
|
||||
if not good_flag:
|
||||
continue
|
||||
tr.append([(x, y), self.frame_idx])
|
||||
if len(tr) > self.track_len:
|
||||
del tr[0]
|
||||
new_tracks.append(tr)
|
||||
self.tracks = new_tracks
|
||||
|
||||
if self.frame_idx % self.detect_interval == 0:
|
||||
goodTracksCount = 0
|
||||
for tr in self.tracks:
|
||||
oldRect = self.render.getRectInTime(self.render.timeStep * tr[0][1])
|
||||
newRect = self.render.getRectInTime(self.render.timeStep * tr[-1][1])
|
||||
if isPointInRect(tr[0][0], oldRect) and isPointInRect(tr[-1][0], newRect):
|
||||
goodTracksCount += 1
|
||||
|
||||
if self.frame_idx == self.detect_interval:
|
||||
foregroundPointsNum = goodTracksCount
|
||||
|
||||
fgIndex = float(foregroundPointsNum) / (foregroundPointsNum + 1)
|
||||
fgRate = float(goodTracksCount) / (len(self.tracks) + 1)
|
||||
|
||||
if self.frame_idx > 0:
|
||||
self.assertGreater(fgIndex, 0.9)
|
||||
self.assertGreater(fgRate, 0.2)
|
||||
|
||||
mask = np.zeros_like(frame_gray)
|
||||
mask[:] = 255
|
||||
for x, y in [np.int32(tr[-1][0]) for tr in self.tracks]:
|
||||
cv.circle(mask, (x, y), 5, 0, -1)
|
||||
p = cv.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)
|
||||
if p is not None:
|
||||
for x, y in np.float32(p).reshape(-1, 2):
|
||||
self.tracks.append([[(x, y), self.frame_idx]])
|
||||
|
||||
self.frame_idx += 1
|
||||
self.prev_gray = frame_gray
|
||||
|
||||
if self.frame_idx > 300:
|
||||
break
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
19
3rdparty/opencv-4.5.4/modules/video/misc/python/test/test_tracking.py
vendored
Normal file
19
3rdparty/opencv-4.5.4/modules/video/misc/python/test/test_tracking.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
from tests_common import NewOpenCVTests, unittest
|
||||
|
||||
class tracking_test(NewOpenCVTests):
|
||||
|
||||
def test_createTracker(self):
|
||||
t = cv.TrackerMIL_create()
|
||||
try:
|
||||
t = cv.TrackerGOTURN_create()
|
||||
except cv.error as e:
|
||||
pass # may fail due to missing DL model files
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
95
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_bgfg_knn.cpp
vendored
Normal file
95
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_bgfg_knn.cpp
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
#include "../perf_bgfg_utils.hpp"
|
||||
|
||||
namespace cvtest {
|
||||
namespace ocl {
|
||||
|
||||
//////////////////////////// KNN//////////////////////////
|
||||
|
||||
typedef tuple<string, int> VideoKNNParamType;
|
||||
typedef TestBaseWithParam<VideoKNNParamType> KNN_Apply;
|
||||
typedef TestBaseWithParam<VideoKNNParamType> KNN_GetBackgroundImage;
|
||||
|
||||
using namespace opencv_test;
|
||||
|
||||
OCL_PERF_TEST_P(KNN_Apply, KNN, Combine(Values("cv/video/768x576.avi", "cv/video/1920x1080.avi"), Values(1,3)))
|
||||
{
|
||||
VideoKNNParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = get<1>(params);
|
||||
int nFrame = 5;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer);
|
||||
|
||||
UMat u_foreground;
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorKNN> knn = createBackgroundSubtractorKNN();
|
||||
knn->setDetectShadows(false);
|
||||
u_foreground.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
knn->apply(frame_buffer[i], u_foreground);
|
||||
}
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
OCL_PERF_TEST_P(KNN_GetBackgroundImage, KNN, Values(
|
||||
std::make_pair<string, int>("cv/video/768x576.avi", 5),
|
||||
std::make_pair<string, int>("cv/video/1920x1080.avi", 5)))
|
||||
{
|
||||
VideoKNNParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = 3;
|
||||
const int skipFrames = get<1>(params);
|
||||
int nFrame = 10;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer, skipFrames);
|
||||
|
||||
UMat u_foreground, u_background;
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorKNN> knn = createBackgroundSubtractorKNN();
|
||||
knn->setDetectShadows(false);
|
||||
u_foreground.release();
|
||||
u_background.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
knn->apply(frame_buffer[i], u_foreground);
|
||||
}
|
||||
knn->getBackgroundImage(u_background);
|
||||
}
|
||||
#ifdef DEBUG_BGFG
|
||||
imwrite(format("fg_%d_%d_knn_ocl.png", frame_buffer[0].rows, cn), u_foreground.getMat(ACCESS_READ));
|
||||
imwrite(format("bg_%d_%d_knn_ocl.png", frame_buffer[0].rows, cn), u_background.getMat(ACCESS_READ));
|
||||
#endif
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}}// namespace cvtest::ocl
|
||||
|
||||
#endif
|
||||
95
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_bgfg_mog2.cpp
vendored
Normal file
95
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_bgfg_mog2.cpp
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
#include "../perf_bgfg_utils.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
//////////////////////////// Mog2//////////////////////////
|
||||
|
||||
typedef tuple<string, int> VideoMOG2ParamType;
|
||||
typedef TestBaseWithParam<VideoMOG2ParamType> MOG2_Apply;
|
||||
typedef TestBaseWithParam<VideoMOG2ParamType> MOG2_GetBackgroundImage;
|
||||
|
||||
using namespace opencv_test;
|
||||
|
||||
OCL_PERF_TEST_P(MOG2_Apply, Mog2, Combine(Values("cv/video/768x576.avi", "cv/video/1920x1080.avi"), Values(1,3)))
|
||||
{
|
||||
VideoMOG2ParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = get<1>(params);
|
||||
int nFrame = 5;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer);
|
||||
|
||||
UMat u_foreground;
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorMOG2> mog2 = createBackgroundSubtractorMOG2();
|
||||
mog2->setDetectShadows(false);
|
||||
u_foreground.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
mog2->apply(frame_buffer[i], u_foreground);
|
||||
}
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
OCL_PERF_TEST_P(MOG2_GetBackgroundImage, Mog2, Values(
|
||||
std::make_pair<string, int>("cv/video/768x576.avi", 5),
|
||||
std::make_pair<string, int>("cv/video/1920x1080.avi", 5)))
|
||||
{
|
||||
VideoMOG2ParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = 3;
|
||||
const int skipFrames = get<1>(params);
|
||||
int nFrame = 10;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer, skipFrames);
|
||||
|
||||
UMat u_foreground, u_background;
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorMOG2> mog2 = createBackgroundSubtractorMOG2();
|
||||
mog2->setDetectShadows(false);
|
||||
u_foreground.release();
|
||||
u_background.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
mog2->apply(frame_buffer[i], u_foreground);
|
||||
}
|
||||
mog2->getBackgroundImage(u_background);
|
||||
}
|
||||
#ifdef DEBUG_BGFG
|
||||
imwrite(format("fg_%d_%d_mog2_ocl.png", frame_buffer[0].rows, cn), u_foreground.getMat(ACCESS_READ));
|
||||
imwrite(format("bg_%d_%d_mog2_ocl.png", frame_buffer[0].rows, cn), u_background.getMat(ACCESS_READ));
|
||||
#endif
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}}// namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
73
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_dis_optflow.cpp
vendored
Normal file
73
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_dis_optflow.cpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
void MakeArtificialExample(UMat &dst_frame1, UMat &dst_frame2);
|
||||
|
||||
typedef tuple<String, Size> DISParams;
|
||||
typedef TestBaseWithParam<DISParams> DenseOpticalFlow_DIS;
|
||||
|
||||
OCL_PERF_TEST_P(DenseOpticalFlow_DIS, perf,
|
||||
Combine(Values("PRESET_ULTRAFAST", "PRESET_FAST", "PRESET_MEDIUM"), Values(szVGA, sz720p, sz1080p)))
|
||||
{
|
||||
DISParams params = GetParam();
|
||||
|
||||
// use strings to print preset names in the perf test results:
|
||||
String preset_string = get<0>(params);
|
||||
int preset = DISOpticalFlow::PRESET_FAST;
|
||||
if (preset_string == "PRESET_ULTRAFAST")
|
||||
preset = DISOpticalFlow::PRESET_ULTRAFAST;
|
||||
else if (preset_string == "PRESET_FAST")
|
||||
preset = DISOpticalFlow::PRESET_FAST;
|
||||
else if (preset_string == "PRESET_MEDIUM")
|
||||
preset = DISOpticalFlow::PRESET_MEDIUM;
|
||||
Size sz = get<1>(params);
|
||||
|
||||
UMat frame1(sz, CV_8U);
|
||||
UMat frame2(sz, CV_8U);
|
||||
UMat flow;
|
||||
|
||||
MakeArtificialExample(frame1, frame2);
|
||||
|
||||
Ptr<DenseOpticalFlow> algo = DISOpticalFlow::create(preset);
|
||||
|
||||
PERF_SAMPLE_BEGIN()
|
||||
{
|
||||
algo->calc(frame1, frame2, flow);
|
||||
}
|
||||
PERF_SAMPLE_END()
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
void MakeArtificialExample(UMat &dst_frame1, UMat &dst_frame2)
|
||||
{
|
||||
int src_scale = 2;
|
||||
int OF_scale = 6;
|
||||
double sigma = dst_frame1.cols / 300;
|
||||
|
||||
UMat tmp(Size(dst_frame1.cols / (1 << src_scale), dst_frame1.rows / (1 << src_scale)), CV_8U);
|
||||
randu(tmp, 0, 255);
|
||||
resize(tmp, dst_frame1, dst_frame1.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
|
||||
resize(tmp, dst_frame2, dst_frame2.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
|
||||
|
||||
Mat displacement_field(Size(dst_frame1.cols / (1 << OF_scale), dst_frame1.rows / (1 << OF_scale)),
|
||||
CV_32FC2);
|
||||
randn(displacement_field, 0.0, sigma);
|
||||
resize(displacement_field, displacement_field, dst_frame2.size(), 0.0, 0.0, INTER_CUBIC);
|
||||
for (int i = 0; i < displacement_field.rows; i++)
|
||||
for (int j = 0; j < displacement_field.cols; j++)
|
||||
displacement_field.at<Vec2f>(i, j) += Vec2f((float)j, (float)i);
|
||||
|
||||
remap(dst_frame2, dst_frame2, displacement_field, Mat(), INTER_LINEAR, BORDER_REPLICATE);
|
||||
}
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
|
||||
}} // namespace
|
||||
36
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_motempl.cpp
vendored
Normal file
36
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_motempl.cpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#if 0 //def HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////// UpdateMotionHistory ////////////////////////
|
||||
|
||||
typedef TestBaseWithParam<Size> UpdateMotionHistoryFixture;
|
||||
|
||||
OCL_PERF_TEST_P(UpdateMotionHistoryFixture, UpdateMotionHistory, OCL_TEST_SIZES)
|
||||
{
|
||||
const Size size = GetParam();
|
||||
checkDeviceMaxMemoryAllocSize(size, CV_32FC1);
|
||||
|
||||
UMat silhouette(size, CV_8UC1), mhi(size, CV_32FC1);
|
||||
randu(silhouette, -5, 5);
|
||||
declare.in(mhi, WARMUP_RNG);
|
||||
|
||||
OCL_TEST_CYCLE() cv::updateMotionHistory(silhouette, mhi, 1, 0.5);
|
||||
|
||||
SANITY_CHECK(mhi);
|
||||
}
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
112
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_optflow_farneback.cpp
vendored
Normal file
112
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_optflow_farneback.cpp
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Fangfang Bai, fangfang@multicorewareinc.com
|
||||
// Jin Ma, jin@multicorewareinc.com
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors as is and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
///////////// FarnebackOpticalFlow ////////////////////////
|
||||
CV_ENUM(farneFlagType, 0, OPTFLOW_FARNEBACK_GAUSSIAN)
|
||||
|
||||
typedef tuple< tuple<int, double>, farneFlagType, bool > FarnebackOpticalFlowParams;
|
||||
typedef TestBaseWithParam<FarnebackOpticalFlowParams> FarnebackOpticalFlowFixture;
|
||||
|
||||
OCL_PERF_TEST_P(FarnebackOpticalFlowFixture, FarnebackOpticalFlow,
|
||||
::testing::Combine(
|
||||
::testing::Values(
|
||||
make_tuple<int, double>(5, 1.1),
|
||||
make_tuple<int, double>(7, 1.5)
|
||||
),
|
||||
farneFlagType::all(),
|
||||
::testing::Bool()
|
||||
)
|
||||
)
|
||||
{
|
||||
Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame0.empty()) << "can't load rubberwhale1.png";
|
||||
|
||||
Mat frame1 = imread(getDataPath("gpu/opticalflow/rubberwhale2.png"), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame1.empty()) << "can't load rubberwhale2.png";
|
||||
|
||||
const Size srcSize = frame0.size();
|
||||
|
||||
const int numLevels = 5;
|
||||
const int winSize = 13;
|
||||
const int numIters = 10;
|
||||
|
||||
const FarnebackOpticalFlowParams params = GetParam();
|
||||
const tuple<int, double> polyParams = get<0>(params);
|
||||
const int polyN = get<0>(polyParams);
|
||||
const double polySigma = get<1>(polyParams);
|
||||
const double pyrScale = 0.5;
|
||||
int flags = get<1>(params);
|
||||
const bool useInitFlow = get<2>(params);
|
||||
const double eps = 0.1;
|
||||
|
||||
UMat uFrame0; frame0.copyTo(uFrame0);
|
||||
UMat uFrame1; frame1.copyTo(uFrame1);
|
||||
UMat uFlow(srcSize, CV_32FC2);
|
||||
declare.in(uFrame0, uFrame1, WARMUP_READ).out(uFlow, WARMUP_READ);
|
||||
if (useInitFlow)
|
||||
{
|
||||
cv::calcOpticalFlowFarneback(uFrame0, uFrame1, uFlow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags);
|
||||
flags |= OPTFLOW_USE_INITIAL_FLOW;
|
||||
}
|
||||
|
||||
OCL_TEST_CYCLE()
|
||||
cv::calcOpticalFlowFarneback(uFrame0, uFrame1, uFlow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags);
|
||||
|
||||
|
||||
SANITY_CHECK(uFlow, eps, ERROR_RELATIVE);
|
||||
}
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
104
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_optflow_pyrlk.cpp
vendored
Normal file
104
3rdparty/opencv-4.5.4/modules/video/perf/opencl/perf_optflow_pyrlk.cpp
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Fangfang Bai, fangfang@multicorewareinc.com
|
||||
// Jin Ma, jin@multicorewareinc.com
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors as is and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../perf_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_perf.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
typedef tuple< int > PyrLKOpticalFlowParams;
|
||||
typedef TestBaseWithParam<PyrLKOpticalFlowParams> PyrLKOpticalFlowFixture;
|
||||
|
||||
OCL_PERF_TEST_P(PyrLKOpticalFlowFixture, PyrLKOpticalFlow,
|
||||
::testing::Values(1000, 2000, 4000)
|
||||
)
|
||||
{
|
||||
Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame0.empty()) << "can't load rubberwhale1.png";
|
||||
|
||||
Mat frame1 = imread(getDataPath("gpu/opticalflow/rubberwhale2.png"), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame1.empty()) << "can't load rubberwhale2.png";
|
||||
|
||||
UMat uFrame0; frame0.copyTo(uFrame0);
|
||||
UMat uFrame1; frame1.copyTo(uFrame1);
|
||||
|
||||
const Size winSize = Size(21, 21);
|
||||
const int maxLevel = 3;
|
||||
const TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01);
|
||||
const int flags = 0;
|
||||
const float minEigThreshold = 1e-4f;
|
||||
const double eps = 1.0;
|
||||
|
||||
const PyrLKOpticalFlowParams params = GetParam();
|
||||
const int pointsCount = get<0>(params);
|
||||
|
||||
// SKIP unstable tests
|
||||
#ifdef __linux__
|
||||
if (cvtest::skipUnstableTests && ocl::useOpenCL())
|
||||
{
|
||||
if (ocl::Device::getDefault().isIntel())
|
||||
throw ::perf::TestBase::PerfSkipTestException();
|
||||
}
|
||||
#endif
|
||||
|
||||
vector<Point2f> pts;
|
||||
goodFeaturesToTrack(frame0, pts, pointsCount, 0.01, 0.0);
|
||||
Mat ptsMat(1, static_cast<int>(pts.size()), CV_32FC2, (void *)&pts[0]);
|
||||
|
||||
declare.in(uFrame0, uFrame1, WARMUP_READ);
|
||||
UMat uNextPts, uStatus, uErr;
|
||||
OCL_TEST_CYCLE()
|
||||
cv::calcOpticalFlowPyrLK(uFrame0, uFrame1, pts, uNextPts, uStatus, uErr, winSize, maxLevel, criteria, flags, minEigThreshold);
|
||||
|
||||
SANITY_CHECK(uNextPts, eps);
|
||||
}
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
88
3rdparty/opencv-4.5.4/modules/video/perf/perf_bgfg_knn.cpp
vendored
Normal file
88
3rdparty/opencv-4.5.4/modules/video/perf/perf_bgfg_knn.cpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
#include "perf_bgfg_utils.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//////////////////////////// KNN//////////////////////////
|
||||
|
||||
typedef tuple<std::string, int> VideoKNNParamType;
|
||||
typedef TestBaseWithParam<VideoKNNParamType> KNN_Apply;
|
||||
typedef TestBaseWithParam<VideoKNNParamType> KNN_GetBackgroundImage;
|
||||
|
||||
PERF_TEST_P(KNN_Apply, KNN, Combine(Values("cv/video/768x576.avi", "cv/video/1920x1080.avi"), Values(1,3)))
|
||||
{
|
||||
VideoKNNParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = get<1>(params);
|
||||
int nFrame = 5;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer);
|
||||
|
||||
Mat foreground;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorKNN> knn = createBackgroundSubtractorKNN();
|
||||
knn->setDetectShadows(false);
|
||||
foreground.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
knn->apply(frame_buffer[i], foreground);
|
||||
}
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P(KNN_GetBackgroundImage, KNN, Values(
|
||||
std::make_pair<string, int>("cv/video/768x576.avi", 5),
|
||||
std::make_pair<string, int>("cv/video/1920x1080.avi", 5)))
|
||||
{
|
||||
VideoKNNParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = 3;
|
||||
const int skipFrames = get<1>(params);
|
||||
int nFrame = 10;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer, skipFrames);
|
||||
|
||||
Mat foreground, background;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorKNN> knn = createBackgroundSubtractorKNN();
|
||||
knn->setDetectShadows(false);
|
||||
foreground.release();
|
||||
background.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
knn->apply(frame_buffer[i], foreground);
|
||||
}
|
||||
knn->getBackgroundImage(background);
|
||||
}
|
||||
#ifdef DEBUG_BGFG
|
||||
imwrite(format("fg_%d_%d_knn.png", frame_buffer[0].rows, cn), foreground);
|
||||
imwrite(format("bg_%d_%d_knn.png", frame_buffer[0].rows, cn), background);
|
||||
#endif
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}}// namespace
|
||||
88
3rdparty/opencv-4.5.4/modules/video/perf/perf_bgfg_mog2.cpp
vendored
Normal file
88
3rdparty/opencv-4.5.4/modules/video/perf/perf_bgfg_mog2.cpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
#include "perf_bgfg_utils.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//////////////////////////// Mog2//////////////////////////
|
||||
|
||||
typedef tuple<std::string, int> VideoMOG2ParamType;
|
||||
typedef TestBaseWithParam<VideoMOG2ParamType> MOG2_Apply;
|
||||
typedef TestBaseWithParam<VideoMOG2ParamType> MOG2_GetBackgroundImage;
|
||||
|
||||
PERF_TEST_P(MOG2_Apply, Mog2, Combine(Values("cv/video/768x576.avi", "cv/video/1920x1080.avi"), Values(1,3)))
|
||||
{
|
||||
VideoMOG2ParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = get<1>(params);
|
||||
int nFrame = 5;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer);
|
||||
|
||||
Mat foreground;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorMOG2> mog2 = createBackgroundSubtractorMOG2();
|
||||
mog2->setDetectShadows(false);
|
||||
foreground.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
mog2->apply(frame_buffer[i], foreground);
|
||||
}
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P(MOG2_GetBackgroundImage, Mog2, Values(
|
||||
std::make_pair<string, int>("cv/video/768x576.avi", 5),
|
||||
std::make_pair<string, int>("cv/video/1920x1080.avi", 5)))
|
||||
{
|
||||
VideoMOG2ParamType params = GetParam();
|
||||
|
||||
const string inputFile = getDataPath(get<0>(params));
|
||||
|
||||
const int cn = 3;
|
||||
const int skipFrames = get<1>(params);
|
||||
int nFrame = 10;
|
||||
|
||||
vector<Mat> frame_buffer(nFrame);
|
||||
|
||||
cv::VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
prepareData(cap, cn, frame_buffer, skipFrames);
|
||||
|
||||
Mat foreground, background;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
Ptr<cv::BackgroundSubtractorMOG2> mog2 = createBackgroundSubtractorMOG2();
|
||||
mog2->setDetectShadows(false);
|
||||
foreground.release();
|
||||
background.release();
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
mog2->apply(frame_buffer[i], foreground);
|
||||
}
|
||||
mog2->getBackgroundImage(background);
|
||||
}
|
||||
#ifdef DEBUG_BGFG
|
||||
imwrite(format("fg_%d_%d_mog2.png", frame_buffer[0].rows, cn), foreground);
|
||||
imwrite(format("bg_%d_%d_mog2.png", frame_buffer[0].rows, cn), background);
|
||||
#endif
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}}// namespace
|
||||
48
3rdparty/opencv-4.5.4/modules/video/perf/perf_bgfg_utils.hpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/video/perf/perf_bgfg_utils.hpp
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
//#define DEBUG_BGFG
|
||||
|
||||
using namespace testing;
|
||||
using namespace cvtest;
|
||||
using namespace perf;
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace cv;
|
||||
|
||||
static void cvtFrameFmt(std::vector<Mat>& input, std::vector<Mat>& output)
|
||||
{
|
||||
for(int i = 0; i< (int)(input.size()); i++)
|
||||
{
|
||||
cvtColor(input[i], output[i], COLOR_RGB2GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
static void prepareData(VideoCapture& cap, int cn, std::vector<Mat>& frame_buffer, int skipFrames = 0)
|
||||
{
|
||||
std::vector<Mat> frame_buffer_init;
|
||||
int nFrame = (int)frame_buffer.size();
|
||||
for (int i = 0; i < skipFrames; i++)
|
||||
{
|
||||
cv::Mat frame;
|
||||
cap >> frame;
|
||||
}
|
||||
for (int i = 0; i < nFrame; i++)
|
||||
{
|
||||
cv::Mat frame;
|
||||
cap >> frame;
|
||||
ASSERT_FALSE(frame.empty());
|
||||
frame_buffer_init.push_back(frame);
|
||||
}
|
||||
|
||||
if (cn == 1)
|
||||
cvtFrameFmt(frame_buffer_init, frame_buffer);
|
||||
else
|
||||
frame_buffer.swap(frame_buffer_init);
|
||||
}
|
||||
|
||||
}}
|
||||
66
3rdparty/opencv-4.5.4/modules/video/perf/perf_disflow.cpp
vendored
Normal file
66
3rdparty/opencv-4.5.4/modules/video/perf/perf_disflow.cpp
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
void MakeArtificialExample(Mat &dst_frame1, Mat &dst_frame2);
|
||||
|
||||
typedef tuple<String, Size> DISParams;
|
||||
typedef TestBaseWithParam<DISParams> DenseOpticalFlow_DIS;
|
||||
|
||||
PERF_TEST_P(DenseOpticalFlow_DIS, perf,
|
||||
Combine(Values("PRESET_ULTRAFAST", "PRESET_FAST", "PRESET_MEDIUM"), Values(szVGA, sz720p, sz1080p)))
|
||||
{
|
||||
DISParams params = GetParam();
|
||||
|
||||
// use strings to print preset names in the perf test results:
|
||||
String preset_string = get<0>(params);
|
||||
int preset = DISOpticalFlow::PRESET_FAST;
|
||||
if (preset_string == "PRESET_ULTRAFAST")
|
||||
preset = DISOpticalFlow::PRESET_ULTRAFAST;
|
||||
else if (preset_string == "PRESET_FAST")
|
||||
preset = DISOpticalFlow::PRESET_FAST;
|
||||
else if (preset_string == "PRESET_MEDIUM")
|
||||
preset = DISOpticalFlow::PRESET_MEDIUM;
|
||||
Size sz = get<1>(params);
|
||||
|
||||
Mat frame1(sz, CV_8U);
|
||||
Mat frame2(sz, CV_8U);
|
||||
Mat flow;
|
||||
|
||||
MakeArtificialExample(frame1, frame2);
|
||||
|
||||
TEST_CYCLE_N(10)
|
||||
{
|
||||
Ptr<DenseOpticalFlow> algo = DISOpticalFlow::create(preset);
|
||||
algo->calc(frame1, frame2, flow);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
void MakeArtificialExample(Mat &dst_frame1, Mat &dst_frame2)
|
||||
{
|
||||
int src_scale = 2;
|
||||
int OF_scale = 6;
|
||||
double sigma = dst_frame1.cols / 300;
|
||||
|
||||
Mat tmp(Size(dst_frame1.cols / (1 << src_scale), dst_frame1.rows / (1 << src_scale)), CV_8U);
|
||||
randu(tmp, 0, 255);
|
||||
resize(tmp, dst_frame1, dst_frame1.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
|
||||
resize(tmp, dst_frame2, dst_frame2.size(), 0.0, 0.0, INTER_LINEAR_EXACT);
|
||||
|
||||
Mat displacement_field(Size(dst_frame1.cols / (1 << OF_scale), dst_frame1.rows / (1 << OF_scale)),
|
||||
CV_32FC2);
|
||||
randn(displacement_field, 0.0, sigma);
|
||||
resize(displacement_field, displacement_field, dst_frame2.size(), 0.0, 0.0, INTER_CUBIC);
|
||||
for (int i = 0; i < displacement_field.rows; i++)
|
||||
for (int j = 0; j < displacement_field.cols; j++)
|
||||
displacement_field.at<Vec2f>(i, j) += Vec2f((float)j, (float)i);
|
||||
|
||||
remap(dst_frame2, dst_frame2, displacement_field, Mat(), INTER_LINEAR, BORDER_REPLICATE);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
71
3rdparty/opencv-4.5.4/modules/video/perf/perf_ecc.cpp
vendored
Normal file
71
3rdparty/opencv-4.5.4/modules/video/perf/perf_ecc.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
using namespace perf;
|
||||
|
||||
CV_ENUM(MotionType, MOTION_TRANSLATION, MOTION_EUCLIDEAN, MOTION_AFFINE, MOTION_HOMOGRAPHY)
|
||||
|
||||
typedef tuple<MotionType> MotionType_t;
|
||||
typedef perf::TestBaseWithParam<MotionType_t> TransformationType;
|
||||
|
||||
|
||||
PERF_TEST_P(TransformationType, findTransformECC, /*testing::ValuesIn(MotionType::all())*/
|
||||
testing::Values((int) MOTION_TRANSLATION, (int) MOTION_EUCLIDEAN,
|
||||
(int) MOTION_AFFINE, (int) MOTION_HOMOGRAPHY)
|
||||
)
|
||||
{
|
||||
Mat img = imread(getDataPath("cv/shared/fruits_ecc.png"),0);
|
||||
Mat templateImage;
|
||||
|
||||
int transform_type = get<0>(GetParam());
|
||||
|
||||
Mat warpMat;
|
||||
Mat warpGround;
|
||||
|
||||
double angle;
|
||||
switch (transform_type) {
|
||||
case MOTION_TRANSLATION:
|
||||
warpGround = (Mat_<float>(2,3) << 1.f, 0.f, 7.234f,
|
||||
0.f, 1.f, 11.839f);
|
||||
|
||||
warpAffine(img, templateImage, warpGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
break;
|
||||
case MOTION_EUCLIDEAN:
|
||||
angle = CV_PI/30;
|
||||
|
||||
warpGround = (Mat_<float>(2,3) << (float)cos(angle), (float)-sin(angle), 12.123f,
|
||||
(float)sin(angle), (float)cos(angle), 14.789f);
|
||||
warpAffine(img, templateImage, warpGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
break;
|
||||
case MOTION_AFFINE:
|
||||
warpGround = (Mat_<float>(2,3) << 0.98f, 0.03f, 15.523f,
|
||||
-0.02f, 0.95f, 10.456f);
|
||||
warpAffine(img, templateImage, warpGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
break;
|
||||
case MOTION_HOMOGRAPHY:
|
||||
warpGround = (Mat_<float>(3,3) << 0.98f, 0.03f, 15.523f,
|
||||
-0.02f, 0.95f, 10.456f,
|
||||
0.0002f, 0.0003f, 1.f);
|
||||
warpPerspective(img, templateImage, warpGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
break;
|
||||
}
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
if (transform_type<3)
|
||||
warpMat = Mat::eye(2,3, CV_32F);
|
||||
else
|
||||
warpMat = Mat::eye(3,3, CV_32F);
|
||||
|
||||
findTransformECC(templateImage, img, warpMat, transform_type,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 5, -1));
|
||||
}
|
||||
SANITY_CHECK(warpMat, 3e-3);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
22
3rdparty/opencv-4.5.4/modules/video/perf/perf_main.cpp
vendored
Normal file
22
3rdparty/opencv-4.5.4/modules/video/perf/perf_main.cpp
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
static
|
||||
void initTests()
|
||||
{
|
||||
const char* extraTestDataPath =
|
||||
#ifdef WINRT
|
||||
NULL;
|
||||
#else
|
||||
getenv("OPENCV_DNN_TEST_DATA_PATH");
|
||||
#endif
|
||||
if (extraTestDataPath)
|
||||
cvtest::addDataSearchPath(extraTestDataPath);
|
||||
|
||||
cvtest::addDataSearchSubDirectory(""); // override "cv" prefix below to access without "../dnn" hacks
|
||||
}
|
||||
|
||||
CV_PERF_TEST_MAIN(video, initTests())
|
||||
269
3rdparty/opencv-4.5.4/modules/video/perf/perf_optflowpyrlk.cpp
vendored
Normal file
269
3rdparty/opencv-4.5.4/modules/video/perf/perf_optflowpyrlk.cpp
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
using namespace perf;
|
||||
|
||||
typedef tuple<std::string, int, int, tuple<int,int>, int> Path_Idx_Cn_NPoints_WSize_t;
|
||||
typedef TestBaseWithParam<Path_Idx_Cn_NPoints_WSize_t> Path_Idx_Cn_NPoints_WSize;
|
||||
|
||||
void FormTrackingPointsArray(vector<Point2f>& points, int width, int height, int nPointsX, int nPointsY)
|
||||
{
|
||||
int stepX = width / nPointsX;
|
||||
int stepY = height / nPointsY;
|
||||
if (stepX < 1 || stepY < 1) FAIL() << "Specified points number is too big";
|
||||
|
||||
points.clear();
|
||||
points.reserve(nPointsX * nPointsY);
|
||||
|
||||
for( int x = stepX / 2; x < width; x += stepX )
|
||||
{
|
||||
for( int y = stepY / 2; y < height; y += stepY )
|
||||
{
|
||||
Point2f pt(static_cast<float>(x), static_cast<float>(y));
|
||||
points.push_back(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PERF_TEST_P(Path_Idx_Cn_NPoints_WSize, OpticalFlowPyrLK_full, testing::Combine(
|
||||
testing::Values<std::string>("cv/optflow/frames/VGA_%02d.png", "cv/optflow/frames/720p_%02d.png"),
|
||||
testing::Range(1, 3),
|
||||
testing::Values(1, 3, 4),
|
||||
testing::Values(make_tuple(9, 9), make_tuple(15, 15)),
|
||||
testing::Values(7, 11)
|
||||
)
|
||||
)
|
||||
{
|
||||
string filename1 = getDataPath(cv::format(get<0>(GetParam()).c_str(), get<1>(GetParam())));
|
||||
string filename2 = getDataPath(cv::format(get<0>(GetParam()).c_str(), get<1>(GetParam()) + 1));
|
||||
Mat img1 = imread(filename1);
|
||||
Mat img2 = imread(filename2);
|
||||
if (img1.empty()) FAIL() << "Unable to load source image " << filename1;
|
||||
if (img2.empty()) FAIL() << "Unable to load source image " << filename2;
|
||||
|
||||
int cn = get<2>(GetParam());
|
||||
int nPointsX = std::min(get<0>(get<3>(GetParam())), img1.cols);
|
||||
int nPointsY = std::min(get<1>(get<3>(GetParam())), img1.rows);
|
||||
int winSize = get<4>(GetParam());
|
||||
|
||||
int maxLevel = 2;
|
||||
TermCriteria criteria(TermCriteria::COUNT|TermCriteria::EPS, 7, 0.001);
|
||||
int flags = 0;
|
||||
double minEigThreshold = 1e-4;
|
||||
|
||||
Mat frame1, frame2;
|
||||
switch(cn)
|
||||
{
|
||||
case 1:
|
||||
cvtColor(img1, frame1, COLOR_BGR2GRAY, cn);
|
||||
cvtColor(img2, frame2, COLOR_BGR2GRAY, cn);
|
||||
break;
|
||||
case 3:
|
||||
frame1 = img1;
|
||||
frame2 = img2;
|
||||
break;
|
||||
case 4:
|
||||
cvtColor(img1, frame1, COLOR_BGR2BGRA, cn);
|
||||
cvtColor(img2, frame2, COLOR_BGR2BGRA, cn);
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Unexpected number of channels: " << cn;
|
||||
}
|
||||
|
||||
vector<Point2f> inPoints;
|
||||
vector<Point2f> outPoints;
|
||||
vector<uchar> status;
|
||||
vector<float> err;
|
||||
|
||||
FormTrackingPointsArray(inPoints, frame1.cols, frame1.rows, nPointsX, nPointsY);
|
||||
outPoints.resize(inPoints.size());
|
||||
status.resize(inPoints.size());
|
||||
err.resize(inPoints.size());
|
||||
|
||||
declare.in(frame1, frame2, inPoints).out(outPoints);
|
||||
|
||||
TEST_CYCLE_N(30)
|
||||
{
|
||||
calcOpticalFlowPyrLK(frame1, frame2, inPoints, outPoints, status, err,
|
||||
Size(winSize, winSize), maxLevel, criteria,
|
||||
flags, minEigThreshold);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef tuple<std::string, int, tuple<int, int>, int> Path_Idx_NPoints_WSize_t;
|
||||
typedef TestBaseWithParam<Path_Idx_NPoints_WSize_t> Path_Idx_NPoints_WSize;
|
||||
|
||||
PERF_TEST_P(Path_Idx_NPoints_WSize, DISABLED_OpticalFlowPyrLK_ovx, testing::Combine(
|
||||
testing::Values<std::string>("cv/optflow/frames/VGA_%02d.png", "cv/optflow/frames/720p_%02d.png"),
|
||||
testing::Range(1, 3),
|
||||
testing::Values(make_tuple(9, 9), make_tuple(15, 15)),
|
||||
testing::Values(7, 11)
|
||||
)
|
||||
)
|
||||
{
|
||||
string filename1 = getDataPath(cv::format(get<0>(GetParam()).c_str(), get<1>(GetParam())));
|
||||
string filename2 = getDataPath(cv::format(get<0>(GetParam()).c_str(), get<1>(GetParam()) + 1));
|
||||
Mat img1 = imread(filename1);
|
||||
Mat img2 = imread(filename2);
|
||||
if (img1.empty()) FAIL() << "Unable to load source image " << filename1;
|
||||
if (img2.empty()) FAIL() << "Unable to load source image " << filename2;
|
||||
|
||||
int nPointsX = std::min(get<0>(get<2>(GetParam())), img1.cols);
|
||||
int nPointsY = std::min(get<1>(get<2>(GetParam())), img1.rows);
|
||||
int winSize = get<3>(GetParam());
|
||||
|
||||
int maxLevel = 2;
|
||||
TermCriteria criteria(TermCriteria::COUNT|TermCriteria::EPS, 7, 0.001);
|
||||
int flags = 0;
|
||||
double minEigThreshold = 1e-4;
|
||||
|
||||
Mat frame1, frame2;
|
||||
cvtColor(img1, frame1, COLOR_BGR2GRAY, 1);
|
||||
cvtColor(img2, frame2, COLOR_BGR2GRAY, 1);
|
||||
|
||||
vector<Point2f> inPoints;
|
||||
vector<Point2f> outPoints;
|
||||
vector<uchar> status;
|
||||
|
||||
FormTrackingPointsArray(inPoints, frame1.cols, frame1.rows, nPointsX, nPointsY);
|
||||
outPoints.resize(inPoints.size());
|
||||
status.resize(inPoints.size());
|
||||
|
||||
declare.in(frame1, frame2, inPoints).out(outPoints);
|
||||
|
||||
TEST_CYCLE_N(30)
|
||||
{
|
||||
calcOpticalFlowPyrLK(frame1, frame2, inPoints, outPoints, status, cv::noArray(),
|
||||
Size(winSize, winSize), maxLevel, criteria,
|
||||
flags, minEigThreshold);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef tuple<std::string, int, int, tuple<int,int>, int, bool> Path_Idx_Cn_NPoints_WSize_Deriv_t;
|
||||
typedef TestBaseWithParam<Path_Idx_Cn_NPoints_WSize_Deriv_t> Path_Idx_Cn_NPoints_WSize_Deriv;
|
||||
|
||||
PERF_TEST_P(Path_Idx_Cn_NPoints_WSize_Deriv, OpticalFlowPyrLK_self, testing::Combine(
|
||||
testing::Values<std::string>("cv/optflow/frames/VGA_%02d.png", "cv/optflow/frames/720p_%02d.png"),
|
||||
testing::Range(1, 3),
|
||||
testing::Values(1, 3, 4),
|
||||
testing::Values(make_tuple(9, 9), make_tuple(15, 15)),
|
||||
testing::Values(7, 11),
|
||||
testing::Bool()
|
||||
)
|
||||
)
|
||||
{
|
||||
string filename1 = getDataPath(cv::format(get<0>(GetParam()).c_str(), get<1>(GetParam())));
|
||||
string filename2 = getDataPath(cv::format(get<0>(GetParam()).c_str(), get<1>(GetParam()) + 1));
|
||||
Mat img1 = imread(filename1);
|
||||
Mat img2 = imread(filename2);
|
||||
if (img1.empty()) FAIL() << "Unable to load source image " << filename1;
|
||||
if (img2.empty()) FAIL() << "Unable to load source image " << filename2;
|
||||
|
||||
int cn = get<2>(GetParam());
|
||||
int nPointsX = std::min(get<0>(get<3>(GetParam())), img1.cols);
|
||||
int nPointsY = std::min(get<1>(get<3>(GetParam())), img1.rows);
|
||||
int winSize = get<4>(GetParam());
|
||||
bool withDerivatives = get<5>(GetParam());
|
||||
|
||||
int maxLevel = 2;
|
||||
TermCriteria criteria(TermCriteria::COUNT|TermCriteria::EPS, 7, 0.001);
|
||||
int flags = 0;
|
||||
double minEigThreshold = 1e-4;
|
||||
|
||||
Mat frame1, frame2;
|
||||
switch(cn)
|
||||
{
|
||||
case 1:
|
||||
cvtColor(img1, frame1, COLOR_BGR2GRAY, cn);
|
||||
cvtColor(img2, frame2, COLOR_BGR2GRAY, cn);
|
||||
break;
|
||||
case 3:
|
||||
frame1 = img1;
|
||||
frame2 = img2;
|
||||
break;
|
||||
case 4:
|
||||
cvtColor(img1, frame1, COLOR_BGR2BGRA, cn);
|
||||
cvtColor(img2, frame2, COLOR_BGR2BGRA, cn);
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Unexpected number of channels: " << cn;
|
||||
}
|
||||
|
||||
vector<Point2f> inPoints;
|
||||
vector<Point2f> outPoints;
|
||||
vector<uchar> status;
|
||||
vector<float> err;
|
||||
|
||||
FormTrackingPointsArray(inPoints, frame1.cols, frame1.rows, nPointsX, nPointsY);
|
||||
outPoints.resize(inPoints.size());
|
||||
status.resize(inPoints.size());
|
||||
err.resize(inPoints.size());
|
||||
|
||||
std::vector<Mat> pyramid1, pyramid2;
|
||||
|
||||
maxLevel = buildOpticalFlowPyramid(frame1, pyramid1, Size(winSize, winSize), maxLevel, withDerivatives);
|
||||
maxLevel = buildOpticalFlowPyramid(frame2, pyramid2, Size(winSize, winSize), maxLevel, withDerivatives);
|
||||
|
||||
declare.in(pyramid1, pyramid2, inPoints).out(outPoints);
|
||||
declare.time(400);
|
||||
|
||||
int runs = 3;
|
||||
TEST_CYCLE_MULTIRUN(runs)
|
||||
{
|
||||
calcOpticalFlowPyrLK(pyramid1, pyramid2, inPoints, outPoints, status, err,
|
||||
Size(winSize, winSize), maxLevel, criteria,
|
||||
flags, minEigThreshold);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
CV_ENUM(PyrBorderMode, BORDER_DEFAULT, BORDER_TRANSPARENT)
|
||||
typedef tuple<std::string, int, bool, PyrBorderMode, bool> Path_Win_Deriv_Border_Reuse_t;
|
||||
typedef TestBaseWithParam<Path_Win_Deriv_Border_Reuse_t> Path_Win_Deriv_Border_Reuse;
|
||||
|
||||
PERF_TEST_P(Path_Win_Deriv_Border_Reuse, OpticalFlowPyrLK_pyr, testing::Combine(
|
||||
testing::Values<std::string>("cv/optflow/frames/720p_01.png"),
|
||||
testing::Values(7, 11),
|
||||
testing::Bool(),
|
||||
PyrBorderMode::all(),
|
||||
testing::Bool()
|
||||
)
|
||||
)
|
||||
{
|
||||
string filename = getDataPath(get<0>(GetParam()));
|
||||
Mat img = imread(filename);
|
||||
Size winSize(get<1>(GetParam()), get<1>(GetParam()));
|
||||
bool withDerivatives = get<2>(GetParam());
|
||||
int derivBorder = get<3>(GetParam());
|
||||
int pyrBorder = derivBorder;
|
||||
if(derivBorder != BORDER_TRANSPARENT)
|
||||
{
|
||||
derivBorder = BORDER_CONSTANT;
|
||||
pyrBorder = BORDER_REFLECT_101;
|
||||
}
|
||||
bool tryReuseInputImage = get<4>(GetParam());
|
||||
std::vector<Mat> pyramid;
|
||||
|
||||
img.adjustROI(winSize.height, winSize.height, winSize.width, winSize.width);
|
||||
|
||||
int maxLevel = buildOpticalFlowPyramid(img, pyramid, winSize, 1000, withDerivatives, BORDER_CONSTANT, BORDER_CONSTANT, tryReuseInputImage);
|
||||
|
||||
declare.in(img).out(pyramid);
|
||||
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
buildOpticalFlowPyramid(img, pyramid, winSize, maxLevel, withDerivatives, pyrBorder, derivBorder, tryReuseInputImage);
|
||||
}
|
||||
|
||||
size_t expected_layers = ((size_t)maxLevel + 1) * (withDerivatives ? 2 : 1);
|
||||
ASSERT_EQ(expected_layers, pyramid.size());
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
16
3rdparty/opencv-4.5.4/modules/video/perf/perf_precomp.hpp
vendored
Normal file
16
3rdparty/opencv-4.5.4/modules/video/perf/perf_precomp.hpp
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef __OPENCV_VIDEO_PRECOMP_HPP__
|
||||
#define __OPENCV_VIDEO_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include <opencv2/video.hpp>
|
||||
#include "opencv2/ts/ts_perf.hpp"
|
||||
|
||||
namespace cvtest
|
||||
{
|
||||
using namespace perf;
|
||||
}
|
||||
|
||||
#endif
|
||||
104
3rdparty/opencv-4.5.4/modules/video/perf/perf_trackers.cpp
vendored
Normal file
104
3rdparty/opencv-4.5.4/modules/video/perf/perf_trackers.cpp
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
using namespace perf;
|
||||
|
||||
typedef tuple<string, int, Rect> TrackingParams_t;
|
||||
|
||||
std::vector<TrackingParams_t> getTrackingParams()
|
||||
{
|
||||
std::vector<TrackingParams_t> params {
|
||||
TrackingParams_t("david/data/david.webm", 300, Rect(163,62,47,56)),
|
||||
TrackingParams_t("dudek/data/dudek.webm", 1, Rect(123,87,132,176)),
|
||||
TrackingParams_t("faceocc2/data/faceocc2.webm", 1, Rect(118,57,82,98))
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
class Tracking : public perf::TestBaseWithParam<TrackingParams_t>
|
||||
{
|
||||
public:
|
||||
template<typename ROI_t = Rect2d, typename Tracker>
|
||||
void runTrackingTest(const Ptr<Tracker>& tracker, const TrackingParams_t& params);
|
||||
};
|
||||
|
||||
template<typename ROI_t, typename Tracker>
|
||||
void Tracking::runTrackingTest(const Ptr<Tracker>& tracker, const TrackingParams_t& params)
|
||||
{
|
||||
const int N = 10;
|
||||
string video = get<0>(params);
|
||||
int startFrame = get<1>(params);
|
||||
//int endFrame = startFrame + N;
|
||||
Rect boundingBox = get<2>(params);
|
||||
|
||||
string videoPath = findDataFile(std::string("cv/tracking/") + video);
|
||||
|
||||
VideoCapture c;
|
||||
c.open(videoPath);
|
||||
if (!c.isOpened())
|
||||
throw SkipTestException("Can't open video file");
|
||||
#if 0
|
||||
// c.set(CAP_PROP_POS_FRAMES, startFrame);
|
||||
#else
|
||||
if (startFrame)
|
||||
std::cout << "startFrame = " << startFrame << std::endl;
|
||||
for (int i = 0; i < startFrame; i++)
|
||||
{
|
||||
Mat dummy_frame;
|
||||
c >> dummy_frame;
|
||||
ASSERT_FALSE(dummy_frame.empty()) << i << ": " << videoPath;
|
||||
}
|
||||
#endif
|
||||
|
||||
// decode frames into memory (don't measure decoding performance)
|
||||
std::vector<Mat> frames;
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
Mat frame;
|
||||
c >> frame;
|
||||
ASSERT_FALSE(frame.empty()) << "i=" << i;
|
||||
frames.push_back(frame);
|
||||
}
|
||||
|
||||
std::cout << "frame size = " << frames[0].size() << std::endl;
|
||||
|
||||
PERF_SAMPLE_BEGIN();
|
||||
{
|
||||
tracker->init(frames[0], (ROI_t)boundingBox);
|
||||
for (int i = 1; i < N; ++i)
|
||||
{
|
||||
ROI_t rc;
|
||||
tracker->update(frames[i], rc);
|
||||
ASSERT_FALSE(rc.empty());
|
||||
}
|
||||
}
|
||||
PERF_SAMPLE_END();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
PERF_TEST_P(Tracking, MIL, testing::ValuesIn(getTrackingParams()))
|
||||
{
|
||||
auto tracker = TrackerMIL::create();
|
||||
runTrackingTest<Rect>(tracker, GetParam());
|
||||
}
|
||||
|
||||
PERF_TEST_P(Tracking, GOTURN, testing::ValuesIn(getTrackingParams()))
|
||||
{
|
||||
std::string model = cvtest::findDataFile("dnn/gsoc2016-goturn/goturn.prototxt");
|
||||
std::string weights = cvtest::findDataFile("dnn/gsoc2016-goturn/goturn.caffemodel", false);
|
||||
TrackerGOTURN::Params params;
|
||||
params.modelTxt = model;
|
||||
params.modelBin = weights;
|
||||
auto tracker = TrackerGOTURN::create(params);
|
||||
runTrackingTest<Rect>(tracker, GetParam());
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
40
3rdparty/opencv-4.5.4/modules/video/perf/perf_variational_refinement.cpp
vendored
Normal file
40
3rdparty/opencv-4.5.4/modules/video/perf/perf_variational_refinement.cpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef tuple<Size, int, int> VarRefParams;
|
||||
typedef TestBaseWithParam<VarRefParams> DenseOpticalFlow_VariationalRefinement;
|
||||
|
||||
PERF_TEST_P(DenseOpticalFlow_VariationalRefinement, perf, Combine(Values(szQVGA, szVGA), Values(5, 10), Values(5, 10)))
|
||||
{
|
||||
VarRefParams params = GetParam();
|
||||
Size sz = get<0>(params);
|
||||
int sorIter = get<1>(params);
|
||||
int fixedPointIter = get<2>(params);
|
||||
|
||||
Mat frame1(sz, CV_8U);
|
||||
Mat frame2(sz, CV_8U);
|
||||
Mat flow(sz, CV_32FC2);
|
||||
|
||||
randu(frame1, 0, 255);
|
||||
randu(frame2, 0, 255);
|
||||
flow.setTo(0.0f);
|
||||
|
||||
TEST_CYCLE_N(10)
|
||||
{
|
||||
Ptr<VariationalRefinement> var = VariationalRefinement::create();
|
||||
var->setAlpha(20.0f);
|
||||
var->setGamma(10.0f);
|
||||
var->setDelta(5.0f);
|
||||
var->setSorIterations(sorIter);
|
||||
var->setFixedPointIterations(fixedPointIter);
|
||||
var->calc(frame1, frame2, flow);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
881
3rdparty/opencv-4.5.4/modules/video/src/bgfg_KNN.cpp
vendored
Normal file
881
3rdparty/opencv-4.5.4/modules/video/src/bgfg_KNN.cpp
vendored
Normal file
@@ -0,0 +1,881 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
//#include <math.h>
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_video.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/*!
|
||||
The class implements the following algorithm:
|
||||
"Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction"
|
||||
Z.Zivkovic, F. van der Heijden
|
||||
Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006
|
||||
http://www.zoranz.net/Publications/zivkovicPRL2006.pdf
|
||||
*/
|
||||
|
||||
// default parameters of gaussian background detection algorithm
|
||||
static const int defaultHistory2 = 500; // Learning rate; alpha = 1/defaultHistory2
|
||||
static const int defaultNsamples = 7; // number of samples saved in memory
|
||||
static const float defaultDist2Threshold = 20.0f*20.0f;//threshold on distance from the sample
|
||||
|
||||
// additional parameters
|
||||
static const unsigned char defaultnShadowDetection2 = (unsigned char)127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection
|
||||
static const float defaultfTau = 0.5f; // Tau - shadow threshold, see the paper for explanation
|
||||
|
||||
class BackgroundSubtractorKNNImpl CV_FINAL : public BackgroundSubtractorKNN
|
||||
{
|
||||
public:
|
||||
//! the default constructor
|
||||
BackgroundSubtractorKNNImpl()
|
||||
{
|
||||
frameSize = Size(0,0);
|
||||
frameType = 0;
|
||||
nframes = 0;
|
||||
history = defaultHistory2;
|
||||
|
||||
//set parameters
|
||||
// N - the number of samples stored in memory per model
|
||||
nN = defaultNsamples;
|
||||
|
||||
//kNN - k nearest neighbour - number on NN for detecting background - default K=[0.1*nN]
|
||||
nkNN=MAX(1,cvRound(0.1*nN*3+0.40));
|
||||
|
||||
//Tb - Threshold Tb*kernelwidth
|
||||
fTb = defaultDist2Threshold;
|
||||
|
||||
// Shadow detection
|
||||
bShadowDetection = 1;//turn on
|
||||
nShadowDetection = defaultnShadowDetection2;
|
||||
fTau = defaultfTau;// Tau - shadow threshold
|
||||
name_ = "BackgroundSubtractor.KNN";
|
||||
nLongCounter = 0;
|
||||
nMidCounter = 0;
|
||||
nShortCounter = 0;
|
||||
#ifdef HAVE_OPENCL
|
||||
opencl_ON = true;
|
||||
#endif
|
||||
}
|
||||
//! the full constructor that takes the length of the history,
|
||||
// the number of gaussian mixtures, the background ratio parameter and the noise strength
|
||||
BackgroundSubtractorKNNImpl(int _history, float _dist2Threshold, bool _bShadowDetection=true)
|
||||
{
|
||||
frameSize = Size(0,0);
|
||||
frameType = 0;
|
||||
|
||||
nframes = 0;
|
||||
history = _history > 0 ? _history : defaultHistory2;
|
||||
|
||||
//set parameters
|
||||
// N - the number of samples stored in memory per model
|
||||
nN = defaultNsamples;
|
||||
//kNN - k nearest neighbour - number on NN for detecting background - default K=[0.1*nN]
|
||||
nkNN=MAX(1,cvRound(0.1*nN*3+0.40));
|
||||
|
||||
//Tb - Threshold Tb*kernelwidth
|
||||
fTb = _dist2Threshold>0? _dist2Threshold : defaultDist2Threshold;
|
||||
|
||||
bShadowDetection = _bShadowDetection;
|
||||
nShadowDetection = defaultnShadowDetection2;
|
||||
fTau = defaultfTau;
|
||||
name_ = "BackgroundSubtractor.KNN";
|
||||
nLongCounter = 0;
|
||||
nMidCounter = 0;
|
||||
nShortCounter = 0;
|
||||
#ifdef HAVE_OPENCL
|
||||
opencl_ON = true;
|
||||
#endif
|
||||
}
|
||||
//! the destructor
|
||||
~BackgroundSubtractorKNNImpl() CV_OVERRIDE {}
|
||||
//! the update operator
|
||||
void apply(InputArray image, OutputArray fgmask, double learningRate) CV_OVERRIDE;
|
||||
|
||||
//! computes a background image which are the mean of all background gaussians
|
||||
virtual void getBackgroundImage(OutputArray backgroundImage) const CV_OVERRIDE;
|
||||
|
||||
//! re-initialization method
|
||||
void initialize(Size _frameSize, int _frameType)
|
||||
{
|
||||
frameSize = _frameSize;
|
||||
frameType = _frameType;
|
||||
nframes = 0;
|
||||
|
||||
int nchannels = CV_MAT_CN(frameType);
|
||||
CV_Assert( nchannels <= CV_CN_MAX );
|
||||
|
||||
// Reserve memory for the model
|
||||
int size=frameSize.height*frameSize.width;
|
||||
//Reset counters
|
||||
nShortCounter = 0;
|
||||
nMidCounter = 0;
|
||||
nLongCounter = 0;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (ocl::isOpenCLActivated() && opencl_ON)
|
||||
{
|
||||
create_ocl_apply_kernel();
|
||||
|
||||
kernel_getBg.create("getBackgroundImage2_kernel", ocl::video::bgfg_knn_oclsrc, format( "-D CN=%d -D NSAMPLES=%d", nchannels, nN));
|
||||
|
||||
if (kernel_apply.empty() || kernel_getBg.empty())
|
||||
opencl_ON = false;
|
||||
}
|
||||
else opencl_ON = false;
|
||||
|
||||
if (opencl_ON)
|
||||
{
|
||||
u_flag.create(frameSize.height * nN * 3, frameSize.width, CV_8UC1);
|
||||
u_flag.setTo(Scalar::all(0));
|
||||
|
||||
if (nchannels==3)
|
||||
nchannels=4;
|
||||
u_sample.create(frameSize.height * nN * 3, frameSize.width, CV_32FC(nchannels));
|
||||
u_sample.setTo(Scalar::all(0));
|
||||
|
||||
u_aModelIndexShort.create(frameSize.height, frameSize.width, CV_8UC1);
|
||||
u_aModelIndexShort.setTo(Scalar::all(0));
|
||||
u_aModelIndexMid.create(frameSize.height, frameSize.width, CV_8UC1);
|
||||
u_aModelIndexMid.setTo(Scalar::all(0));
|
||||
u_aModelIndexLong.create(frameSize.height, frameSize.width, CV_8UC1);
|
||||
u_aModelIndexLong.setTo(Scalar::all(0));
|
||||
|
||||
u_nNextShortUpdate.create(frameSize.height, frameSize.width, CV_8UC1);
|
||||
u_nNextShortUpdate.setTo(Scalar::all(0));
|
||||
u_nNextMidUpdate.create(frameSize.height, frameSize.width, CV_8UC1);
|
||||
u_nNextMidUpdate.setTo(Scalar::all(0));
|
||||
u_nNextLongUpdate.create(frameSize.height, frameSize.width, CV_8UC1);
|
||||
u_nNextLongUpdate.setTo(Scalar::all(0));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// for each sample of 3 speed pixel models each pixel bg model we store ...
|
||||
// values + flag (nchannels+1 values)
|
||||
bgmodel.create( 1,(nN * 3) * (nchannels+1)* size,CV_8U);
|
||||
bgmodel = Scalar::all(0);
|
||||
|
||||
//index through the three circular lists
|
||||
aModelIndexShort.create(1,size,CV_8U);
|
||||
aModelIndexMid.create(1,size,CV_8U);
|
||||
aModelIndexLong.create(1,size,CV_8U);
|
||||
//when to update next
|
||||
nNextShortUpdate.create(1,size,CV_8U);
|
||||
nNextMidUpdate.create(1,size,CV_8U);
|
||||
nNextLongUpdate.create(1,size,CV_8U);
|
||||
|
||||
aModelIndexShort = Scalar::all(0);//random? //((m_nN)*rand())/(RAND_MAX+1);//0...m_nN-1
|
||||
aModelIndexMid = Scalar::all(0);
|
||||
aModelIndexLong = Scalar::all(0);
|
||||
nNextShortUpdate = Scalar::all(0);
|
||||
nNextMidUpdate = Scalar::all(0);
|
||||
nNextLongUpdate = Scalar::all(0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int getHistory() const CV_OVERRIDE { return history; }
|
||||
virtual void setHistory(int _nframes) CV_OVERRIDE { history = _nframes; }
|
||||
|
||||
virtual int getNSamples() const CV_OVERRIDE { return nN; }
|
||||
virtual void setNSamples(int _nN) CV_OVERRIDE { nN = _nN; }//needs reinitialization!
|
||||
|
||||
virtual int getkNNSamples() const CV_OVERRIDE { return nkNN; }
|
||||
virtual void setkNNSamples(int _nkNN) CV_OVERRIDE { nkNN = _nkNN; }
|
||||
|
||||
virtual double getDist2Threshold() const CV_OVERRIDE { return fTb; }
|
||||
virtual void setDist2Threshold(double _dist2Threshold) CV_OVERRIDE { fTb = (float)_dist2Threshold; }
|
||||
|
||||
virtual bool getDetectShadows() const CV_OVERRIDE { return bShadowDetection; }
|
||||
virtual void setDetectShadows(bool detectshadows) CV_OVERRIDE
|
||||
{
|
||||
if (bShadowDetection == detectshadows)
|
||||
return;
|
||||
bShadowDetection = detectshadows;
|
||||
#ifdef HAVE_OPENCL
|
||||
if (!kernel_apply.empty())
|
||||
{
|
||||
create_ocl_apply_kernel();
|
||||
CV_Assert( !kernel_apply.empty() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual int getShadowValue() const CV_OVERRIDE { return nShadowDetection; }
|
||||
virtual void setShadowValue(int value) CV_OVERRIDE { nShadowDetection = (uchar)value; }
|
||||
|
||||
virtual double getShadowThreshold() const CV_OVERRIDE { return fTau; }
|
||||
virtual void setShadowThreshold(double value) CV_OVERRIDE { fTau = (float)value; }
|
||||
|
||||
virtual void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name_
|
||||
<< "history" << history
|
||||
<< "nsamples" << nN
|
||||
<< "nKNN" << nkNN
|
||||
<< "dist2Threshold" << fTb
|
||||
<< "detectShadows" << (int)bShadowDetection
|
||||
<< "shadowValue" << (int)nShadowDetection
|
||||
<< "shadowThreshold" << fTau;
|
||||
}
|
||||
|
||||
virtual void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
CV_Assert( (String)fn["name"] == name_ );
|
||||
history = (int)fn["history"];
|
||||
nN = (int)fn["nsamples"];
|
||||
nkNN = (int)fn["nKNN"];
|
||||
fTb = (float)fn["dist2Threshold"];
|
||||
bShadowDetection = (int)fn["detectShadows"] != 0;
|
||||
nShadowDetection = saturate_cast<uchar>((int)fn["shadowValue"]);
|
||||
fTau = (float)fn["shadowThreshold"];
|
||||
}
|
||||
|
||||
protected:
|
||||
Size frameSize;
|
||||
int frameType;
|
||||
int nframes;
|
||||
/////////////////////////
|
||||
//very important parameters - things you will change
|
||||
////////////////////////
|
||||
int history;
|
||||
//alpha=1/history - speed of update - if the time interval you want to average over is T
|
||||
//set alpha=1/history. It is also useful at start to make T slowly increase
|
||||
//from 1 until the desired T
|
||||
float fTb;
|
||||
//Tb - threshold on the squared distance from the sample used to decide if it is well described
|
||||
//by the background model or not. A typical value could be 2 sigma
|
||||
//and that is Tb=2*2*10*10 =400; where we take typical pixel level sigma=10
|
||||
|
||||
/////////////////////////
|
||||
//less important parameters - things you might change but be careful
|
||||
////////////////////////
|
||||
int nN;//totlal number of samples
|
||||
int nkNN;//number on NN for detecting background - default K=[0.1*nN]
|
||||
|
||||
//shadow detection parameters
|
||||
bool bShadowDetection;//default 1 - do shadow detection
|
||||
unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result - 127 default value
|
||||
float fTau;
|
||||
// Tau - shadow threshold. The shadow is detected if the pixel is darker
|
||||
//version of the background. Tau is a threshold on how much darker the shadow can be.
|
||||
//Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow
|
||||
//See: Prati,Mikic,Trivedi,Cucchiara,"Detecting Moving Shadows...",IEEE PAMI,2003.
|
||||
|
||||
//model data
|
||||
int nLongCounter;//circular counter
|
||||
int nMidCounter;
|
||||
int nShortCounter;
|
||||
Mat bgmodel; // model data pixel values
|
||||
Mat aModelIndexShort;// index into the models
|
||||
Mat aModelIndexMid;
|
||||
Mat aModelIndexLong;
|
||||
Mat nNextShortUpdate;//random update points per model
|
||||
Mat nNextMidUpdate;
|
||||
Mat nNextLongUpdate;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
mutable bool opencl_ON;
|
||||
|
||||
UMat u_flag;
|
||||
UMat u_sample;
|
||||
UMat u_aModelIndexShort;
|
||||
UMat u_aModelIndexMid;
|
||||
UMat u_aModelIndexLong;
|
||||
UMat u_nNextShortUpdate;
|
||||
UMat u_nNextMidUpdate;
|
||||
UMat u_nNextLongUpdate;
|
||||
|
||||
mutable ocl::Kernel kernel_apply;
|
||||
mutable ocl::Kernel kernel_getBg;
|
||||
#endif
|
||||
|
||||
String name_;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
bool ocl_getBackgroundImage(OutputArray backgroundImage) const;
|
||||
bool ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate=-1);
|
||||
void create_ocl_apply_kernel();
|
||||
#endif
|
||||
};
|
||||
|
||||
CV_INLINE void
|
||||
_cvUpdatePixelBackgroundNP(int x_idx, const uchar* data, int nchannels, int m_nN,
|
||||
uchar* m_aModel,
|
||||
uchar* m_nNextLongUpdate,
|
||||
uchar* m_nNextMidUpdate,
|
||||
uchar* m_nNextShortUpdate,
|
||||
uchar* m_aModelIndexLong,
|
||||
uchar* m_aModelIndexMid,
|
||||
uchar* m_aModelIndexShort,
|
||||
int m_nLongCounter,
|
||||
int m_nMidCounter,
|
||||
int m_nShortCounter,
|
||||
uchar include
|
||||
)
|
||||
{
|
||||
// hold the offset
|
||||
int ndata=1+nchannels;
|
||||
long offsetLong = ndata * (m_aModelIndexLong[x_idx] + m_nN * 2);
|
||||
long offsetMid = ndata * (m_aModelIndexMid[x_idx] + m_nN * 1);
|
||||
long offsetShort = ndata * (m_aModelIndexShort[x_idx]);
|
||||
|
||||
// Long update?
|
||||
if (m_nNextLongUpdate[x_idx] == m_nLongCounter)
|
||||
{
|
||||
// add the oldest pixel from Mid to the list of values (for each color)
|
||||
memcpy(&m_aModel[offsetLong],&m_aModel[offsetMid],ndata*sizeof(unsigned char));
|
||||
// increase the index
|
||||
m_aModelIndexLong[x_idx] = (m_aModelIndexLong[x_idx] >= (m_nN-1)) ? 0 : (m_aModelIndexLong[x_idx] + 1);
|
||||
};
|
||||
|
||||
// Mid update?
|
||||
if (m_nNextMidUpdate[x_idx] == m_nMidCounter)
|
||||
{
|
||||
// add this pixel to the list of values (for each color)
|
||||
memcpy(&m_aModel[offsetMid],&m_aModel[offsetShort],ndata*sizeof(unsigned char));
|
||||
// increase the index
|
||||
m_aModelIndexMid[x_idx] = (m_aModelIndexMid[x_idx] >= (m_nN-1)) ? 0 : (m_aModelIndexMid[x_idx] + 1);
|
||||
};
|
||||
|
||||
// Short update?
|
||||
if (m_nNextShortUpdate[x_idx] == m_nShortCounter)
|
||||
{
|
||||
// add this pixel to the list of values (for each color)
|
||||
memcpy(&m_aModel[offsetShort],data,nchannels*sizeof(unsigned char));
|
||||
//set the include flag
|
||||
m_aModel[offsetShort+nchannels]=include;
|
||||
// increase the index
|
||||
m_aModelIndexShort[x_idx] = (m_aModelIndexShort[x_idx] >= (m_nN-1)) ? 0 : (m_aModelIndexShort[x_idx] + 1);
|
||||
};
|
||||
}
|
||||
|
||||
CV_INLINE int
|
||||
_cvCheckPixelBackgroundNP(const uchar* data, int nchannels,
|
||||
int m_nN,
|
||||
uchar* m_aModel,
|
||||
float m_fTb,
|
||||
int m_nkNN,
|
||||
float tau,
|
||||
bool m_bShadowDetection,
|
||||
uchar& include)
|
||||
{
|
||||
int Pbf = 0; // the total probability that this pixel is background
|
||||
int Pb = 0; //background model probability
|
||||
float dData[CV_CN_MAX];
|
||||
|
||||
//uchar& include=data[nchannels];
|
||||
include=0;//do we include this pixel into background model?
|
||||
|
||||
int ndata=nchannels+1;
|
||||
// now increase the probability for each pixel
|
||||
for (int n = 0; n < m_nN*3; n++)
|
||||
{
|
||||
uchar* mean_m = &m_aModel[n*ndata];
|
||||
|
||||
//calculate difference and distance
|
||||
float dist2;
|
||||
|
||||
if( nchannels == 3 )
|
||||
{
|
||||
dData[0] = (float)mean_m[0] - data[0];
|
||||
dData[1] = (float)mean_m[1] - data[1];
|
||||
dData[2] = (float)mean_m[2] - data[2];
|
||||
dist2 = dData[0]*dData[0] + dData[1]*dData[1] + dData[2]*dData[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
dist2 = 0.f;
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
{
|
||||
dData[c] = (float)mean_m[c] - data[c];
|
||||
dist2 += dData[c]*dData[c];
|
||||
}
|
||||
}
|
||||
|
||||
if (dist2<m_fTb)
|
||||
{
|
||||
Pbf++;//all
|
||||
//background only
|
||||
//if(m_aModel[subPosPixel + nchannels])//indicator
|
||||
if(mean_m[nchannels])//indicator
|
||||
{
|
||||
Pb++;
|
||||
if (Pb >= m_nkNN)//Tb
|
||||
{
|
||||
include=1;//include
|
||||
return 1;//background ->exit
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//include?
|
||||
if (Pbf>=m_nkNN)//m_nTbf)
|
||||
{
|
||||
include=1;
|
||||
}
|
||||
|
||||
int Ps = 0; // the total probability that this pixel is background shadow
|
||||
// Detected as moving object, perform shadow detection
|
||||
if (m_bShadowDetection)
|
||||
{
|
||||
for (int n = 0; n < m_nN*3; n++)
|
||||
{
|
||||
//long subPosPixel = posPixel + n*ndata;
|
||||
uchar* mean_m = &m_aModel[n*ndata];
|
||||
|
||||
if(mean_m[nchannels])//check only background
|
||||
{
|
||||
float numerator = 0.0f;
|
||||
float denominator = 0.0f;
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
{
|
||||
numerator += (float)data[c] * mean_m[c];
|
||||
denominator += (float)mean_m[c] * mean_m[c];
|
||||
}
|
||||
|
||||
// no division by zero allowed
|
||||
if( denominator == 0 )
|
||||
return 0;
|
||||
|
||||
// if tau < a < 1 then also check the color distortion
|
||||
if( numerator <= denominator && numerator >= tau*denominator )
|
||||
{
|
||||
float a = numerator / denominator;
|
||||
float dist2a = 0.0f;
|
||||
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
{
|
||||
float dD= a*mean_m[c] - data[c];
|
||||
dist2a += dD*dD;
|
||||
}
|
||||
|
||||
if (dist2a<m_fTb*a*a)
|
||||
{
|
||||
Ps++;
|
||||
if (Ps >= m_nkNN)//shadow
|
||||
return 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class KNNInvoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
KNNInvoker(const Mat& _src, Mat& _dst,
|
||||
uchar* _bgmodel,
|
||||
uchar* _nNextLongUpdate,
|
||||
uchar* _nNextMidUpdate,
|
||||
uchar* _nNextShortUpdate,
|
||||
uchar* _aModelIndexLong,
|
||||
uchar* _aModelIndexMid,
|
||||
uchar* _aModelIndexShort,
|
||||
int _nLongCounter,
|
||||
int _nMidCounter,
|
||||
int _nShortCounter,
|
||||
int _nN,
|
||||
float _fTb,
|
||||
int _nkNN,
|
||||
float _fTau,
|
||||
bool _bShadowDetection,
|
||||
uchar _nShadowDetection)
|
||||
{
|
||||
src = &_src;
|
||||
dst = &_dst;
|
||||
m_aModel0 = _bgmodel;
|
||||
m_nNextLongUpdate0 = _nNextLongUpdate;
|
||||
m_nNextMidUpdate0 = _nNextMidUpdate;
|
||||
m_nNextShortUpdate0 = _nNextShortUpdate;
|
||||
m_aModelIndexLong0 = _aModelIndexLong;
|
||||
m_aModelIndexMid0 = _aModelIndexMid;
|
||||
m_aModelIndexShort0 = _aModelIndexShort;
|
||||
m_nLongCounter = _nLongCounter;
|
||||
m_nMidCounter = _nMidCounter;
|
||||
m_nShortCounter = _nShortCounter;
|
||||
m_nN = _nN;
|
||||
m_fTb = _fTb;
|
||||
m_fTau = _fTau;
|
||||
m_nkNN = _nkNN;
|
||||
m_bShadowDetection = _bShadowDetection;
|
||||
m_nShadowDetection = _nShadowDetection;
|
||||
}
|
||||
|
||||
void operator()(const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int y0 = range.start, y1 = range.end;
|
||||
int ncols = src->cols, nchannels = src->channels();
|
||||
int ndata=nchannels+1;
|
||||
|
||||
for ( int y = y0; y < y1; y++ )
|
||||
{
|
||||
const uchar* data = src->ptr(y);
|
||||
uchar* m_aModel = m_aModel0 + ncols*m_nN*3*ndata*y;
|
||||
uchar* m_nNextLongUpdate = m_nNextLongUpdate0 + ncols*y;
|
||||
uchar* m_nNextMidUpdate = m_nNextMidUpdate0 + ncols*y;
|
||||
uchar* m_nNextShortUpdate = m_nNextShortUpdate0 + ncols*y;
|
||||
uchar* m_aModelIndexLong = m_aModelIndexLong0 + ncols*y;
|
||||
uchar* m_aModelIndexMid = m_aModelIndexMid0 + ncols*y;
|
||||
uchar* m_aModelIndexShort = m_aModelIndexShort0 + ncols*y;
|
||||
uchar* mask = dst->ptr(y);
|
||||
|
||||
for ( int x = 0; x < ncols; x++ )
|
||||
{
|
||||
|
||||
//update model+ background subtract
|
||||
uchar include=0;
|
||||
int result= _cvCheckPixelBackgroundNP(data, nchannels,
|
||||
m_nN, m_aModel, m_fTb,m_nkNN, m_fTau,m_bShadowDetection,include);
|
||||
|
||||
_cvUpdatePixelBackgroundNP(x,data,nchannels,
|
||||
m_nN, m_aModel,
|
||||
m_nNextLongUpdate,
|
||||
m_nNextMidUpdate,
|
||||
m_nNextShortUpdate,
|
||||
m_aModelIndexLong,
|
||||
m_aModelIndexMid,
|
||||
m_aModelIndexShort,
|
||||
m_nLongCounter,
|
||||
m_nMidCounter,
|
||||
m_nShortCounter,
|
||||
include
|
||||
);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
//foreground
|
||||
mask[x] = 255;
|
||||
break;
|
||||
case 1:
|
||||
//background
|
||||
mask[x] = 0;
|
||||
break;
|
||||
case 2:
|
||||
//shadow
|
||||
mask[x] = m_nShadowDetection;
|
||||
break;
|
||||
}
|
||||
data += nchannels;
|
||||
m_aModel += m_nN*3*ndata;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Mat* src;
|
||||
Mat* dst;
|
||||
uchar* m_aModel0;
|
||||
uchar* m_nNextLongUpdate0;
|
||||
uchar* m_nNextMidUpdate0;
|
||||
uchar* m_nNextShortUpdate0;
|
||||
uchar* m_aModelIndexLong0;
|
||||
uchar* m_aModelIndexMid0;
|
||||
uchar* m_aModelIndexShort0;
|
||||
int m_nLongCounter;
|
||||
int m_nMidCounter;
|
||||
int m_nShortCounter;
|
||||
int m_nN;
|
||||
float m_fTb;
|
||||
float m_fTau;
|
||||
int m_nkNN;
|
||||
bool m_bShadowDetection;
|
||||
uchar m_nShadowDetection;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
bool BackgroundSubtractorKNNImpl::ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate)
|
||||
{
|
||||
bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType;
|
||||
|
||||
if( needToInitialize )
|
||||
initialize(_image.size(), _image.type());
|
||||
|
||||
++nframes;
|
||||
learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history );
|
||||
CV_Assert(learningRate >= 0);
|
||||
|
||||
_fgmask.create(_image.size(), CV_8U);
|
||||
UMat fgmask = _fgmask.getUMat();
|
||||
|
||||
UMat frame = _image.getUMat();
|
||||
|
||||
//recalculate update rates - in case alpha is changed
|
||||
// calculate update parameters (using alpha)
|
||||
int Kshort,Kmid,Klong;
|
||||
//approximate exponential learning curve
|
||||
Kshort=(int)(log(0.7)/log(1-learningRate))+1;//Kshort
|
||||
Kmid=(int)(log(0.4)/log(1-learningRate))-Kshort+1;//Kmid
|
||||
Klong=(int)(log(0.1)/log(1-learningRate))-Kshort-Kmid+1;//Klong
|
||||
|
||||
//refresh rates
|
||||
int nShortUpdate = (Kshort/nN)+1;
|
||||
int nMidUpdate = (Kmid/nN)+1;
|
||||
int nLongUpdate = (Klong/nN)+1;
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadOnly(frame));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadOnly(u_nNextLongUpdate));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadOnly(u_nNextMidUpdate));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadOnly(u_nNextShortUpdate));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_aModelIndexLong));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_aModelIndexMid));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_aModelIndexShort));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_flag));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_sample));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::WriteOnlyNoSize(fgmask));
|
||||
|
||||
idxArg = kernel_apply.set(idxArg, nLongCounter);
|
||||
idxArg = kernel_apply.set(idxArg, nMidCounter);
|
||||
idxArg = kernel_apply.set(idxArg, nShortCounter);
|
||||
idxArg = kernel_apply.set(idxArg, fTb);
|
||||
idxArg = kernel_apply.set(idxArg, nkNN);
|
||||
idxArg = kernel_apply.set(idxArg, fTau);
|
||||
if (bShadowDetection)
|
||||
kernel_apply.set(idxArg, nShadowDetection);
|
||||
|
||||
size_t globalsize[2] = {(size_t)frame.cols, (size_t)frame.rows};
|
||||
if(!kernel_apply.run(2, globalsize, NULL, true))
|
||||
return false;
|
||||
|
||||
nShortCounter++;//0,1,...,nShortUpdate-1
|
||||
nMidCounter++;
|
||||
nLongCounter++;
|
||||
if (nShortCounter >= nShortUpdate)
|
||||
{
|
||||
nShortCounter = 0;
|
||||
randu(u_nNextShortUpdate, Scalar::all(0), Scalar::all(nShortUpdate));
|
||||
}
|
||||
if (nMidCounter >= nMidUpdate)
|
||||
{
|
||||
nMidCounter = 0;
|
||||
randu(u_nNextMidUpdate, Scalar::all(0), Scalar::all(nMidUpdate));
|
||||
}
|
||||
if (nLongCounter >= nLongUpdate)
|
||||
{
|
||||
nLongCounter = 0;
|
||||
randu(u_nNextLongUpdate, Scalar::all(0), Scalar::all(nLongUpdate));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BackgroundSubtractorKNNImpl::ocl_getBackgroundImage(OutputArray _backgroundImage) const
|
||||
{
|
||||
_backgroundImage.create(frameSize, frameType);
|
||||
UMat dst = _backgroundImage.getUMat();
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::PtrReadOnly(u_flag));
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::PtrReadOnly(u_sample));
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
size_t globalsize[2] = {(size_t)dst.cols, (size_t)dst.rows};
|
||||
|
||||
return kernel_getBg.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
void BackgroundSubtractorKNNImpl::create_ocl_apply_kernel()
|
||||
{
|
||||
int nchannels = CV_MAT_CN(frameType);
|
||||
String opts = format("-D CN=%d -D NSAMPLES=%d%s", nchannels, nN, bShadowDetection ? " -D SHADOW_DETECT" : "");
|
||||
kernel_apply.create("knn_kernel", ocl::video::bgfg_knn_oclsrc, opts);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void BackgroundSubtractorKNNImpl::apply(InputArray _image, OutputArray _fgmask, double learningRate)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (opencl_ON)
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
CV_OCL_RUN(_fgmask.isUMat() && OCL_PERFORMANCE_CHECK(!ocl::Device::getDefault().isIntel() || _image.channels() == 1),
|
||||
ocl_apply(_image, _fgmask, learningRate))
|
||||
#else
|
||||
CV_OCL_RUN(_fgmask.isUMat() && OCL_PERFORMANCE_CHECK(!ocl::Device::getDefault().isIntel()),
|
||||
ocl_apply(_image, _fgmask, learningRate))
|
||||
#endif
|
||||
|
||||
opencl_ON = false;
|
||||
nframes = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType;
|
||||
|
||||
if( needToInitialize )
|
||||
initialize(_image.size(), _image.type());
|
||||
|
||||
Mat image = _image.getMat();
|
||||
_fgmask.create( image.size(), CV_8U );
|
||||
Mat fgmask = _fgmask.getMat();
|
||||
|
||||
++nframes;
|
||||
learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history );
|
||||
CV_Assert(learningRate >= 0);
|
||||
|
||||
//recalculate update rates - in case alpha is changed
|
||||
// calculate update parameters (using alpha)
|
||||
int Kshort,Kmid,Klong;
|
||||
//approximate exponential learning curve
|
||||
Kshort=(int)(log(0.7)/log(1-learningRate))+1;//Kshort
|
||||
Kmid=(int)(log(0.4)/log(1-learningRate))-Kshort+1;//Kmid
|
||||
Klong=(int)(log(0.1)/log(1-learningRate))-Kshort-Kmid+1;//Klong
|
||||
|
||||
//refresh rates
|
||||
int nShortUpdate = (Kshort/nN)+1;
|
||||
int nMidUpdate = (Kmid/nN)+1;
|
||||
int nLongUpdate = (Klong/nN)+1;
|
||||
|
||||
parallel_for_(Range(0, image.rows),
|
||||
KNNInvoker(image, fgmask,
|
||||
bgmodel.ptr(),
|
||||
nNextLongUpdate.ptr(),
|
||||
nNextMidUpdate.ptr(),
|
||||
nNextShortUpdate.ptr(),
|
||||
aModelIndexLong.ptr(),
|
||||
aModelIndexMid.ptr(),
|
||||
aModelIndexShort.ptr(),
|
||||
nLongCounter,
|
||||
nMidCounter,
|
||||
nShortCounter,
|
||||
nN,
|
||||
fTb,
|
||||
nkNN,
|
||||
fTau,
|
||||
bShadowDetection,
|
||||
nShadowDetection),
|
||||
image.total()/(double)(1 << 16));
|
||||
|
||||
nShortCounter++;//0,1,...,nShortUpdate-1
|
||||
nMidCounter++;
|
||||
nLongCounter++;
|
||||
if (nShortCounter >= nShortUpdate)
|
||||
{
|
||||
nShortCounter = 0;
|
||||
randu(nNextShortUpdate, Scalar::all(0), Scalar::all(nShortUpdate));
|
||||
}
|
||||
if (nMidCounter >= nMidUpdate)
|
||||
{
|
||||
nMidCounter = 0;
|
||||
randu(nNextMidUpdate, Scalar::all(0), Scalar::all(nMidUpdate));
|
||||
}
|
||||
if (nLongCounter >= nLongUpdate)
|
||||
{
|
||||
nLongCounter = 0;
|
||||
randu(nNextLongUpdate, Scalar::all(0), Scalar::all(nLongUpdate));
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundSubtractorKNNImpl::getBackgroundImage(OutputArray backgroundImage) const
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (opencl_ON)
|
||||
{
|
||||
CV_OCL_RUN(opencl_ON, ocl_getBackgroundImage(backgroundImage))
|
||||
|
||||
opencl_ON = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
int nchannels = CV_MAT_CN(frameType);
|
||||
//CV_Assert( nchannels == 3 );
|
||||
Mat meanBackground(frameSize, CV_8UC3, Scalar::all(0));
|
||||
|
||||
int ndata=nchannels+1;
|
||||
int modelstep=(ndata * nN * 3);
|
||||
|
||||
const uchar* pbgmodel=bgmodel.ptr(0);
|
||||
for(int row=0; row<meanBackground.rows; row++)
|
||||
{
|
||||
for(int col=0; col<meanBackground.cols; col++)
|
||||
{
|
||||
for (int n = 0; n < nN*3; n++)
|
||||
{
|
||||
const uchar* mean_m = &pbgmodel[n*ndata];
|
||||
if (mean_m[nchannels])
|
||||
{
|
||||
meanBackground.at<Vec3b>(row, col) = Vec3b(mean_m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pbgmodel=pbgmodel+modelstep;
|
||||
}
|
||||
}
|
||||
|
||||
switch(CV_MAT_CN(frameType))
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
std::vector<Mat> channels;
|
||||
split(meanBackground, channels);
|
||||
channels[0].copyTo(backgroundImage);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
meanBackground.copyTo(backgroundImage);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CV_Error(Error::StsUnsupportedFormat, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ptr<BackgroundSubtractorKNN> createBackgroundSubtractorKNN(int _history, double _threshold2,
|
||||
bool _bShadowDetection)
|
||||
{
|
||||
return makePtr<BackgroundSubtractorKNNImpl>(_history, (float)_threshold2, _bShadowDetection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
965
3rdparty/opencv-4.5.4/modules/video/src/bgfg_gaussmix2.cpp
vendored
Normal file
965
3rdparty/opencv-4.5.4/modules/video/src/bgfg_gaussmix2.cpp
vendored
Normal file
@@ -0,0 +1,965 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/*//Implementation of the Gaussian mixture model background subtraction from:
|
||||
//
|
||||
//"Improved adaptive Gaussian mixture model for background subtraction"
|
||||
//Z.Zivkovic
|
||||
//International Conference Pattern Recognition, UK, August, 2004
|
||||
//http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf
|
||||
//The code is very fast and performs also shadow detection.
|
||||
//Number of Gausssian components is adapted per pixel.
|
||||
//
|
||||
// and
|
||||
//
|
||||
//"Efficient Adaptive Density Estimapion per Image Pixel for the Task of Background Subtraction"
|
||||
//Z.Zivkovic, F. van der Heijden
|
||||
//Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
|
||||
//
|
||||
//The algorithm similar to the standard Stauffer&Grimson algorithm with
|
||||
//additional selection of the number of the Gaussian components based on:
|
||||
//
|
||||
//"Recursive unsupervised learning of finite mixture models "
|
||||
//Z.Zivkovic, F.van der Heijden
|
||||
//IEEE Trans. on Pattern Analysis and Machine Intelligence, vol.26, no.5, pages 651-656, 2004
|
||||
//http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf
|
||||
//
|
||||
//
|
||||
//Example usage with as cpp class
|
||||
// BackgroundSubtractorMOG2 bg_model;
|
||||
//For each new image the model is updates using:
|
||||
// bg_model(img, fgmask);
|
||||
//
|
||||
//Example usage as part of the CvBGStatModel:
|
||||
// CvBGStatModel* bg_model = cvCreateGaussianBGModel2( first_frame );
|
||||
//
|
||||
// //update for each frame
|
||||
// cvUpdateBGStatModel( tmp_frame, bg_model );//segmentation result is in bg_model->foreground
|
||||
//
|
||||
// //release at the program termination
|
||||
// cvReleaseBGStatModel( &bg_model );
|
||||
//
|
||||
//Author: Z.Zivkovic, www.zoranz.net
|
||||
//Date: 7-April-2011, Version:1.0
|
||||
///////////*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_video.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/*
|
||||
Interface of Gaussian mixture algorithm from:
|
||||
|
||||
"Improved adaptive Gaussian mixture model for background subtraction"
|
||||
Z.Zivkovic
|
||||
International Conference Pattern Recognition, UK, August, 2004
|
||||
http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf
|
||||
|
||||
Advantages:
|
||||
-fast - number of Gausssian components is constantly adapted per pixel.
|
||||
-performs also shadow detection (see bgfg_segm_test.cpp example)
|
||||
|
||||
*/
|
||||
|
||||
// default parameters of gaussian background detection algorithm
|
||||
static const int defaultHistory2 = 500; // Learning rate; alpha = 1/defaultHistory2
|
||||
static const float defaultVarThreshold2 = 4.0f*4.0f;
|
||||
static const int defaultNMixtures2 = 5; // maximal number of Gaussians in mixture
|
||||
static const float defaultBackgroundRatio2 = 0.9f; // threshold sum of weights for background test
|
||||
static const float defaultVarThresholdGen2 = 3.0f*3.0f;
|
||||
static const float defaultVarInit2 = 15.0f; // initial variance for new components
|
||||
static const float defaultVarMax2 = 5*defaultVarInit2;
|
||||
static const float defaultVarMin2 = 4.0f;
|
||||
|
||||
// additional parameters
|
||||
static const float defaultfCT2 = 0.05f; // complexity reduction prior constant 0 - no reduction of number of components
|
||||
static const unsigned char defaultnShadowDetection2 = (unsigned char)127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection
|
||||
static const float defaultfTau = 0.5f; // Tau - shadow threshold, see the paper for explanation
|
||||
|
||||
|
||||
class BackgroundSubtractorMOG2Impl CV_FINAL : public BackgroundSubtractorMOG2
|
||||
{
|
||||
public:
|
||||
//! the default constructor
|
||||
BackgroundSubtractorMOG2Impl()
|
||||
{
|
||||
frameSize = Size(0,0);
|
||||
frameType = 0;
|
||||
|
||||
nframes = 0;
|
||||
history = defaultHistory2;
|
||||
varThreshold = defaultVarThreshold2;
|
||||
bShadowDetection = 1;
|
||||
|
||||
nmixtures = defaultNMixtures2;
|
||||
backgroundRatio = defaultBackgroundRatio2;
|
||||
fVarInit = defaultVarInit2;
|
||||
fVarMax = defaultVarMax2;
|
||||
fVarMin = defaultVarMin2;
|
||||
|
||||
varThresholdGen = defaultVarThresholdGen2;
|
||||
fCT = defaultfCT2;
|
||||
nShadowDetection = defaultnShadowDetection2;
|
||||
fTau = defaultfTau;
|
||||
#ifdef HAVE_OPENCL
|
||||
opencl_ON = true;
|
||||
#endif
|
||||
}
|
||||
//! the full constructor that takes the length of the history,
|
||||
// the number of gaussian mixtures, the background ratio parameter and the noise strength
|
||||
BackgroundSubtractorMOG2Impl(int _history, float _varThreshold, bool _bShadowDetection=true)
|
||||
{
|
||||
frameSize = Size(0,0);
|
||||
frameType = 0;
|
||||
|
||||
nframes = 0;
|
||||
history = _history > 0 ? _history : defaultHistory2;
|
||||
varThreshold = (_varThreshold>0)? _varThreshold : defaultVarThreshold2;
|
||||
bShadowDetection = _bShadowDetection;
|
||||
|
||||
nmixtures = defaultNMixtures2;
|
||||
backgroundRatio = defaultBackgroundRatio2;
|
||||
fVarInit = defaultVarInit2;
|
||||
fVarMax = defaultVarMax2;
|
||||
fVarMin = defaultVarMin2;
|
||||
|
||||
varThresholdGen = defaultVarThresholdGen2;
|
||||
fCT = defaultfCT2;
|
||||
nShadowDetection = defaultnShadowDetection2;
|
||||
fTau = defaultfTau;
|
||||
name_ = "BackgroundSubtractor.MOG2";
|
||||
#ifdef HAVE_OPENCL
|
||||
opencl_ON = true;
|
||||
#endif
|
||||
}
|
||||
//! the destructor
|
||||
~BackgroundSubtractorMOG2Impl() CV_OVERRIDE {}
|
||||
//! the update operator
|
||||
void apply(InputArray image, OutputArray fgmask, double learningRate) CV_OVERRIDE;
|
||||
|
||||
//! computes a background image which are the mean of all background gaussians
|
||||
virtual void getBackgroundImage(OutputArray backgroundImage) const CV_OVERRIDE;
|
||||
|
||||
//! re-initialization method
|
||||
void initialize(Size _frameSize, int _frameType)
|
||||
{
|
||||
frameSize = _frameSize;
|
||||
frameType = _frameType;
|
||||
nframes = 0;
|
||||
|
||||
int nchannels = CV_MAT_CN(frameType);
|
||||
CV_Assert( nchannels <= CV_CN_MAX );
|
||||
CV_Assert( nmixtures <= 255);
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (ocl::isOpenCLActivated() && opencl_ON)
|
||||
{
|
||||
create_ocl_apply_kernel();
|
||||
|
||||
bool isFloat = CV_MAKETYPE(CV_32F,nchannels) == frameType;
|
||||
kernel_getBg.create("getBackgroundImage2_kernel", ocl::video::bgfg_mog2_oclsrc, format( "-D CN=%d -D FL=%d -D NMIXTURES=%d", nchannels, isFloat, nmixtures));
|
||||
|
||||
if (kernel_apply.empty() || kernel_getBg.empty())
|
||||
opencl_ON = false;
|
||||
}
|
||||
else opencl_ON = false;
|
||||
|
||||
if (opencl_ON)
|
||||
{
|
||||
u_weight.create(frameSize.height * nmixtures, frameSize.width, CV_32FC1);
|
||||
u_weight.setTo(Scalar::all(0));
|
||||
|
||||
u_variance.create(frameSize.height * nmixtures, frameSize.width, CV_32FC1);
|
||||
u_variance.setTo(Scalar::all(0));
|
||||
|
||||
if (nchannels==3)
|
||||
nchannels=4;
|
||||
u_mean.create(frameSize.height * nmixtures, frameSize.width, CV_32FC(nchannels)); //4 channels
|
||||
u_mean.setTo(Scalar::all(0));
|
||||
|
||||
//make the array for keeping track of the used modes per pixel - all zeros at start
|
||||
u_bgmodelUsedModes.create(frameSize, CV_8UC1);
|
||||
u_bgmodelUsedModes.setTo(cv::Scalar::all(0));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// for each gaussian mixture of each pixel bg model we store ...
|
||||
// the mixture weight (w),
|
||||
// the mean (nchannels values) and
|
||||
// the covariance
|
||||
bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + nchannels), CV_32F );
|
||||
//make the array for keeping track of the used modes per pixel - all zeros at start
|
||||
bgmodelUsedModes.create(frameSize,CV_8U);
|
||||
bgmodelUsedModes = Scalar::all(0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int getHistory() const CV_OVERRIDE { return history; }
|
||||
virtual void setHistory(int _nframes) CV_OVERRIDE { history = _nframes; }
|
||||
|
||||
virtual int getNMixtures() const CV_OVERRIDE { return nmixtures; }
|
||||
virtual void setNMixtures(int nmix) CV_OVERRIDE { nmixtures = nmix; }
|
||||
|
||||
virtual double getBackgroundRatio() const CV_OVERRIDE { return backgroundRatio; }
|
||||
virtual void setBackgroundRatio(double _backgroundRatio) CV_OVERRIDE { backgroundRatio = (float)_backgroundRatio; }
|
||||
|
||||
virtual double getVarThreshold() const CV_OVERRIDE { return varThreshold; }
|
||||
virtual void setVarThreshold(double _varThreshold) CV_OVERRIDE { varThreshold = _varThreshold; }
|
||||
|
||||
virtual double getVarThresholdGen() const CV_OVERRIDE { return varThresholdGen; }
|
||||
virtual void setVarThresholdGen(double _varThresholdGen) CV_OVERRIDE { varThresholdGen = (float)_varThresholdGen; }
|
||||
|
||||
virtual double getVarInit() const CV_OVERRIDE { return fVarInit; }
|
||||
virtual void setVarInit(double varInit) CV_OVERRIDE { fVarInit = (float)varInit; }
|
||||
|
||||
virtual double getVarMin() const CV_OVERRIDE { return fVarMin; }
|
||||
virtual void setVarMin(double varMin) CV_OVERRIDE { fVarMin = (float)varMin; }
|
||||
|
||||
virtual double getVarMax() const CV_OVERRIDE { return fVarMax; }
|
||||
virtual void setVarMax(double varMax) CV_OVERRIDE { fVarMax = (float)varMax; }
|
||||
|
||||
virtual double getComplexityReductionThreshold() const CV_OVERRIDE { return fCT; }
|
||||
virtual void setComplexityReductionThreshold(double ct) CV_OVERRIDE { fCT = (float)ct; }
|
||||
|
||||
virtual bool getDetectShadows() const CV_OVERRIDE { return bShadowDetection; }
|
||||
virtual void setDetectShadows(bool detectshadows) CV_OVERRIDE
|
||||
{
|
||||
if (bShadowDetection == detectshadows)
|
||||
return;
|
||||
bShadowDetection = detectshadows;
|
||||
#ifdef HAVE_OPENCL
|
||||
if (!kernel_apply.empty())
|
||||
{
|
||||
create_ocl_apply_kernel();
|
||||
CV_Assert( !kernel_apply.empty() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual int getShadowValue() const CV_OVERRIDE { return nShadowDetection; }
|
||||
virtual void setShadowValue(int value) CV_OVERRIDE { nShadowDetection = (uchar)value; }
|
||||
|
||||
virtual double getShadowThreshold() const CV_OVERRIDE { return fTau; }
|
||||
virtual void setShadowThreshold(double value) CV_OVERRIDE { fTau = (float)value; }
|
||||
|
||||
virtual void write(FileStorage& fs) const CV_OVERRIDE
|
||||
{
|
||||
writeFormat(fs);
|
||||
fs << "name" << name_
|
||||
<< "history" << history
|
||||
<< "nmixtures" << nmixtures
|
||||
<< "backgroundRatio" << backgroundRatio
|
||||
<< "varThreshold" << varThreshold
|
||||
<< "varThresholdGen" << varThresholdGen
|
||||
<< "varInit" << fVarInit
|
||||
<< "varMin" << fVarMin
|
||||
<< "varMax" << fVarMax
|
||||
<< "complexityReductionThreshold" << fCT
|
||||
<< "detectShadows" << (int)bShadowDetection
|
||||
<< "shadowValue" << (int)nShadowDetection
|
||||
<< "shadowThreshold" << fTau;
|
||||
}
|
||||
|
||||
virtual void read(const FileNode& fn) CV_OVERRIDE
|
||||
{
|
||||
CV_Assert( (String)fn["name"] == name_ );
|
||||
history = (int)fn["history"];
|
||||
nmixtures = (int)fn["nmixtures"];
|
||||
backgroundRatio = (float)fn["backgroundRatio"];
|
||||
varThreshold = (double)fn["varThreshold"];
|
||||
varThresholdGen = (float)fn["varThresholdGen"];
|
||||
fVarInit = (float)fn["varInit"];
|
||||
fVarMin = (float)fn["varMin"];
|
||||
fVarMax = (float)fn["varMax"];
|
||||
fCT = (float)fn["complexityReductionThreshold"];
|
||||
bShadowDetection = (int)fn["detectShadows"] != 0;
|
||||
nShadowDetection = saturate_cast<uchar>((int)fn["shadowValue"]);
|
||||
fTau = (float)fn["shadowThreshold"];
|
||||
}
|
||||
|
||||
protected:
|
||||
Size frameSize;
|
||||
int frameType;
|
||||
Mat bgmodel;
|
||||
Mat bgmodelUsedModes;//keep track of number of modes per pixel
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
//for OCL
|
||||
|
||||
mutable bool opencl_ON;
|
||||
|
||||
UMat u_weight;
|
||||
UMat u_variance;
|
||||
UMat u_mean;
|
||||
UMat u_bgmodelUsedModes;
|
||||
|
||||
mutable ocl::Kernel kernel_apply;
|
||||
mutable ocl::Kernel kernel_getBg;
|
||||
#endif
|
||||
|
||||
int nframes;
|
||||
int history;
|
||||
int nmixtures;
|
||||
//! here it is the maximum allowed number of mixture components.
|
||||
//! Actual number is determined dynamically per pixel
|
||||
double varThreshold;
|
||||
// threshold on the squared Mahalanobis distance to decide if it is well described
|
||||
// by the background model or not. Related to Cthr from the paper.
|
||||
// This does not influence the update of the background. A typical value could be 4 sigma
|
||||
// and that is varThreshold=4*4=16; Corresponds to Tb in the paper.
|
||||
|
||||
/////////////////////////
|
||||
// less important parameters - things you might change but be careful
|
||||
////////////////////////
|
||||
float backgroundRatio;
|
||||
// corresponds to fTB=1-cf from the paper
|
||||
// TB - threshold when the component becomes significant enough to be included into
|
||||
// the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0.
|
||||
// For alpha=0.001 it means that the mode should exist for approximately 105 frames before
|
||||
// it is considered foreground
|
||||
// float noiseSigma;
|
||||
float varThresholdGen;
|
||||
//correspondts to Tg - threshold on the squared Mahalan. dist. to decide
|
||||
//when a sample is close to the existing components. If it is not close
|
||||
//to any a new component will be generated. I use 3 sigma => Tg=3*3=9.
|
||||
//Smaller Tg leads to more generated components and higher Tg might make
|
||||
//lead to small number of components but they can grow too large
|
||||
float fVarInit;
|
||||
float fVarMin;
|
||||
float fVarMax;
|
||||
//initial variance for the newly generated components.
|
||||
//It will will influence the speed of adaptation. A good guess should be made.
|
||||
//A simple way is to estimate the typical standard deviation from the images.
|
||||
//I used here 10 as a reasonable value
|
||||
// min and max can be used to further control the variance
|
||||
float fCT;//CT - complexity reduction prior
|
||||
//this is related to the number of samples needed to accept that a component
|
||||
//actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get
|
||||
//the standard Stauffer&Grimson algorithm (maybe not exact but very similar)
|
||||
|
||||
//shadow detection parameters
|
||||
bool bShadowDetection;//default 1 - do shadow detection
|
||||
unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result - 127 default value
|
||||
float fTau;
|
||||
// Tau - shadow threshold. The shadow is detected if the pixel is darker
|
||||
//version of the background. Tau is a threshold on how much darker the shadow can be.
|
||||
//Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow
|
||||
//See: Prati,Mikic,Trivedi,Cucchiara,"Detecting Moving Shadows...",IEEE PAMI,2003.
|
||||
|
||||
String name_;
|
||||
|
||||
template <typename T, int CN>
|
||||
void getBackgroundImage_intern(OutputArray backgroundImage) const;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
bool ocl_getBackgroundImage(OutputArray backgroundImage) const;
|
||||
bool ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate=-1);
|
||||
void create_ocl_apply_kernel();
|
||||
#endif
|
||||
};
|
||||
|
||||
struct GaussBGStatModel2Params
|
||||
{
|
||||
//image info
|
||||
int nWidth;
|
||||
int nHeight;
|
||||
int nND;//number of data dimensions (image channels)
|
||||
|
||||
bool bPostFiltering;//default 1 - do postfiltering - will make shadow detection results also give value 255
|
||||
double minArea; // for postfiltering
|
||||
|
||||
bool bInit;//default 1, faster updates at start
|
||||
|
||||
/////////////////////////
|
||||
//very important parameters - things you will change
|
||||
////////////////////////
|
||||
float fAlphaT;
|
||||
//alpha - speed of update - if the time interval you want to average over is T
|
||||
//set alpha=1/T. It is also useful at start to make T slowly increase
|
||||
//from 1 until the desired T
|
||||
float fTb;
|
||||
//Tb - threshold on the squared Mahalan. dist. to decide if it is well described
|
||||
//by the background model or not. Related to Cthr from the paper.
|
||||
//This does not influence the update of the background. A typical value could be 4 sigma
|
||||
//and that is Tb=4*4=16;
|
||||
|
||||
/////////////////////////
|
||||
//less important parameters - things you might change but be careful
|
||||
////////////////////////
|
||||
float fTg;
|
||||
//Tg - threshold on the squared Mahalan. dist. to decide
|
||||
//when a sample is close to the existing components. If it is not close
|
||||
//to any a new component will be generated. I use 3 sigma => Tg=3*3=9.
|
||||
//Smaller Tg leads to more generated components and higher Tg might make
|
||||
//lead to small number of components but they can grow too large
|
||||
float fTB;//1-cf from the paper
|
||||
//TB - threshold when the component becomes significant enough to be included into
|
||||
//the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0.
|
||||
//For alpha=0.001 it means that the mode should exist for approximately 105 frames before
|
||||
//it is considered foreground
|
||||
float fVarInit;
|
||||
float fVarMax;
|
||||
float fVarMin;
|
||||
//initial standard deviation for the newly generated components.
|
||||
//It will will influence the speed of adaptation. A good guess should be made.
|
||||
//A simple way is to estimate the typical standard deviation from the images.
|
||||
//I used here 10 as a reasonable value
|
||||
float fCT;//CT - complexity reduction prior
|
||||
//this is related to the number of samples needed to accept that a component
|
||||
//actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get
|
||||
//the standard Stauffer&Grimson algorithm (maybe not exact but very similar)
|
||||
|
||||
//even less important parameters
|
||||
int nM;//max number of modes - const - 4 is usually enough
|
||||
|
||||
//shadow detection parameters
|
||||
bool bShadowDetection;//default 1 - do shadow detection
|
||||
unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result
|
||||
float fTau;
|
||||
// Tau - shadow threshold. The shadow is detected if the pixel is darker
|
||||
//version of the background. Tau is a threshold on how much darker the shadow can be.
|
||||
//Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow
|
||||
//See: Prati,Mikic,Trivedi,Cucchiara,"Detecting Moving Shadows...",IEEE PAMI,2003.
|
||||
};
|
||||
|
||||
struct GMM
|
||||
{
|
||||
float weight;
|
||||
float variance;
|
||||
};
|
||||
|
||||
// shadow detection performed per pixel
|
||||
// should work for rgb data, could be useful for gray scale and depth data as well
|
||||
// See: Prati,Mikic,Trivedi,Cucchiara,"Detecting Moving Shadows...",IEEE PAMI,2003.
|
||||
CV_INLINE bool
|
||||
detectShadowGMM(const float* data, int nchannels, int nmodes,
|
||||
const GMM* gmm, const float* mean,
|
||||
float Tb, float TB, float tau)
|
||||
{
|
||||
float tWeight = 0;
|
||||
|
||||
// check all the components marked as background:
|
||||
for( int mode = 0; mode < nmodes; mode++, mean += nchannels )
|
||||
{
|
||||
GMM g = gmm[mode];
|
||||
|
||||
float numerator = 0.0f;
|
||||
float denominator = 0.0f;
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
{
|
||||
numerator += data[c] * mean[c];
|
||||
denominator += mean[c] * mean[c];
|
||||
}
|
||||
|
||||
// no division by zero allowed
|
||||
if( denominator == 0 )
|
||||
return false;
|
||||
|
||||
// if tau < a < 1 then also check the color distortion
|
||||
if( numerator <= denominator && numerator >= tau*denominator )
|
||||
{
|
||||
float a = numerator / denominator;
|
||||
float dist2a = 0.0f;
|
||||
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
{
|
||||
float dD= a*mean[c] - data[c];
|
||||
dist2a += dD*dD;
|
||||
}
|
||||
|
||||
if (dist2a < Tb*g.variance*a*a)
|
||||
return true;
|
||||
};
|
||||
|
||||
tWeight += g.weight;
|
||||
if( tWeight > TB )
|
||||
return false;
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
//update GMM - the base update function performed per pixel
|
||||
//
|
||||
//"Efficient Adaptive Density Estimapion per Image Pixel for the Task of Background Subtraction"
|
||||
//Z.Zivkovic, F. van der Heijden
|
||||
//Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
|
||||
//
|
||||
//The algorithm similar to the standard Stauffer&Grimson algorithm with
|
||||
//additional selection of the number of the Gaussian components based on:
|
||||
//
|
||||
//"Recursive unsupervised learning of finite mixture models "
|
||||
//Z.Zivkovic, F.van der Heijden
|
||||
//IEEE Trans. on Pattern Analysis and Machine Intelligence, vol.26, no.5, pages 651-656, 2004
|
||||
//http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf
|
||||
|
||||
class MOG2Invoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
MOG2Invoker(const Mat& _src, Mat& _dst,
|
||||
GMM* _gmm, float* _mean,
|
||||
uchar* _modesUsed,
|
||||
int _nmixtures, float _alphaT,
|
||||
float _Tb, float _TB, float _Tg,
|
||||
float _varInit, float _varMin, float _varMax,
|
||||
float _prune, float _tau, bool _detectShadows,
|
||||
uchar _shadowVal)
|
||||
{
|
||||
src = &_src;
|
||||
dst = &_dst;
|
||||
gmm0 = _gmm;
|
||||
mean0 = _mean;
|
||||
modesUsed0 = _modesUsed;
|
||||
nmixtures = _nmixtures;
|
||||
alphaT = _alphaT;
|
||||
Tb = _Tb;
|
||||
TB = _TB;
|
||||
Tg = _Tg;
|
||||
varInit = _varInit;
|
||||
varMin = MIN(_varMin, _varMax);
|
||||
varMax = MAX(_varMin, _varMax);
|
||||
prune = _prune;
|
||||
tau = _tau;
|
||||
detectShadows = _detectShadows;
|
||||
shadowVal = _shadowVal;
|
||||
}
|
||||
|
||||
void operator()(const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int y0 = range.start, y1 = range.end;
|
||||
int ncols = src->cols, nchannels = src->channels();
|
||||
AutoBuffer<float> buf(src->cols*nchannels);
|
||||
float alpha1 = 1.f - alphaT;
|
||||
float dData[CV_CN_MAX];
|
||||
|
||||
for( int y = y0; y < y1; y++ )
|
||||
{
|
||||
const float* data = buf.data();
|
||||
if( src->depth() != CV_32F )
|
||||
src->row(y).convertTo(Mat(1, ncols, CV_32FC(nchannels), (void*)data), CV_32F);
|
||||
else
|
||||
data = src->ptr<float>(y);
|
||||
|
||||
float* mean = mean0 + ncols*nmixtures*nchannels*y;
|
||||
GMM* gmm = gmm0 + ncols*nmixtures*y;
|
||||
uchar* modesUsed = modesUsed0 + ncols*y;
|
||||
uchar* mask = dst->ptr(y);
|
||||
|
||||
for( int x = 0; x < ncols; x++, data += nchannels, gmm += nmixtures, mean += nmixtures*nchannels )
|
||||
{
|
||||
//calculate distances to the modes (+ sort)
|
||||
//here we need to go in descending order!!!
|
||||
bool background = false;//return value -> true - the pixel classified as background
|
||||
|
||||
//internal:
|
||||
bool fitsPDF = false;//if it remains zero a new GMM mode will be added
|
||||
int nmodes = modesUsed[x];//current number of modes in GMM
|
||||
float totalWeight = 0.f;
|
||||
|
||||
float* mean_m = mean;
|
||||
|
||||
//////
|
||||
//go through all modes
|
||||
for( int mode = 0; mode < nmodes; mode++, mean_m += nchannels )
|
||||
{
|
||||
float weight = alpha1*gmm[mode].weight + prune;//need only weight if fit is found
|
||||
int swap_count = 0;
|
||||
////
|
||||
//fit not found yet
|
||||
if( !fitsPDF )
|
||||
{
|
||||
//check if it belongs to some of the remaining modes
|
||||
float var = gmm[mode].variance;
|
||||
|
||||
//calculate difference and distance
|
||||
float dist2;
|
||||
|
||||
if( nchannels == 3 )
|
||||
{
|
||||
dData[0] = mean_m[0] - data[0];
|
||||
dData[1] = mean_m[1] - data[1];
|
||||
dData[2] = mean_m[2] - data[2];
|
||||
dist2 = dData[0]*dData[0] + dData[1]*dData[1] + dData[2]*dData[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
dist2 = 0.f;
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
{
|
||||
dData[c] = mean_m[c] - data[c];
|
||||
dist2 += dData[c]*dData[c];
|
||||
}
|
||||
}
|
||||
|
||||
//background? - Tb - usually larger than Tg
|
||||
if( totalWeight < TB && dist2 < Tb*var )
|
||||
background = true;
|
||||
|
||||
//check fit
|
||||
if( dist2 < Tg*var )
|
||||
{
|
||||
/////
|
||||
//belongs to the mode
|
||||
fitsPDF = true;
|
||||
|
||||
//update distribution
|
||||
|
||||
//update weight
|
||||
weight += alphaT;
|
||||
float k = alphaT/weight;
|
||||
|
||||
//update mean
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
mean_m[c] -= k*dData[c];
|
||||
|
||||
//update variance
|
||||
float varnew = var + k*(dist2-var);
|
||||
//limit the variance
|
||||
varnew = MAX(varnew, varMin);
|
||||
varnew = MIN(varnew, varMax);
|
||||
gmm[mode].variance = varnew;
|
||||
|
||||
//sort
|
||||
//all other weights are at the same place and
|
||||
//only the matched (iModes) is higher -> just find the new place for it
|
||||
for( int i = mode; i > 0; i-- )
|
||||
{
|
||||
//check one up
|
||||
if( weight < gmm[i-1].weight )
|
||||
break;
|
||||
|
||||
swap_count++;
|
||||
//swap one up
|
||||
std::swap(gmm[i], gmm[i-1]);
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
std::swap(mean[i*nchannels + c], mean[(i-1)*nchannels + c]);
|
||||
}
|
||||
//belongs to the mode - bFitsPDF becomes 1
|
||||
/////
|
||||
}
|
||||
}//!bFitsPDF)
|
||||
|
||||
//check prune
|
||||
if( weight < -prune )
|
||||
{
|
||||
weight = 0.0;
|
||||
nmodes--;
|
||||
}
|
||||
|
||||
gmm[mode-swap_count].weight = weight;//update weight by the calculated value
|
||||
totalWeight += weight;
|
||||
}
|
||||
//go through all modes
|
||||
//////
|
||||
|
||||
// Renormalize weights. In the special case that the pixel does
|
||||
// not agree with any modes, set weights to zero (a new mode will be added below).
|
||||
float invWeight = 0.f;
|
||||
if (std::abs(totalWeight) > FLT_EPSILON) {
|
||||
invWeight = 1.f/totalWeight;
|
||||
}
|
||||
|
||||
for( int mode = 0; mode < nmodes; mode++ )
|
||||
{
|
||||
gmm[mode].weight *= invWeight;
|
||||
}
|
||||
|
||||
//make new mode if needed and exit
|
||||
if( !fitsPDF && alphaT > 0.f )
|
||||
{
|
||||
// replace the weakest or add a new one
|
||||
int mode = nmodes == nmixtures ? nmixtures-1 : nmodes++;
|
||||
|
||||
if (nmodes==1)
|
||||
gmm[mode].weight = 1.f;
|
||||
else
|
||||
{
|
||||
gmm[mode].weight = alphaT;
|
||||
|
||||
// renormalize all other weights
|
||||
for( int i = 0; i < nmodes-1; i++ )
|
||||
gmm[i].weight *= alpha1;
|
||||
}
|
||||
|
||||
// init
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
mean[mode*nchannels + c] = data[c];
|
||||
|
||||
gmm[mode].variance = varInit;
|
||||
|
||||
//sort
|
||||
//find the new place for it
|
||||
for( int i = nmodes - 1; i > 0; i-- )
|
||||
{
|
||||
// check one up
|
||||
if( alphaT < gmm[i-1].weight )
|
||||
break;
|
||||
|
||||
// swap one up
|
||||
std::swap(gmm[i], gmm[i-1]);
|
||||
for( int c = 0; c < nchannels; c++ )
|
||||
std::swap(mean[i*nchannels + c], mean[(i-1)*nchannels + c]);
|
||||
}
|
||||
}
|
||||
|
||||
//set the number of modes
|
||||
modesUsed[x] = uchar(nmodes);
|
||||
mask[x] = background ? 0 :
|
||||
detectShadows && detectShadowGMM(data, nchannels, nmodes, gmm, mean, Tb, TB, tau) ?
|
||||
shadowVal : 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Mat* src;
|
||||
Mat* dst;
|
||||
GMM* gmm0;
|
||||
float* mean0;
|
||||
uchar* modesUsed0;
|
||||
|
||||
int nmixtures;
|
||||
float alphaT, Tb, TB, Tg;
|
||||
float varInit, varMin, varMax, prune, tau;
|
||||
|
||||
bool detectShadows;
|
||||
uchar shadowVal;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate)
|
||||
{
|
||||
bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType;
|
||||
|
||||
if( needToInitialize )
|
||||
initialize(_image.size(), _image.type());
|
||||
|
||||
++nframes;
|
||||
learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history );
|
||||
CV_Assert(learningRate >= 0);
|
||||
|
||||
_fgmask.create(_image.size(), CV_8U);
|
||||
UMat fgmask = _fgmask.getUMat();
|
||||
|
||||
const double alpha1 = 1.0f - learningRate;
|
||||
|
||||
UMat frame = _image.getUMat();
|
||||
|
||||
float varMax = MAX(fVarMin, fVarMax);
|
||||
float varMin = MIN(fVarMin, fVarMax);
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadOnly(frame));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_bgmodelUsedModes));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_weight));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_mean));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::PtrReadWrite(u_variance));
|
||||
idxArg = kernel_apply.set(idxArg, ocl::KernelArg::WriteOnlyNoSize(fgmask));
|
||||
|
||||
idxArg = kernel_apply.set(idxArg, (float)learningRate); //alphaT
|
||||
idxArg = kernel_apply.set(idxArg, (float)alpha1);
|
||||
idxArg = kernel_apply.set(idxArg, (float)(-learningRate*fCT)); //prune
|
||||
|
||||
idxArg = kernel_apply.set(idxArg, (float)varThreshold); //c_Tb
|
||||
idxArg = kernel_apply.set(idxArg, backgroundRatio); //c_TB
|
||||
idxArg = kernel_apply.set(idxArg, varThresholdGen); //c_Tg
|
||||
idxArg = kernel_apply.set(idxArg, varMin);
|
||||
idxArg = kernel_apply.set(idxArg, varMax);
|
||||
idxArg = kernel_apply.set(idxArg, fVarInit);
|
||||
idxArg = kernel_apply.set(idxArg, fTau);
|
||||
if (bShadowDetection)
|
||||
kernel_apply.set(idxArg, nShadowDetection);
|
||||
|
||||
size_t globalsize[] = {(size_t)frame.cols, (size_t)frame.rows, 1};
|
||||
return kernel_apply.run(2, globalsize, NULL, true);
|
||||
}
|
||||
|
||||
bool BackgroundSubtractorMOG2Impl::ocl_getBackgroundImage(OutputArray _backgroundImage) const
|
||||
{
|
||||
_backgroundImage.create(frameSize, frameType);
|
||||
UMat dst = _backgroundImage.getUMat();
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::PtrReadOnly(u_bgmodelUsedModes));
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::PtrReadOnly(u_weight));
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::PtrReadOnly(u_mean));
|
||||
idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnly(dst));
|
||||
kernel_getBg.set(idxArg, backgroundRatio);
|
||||
|
||||
size_t globalsize[2] = {(size_t)u_bgmodelUsedModes.cols, (size_t)u_bgmodelUsedModes.rows};
|
||||
|
||||
return kernel_getBg.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
void BackgroundSubtractorMOG2Impl::create_ocl_apply_kernel()
|
||||
{
|
||||
int nchannels = CV_MAT_CN(frameType);
|
||||
bool isFloat = CV_MAKETYPE(CV_32F,nchannels) == frameType;
|
||||
String opts = format("-D CN=%d -D FL=%d -D NMIXTURES=%d%s", nchannels, isFloat, nmixtures, bShadowDetection ? " -D SHADOW_DETECT" : "");
|
||||
kernel_apply.create("mog2_kernel", ocl::video::bgfg_mog2_oclsrc, opts);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, double learningRate)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (opencl_ON)
|
||||
{
|
||||
CV_OCL_RUN(_fgmask.isUMat(), ocl_apply(_image, _fgmask, learningRate))
|
||||
|
||||
opencl_ON = false;
|
||||
nframes = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType;
|
||||
|
||||
if( needToInitialize )
|
||||
initialize(_image.size(), _image.type());
|
||||
|
||||
Mat image = _image.getMat();
|
||||
_fgmask.create( image.size(), CV_8U );
|
||||
Mat fgmask = _fgmask.getMat();
|
||||
|
||||
++nframes;
|
||||
learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history );
|
||||
CV_Assert(learningRate >= 0);
|
||||
|
||||
parallel_for_(Range(0, image.rows),
|
||||
MOG2Invoker(image, fgmask,
|
||||
bgmodel.ptr<GMM>(),
|
||||
(float*)(bgmodel.ptr() + sizeof(GMM)*nmixtures*image.rows*image.cols),
|
||||
bgmodelUsedModes.ptr(), nmixtures, (float)learningRate,
|
||||
(float)varThreshold,
|
||||
backgroundRatio, varThresholdGen,
|
||||
fVarInit, fVarMin, fVarMax, float(-learningRate*fCT), fTau,
|
||||
bShadowDetection, nShadowDetection),
|
||||
image.total()/(double)(1 << 16));
|
||||
}
|
||||
|
||||
template <typename T, int CN>
|
||||
void BackgroundSubtractorMOG2Impl::getBackgroundImage_intern(OutputArray backgroundImage) const
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat meanBackground(frameSize, frameType, Scalar::all(0));
|
||||
int firstGaussianIdx = 0;
|
||||
const GMM* gmm = bgmodel.ptr<GMM>();
|
||||
const float* mean = reinterpret_cast<const float*>(gmm + frameSize.width*frameSize.height*nmixtures);
|
||||
Vec<float,CN> meanVal(0.f);
|
||||
for(int row=0; row<meanBackground.rows; row++)
|
||||
{
|
||||
for(int col=0; col<meanBackground.cols; col++)
|
||||
{
|
||||
int nmodes = bgmodelUsedModes.at<uchar>(row, col);
|
||||
float totalWeight = 0.f;
|
||||
for(int gaussianIdx = firstGaussianIdx; gaussianIdx < firstGaussianIdx + nmodes; gaussianIdx++)
|
||||
{
|
||||
GMM gaussian = gmm[gaussianIdx];
|
||||
size_t meanPosition = gaussianIdx*CN;
|
||||
for(int chn = 0; chn < CN; chn++)
|
||||
{
|
||||
meanVal(chn) += gaussian.weight * mean[meanPosition + chn];
|
||||
}
|
||||
totalWeight += gaussian.weight;
|
||||
|
||||
if(totalWeight > backgroundRatio)
|
||||
break;
|
||||
}
|
||||
float invWeight = 0.f;
|
||||
if (std::abs(totalWeight) > FLT_EPSILON) {
|
||||
invWeight = 1.f/totalWeight;
|
||||
}
|
||||
|
||||
meanBackground.at<Vec<T,CN> >(row, col) = Vec<T,CN>(meanVal * invWeight);
|
||||
meanVal = 0.f;
|
||||
|
||||
firstGaussianIdx += nmixtures;
|
||||
}
|
||||
}
|
||||
meanBackground.copyTo(backgroundImage);
|
||||
}
|
||||
|
||||
void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImage) const
|
||||
{
|
||||
CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_32FC1 || frameType == CV_32FC3);
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (opencl_ON)
|
||||
{
|
||||
CV_OCL_RUN(opencl_ON, ocl_getBackgroundImage(backgroundImage))
|
||||
|
||||
opencl_ON = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(frameType)
|
||||
{
|
||||
case CV_8UC1:
|
||||
getBackgroundImage_intern<uchar,1>(backgroundImage);
|
||||
break;
|
||||
case CV_8UC3:
|
||||
getBackgroundImage_intern<uchar,3>(backgroundImage);
|
||||
break;
|
||||
case CV_32FC1:
|
||||
getBackgroundImage_intern<float,1>(backgroundImage);
|
||||
break;
|
||||
case CV_32FC3:
|
||||
getBackgroundImage_intern<float,3>(backgroundImage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<BackgroundSubtractorMOG2> createBackgroundSubtractorMOG2(int _history, double _varThreshold,
|
||||
bool _bShadowDetection)
|
||||
{
|
||||
return makePtr<BackgroundSubtractorMOG2Impl>(_history, (float)_varThreshold, _bShadowDetection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
220
3rdparty/opencv-4.5.4/modules/video/src/camshift.cpp
vendored
Normal file
220
3rdparty/opencv-4.5.4/modules/video/src/camshift.cpp
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
|
||||
int cv::meanShift( InputArray _probImage, Rect& window, TermCriteria criteria )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Size size;
|
||||
int cn;
|
||||
Mat mat;
|
||||
UMat umat;
|
||||
bool isUMat = _probImage.isUMat();
|
||||
|
||||
if (isUMat)
|
||||
umat = _probImage.getUMat(), cn = umat.channels(), size = umat.size();
|
||||
else
|
||||
mat = _probImage.getMat(), cn = mat.channels(), size = mat.size();
|
||||
|
||||
Rect cur_rect = window;
|
||||
|
||||
CV_Assert( cn == 1 );
|
||||
|
||||
if( window.height <= 0 || window.width <= 0 )
|
||||
CV_Error( Error::StsBadArg, "Input window has non-positive sizes" );
|
||||
|
||||
window = window & Rect(0, 0, size.width, size.height);
|
||||
|
||||
double eps = (criteria.type & TermCriteria::EPS) ? std::max(criteria.epsilon, 0.) : 1.;
|
||||
eps = cvRound(eps*eps);
|
||||
int i, niters = (criteria.type & TermCriteria::MAX_ITER) ? std::max(criteria.maxCount, 1) : 100;
|
||||
|
||||
for( i = 0; i < niters; i++ )
|
||||
{
|
||||
cur_rect = cur_rect & Rect(0, 0, size.width, size.height);
|
||||
if( cur_rect == Rect() )
|
||||
{
|
||||
cur_rect.x = size.width/2;
|
||||
cur_rect.y = size.height/2;
|
||||
}
|
||||
cur_rect.width = std::max(cur_rect.width, 1);
|
||||
cur_rect.height = std::max(cur_rect.height, 1);
|
||||
|
||||
Moments m = isUMat ? moments(umat(cur_rect)) : moments(mat(cur_rect));
|
||||
|
||||
// Calculating center of mass
|
||||
if( fabs(m.m00) < DBL_EPSILON )
|
||||
break;
|
||||
|
||||
int dx = cvRound( m.m10/m.m00 - window.width*0.5 );
|
||||
int dy = cvRound( m.m01/m.m00 - window.height*0.5 );
|
||||
|
||||
int nx = std::min(std::max(cur_rect.x + dx, 0), size.width - cur_rect.width);
|
||||
int ny = std::min(std::max(cur_rect.y + dy, 0), size.height - cur_rect.height);
|
||||
|
||||
dx = nx - cur_rect.x;
|
||||
dy = ny - cur_rect.y;
|
||||
cur_rect.x = nx;
|
||||
cur_rect.y = ny;
|
||||
|
||||
// Check for coverage centers mass & window
|
||||
if( dx*dx + dy*dy < eps )
|
||||
break;
|
||||
}
|
||||
|
||||
window = cur_rect;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
cv::RotatedRect cv::CamShift( InputArray _probImage, Rect& window,
|
||||
TermCriteria criteria )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
const int TOLERANCE = 10;
|
||||
Size size;
|
||||
Mat mat;
|
||||
UMat umat;
|
||||
bool isUMat = _probImage.isUMat();
|
||||
|
||||
if (isUMat)
|
||||
umat = _probImage.getUMat(), size = umat.size();
|
||||
else
|
||||
mat = _probImage.getMat(), size = mat.size();
|
||||
|
||||
meanShift( _probImage, window, criteria );
|
||||
|
||||
window.x -= TOLERANCE;
|
||||
if( window.x < 0 )
|
||||
window.x = 0;
|
||||
|
||||
window.y -= TOLERANCE;
|
||||
if( window.y < 0 )
|
||||
window.y = 0;
|
||||
|
||||
window.width += 2 * TOLERANCE;
|
||||
if( window.x + window.width > size.width )
|
||||
window.width = size.width - window.x;
|
||||
|
||||
window.height += 2 * TOLERANCE;
|
||||
if( window.y + window.height > size.height )
|
||||
window.height = size.height - window.y;
|
||||
|
||||
// Calculating moments in new center mass
|
||||
Moments m = isUMat ? moments(umat(window)) : moments(mat(window));
|
||||
|
||||
double m00 = m.m00, m10 = m.m10, m01 = m.m01;
|
||||
double mu11 = m.mu11, mu20 = m.mu20, mu02 = m.mu02;
|
||||
|
||||
if( fabs(m00) < DBL_EPSILON )
|
||||
return RotatedRect();
|
||||
|
||||
double inv_m00 = 1. / m00;
|
||||
int xc = cvRound( m10 * inv_m00 + window.x );
|
||||
int yc = cvRound( m01 * inv_m00 + window.y );
|
||||
double a = mu20 * inv_m00, b = mu11 * inv_m00, c = mu02 * inv_m00;
|
||||
|
||||
// Calculating width & height
|
||||
double square = std::sqrt( 4 * b * b + (a - c) * (a - c) );
|
||||
|
||||
// Calculating orientation
|
||||
double theta = atan2( 2 * b, a - c + square );
|
||||
|
||||
// Calculating width & length of figure
|
||||
double cs = cos( theta );
|
||||
double sn = sin( theta );
|
||||
|
||||
double rotate_a = cs * cs * mu20 + 2 * cs * sn * mu11 + sn * sn * mu02;
|
||||
double rotate_c = sn * sn * mu20 - 2 * cs * sn * mu11 + cs * cs * mu02;
|
||||
rotate_a = std::max(0.0, rotate_a); // avoid negative result due calculation numeric errors
|
||||
rotate_c = std::max(0.0, rotate_c); // avoid negative result due calculation numeric errors
|
||||
double length = std::sqrt( rotate_a * inv_m00 ) * 4;
|
||||
double width = std::sqrt( rotate_c * inv_m00 ) * 4;
|
||||
|
||||
// In case, when tetta is 0 or 1.57... the Length & Width may be exchanged
|
||||
if( length < width )
|
||||
{
|
||||
std::swap( length, width );
|
||||
std::swap( cs, sn );
|
||||
theta = CV_PI*0.5 - theta;
|
||||
}
|
||||
|
||||
// Saving results
|
||||
int _xc = cvRound( xc );
|
||||
int _yc = cvRound( yc );
|
||||
|
||||
int t0 = cvRound( fabs( length * cs ));
|
||||
int t1 = cvRound( fabs( width * sn ));
|
||||
|
||||
t0 = MAX( t0, t1 ) + 2;
|
||||
window.width = MIN( t0, (size.width - _xc) * 2 );
|
||||
|
||||
t0 = cvRound( fabs( length * sn ));
|
||||
t1 = cvRound( fabs( width * cs ));
|
||||
|
||||
t0 = MAX( t0, t1 ) + 2;
|
||||
window.height = MIN( t0, (size.height - _yc) * 2 );
|
||||
|
||||
window.x = MAX( 0, _xc - window.width / 2 );
|
||||
window.y = MAX( 0, _yc - window.height / 2 );
|
||||
|
||||
window.width = MIN( size.width - window.x, window.width );
|
||||
window.height = MIN( size.height - window.y, window.height );
|
||||
|
||||
RotatedRect box;
|
||||
box.size.height = (float)length;
|
||||
box.size.width = (float)width;
|
||||
box.angle = (float)((CV_PI*0.5+theta)*180./CV_PI);
|
||||
while(box.angle < 0)
|
||||
box.angle += 360;
|
||||
while(box.angle >= 360)
|
||||
box.angle -= 360;
|
||||
if(box.angle >= 180)
|
||||
box.angle -= 180;
|
||||
box.center = Point2f( window.x + window.width*0.5f, window.y + window.height*0.5f);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
1583
3rdparty/opencv-4.5.4/modules/video/src/dis_flow.cpp
vendored
Normal file
1583
3rdparty/opencv-4.5.4/modules/video/src/dis_flow.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
618
3rdparty/opencv-4.5.4/modules/video/src/ecc.cpp
vendored
Normal file
618
3rdparty/opencv-4.5.4/modules/video/src/ecc.cpp
vendored
Normal file
@@ -0,0 +1,618 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Image Alignment (ECC algorithm) *
|
||||
\****************************************************************************************/
|
||||
|
||||
using namespace cv;
|
||||
|
||||
static void image_jacobian_homo_ECC(const Mat& src1, const Mat& src2,
|
||||
const Mat& src3, const Mat& src4,
|
||||
const Mat& src5, Mat& dst)
|
||||
{
|
||||
|
||||
|
||||
CV_Assert(src1.size() == src2.size());
|
||||
CV_Assert(src1.size() == src3.size());
|
||||
CV_Assert(src1.size() == src4.size());
|
||||
|
||||
CV_Assert( src1.rows == dst.rows);
|
||||
CV_Assert(dst.cols == (src1.cols*8));
|
||||
CV_Assert(dst.type() == CV_32FC1);
|
||||
|
||||
CV_Assert(src5.isContinuous());
|
||||
|
||||
|
||||
const float* hptr = src5.ptr<float>(0);
|
||||
|
||||
const float h0_ = hptr[0];
|
||||
const float h1_ = hptr[3];
|
||||
const float h2_ = hptr[6];
|
||||
const float h3_ = hptr[1];
|
||||
const float h4_ = hptr[4];
|
||||
const float h5_ = hptr[7];
|
||||
const float h6_ = hptr[2];
|
||||
const float h7_ = hptr[5];
|
||||
|
||||
const int w = src1.cols;
|
||||
|
||||
|
||||
//create denominator for all points as a block
|
||||
Mat den_ = src3*h2_ + src4*h5_ + 1.0;//check the time of this! otherwise use addWeighted
|
||||
|
||||
//create projected points
|
||||
Mat hatX_ = -src3*h0_ - src4*h3_ - h6_;
|
||||
divide(hatX_, den_, hatX_);
|
||||
Mat hatY_ = -src3*h1_ - src4*h4_ - h7_;
|
||||
divide(hatY_, den_, hatY_);
|
||||
|
||||
|
||||
//instead of dividing each block with den,
|
||||
//just pre-divide the block of gradients (it's more efficient)
|
||||
|
||||
Mat src1Divided_;
|
||||
Mat src2Divided_;
|
||||
|
||||
divide(src1, den_, src1Divided_);
|
||||
divide(src2, den_, src2Divided_);
|
||||
|
||||
|
||||
//compute Jacobian blocks (8 blocks)
|
||||
|
||||
dst.colRange(0, w) = src1Divided_.mul(src3);//1
|
||||
|
||||
dst.colRange(w,2*w) = src2Divided_.mul(src3);//2
|
||||
|
||||
Mat temp_ = (hatX_.mul(src1Divided_)+hatY_.mul(src2Divided_));
|
||||
dst.colRange(2*w,3*w) = temp_.mul(src3);//3
|
||||
|
||||
hatX_.release();
|
||||
hatY_.release();
|
||||
|
||||
dst.colRange(3*w, 4*w) = src1Divided_.mul(src4);//4
|
||||
|
||||
dst.colRange(4*w, 5*w) = src2Divided_.mul(src4);//5
|
||||
|
||||
dst.colRange(5*w, 6*w) = temp_.mul(src4);//6
|
||||
|
||||
src1Divided_.copyTo(dst.colRange(6*w, 7*w));//7
|
||||
|
||||
src2Divided_.copyTo(dst.colRange(7*w, 8*w));//8
|
||||
}
|
||||
|
||||
static void image_jacobian_euclidean_ECC(const Mat& src1, const Mat& src2,
|
||||
const Mat& src3, const Mat& src4,
|
||||
const Mat& src5, Mat& dst)
|
||||
{
|
||||
|
||||
CV_Assert( src1.size()==src2.size());
|
||||
CV_Assert( src1.size()==src3.size());
|
||||
CV_Assert( src1.size()==src4.size());
|
||||
|
||||
CV_Assert( src1.rows == dst.rows);
|
||||
CV_Assert(dst.cols == (src1.cols*3));
|
||||
CV_Assert(dst.type() == CV_32FC1);
|
||||
|
||||
CV_Assert(src5.isContinuous());
|
||||
|
||||
const float* hptr = src5.ptr<float>(0);
|
||||
|
||||
const float h0 = hptr[0];//cos(theta)
|
||||
const float h1 = hptr[3];//sin(theta)
|
||||
|
||||
const int w = src1.cols;
|
||||
|
||||
//create -sin(theta)*X -cos(theta)*Y for all points as a block -> hatX
|
||||
Mat hatX = -(src3*h1) - (src4*h0);
|
||||
|
||||
//create cos(theta)*X -sin(theta)*Y for all points as a block -> hatY
|
||||
Mat hatY = (src3*h0) - (src4*h1);
|
||||
|
||||
|
||||
//compute Jacobian blocks (3 blocks)
|
||||
dst.colRange(0, w) = (src1.mul(hatX))+(src2.mul(hatY));//1
|
||||
|
||||
src1.copyTo(dst.colRange(w, 2*w));//2
|
||||
src2.copyTo(dst.colRange(2*w, 3*w));//3
|
||||
}
|
||||
|
||||
|
||||
static void image_jacobian_affine_ECC(const Mat& src1, const Mat& src2,
|
||||
const Mat& src3, const Mat& src4,
|
||||
Mat& dst)
|
||||
{
|
||||
|
||||
CV_Assert(src1.size() == src2.size());
|
||||
CV_Assert(src1.size() == src3.size());
|
||||
CV_Assert(src1.size() == src4.size());
|
||||
|
||||
CV_Assert(src1.rows == dst.rows);
|
||||
CV_Assert(dst.cols == (6*src1.cols));
|
||||
|
||||
CV_Assert(dst.type() == CV_32FC1);
|
||||
|
||||
|
||||
const int w = src1.cols;
|
||||
|
||||
//compute Jacobian blocks (6 blocks)
|
||||
|
||||
dst.colRange(0,w) = src1.mul(src3);//1
|
||||
dst.colRange(w,2*w) = src2.mul(src3);//2
|
||||
dst.colRange(2*w,3*w) = src1.mul(src4);//3
|
||||
dst.colRange(3*w,4*w) = src2.mul(src4);//4
|
||||
src1.copyTo(dst.colRange(4*w,5*w));//5
|
||||
src2.copyTo(dst.colRange(5*w,6*w));//6
|
||||
}
|
||||
|
||||
|
||||
static void image_jacobian_translation_ECC(const Mat& src1, const Mat& src2, Mat& dst)
|
||||
{
|
||||
|
||||
CV_Assert( src1.size()==src2.size());
|
||||
|
||||
CV_Assert( src1.rows == dst.rows);
|
||||
CV_Assert(dst.cols == (src1.cols*2));
|
||||
CV_Assert(dst.type() == CV_32FC1);
|
||||
|
||||
const int w = src1.cols;
|
||||
|
||||
//compute Jacobian blocks (2 blocks)
|
||||
src1.copyTo(dst.colRange(0, w));
|
||||
src2.copyTo(dst.colRange(w, 2*w));
|
||||
}
|
||||
|
||||
|
||||
static void project_onto_jacobian_ECC(const Mat& src1, const Mat& src2, Mat& dst)
|
||||
{
|
||||
/* this functions is used for two types of projections. If src1.cols ==src.cols
|
||||
it does a blockwise multiplication (like in the outer product of vectors)
|
||||
of the blocks in matrices src1 and src2 and dst
|
||||
has size (number_of_blcks x number_of_blocks), otherwise dst is a vector of size
|
||||
(number_of_blocks x 1) since src2 is "multiplied"(dot) with each block of src1.
|
||||
|
||||
The number_of_blocks is equal to the number of parameters we are lloking for
|
||||
(i.e. rtanslation:2, euclidean: 3, affine: 6, homography: 8)
|
||||
|
||||
*/
|
||||
CV_Assert(src1.rows == src2.rows);
|
||||
CV_Assert((src1.cols % src2.cols) == 0);
|
||||
int w;
|
||||
|
||||
float* dstPtr = dst.ptr<float>(0);
|
||||
|
||||
if (src1.cols !=src2.cols){//dst.cols==1
|
||||
w = src2.cols;
|
||||
for (int i=0; i<dst.rows; i++){
|
||||
dstPtr[i] = (float) src2.dot(src1.colRange(i*w,(i+1)*w));
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
CV_Assert(dst.cols == dst.rows); //dst is square (and symmetric)
|
||||
w = src2.cols/dst.cols;
|
||||
Mat mat;
|
||||
for (int i=0; i<dst.rows; i++){
|
||||
|
||||
mat = Mat(src1.colRange(i*w, (i+1)*w));
|
||||
dstPtr[i*(dst.rows+1)] = (float) pow(norm(mat),2); //diagonal elements
|
||||
|
||||
for (int j=i+1; j<dst.cols; j++){ //j starts from i+1
|
||||
dstPtr[i*dst.cols+j] = (float) mat.dot(src2.colRange(j*w, (j+1)*w));
|
||||
dstPtr[j*dst.cols+i] = dstPtr[i*dst.cols+j]; //due to symmetry
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void update_warping_matrix_ECC (Mat& map_matrix, const Mat& update, const int motionType)
|
||||
{
|
||||
CV_Assert (map_matrix.type() == CV_32FC1);
|
||||
CV_Assert (update.type() == CV_32FC1);
|
||||
|
||||
CV_Assert (motionType == MOTION_TRANSLATION || motionType == MOTION_EUCLIDEAN ||
|
||||
motionType == MOTION_AFFINE || motionType == MOTION_HOMOGRAPHY);
|
||||
|
||||
if (motionType == MOTION_HOMOGRAPHY)
|
||||
CV_Assert (map_matrix.rows == 3 && update.rows == 8);
|
||||
else if (motionType == MOTION_AFFINE)
|
||||
CV_Assert(map_matrix.rows == 2 && update.rows == 6);
|
||||
else if (motionType == MOTION_EUCLIDEAN)
|
||||
CV_Assert (map_matrix.rows == 2 && update.rows == 3);
|
||||
else
|
||||
CV_Assert (map_matrix.rows == 2 && update.rows == 2);
|
||||
|
||||
CV_Assert (update.cols == 1);
|
||||
|
||||
CV_Assert( map_matrix.isContinuous());
|
||||
CV_Assert( update.isContinuous() );
|
||||
|
||||
|
||||
float* mapPtr = map_matrix.ptr<float>(0);
|
||||
const float* updatePtr = update.ptr<float>(0);
|
||||
|
||||
|
||||
if (motionType == MOTION_TRANSLATION){
|
||||
mapPtr[2] += updatePtr[0];
|
||||
mapPtr[5] += updatePtr[1];
|
||||
}
|
||||
if (motionType == MOTION_AFFINE) {
|
||||
mapPtr[0] += updatePtr[0];
|
||||
mapPtr[3] += updatePtr[1];
|
||||
mapPtr[1] += updatePtr[2];
|
||||
mapPtr[4] += updatePtr[3];
|
||||
mapPtr[2] += updatePtr[4];
|
||||
mapPtr[5] += updatePtr[5];
|
||||
}
|
||||
if (motionType == MOTION_HOMOGRAPHY) {
|
||||
mapPtr[0] += updatePtr[0];
|
||||
mapPtr[3] += updatePtr[1];
|
||||
mapPtr[6] += updatePtr[2];
|
||||
mapPtr[1] += updatePtr[3];
|
||||
mapPtr[4] += updatePtr[4];
|
||||
mapPtr[7] += updatePtr[5];
|
||||
mapPtr[2] += updatePtr[6];
|
||||
mapPtr[5] += updatePtr[7];
|
||||
}
|
||||
if (motionType == MOTION_EUCLIDEAN) {
|
||||
double new_theta = updatePtr[0];
|
||||
new_theta += asin(mapPtr[3]);
|
||||
|
||||
mapPtr[2] += updatePtr[1];
|
||||
mapPtr[5] += updatePtr[2];
|
||||
mapPtr[0] = mapPtr[4] = (float) cos(new_theta);
|
||||
mapPtr[3] = (float) sin(new_theta);
|
||||
mapPtr[1] = -mapPtr[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Function that computes enhanced corelation coefficient from Georgios et.al. 2008
|
||||
* See https://github.com/opencv/opencv/issues/12432
|
||||
*/
|
||||
double cv::computeECC(InputArray templateImage, InputArray inputImage, InputArray inputMask)
|
||||
{
|
||||
CV_Assert(!templateImage.empty());
|
||||
CV_Assert(!inputImage.empty());
|
||||
|
||||
if( ! (templateImage.type()==inputImage.type()))
|
||||
CV_Error( Error::StsUnmatchedFormats, "Both input images must have the same data type" );
|
||||
|
||||
Scalar meanTemplate, sdTemplate;
|
||||
|
||||
int active_pixels = inputMask.empty() ? templateImage.size().area() : countNonZero(inputMask);
|
||||
int type = templateImage.type();
|
||||
meanStdDev(templateImage, meanTemplate, sdTemplate, inputMask);
|
||||
Mat templateImage_zeromean = Mat::zeros(templateImage.size(), templateImage.type());
|
||||
Mat templateMat = templateImage.getMat();
|
||||
Mat inputMat = inputImage.getMat();
|
||||
|
||||
/*
|
||||
* For unsigned ints, when the mean is computed and subtracted, any values less than the mean
|
||||
* will be set to 0 (since there are no negatives values). This impacts the norm and dot product, which
|
||||
* ultimately results in an incorrect ECC. To circumvent this problem, if unsigned ints are provided,
|
||||
* we convert them to a signed ints with larger resolution for the subtraction step.
|
||||
*/
|
||||
if(type == CV_8U || type == CV_16U) {
|
||||
int newType = type == CV_8U ? CV_16S : CV_32S;
|
||||
Mat templateMatConverted, inputMatConverted;
|
||||
templateMat.convertTo(templateMatConverted, newType);
|
||||
cv::swap(templateMat, templateMatConverted);
|
||||
inputMat.convertTo(inputMatConverted, newType);
|
||||
cv::swap(inputMat, inputMatConverted);
|
||||
}
|
||||
subtract(templateMat, meanTemplate, templateImage_zeromean, inputMask);
|
||||
double templateImagenorm = std::sqrt(active_pixels*sdTemplate.val[0]*sdTemplate.val[0]);
|
||||
|
||||
Scalar meanInput, sdInput;
|
||||
|
||||
Mat inputImage_zeromean = Mat::zeros(inputImage.size(), inputImage.type());
|
||||
meanStdDev(inputImage, meanInput, sdInput, inputMask);
|
||||
subtract(inputMat, meanInput, inputImage_zeromean, inputMask);
|
||||
double inputImagenorm = std::sqrt(active_pixels*sdInput.val[0]*sdInput.val[0]);
|
||||
|
||||
return templateImage_zeromean.dot(inputImage_zeromean)/(templateImagenorm*inputImagenorm);
|
||||
}
|
||||
|
||||
|
||||
double cv::findTransformECC(InputArray templateImage,
|
||||
InputArray inputImage,
|
||||
InputOutputArray warpMatrix,
|
||||
int motionType,
|
||||
TermCriteria criteria,
|
||||
InputArray inputMask,
|
||||
int gaussFiltSize)
|
||||
{
|
||||
|
||||
|
||||
Mat src = templateImage.getMat();//template image
|
||||
Mat dst = inputImage.getMat(); //input image (to be warped)
|
||||
Mat map = warpMatrix.getMat(); //warp (transformation)
|
||||
|
||||
CV_Assert(!src.empty());
|
||||
CV_Assert(!dst.empty());
|
||||
|
||||
// If the user passed an un-initialized warpMatrix, initialize to identity
|
||||
if(map.empty()) {
|
||||
int rowCount = 2;
|
||||
if(motionType == MOTION_HOMOGRAPHY)
|
||||
rowCount = 3;
|
||||
|
||||
warpMatrix.create(rowCount, 3, CV_32FC1);
|
||||
map = warpMatrix.getMat();
|
||||
map = Mat::eye(rowCount, 3, CV_32F);
|
||||
}
|
||||
|
||||
if( ! (src.type()==dst.type()))
|
||||
CV_Error( Error::StsUnmatchedFormats, "Both input images must have the same data type" );
|
||||
|
||||
//accept only 1-channel images
|
||||
if( src.type() != CV_8UC1 && src.type()!= CV_32FC1)
|
||||
CV_Error( Error::StsUnsupportedFormat, "Images must have 8uC1 or 32fC1 type");
|
||||
|
||||
if( map.type() != CV_32FC1)
|
||||
CV_Error( Error::StsUnsupportedFormat, "warpMatrix must be single-channel floating-point matrix");
|
||||
|
||||
CV_Assert (map.cols == 3);
|
||||
CV_Assert (map.rows == 2 || map.rows ==3);
|
||||
|
||||
CV_Assert (motionType == MOTION_AFFINE || motionType == MOTION_HOMOGRAPHY ||
|
||||
motionType == MOTION_EUCLIDEAN || motionType == MOTION_TRANSLATION);
|
||||
|
||||
if (motionType == MOTION_HOMOGRAPHY){
|
||||
CV_Assert (map.rows ==3);
|
||||
}
|
||||
|
||||
CV_Assert (criteria.type & TermCriteria::COUNT || criteria.type & TermCriteria::EPS);
|
||||
const int numberOfIterations = (criteria.type & TermCriteria::COUNT) ? criteria.maxCount : 200;
|
||||
const double termination_eps = (criteria.type & TermCriteria::EPS) ? criteria.epsilon : -1;
|
||||
|
||||
int paramTemp = 6;//default: affine
|
||||
switch (motionType){
|
||||
case MOTION_TRANSLATION:
|
||||
paramTemp = 2;
|
||||
break;
|
||||
case MOTION_EUCLIDEAN:
|
||||
paramTemp = 3;
|
||||
break;
|
||||
case MOTION_HOMOGRAPHY:
|
||||
paramTemp = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
const int numberOfParameters = paramTemp;
|
||||
|
||||
const int ws = src.cols;
|
||||
const int hs = src.rows;
|
||||
const int wd = dst.cols;
|
||||
const int hd = dst.rows;
|
||||
|
||||
Mat Xcoord = Mat(1, ws, CV_32F);
|
||||
Mat Ycoord = Mat(hs, 1, CV_32F);
|
||||
Mat Xgrid = Mat(hs, ws, CV_32F);
|
||||
Mat Ygrid = Mat(hs, ws, CV_32F);
|
||||
|
||||
float* XcoPtr = Xcoord.ptr<float>(0);
|
||||
float* YcoPtr = Ycoord.ptr<float>(0);
|
||||
int j;
|
||||
for (j=0; j<ws; j++)
|
||||
XcoPtr[j] = (float) j;
|
||||
for (j=0; j<hs; j++)
|
||||
YcoPtr[j] = (float) j;
|
||||
|
||||
repeat(Xcoord, hs, 1, Xgrid);
|
||||
repeat(Ycoord, 1, ws, Ygrid);
|
||||
|
||||
Xcoord.release();
|
||||
Ycoord.release();
|
||||
|
||||
Mat templateZM = Mat(hs, ws, CV_32F);// to store the (smoothed)zero-mean version of template
|
||||
Mat templateFloat = Mat(hs, ws, CV_32F);// to store the (smoothed) template
|
||||
Mat imageFloat = Mat(hd, wd, CV_32F);// to store the (smoothed) input image
|
||||
Mat imageWarped = Mat(hs, ws, CV_32F);// to store the warped zero-mean input image
|
||||
Mat imageMask = Mat(hs, ws, CV_8U); // to store the final mask
|
||||
|
||||
Mat inputMaskMat = inputMask.getMat();
|
||||
//to use it for mask warping
|
||||
Mat preMask;
|
||||
if(inputMask.empty())
|
||||
preMask = Mat::ones(hd, wd, CV_8U);
|
||||
else
|
||||
threshold(inputMask, preMask, 0, 1, THRESH_BINARY);
|
||||
|
||||
//gaussian filtering is optional
|
||||
src.convertTo(templateFloat, templateFloat.type());
|
||||
GaussianBlur(templateFloat, templateFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
|
||||
Mat preMaskFloat;
|
||||
preMask.convertTo(preMaskFloat, CV_32F);
|
||||
GaussianBlur(preMaskFloat, preMaskFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
// Change threshold.
|
||||
preMaskFloat *= (0.5/0.95);
|
||||
// Rounding conversion.
|
||||
preMaskFloat.convertTo(preMask, preMask.type());
|
||||
preMask.convertTo(preMaskFloat, preMaskFloat.type());
|
||||
|
||||
dst.convertTo(imageFloat, imageFloat.type());
|
||||
GaussianBlur(imageFloat, imageFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
|
||||
|
||||
// needed matrices for gradients and warped gradients
|
||||
Mat gradientX = Mat::zeros(hd, wd, CV_32FC1);
|
||||
Mat gradientY = Mat::zeros(hd, wd, CV_32FC1);
|
||||
Mat gradientXWarped = Mat(hs, ws, CV_32FC1);
|
||||
Mat gradientYWarped = Mat(hs, ws, CV_32FC1);
|
||||
|
||||
|
||||
// calculate first order image derivatives
|
||||
Matx13f dx(-0.5f, 0.0f, 0.5f);
|
||||
|
||||
filter2D(imageFloat, gradientX, -1, dx);
|
||||
filter2D(imageFloat, gradientY, -1, dx.t());
|
||||
|
||||
gradientX = gradientX.mul(preMaskFloat);
|
||||
gradientY = gradientY.mul(preMaskFloat);
|
||||
|
||||
// matrices needed for solving linear equation system for maximizing ECC
|
||||
Mat jacobian = Mat(hs, ws*numberOfParameters, CV_32F);
|
||||
Mat hessian = Mat(numberOfParameters, numberOfParameters, CV_32F);
|
||||
Mat hessianInv = Mat(numberOfParameters, numberOfParameters, CV_32F);
|
||||
Mat imageProjection = Mat(numberOfParameters, 1, CV_32F);
|
||||
Mat templateProjection = Mat(numberOfParameters, 1, CV_32F);
|
||||
Mat imageProjectionHessian = Mat(numberOfParameters, 1, CV_32F);
|
||||
Mat errorProjection = Mat(numberOfParameters, 1, CV_32F);
|
||||
|
||||
Mat deltaP = Mat(numberOfParameters, 1, CV_32F);//transformation parameter correction
|
||||
Mat error = Mat(hs, ws, CV_32F);//error as 2D matrix
|
||||
|
||||
const int imageFlags = INTER_LINEAR + WARP_INVERSE_MAP;
|
||||
const int maskFlags = INTER_NEAREST + WARP_INVERSE_MAP;
|
||||
|
||||
|
||||
// iteratively update map_matrix
|
||||
double rho = -1;
|
||||
double last_rho = - termination_eps;
|
||||
for (int i = 1; (i <= numberOfIterations) && (fabs(rho-last_rho)>= termination_eps); i++)
|
||||
{
|
||||
|
||||
// warp-back portion of the inputImage and gradients to the coordinate space of the templateImage
|
||||
if (motionType != MOTION_HOMOGRAPHY)
|
||||
{
|
||||
warpAffine(imageFloat, imageWarped, map, imageWarped.size(), imageFlags);
|
||||
warpAffine(gradientX, gradientXWarped, map, gradientXWarped.size(), imageFlags);
|
||||
warpAffine(gradientY, gradientYWarped, map, gradientYWarped.size(), imageFlags);
|
||||
warpAffine(preMask, imageMask, map, imageMask.size(), maskFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
warpPerspective(imageFloat, imageWarped, map, imageWarped.size(), imageFlags);
|
||||
warpPerspective(gradientX, gradientXWarped, map, gradientXWarped.size(), imageFlags);
|
||||
warpPerspective(gradientY, gradientYWarped, map, gradientYWarped.size(), imageFlags);
|
||||
warpPerspective(preMask, imageMask, map, imageMask.size(), maskFlags);
|
||||
}
|
||||
|
||||
Scalar imgMean, imgStd, tmpMean, tmpStd;
|
||||
meanStdDev(imageWarped, imgMean, imgStd, imageMask);
|
||||
meanStdDev(templateFloat, tmpMean, tmpStd, imageMask);
|
||||
|
||||
subtract(imageWarped, imgMean, imageWarped, imageMask);//zero-mean input
|
||||
templateZM = Mat::zeros(templateZM.rows, templateZM.cols, templateZM.type());
|
||||
subtract(templateFloat, tmpMean, templateZM, imageMask);//zero-mean template
|
||||
|
||||
const double tmpNorm = std::sqrt(countNonZero(imageMask)*(tmpStd.val[0])*(tmpStd.val[0]));
|
||||
const double imgNorm = std::sqrt(countNonZero(imageMask)*(imgStd.val[0])*(imgStd.val[0]));
|
||||
|
||||
// calculate jacobian of image wrt parameters
|
||||
switch (motionType){
|
||||
case MOTION_AFFINE:
|
||||
image_jacobian_affine_ECC(gradientXWarped, gradientYWarped, Xgrid, Ygrid, jacobian);
|
||||
break;
|
||||
case MOTION_HOMOGRAPHY:
|
||||
image_jacobian_homo_ECC(gradientXWarped, gradientYWarped, Xgrid, Ygrid, map, jacobian);
|
||||
break;
|
||||
case MOTION_TRANSLATION:
|
||||
image_jacobian_translation_ECC(gradientXWarped, gradientYWarped, jacobian);
|
||||
break;
|
||||
case MOTION_EUCLIDEAN:
|
||||
image_jacobian_euclidean_ECC(gradientXWarped, gradientYWarped, Xgrid, Ygrid, map, jacobian);
|
||||
break;
|
||||
}
|
||||
|
||||
// calculate Hessian and its inverse
|
||||
project_onto_jacobian_ECC(jacobian, jacobian, hessian);
|
||||
|
||||
hessianInv = hessian.inv();
|
||||
|
||||
const double correlation = templateZM.dot(imageWarped);
|
||||
|
||||
// calculate enhanced correlation coefficient (ECC)->rho
|
||||
last_rho = rho;
|
||||
rho = correlation/(imgNorm*tmpNorm);
|
||||
if (cvIsNaN(rho)) {
|
||||
CV_Error(Error::StsNoConv, "NaN encountered.");
|
||||
}
|
||||
|
||||
// project images into jacobian
|
||||
project_onto_jacobian_ECC( jacobian, imageWarped, imageProjection);
|
||||
project_onto_jacobian_ECC(jacobian, templateZM, templateProjection);
|
||||
|
||||
|
||||
// calculate the parameter lambda to account for illumination variation
|
||||
imageProjectionHessian = hessianInv*imageProjection;
|
||||
const double lambda_n = (imgNorm*imgNorm) - imageProjection.dot(imageProjectionHessian);
|
||||
const double lambda_d = correlation - templateProjection.dot(imageProjectionHessian);
|
||||
if (lambda_d <= 0.0)
|
||||
{
|
||||
rho = -1;
|
||||
CV_Error(Error::StsNoConv, "The algorithm stopped before its convergence. The correlation is going to be minimized. Images may be uncorrelated or non-overlapped");
|
||||
|
||||
}
|
||||
const double lambda = (lambda_n/lambda_d);
|
||||
|
||||
// estimate the update step delta_p
|
||||
error = lambda*templateZM - imageWarped;
|
||||
project_onto_jacobian_ECC(jacobian, error, errorProjection);
|
||||
deltaP = hessianInv * errorProjection;
|
||||
|
||||
// update warping matrix
|
||||
update_warping_matrix_ECC( map, deltaP, motionType);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// return final correlation coefficient
|
||||
return rho;
|
||||
}
|
||||
|
||||
double cv::findTransformECC(InputArray templateImage, InputArray inputImage,
|
||||
InputOutputArray warpMatrix, int motionType,
|
||||
TermCriteria criteria,
|
||||
InputArray inputMask)
|
||||
{
|
||||
// Use default value of 5 for gaussFiltSize to maintain backward compatibility.
|
||||
return findTransformECC(templateImage, inputImage, warpMatrix, motionType, criteria, inputMask, 5);
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
134
3rdparty/opencv-4.5.4/modules/video/src/kalman.cpp
vendored
Normal file
134
3rdparty/opencv-4.5.4/modules/video/src/kalman.cpp
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
KalmanFilter::KalmanFilter() {}
|
||||
KalmanFilter::KalmanFilter(int dynamParams, int measureParams, int controlParams, int type)
|
||||
{
|
||||
init(dynamParams, measureParams, controlParams, type);
|
||||
}
|
||||
|
||||
void KalmanFilter::init(int DP, int MP, int CP, int type)
|
||||
{
|
||||
CV_Assert( DP > 0 && MP > 0 );
|
||||
CV_Assert( type == CV_32F || type == CV_64F );
|
||||
CP = std::max(CP, 0);
|
||||
|
||||
statePre = Mat::zeros(DP, 1, type);
|
||||
statePost = Mat::zeros(DP, 1, type);
|
||||
transitionMatrix = Mat::eye(DP, DP, type);
|
||||
|
||||
processNoiseCov = Mat::eye(DP, DP, type);
|
||||
measurementMatrix = Mat::zeros(MP, DP, type);
|
||||
measurementNoiseCov = Mat::eye(MP, MP, type);
|
||||
|
||||
errorCovPre = Mat::zeros(DP, DP, type);
|
||||
errorCovPost = Mat::zeros(DP, DP, type);
|
||||
gain = Mat::zeros(DP, MP, type);
|
||||
|
||||
if( CP > 0 )
|
||||
controlMatrix = Mat::zeros(DP, CP, type);
|
||||
else
|
||||
controlMatrix.release();
|
||||
|
||||
temp1.create(DP, DP, type);
|
||||
temp2.create(MP, DP, type);
|
||||
temp3.create(MP, MP, type);
|
||||
temp4.create(MP, DP, type);
|
||||
temp5.create(MP, 1, type);
|
||||
}
|
||||
|
||||
const Mat& KalmanFilter::predict(const Mat& control)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
// update the state: x'(k) = A*x(k)
|
||||
statePre = transitionMatrix*statePost;
|
||||
|
||||
if( !control.empty() )
|
||||
// x'(k) = x'(k) + B*u(k)
|
||||
statePre += controlMatrix*control;
|
||||
|
||||
// update error covariance matrices: temp1 = A*P(k)
|
||||
temp1 = transitionMatrix*errorCovPost;
|
||||
|
||||
// P'(k) = temp1*At + Q
|
||||
gemm(temp1, transitionMatrix, 1, processNoiseCov, 1, errorCovPre, GEMM_2_T);
|
||||
|
||||
// handle the case when there will be measurement before the next predict.
|
||||
statePre.copyTo(statePost);
|
||||
errorCovPre.copyTo(errorCovPost);
|
||||
|
||||
return statePre;
|
||||
}
|
||||
|
||||
const Mat& KalmanFilter::correct(const Mat& measurement)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
// temp2 = H*P'(k)
|
||||
temp2 = measurementMatrix * errorCovPre;
|
||||
|
||||
// temp3 = temp2*Ht + R
|
||||
gemm(temp2, measurementMatrix, 1, measurementNoiseCov, 1, temp3, GEMM_2_T);
|
||||
|
||||
// temp4 = inv(temp3)*temp2 = Kt(k)
|
||||
solve(temp3, temp2, temp4, DECOMP_SVD);
|
||||
|
||||
// K(k)
|
||||
gain = temp4.t();
|
||||
|
||||
// temp5 = z(k) - H*x'(k)
|
||||
temp5 = measurement - measurementMatrix*statePre;
|
||||
|
||||
// x(k) = x'(k) + K(k)*temp5
|
||||
statePost = statePre + gain*temp5;
|
||||
|
||||
// P(k) = P'(k) - K(k)*temp2
|
||||
errorCovPost = errorCovPre - gain*temp2;
|
||||
|
||||
return statePost;
|
||||
}
|
||||
|
||||
}
|
||||
1537
3rdparty/opencv-4.5.4/modules/video/src/lkpyramid.cpp
vendored
Normal file
1537
3rdparty/opencv-4.5.4/modules/video/src/lkpyramid.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
48
3rdparty/opencv-4.5.4/modules/video/src/lkpyramid.hpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/video/src/lkpyramid.hpp
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
typedef short deriv_type;
|
||||
|
||||
struct ScharrDerivInvoker : ParallelLoopBody
|
||||
{
|
||||
ScharrDerivInvoker(const Mat& _src, const Mat& _dst)
|
||||
: src(_src), dst(_dst)
|
||||
{ }
|
||||
|
||||
void operator()(const Range& range) const CV_OVERRIDE;
|
||||
|
||||
const Mat& src;
|
||||
const Mat& dst;
|
||||
};
|
||||
|
||||
struct LKTrackerInvoker : ParallelLoopBody
|
||||
{
|
||||
LKTrackerInvoker( const Mat& _prevImg, const Mat& _prevDeriv, const Mat& _nextImg,
|
||||
const Point2f* _prevPts, Point2f* _nextPts,
|
||||
uchar* _status, float* _err,
|
||||
Size _winSize, TermCriteria _criteria,
|
||||
int _level, int _maxLevel, int _flags, float _minEigThreshold );
|
||||
|
||||
void operator()(const Range& range) const CV_OVERRIDE;
|
||||
|
||||
const Mat* prevImg;
|
||||
const Mat* nextImg;
|
||||
const Mat* prevDeriv;
|
||||
const Point2f* prevPts;
|
||||
Point2f* nextPts;
|
||||
uchar* status;
|
||||
float* err;
|
||||
Size winSize;
|
||||
TermCriteria criteria;
|
||||
int level;
|
||||
int maxLevel;
|
||||
int flags;
|
||||
float minEigThreshold;
|
||||
};
|
||||
|
||||
}// namespace detail
|
||||
}// namespace cv
|
||||
248
3rdparty/opencv-4.5.4/modules/video/src/opencl/bgfg_knn.cl
vendored
Normal file
248
3rdparty/opencv-4.5.4/modules/video/src/opencl/bgfg_knn.cl
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2018 Ya-Chiu Wu, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Ya-Chiu Wu, yacwu@cs.nctu.edu.tw
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if CN==1
|
||||
|
||||
#define T_MEAN float
|
||||
#define F_ZERO (0.0f)
|
||||
|
||||
#define frameToMean(a, b) (b) = *(a);
|
||||
#define meanToFrame(a, b) *b = convert_uchar_sat(a);
|
||||
|
||||
#else
|
||||
|
||||
#define T_MEAN float4
|
||||
#define F_ZERO (0.0f, 0.0f, 0.0f, 0.0f)
|
||||
|
||||
#define meanToFrame(a, b)\
|
||||
b[0] = convert_uchar_sat(a.x); \
|
||||
b[1] = convert_uchar_sat(a.y); \
|
||||
b[2] = convert_uchar_sat(a.z);
|
||||
|
||||
#define frameToMean(a, b)\
|
||||
b.x = a[0]; \
|
||||
b.y = a[1]; \
|
||||
b.z = a[2]; \
|
||||
b.w = 0.0f;
|
||||
|
||||
#endif
|
||||
|
||||
__kernel void knn_kernel(__global const uchar* frame, int frame_step, int frame_offset, int frame_row, int frame_col,
|
||||
__global const uchar* nNextLongUpdate,
|
||||
__global const uchar* nNextMidUpdate,
|
||||
__global const uchar* nNextShortUpdate,
|
||||
__global uchar* aModelIndexLong,
|
||||
__global uchar* aModelIndexMid,
|
||||
__global uchar* aModelIndexShort,
|
||||
__global uchar* flag,
|
||||
__global uchar* sample,
|
||||
__global uchar* fgmask, int fgmask_step, int fgmask_offset,
|
||||
int nLongCounter, int nMidCounter, int nShortCounter,
|
||||
float c_Tb, int c_nkNN, float c_tau
|
||||
#ifdef SHADOW_DETECT
|
||||
, uchar c_shadowVal
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if( x < frame_col && y < frame_row)
|
||||
{
|
||||
__global const uchar* _frame = (frame + mad24(y, frame_step, mad24(x, CN, frame_offset)));
|
||||
T_MEAN pix;
|
||||
frameToMean(_frame, pix);
|
||||
|
||||
uchar foreground = 255; // 0 - the pixel classified as background
|
||||
|
||||
int Pbf = 0;
|
||||
int Pb = 0;
|
||||
uchar include = 0;
|
||||
|
||||
int pt_idx = mad24(y, frame_col, x);
|
||||
int idx_step = frame_row * frame_col;
|
||||
|
||||
__global T_MEAN* _sample = (__global T_MEAN*)(sample);
|
||||
|
||||
for (uchar n = 0; n < (NSAMPLES) * 3 ; ++n)
|
||||
{
|
||||
int n_idx = mad24(n, idx_step, pt_idx);
|
||||
|
||||
T_MEAN c_mean = _sample[n_idx];
|
||||
|
||||
uchar c_flag = flag[n_idx];
|
||||
|
||||
T_MEAN diff = c_mean - pix;
|
||||
float dist2 = dot(diff, diff);
|
||||
|
||||
if (dist2 < c_Tb)
|
||||
{
|
||||
Pbf++;
|
||||
if (c_flag)
|
||||
{
|
||||
Pb++;
|
||||
if (Pb >= c_nkNN)
|
||||
{
|
||||
include = 1;
|
||||
foreground = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Pbf >= c_nkNN)
|
||||
{
|
||||
include = 1;
|
||||
}
|
||||
|
||||
#ifdef SHADOW_DETECT
|
||||
if (foreground)
|
||||
{
|
||||
int Ps = 0;
|
||||
for (uchar n = 0; n < (NSAMPLES) * 3 ; ++n)
|
||||
{
|
||||
int n_idx = mad24(n, idx_step, pt_idx);
|
||||
uchar c_flag = flag[n_idx];
|
||||
|
||||
if (c_flag)
|
||||
{
|
||||
T_MEAN c_mean = _sample[n_idx];
|
||||
|
||||
float numerator = dot(pix, c_mean);
|
||||
float denominator = dot(c_mean, c_mean);
|
||||
|
||||
if (denominator == 0)
|
||||
break;
|
||||
|
||||
if (numerator <= denominator && numerator >= c_tau * denominator)
|
||||
{
|
||||
float a = numerator / denominator;
|
||||
|
||||
T_MEAN dD = mad(a, c_mean, -pix);
|
||||
|
||||
if (dot(dD, dD) < c_Tb * a * a)
|
||||
{
|
||||
Ps++;
|
||||
if (Ps >= c_nkNN)
|
||||
{
|
||||
foreground = c_shadowVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__global uchar* _fgmask = fgmask + mad24(y, fgmask_step, x + fgmask_offset);
|
||||
*_fgmask = (uchar)foreground;
|
||||
|
||||
__global const uchar* _nNextLongUpdate = nNextLongUpdate + pt_idx;
|
||||
__global const uchar* _nNextMidUpdate = nNextMidUpdate + pt_idx;
|
||||
__global const uchar* _nNextShortUpdate = nNextShortUpdate + pt_idx;
|
||||
__global uchar* _aModelIndexLong = aModelIndexLong + pt_idx;
|
||||
__global uchar* _aModelIndexMid = aModelIndexMid + pt_idx;
|
||||
__global uchar* _aModelIndexShort = aModelIndexShort + pt_idx;
|
||||
|
||||
uchar nextLongUpdate = _nNextLongUpdate[0];
|
||||
uchar nextMidUpdate = _nNextMidUpdate[0];
|
||||
uchar nextShortUpdate = _nNextShortUpdate[0];
|
||||
uchar modelIndexLong = _aModelIndexLong[0];
|
||||
uchar modelIndexMid = _aModelIndexMid[0];
|
||||
uchar modelIndexShort = _aModelIndexShort[0];
|
||||
int offsetLong = mad24(mad24(2, (NSAMPLES), modelIndexLong), idx_step, pt_idx);
|
||||
int offsetMid = mad24((NSAMPLES)+modelIndexMid, idx_step, pt_idx);
|
||||
int offsetShort = mad24(modelIndexShort, idx_step, pt_idx);
|
||||
if (nextLongUpdate == nLongCounter)
|
||||
{
|
||||
_sample[offsetLong] = _sample[offsetMid];
|
||||
flag[offsetLong] = flag[offsetMid];
|
||||
_aModelIndexLong[0] = (modelIndexLong >= ((NSAMPLES)-1)) ? 0 : (modelIndexLong + 1);
|
||||
}
|
||||
|
||||
if (nextMidUpdate == nMidCounter)
|
||||
{
|
||||
_sample[offsetMid] = _sample[offsetShort];
|
||||
flag[offsetMid] = flag[offsetShort];
|
||||
_aModelIndexMid[0] = (modelIndexMid >= ((NSAMPLES)-1)) ? 0 : (modelIndexMid + 1);
|
||||
}
|
||||
|
||||
if (nextShortUpdate == nShortCounter)
|
||||
{
|
||||
_sample[offsetShort] = pix;
|
||||
flag[offsetShort] = include;
|
||||
_aModelIndexShort[0] = (modelIndexShort >= ((NSAMPLES)-1)) ? 0 : (modelIndexShort + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void getBackgroundImage2_kernel(__global const uchar* flag,
|
||||
__global const uchar* sample,
|
||||
__global uchar* dst, int dst_step, int dst_offset, int dst_row, int dst_col)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if(x < dst_col && y < dst_row)
|
||||
{
|
||||
int pt_idx = mad24(y, dst_col, x);
|
||||
|
||||
T_MEAN meanVal = (T_MEAN)F_ZERO;
|
||||
|
||||
__global T_MEAN* _sample = (__global T_MEAN*)(sample);
|
||||
int idx_step = dst_row * dst_col;
|
||||
for (uchar n = 0; n < (NSAMPLES) * 3 ; ++n)
|
||||
{
|
||||
int n_idx = mad24(n, idx_step, pt_idx);
|
||||
uchar c_flag = flag[n_idx];
|
||||
if(c_flag)
|
||||
{
|
||||
meanVal = _sample[n_idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
__global uchar* _dst = dst + mad24(y, dst_step, mad24(x, CN, dst_offset));
|
||||
meanToFrame(meanVal, _dst);
|
||||
}
|
||||
}
|
||||
282
3rdparty/opencv-4.5.4/modules/video/src/opencl/bgfg_mog2.cl
vendored
Normal file
282
3rdparty/opencv-4.5.4/modules/video/src/opencl/bgfg_mog2.cl
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
#if CN==1
|
||||
|
||||
#define T_MEAN float
|
||||
#define F_ZERO (0.0f)
|
||||
#define cnMode 1
|
||||
|
||||
#define frameToMean(a, b) (b) = *(a);
|
||||
#if FL==0
|
||||
#define meanToFrame(a, b) *b = convert_uchar_sat(a);
|
||||
#else
|
||||
#define meanToFrame(a, b) *b = (float)a;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define T_MEAN float4
|
||||
#define F_ZERO (0.0f, 0.0f, 0.0f, 0.0f)
|
||||
#define cnMode 4
|
||||
|
||||
#if FL == 0
|
||||
#define meanToFrame(a, b)\
|
||||
b[0] = convert_uchar_sat(a.x); \
|
||||
b[1] = convert_uchar_sat(a.y); \
|
||||
b[2] = convert_uchar_sat(a.z);
|
||||
#else
|
||||
#define meanToFrame(a, b)\
|
||||
b[0] = a.x; \
|
||||
b[1] = a.y; \
|
||||
b[2] = a.z;
|
||||
#endif
|
||||
|
||||
#define frameToMean(a, b)\
|
||||
b.x = a[0]; \
|
||||
b.y = a[1]; \
|
||||
b.z = a[2]; \
|
||||
b.w = 0.0f;
|
||||
|
||||
#endif
|
||||
|
||||
__kernel void mog2_kernel(__global const uchar* frame, int frame_step, int frame_offset, int frame_row, int frame_col, //uchar || uchar3
|
||||
__global uchar* modesUsed, //uchar
|
||||
__global uchar* weight, //float
|
||||
__global uchar* mean, //T_MEAN=float || float4
|
||||
__global uchar* variance, //float
|
||||
__global uchar* fgmask, int fgmask_step, int fgmask_offset, //uchar
|
||||
float alphaT, float alpha1, float prune,
|
||||
float c_Tb, float c_TB, float c_Tg, float c_varMin, //constants
|
||||
float c_varMax, float c_varInit, float c_tau
|
||||
#ifdef SHADOW_DETECT
|
||||
, uchar c_shadowVal
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if( x < frame_col && y < frame_row)
|
||||
{
|
||||
#if FL==0
|
||||
__global const uchar* _frame = (frame + mad24(y, frame_step, mad24(x, CN, frame_offset)));
|
||||
#else
|
||||
__global const float* _frame = ((__global const float*)( frame + mad24(y, frame_step, frame_offset)) + mad24(x, CN, 0));
|
||||
#endif
|
||||
T_MEAN pix;
|
||||
frameToMean(_frame, pix);
|
||||
|
||||
uchar foreground = 255; // 0 - the pixel classified as background
|
||||
|
||||
bool fitsPDF = false; //if it remains zero a new GMM mode will be added
|
||||
|
||||
int pt_idx = mad24(y, frame_col, x);
|
||||
int idx_step = frame_row * frame_col;
|
||||
|
||||
__global uchar* _modesUsed = modesUsed + pt_idx;
|
||||
uchar nmodes = _modesUsed[0];
|
||||
|
||||
float totalWeight = 0.0f;
|
||||
|
||||
__global float* _weight = (__global float*)(weight);
|
||||
__global float* _variance = (__global float*)(variance);
|
||||
__global T_MEAN* _mean = (__global T_MEAN*)(mean);
|
||||
|
||||
uchar mode = 0;
|
||||
for (; mode < nmodes; ++mode)
|
||||
{
|
||||
int mode_idx = mad24(mode, idx_step, pt_idx);
|
||||
float c_weight = mad(alpha1, _weight[mode_idx], prune);
|
||||
|
||||
float c_var = _variance[mode_idx];
|
||||
|
||||
T_MEAN c_mean = _mean[mode_idx];
|
||||
|
||||
T_MEAN diff = c_mean - pix;
|
||||
float dist2 = dot(diff, diff);
|
||||
|
||||
if (totalWeight < c_TB && dist2 < c_Tb * c_var)
|
||||
foreground = 0;
|
||||
|
||||
if (dist2 < c_Tg * c_var)
|
||||
{
|
||||
fitsPDF = true;
|
||||
c_weight += alphaT;
|
||||
|
||||
float k = alphaT / c_weight;
|
||||
T_MEAN mean_new = mad((T_MEAN)-k, diff, c_mean);
|
||||
float variance_new = clamp(mad(k, (dist2 - c_var), c_var), c_varMin, c_varMax);
|
||||
|
||||
for (int i = mode; i > 0; --i)
|
||||
{
|
||||
int prev_idx = mode_idx - idx_step;
|
||||
if (c_weight < _weight[prev_idx])
|
||||
break;
|
||||
|
||||
_weight[mode_idx] = _weight[prev_idx];
|
||||
_variance[mode_idx] = _variance[prev_idx];
|
||||
_mean[mode_idx] = _mean[prev_idx];
|
||||
|
||||
mode_idx = prev_idx;
|
||||
}
|
||||
|
||||
_mean[mode_idx] = mean_new;
|
||||
_variance[mode_idx] = variance_new;
|
||||
_weight[mode_idx] = c_weight; //update weight by the calculated value
|
||||
|
||||
totalWeight += c_weight;
|
||||
|
||||
mode ++;
|
||||
|
||||
break;
|
||||
}
|
||||
if (c_weight < -prune)
|
||||
c_weight = 0.0f;
|
||||
|
||||
_weight[mode_idx] = c_weight; //update weight by the calculated value
|
||||
totalWeight += c_weight;
|
||||
}
|
||||
|
||||
for (; mode < nmodes; ++mode)
|
||||
{
|
||||
int mode_idx = mad24(mode, idx_step, pt_idx);
|
||||
float c_weight = mad(alpha1, _weight[mode_idx], prune);
|
||||
|
||||
if (c_weight < -prune)
|
||||
{
|
||||
c_weight = 0.0f;
|
||||
nmodes = mode;
|
||||
break;
|
||||
}
|
||||
_weight[mode_idx] = c_weight; //update weight by the calculated value
|
||||
totalWeight += c_weight;
|
||||
}
|
||||
|
||||
if (0.f < totalWeight)
|
||||
{
|
||||
totalWeight = 1.f / totalWeight;
|
||||
for (int mode = 0; mode < nmodes; ++mode)
|
||||
_weight[mad24(mode, idx_step, pt_idx)] *= totalWeight;
|
||||
}
|
||||
|
||||
if (!fitsPDF)
|
||||
{
|
||||
uchar mode = nmodes == (NMIXTURES) ? (NMIXTURES) - 1 : nmodes++;
|
||||
int mode_idx = mad24(mode, idx_step, pt_idx);
|
||||
|
||||
if (nmodes == 1)
|
||||
_weight[mode_idx] = 1.f;
|
||||
else
|
||||
{
|
||||
_weight[mode_idx] = alphaT;
|
||||
|
||||
for (int i = pt_idx; i < mode_idx; i += idx_step)
|
||||
_weight[i] *= alpha1;
|
||||
}
|
||||
|
||||
for (int i = nmodes - 1; i > 0; --i)
|
||||
{
|
||||
int prev_idx = mode_idx - idx_step;
|
||||
if (alphaT < _weight[prev_idx])
|
||||
break;
|
||||
|
||||
_weight[mode_idx] = _weight[prev_idx];
|
||||
_variance[mode_idx] = _variance[prev_idx];
|
||||
_mean[mode_idx] = _mean[prev_idx];
|
||||
|
||||
mode_idx = prev_idx;
|
||||
}
|
||||
|
||||
_mean[mode_idx] = pix;
|
||||
_variance[mode_idx] = c_varInit;
|
||||
}
|
||||
|
||||
_modesUsed[0] = nmodes;
|
||||
#ifdef SHADOW_DETECT
|
||||
if (foreground)
|
||||
{
|
||||
float tWeight = 0.0f;
|
||||
|
||||
for (uchar mode = 0; mode < nmodes; ++mode)
|
||||
{
|
||||
int mode_idx = mad24(mode, idx_step, pt_idx);
|
||||
T_MEAN c_mean = _mean[mode_idx];
|
||||
|
||||
float numerator = dot(pix, c_mean);
|
||||
float denominator = dot(c_mean, c_mean);
|
||||
|
||||
if (denominator == 0)
|
||||
break;
|
||||
|
||||
if (numerator <= denominator && numerator >= c_tau * denominator)
|
||||
{
|
||||
float a = numerator / denominator;
|
||||
|
||||
T_MEAN dD = mad(a, c_mean, -pix);
|
||||
|
||||
if (dot(dD, dD) < c_Tb * _variance[mode_idx] * a * a)
|
||||
{
|
||||
foreground = c_shadowVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tWeight += _weight[mode_idx];
|
||||
if (tWeight > c_TB)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__global uchar* _fgmask = fgmask + mad24(y, fgmask_step, x + fgmask_offset);
|
||||
*_fgmask = (uchar)foreground;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void getBackgroundImage2_kernel(__global const uchar* modesUsed,
|
||||
__global const uchar* weight,
|
||||
__global const uchar* mean,
|
||||
__global uchar* dst, int dst_step, int dst_offset, int dst_row, int dst_col,
|
||||
float c_TB)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if(x < dst_col && y < dst_row)
|
||||
{
|
||||
int pt_idx = mad24(y, dst_col, x);
|
||||
|
||||
__global const uchar* _modesUsed = modesUsed + pt_idx;
|
||||
uchar nmodes = _modesUsed[0];
|
||||
|
||||
T_MEAN meanVal = (T_MEAN)F_ZERO;
|
||||
|
||||
float totalWeight = 0.0f;
|
||||
__global const float* _weight = (__global const float*)weight;
|
||||
__global const T_MEAN* _mean = (__global const T_MEAN*)(mean);
|
||||
int idx_step = dst_row * dst_col;
|
||||
for (uchar mode = 0; mode < nmodes; ++mode)
|
||||
{
|
||||
int mode_idx = mad24(mode, idx_step, pt_idx);
|
||||
float c_weight = _weight[mode_idx];
|
||||
T_MEAN c_mean = _mean[mode_idx];
|
||||
|
||||
meanVal = mad(c_weight, c_mean, meanVal);
|
||||
|
||||
totalWeight += c_weight;
|
||||
|
||||
if (totalWeight > c_TB)
|
||||
break;
|
||||
}
|
||||
|
||||
if (0.f < totalWeight)
|
||||
meanVal = meanVal / totalWeight;
|
||||
else
|
||||
meanVal = (T_MEAN)(0.f);
|
||||
|
||||
#if FL==0
|
||||
__global uchar* _dst = dst + mad24(y, dst_step, mad24(x, CN, dst_offset));
|
||||
meanToFrame(meanVal, _dst);
|
||||
#else
|
||||
__global float* _dst = ((__global float*)( dst + mad24(y, dst_step, dst_offset)) + mad24(x, CN, 0));
|
||||
meanToFrame(meanVal, _dst);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
540
3rdparty/opencv-4.5.4/modules/video/src/opencl/dis_flow.cl
vendored
Normal file
540
3rdparty/opencv-4.5.4/modules/video/src/opencl/dis_flow.cl
vendored
Normal file
@@ -0,0 +1,540 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
//#define CV_USE_SUBGROUPS
|
||||
|
||||
#define EPS 0.001f
|
||||
#define INF 1E+10F
|
||||
|
||||
//#define DIS_BORDER_SIZE xxx
|
||||
//#define DIS_PATCH_SIZE xxx
|
||||
//#define DIS_PATCH_STRIDE xxx
|
||||
|
||||
#define DIS_PATCH_SIZE_HALF (DIS_PATCH_SIZE / 2)
|
||||
|
||||
#ifndef DIS_BORDER_SIZE
|
||||
|
||||
__kernel void dis_precomputeStructureTensor_hor(__global const short *I0x,
|
||||
__global const short *I0y,
|
||||
int w, int h, int ws,
|
||||
__global float *I0xx_aux_ptr,
|
||||
__global float *I0yy_aux_ptr,
|
||||
__global float *I0xy_aux_ptr,
|
||||
__global float *I0x_aux_ptr,
|
||||
__global float *I0y_aux_ptr)
|
||||
{
|
||||
|
||||
int i = get_global_id(0);
|
||||
|
||||
if (i >= h) return;
|
||||
|
||||
const __global short *x_row = I0x + i * w;
|
||||
const __global short *y_row = I0y + i * w;
|
||||
|
||||
float sum_xx = 0.0f, sum_yy = 0.0f, sum_xy = 0.0f, sum_x = 0.0f, sum_y = 0.0f;
|
||||
float8 x_vec = convert_float8(vload8(0, x_row));
|
||||
float8 y_vec = convert_float8(vload8(0, y_row));
|
||||
sum_xx = dot(x_vec.lo, x_vec.lo) + dot(x_vec.hi, x_vec.hi);
|
||||
sum_yy = dot(y_vec.lo, y_vec.lo) + dot(y_vec.hi, y_vec.hi);
|
||||
sum_xy = dot(x_vec.lo, y_vec.lo) + dot(x_vec.hi, y_vec.hi);
|
||||
sum_x = dot(x_vec.lo, 1.0f) + dot(x_vec.hi, 1.0f);
|
||||
sum_y = dot(y_vec.lo, 1.0f) + dot(y_vec.hi, 1.0f);
|
||||
|
||||
I0xx_aux_ptr[i * ws] = sum_xx;
|
||||
I0yy_aux_ptr[i * ws] = sum_yy;
|
||||
I0xy_aux_ptr[i * ws] = sum_xy;
|
||||
I0x_aux_ptr[i * ws] = sum_x;
|
||||
I0y_aux_ptr[i * ws] = sum_y;
|
||||
|
||||
int js = 1;
|
||||
for (int j = DIS_PATCH_SIZE; j < w; j++)
|
||||
{
|
||||
short x_val1 = x_row[j];
|
||||
short x_val2 = x_row[j - DIS_PATCH_SIZE];
|
||||
short y_val1 = y_row[j];
|
||||
short y_val2 = y_row[j - DIS_PATCH_SIZE];
|
||||
sum_xx += (x_val1 * x_val1 - x_val2 * x_val2);
|
||||
sum_yy += (y_val1 * y_val1 - y_val2 * y_val2);
|
||||
sum_xy += (x_val1 * y_val1 - x_val2 * y_val2);
|
||||
sum_x += (x_val1 - x_val2);
|
||||
sum_y += (y_val1 - y_val2);
|
||||
if ((j - DIS_PATCH_SIZE + 1) % DIS_PATCH_STRIDE == 0)
|
||||
{
|
||||
int index = i * ws + js;
|
||||
I0xx_aux_ptr[index] = sum_xx;
|
||||
I0yy_aux_ptr[index] = sum_yy;
|
||||
I0xy_aux_ptr[index] = sum_xy;
|
||||
I0x_aux_ptr[index] = sum_x;
|
||||
I0y_aux_ptr[index] = sum_y;
|
||||
js++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void dis_precomputeStructureTensor_ver(__global const float *I0xx_aux_ptr,
|
||||
__global const float *I0yy_aux_ptr,
|
||||
__global const float *I0xy_aux_ptr,
|
||||
__global const float *I0x_aux_ptr,
|
||||
__global const float *I0y_aux_ptr,
|
||||
int w, int h, int ws,
|
||||
__global float *I0xx_ptr,
|
||||
__global float *I0yy_ptr,
|
||||
__global float *I0xy_ptr,
|
||||
__global float *I0x_ptr,
|
||||
__global float *I0y_ptr)
|
||||
{
|
||||
int j = get_global_id(0);
|
||||
|
||||
if (j >= ws) return;
|
||||
|
||||
float sum_xx, sum_yy, sum_xy, sum_x, sum_y;
|
||||
sum_xx = sum_yy = sum_xy = sum_x = sum_y = 0.0f;
|
||||
|
||||
for (int i = 0; i < DIS_PATCH_SIZE; i++)
|
||||
{
|
||||
sum_xx += I0xx_aux_ptr[i * ws + j];
|
||||
sum_yy += I0yy_aux_ptr[i * ws + j];
|
||||
sum_xy += I0xy_aux_ptr[i * ws + j];
|
||||
sum_x += I0x_aux_ptr[i * ws + j];
|
||||
sum_y += I0y_aux_ptr[i * ws + j];
|
||||
}
|
||||
I0xx_ptr[j] = sum_xx;
|
||||
I0yy_ptr[j] = sum_yy;
|
||||
I0xy_ptr[j] = sum_xy;
|
||||
I0x_ptr[j] = sum_x;
|
||||
I0y_ptr[j] = sum_y;
|
||||
|
||||
int is = 1;
|
||||
for (int i = DIS_PATCH_SIZE; i < h; i++)
|
||||
{
|
||||
sum_xx += (I0xx_aux_ptr[i * ws + j] - I0xx_aux_ptr[(i - DIS_PATCH_SIZE) * ws + j]);
|
||||
sum_yy += (I0yy_aux_ptr[i * ws + j] - I0yy_aux_ptr[(i - DIS_PATCH_SIZE) * ws + j]);
|
||||
sum_xy += (I0xy_aux_ptr[i * ws + j] - I0xy_aux_ptr[(i - DIS_PATCH_SIZE) * ws + j]);
|
||||
sum_x += (I0x_aux_ptr[i * ws + j] - I0x_aux_ptr[(i - DIS_PATCH_SIZE) * ws + j]);
|
||||
sum_y += (I0y_aux_ptr[i * ws + j] - I0y_aux_ptr[(i - DIS_PATCH_SIZE) * ws + j]);
|
||||
|
||||
if ((i - DIS_PATCH_SIZE + 1) % DIS_PATCH_STRIDE == 0)
|
||||
{
|
||||
I0xx_ptr[is * ws + j] = sum_xx;
|
||||
I0yy_ptr[is * ws + j] = sum_yy;
|
||||
I0xy_ptr[is * ws + j] = sum_xy;
|
||||
I0x_ptr[is * ws + j] = sum_x;
|
||||
I0y_ptr[is * ws + j] = sum_y;
|
||||
is++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void dis_densification(__global const float2 *S_ptr,
|
||||
__global const uchar *i0, __global const uchar *i1,
|
||||
int w, int h, int ws,
|
||||
__global float2 *U_ptr)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
int i, j;
|
||||
|
||||
if (x >= w || y >= h) return;
|
||||
|
||||
int start_is, end_is;
|
||||
int start_js, end_js;
|
||||
|
||||
end_is = min(y / DIS_PATCH_STRIDE, (h - DIS_PATCH_SIZE) / DIS_PATCH_STRIDE);
|
||||
start_is = max(0, y - DIS_PATCH_SIZE + DIS_PATCH_STRIDE) / DIS_PATCH_STRIDE;
|
||||
start_is = min(start_is, end_is);
|
||||
|
||||
end_js = min(x / DIS_PATCH_STRIDE, (w - DIS_PATCH_SIZE) / DIS_PATCH_STRIDE);
|
||||
start_js = max(0, x - DIS_PATCH_SIZE + DIS_PATCH_STRIDE) / DIS_PATCH_STRIDE;
|
||||
start_js = min(start_js, end_js);
|
||||
|
||||
float sum_coef = 0.0f;
|
||||
float2 sum_U = (float2)(0.0f, 0.0f);
|
||||
|
||||
int i_l, i_u;
|
||||
int j_l, j_u;
|
||||
float i_m, j_m, diff;
|
||||
|
||||
i = y;
|
||||
j = x;
|
||||
|
||||
/* Iterate through all the patches that overlap the current location (i,j) */
|
||||
for (int is = start_is; is <= end_is; is++)
|
||||
for (int js = start_js; js <= end_js; js++)
|
||||
{
|
||||
float2 s_val = S_ptr[is * ws + js];
|
||||
uchar2 i1_vec1, i1_vec2;
|
||||
|
||||
j_m = min(max(j + s_val.x, 0.0f), w - 1.0f - EPS);
|
||||
i_m = min(max(i + s_val.y, 0.0f), h - 1.0f - EPS);
|
||||
j_l = (int)j_m;
|
||||
j_u = j_l + 1;
|
||||
i_l = (int)i_m;
|
||||
i_u = i_l + 1;
|
||||
i1_vec1 = vload2(0, i1 + i_u * w + j_l);
|
||||
i1_vec2 = vload2(0, i1 + i_l * w + j_l);
|
||||
diff = (j_m - j_l) * (i_m - i_l) * i1_vec1.y +
|
||||
(j_u - j_m) * (i_m - i_l) * i1_vec1.x +
|
||||
(j_m - j_l) * (i_u - i_m) * i1_vec2.y +
|
||||
(j_u - j_m) * (i_u - i_m) * i1_vec2.x - i0[i * w + j];
|
||||
float coef = 1.0f / max(1.0f, fabs(diff));
|
||||
sum_U += coef * s_val;
|
||||
sum_coef += coef;
|
||||
}
|
||||
|
||||
float inv_sum_coef = 1.0 / sum_coef;
|
||||
U_ptr[i * w + j] = sum_U * inv_sum_coef;
|
||||
}
|
||||
|
||||
#else // DIS_BORDER_SIZE
|
||||
|
||||
#define INIT_BILINEAR_WEIGHTS(Ux, Uy) \
|
||||
i_I1 = clamp(i + Uy + DIS_BORDER_SIZE, i_lower_limit, i_upper_limit); \
|
||||
j_I1 = clamp(j + Ux + DIS_BORDER_SIZE, j_lower_limit, j_upper_limit); \
|
||||
{ \
|
||||
float di = i_I1 - floor(i_I1); \
|
||||
float dj = j_I1 - floor(j_I1); \
|
||||
w11 = di * dj; \
|
||||
w10 = di * (1 - dj); \
|
||||
w01 = (1 - di) * dj; \
|
||||
w00 = (1 - di) * (1 - dj); \
|
||||
}
|
||||
|
||||
float computeSSDMeanNorm(const __global uchar *I0_ptr, const __global uchar *I1_ptr,
|
||||
int I0_stride, int I1_stride,
|
||||
float w00, float w01, float w10, float w11, int i
|
||||
#ifndef CV_USE_SUBGROUPS
|
||||
, __local float2 *smem /*[8]*/
|
||||
#endif
|
||||
)
|
||||
{
|
||||
float sum_diff = 0.0f, sum_diff_sq = 0.0f;
|
||||
int n = DIS_PATCH_SIZE * DIS_PATCH_SIZE;
|
||||
|
||||
uchar8 I1_vec1, I1_vec2, I0_vec;
|
||||
uchar I1_val1, I1_val2;
|
||||
|
||||
I0_vec = vload8(0, I0_ptr + i * I0_stride);
|
||||
I1_vec1 = vload8(0, I1_ptr + i * I1_stride);
|
||||
I1_vec2 = vload8(0, I1_ptr + (i + 1) * I1_stride);
|
||||
I1_val1 = I1_ptr[i * I1_stride + 8];
|
||||
I1_val2 = I1_ptr[(i + 1) * I1_stride + 8];
|
||||
|
||||
float8 vec = w00 * convert_float8(I1_vec1) + w01 * convert_float8((uchar8)(I1_vec1.s123, I1_vec1.s4567, I1_val1)) +
|
||||
w10 * convert_float8(I1_vec2) + w11 * convert_float8((uchar8)(I1_vec2.s123, I1_vec2.s4567, I1_val2)) -
|
||||
convert_float8(I0_vec);
|
||||
|
||||
sum_diff = (dot(vec.lo, 1.0) + dot(vec.hi, 1.0));
|
||||
sum_diff_sq = (dot(vec.lo, vec.lo) + dot(vec.hi, vec.hi));
|
||||
|
||||
#ifdef CV_USE_SUBGROUPS
|
||||
sum_diff = sub_group_reduce_add(sum_diff);
|
||||
sum_diff_sq = sub_group_reduce_add(sum_diff_sq);
|
||||
#else
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
smem[i] = (float2)(sum_diff, sum_diff_sq);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (i < 4)
|
||||
smem[i] += smem[i + 4];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (i < 2)
|
||||
smem[i] += smem[i + 2];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (i == 0)
|
||||
smem[0] += smem[1];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
float2 reduce_add_result = smem[0];
|
||||
sum_diff = reduce_add_result.x;
|
||||
sum_diff_sq = reduce_add_result.y;
|
||||
#endif
|
||||
|
||||
return sum_diff_sq - sum_diff * sum_diff / n;
|
||||
}
|
||||
|
||||
__attribute__((reqd_work_group_size(8, 1, 1)))
|
||||
__kernel void dis_patch_inverse_search_fwd_1(__global const float2 *U_ptr,
|
||||
__global const uchar *I0_ptr, __global const uchar *I1_ptr,
|
||||
int w, int h, int ws, int hs,
|
||||
__global float2 *S_ptr)
|
||||
{
|
||||
int id = get_global_id(0);
|
||||
int is = get_group_id(0);
|
||||
|
||||
int i = is * DIS_PATCH_STRIDE;
|
||||
int j = 0;
|
||||
int w_ext = w + 2 * DIS_BORDER_SIZE;
|
||||
|
||||
float i_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
float i_upper_limit = DIS_BORDER_SIZE + h - 1.0f;
|
||||
float j_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
float j_upper_limit = DIS_BORDER_SIZE + w - 1.0f;
|
||||
|
||||
float2 prev_U = U_ptr[(i + DIS_PATCH_SIZE_HALF) * w + j + DIS_PATCH_SIZE_HALF];
|
||||
S_ptr[is * ws] = prev_U;
|
||||
j += DIS_PATCH_STRIDE;
|
||||
|
||||
#ifdef CV_USE_SUBGROUPS
|
||||
int sid = get_sub_group_local_id();
|
||||
#define EXTRA_ARGS_computeSSDMeanNorm sid
|
||||
#else
|
||||
__local float2 smem[8];
|
||||
int sid = get_local_id(0);
|
||||
#define EXTRA_ARGS_computeSSDMeanNorm sid, smem
|
||||
#endif
|
||||
for (int js = 1; js < ws; js++, j += DIS_PATCH_STRIDE)
|
||||
{
|
||||
float2 U = U_ptr[(i + DIS_PATCH_SIZE_HALF) * w + j + DIS_PATCH_SIZE_HALF];
|
||||
|
||||
float i_I1, j_I1, w00, w01, w10, w11;
|
||||
|
||||
INIT_BILINEAR_WEIGHTS(U.x, U.y);
|
||||
float min_SSD = computeSSDMeanNorm(
|
||||
I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1,
|
||||
w, w_ext, w00, w01, w10, w11, EXTRA_ARGS_computeSSDMeanNorm);
|
||||
|
||||
INIT_BILINEAR_WEIGHTS(prev_U.x, prev_U.y);
|
||||
float cur_SSD = computeSSDMeanNorm(
|
||||
I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1,
|
||||
w, w_ext, w00, w01, w10, w11, EXTRA_ARGS_computeSSDMeanNorm);
|
||||
|
||||
prev_U = (cur_SSD < min_SSD) ? prev_U : U;
|
||||
S_ptr[is * ws + js] = prev_U;
|
||||
}
|
||||
|
||||
#undef EXTRA_ARGS_computeSSDMeanNorm
|
||||
}
|
||||
#endif // DIS_BORDER_SIZE
|
||||
|
||||
float4 processPatchMeanNorm(const __global uchar *I0_ptr, const __global uchar *I1_ptr,
|
||||
const __global short *I0x_ptr, const __global short *I0y_ptr,
|
||||
int I0_stride, int I1_stride, float w00, float w01, float w10,
|
||||
float w11, float x_grad_sum, float y_grad_sum)
|
||||
{
|
||||
const float inv_n = 1.0f / (float)(DIS_PATCH_SIZE * DIS_PATCH_SIZE);
|
||||
|
||||
float sum_diff = 0.0, sum_diff_sq = 0.0;
|
||||
float sum_I0x_mul = 0.0, sum_I0y_mul = 0.0;
|
||||
|
||||
uchar8 I1_vec1;
|
||||
uchar8 I1_vec2 = vload8(0, I1_ptr);
|
||||
uchar I1_val1;
|
||||
uchar I1_val2 = I1_ptr[DIS_PATCH_SIZE];
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uchar8 I0_vec = vload8(0, I0_ptr + i * I0_stride);
|
||||
|
||||
I1_vec1 = I1_vec2;
|
||||
I1_vec2 = vload8(0, I1_ptr + (i + 1) * I1_stride);
|
||||
I1_val1 = I1_val2;
|
||||
I1_val2 = I1_ptr[(i + 1) * I1_stride + DIS_PATCH_SIZE];
|
||||
|
||||
float8 vec = w00 * convert_float8(I1_vec1) + w01 * convert_float8((uchar8)(I1_vec1.s123, I1_vec1.s4567, I1_val1)) +
|
||||
w10 * convert_float8(I1_vec2) + w11 * convert_float8((uchar8)(I1_vec2.s123, I1_vec2.s4567, I1_val2)) -
|
||||
convert_float8(I0_vec);
|
||||
|
||||
sum_diff += (dot(vec.lo, 1.0) + dot(vec.hi, 1.0));
|
||||
sum_diff_sq += (dot(vec.lo, vec.lo) + dot(vec.hi, vec.hi));
|
||||
|
||||
short8 I0x_vec = vload8(0, I0x_ptr + i * I0_stride);
|
||||
short8 I0y_vec = vload8(0, I0y_ptr + i * I0_stride);
|
||||
|
||||
sum_I0x_mul += dot(vec.lo, convert_float4(I0x_vec.lo));
|
||||
sum_I0x_mul += dot(vec.hi, convert_float4(I0x_vec.hi));
|
||||
sum_I0y_mul += dot(vec.lo, convert_float4(I0y_vec.lo));
|
||||
sum_I0y_mul += dot(vec.hi, convert_float4(I0y_vec.hi));
|
||||
}
|
||||
|
||||
float dst_dUx = sum_I0x_mul - sum_diff * x_grad_sum * inv_n;
|
||||
float dst_dUy = sum_I0y_mul - sum_diff * y_grad_sum * inv_n;
|
||||
float SSD = sum_diff_sq - sum_diff * sum_diff * inv_n;
|
||||
|
||||
return (float4)(SSD, dst_dUx, dst_dUy, 0);
|
||||
}
|
||||
|
||||
#ifdef DIS_BORDER_SIZE
|
||||
__kernel void dis_patch_inverse_search_fwd_2(__global const float2 *U_ptr,
|
||||
__global const uchar *I0_ptr, __global const uchar *I1_ptr,
|
||||
__global const short *I0x_ptr, __global const short *I0y_ptr,
|
||||
__global const float *xx_ptr, __global const float *yy_ptr,
|
||||
__global const float *xy_ptr,
|
||||
__global const float *x_ptr, __global const float *y_ptr,
|
||||
int w, int h, int ws, int hs, int num_inner_iter,
|
||||
__global float2 *S_ptr)
|
||||
{
|
||||
int js = get_global_id(0);
|
||||
int is = get_global_id(1);
|
||||
int i = is * DIS_PATCH_STRIDE;
|
||||
int j = js * DIS_PATCH_STRIDE;
|
||||
const int psz = DIS_PATCH_SIZE;
|
||||
int w_ext = w + 2 * DIS_BORDER_SIZE;
|
||||
int index = is * ws + js;
|
||||
|
||||
if (js >= ws || is >= hs) return;
|
||||
|
||||
float2 U0 = S_ptr[index];
|
||||
float2 cur_U = U0;
|
||||
float cur_xx = xx_ptr[index];
|
||||
float cur_yy = yy_ptr[index];
|
||||
float cur_xy = xy_ptr[index];
|
||||
float detH = cur_xx * cur_yy - cur_xy * cur_xy;
|
||||
|
||||
float inv_detH = (fabs(detH) < EPS) ? 1.0 / EPS : 1.0 / detH;
|
||||
float invH11 = cur_yy * inv_detH;
|
||||
float invH12 = -cur_xy * inv_detH;
|
||||
float invH22 = cur_xx * inv_detH;
|
||||
|
||||
float prev_SSD = INF;
|
||||
float x_grad_sum = x_ptr[index];
|
||||
float y_grad_sum = y_ptr[index];
|
||||
|
||||
const float i_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
const float i_upper_limit = DIS_BORDER_SIZE + h - 1.0f;
|
||||
const float j_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
const float j_upper_limit = DIS_BORDER_SIZE + w - 1.0f;
|
||||
|
||||
for (int t = 0; t < num_inner_iter; t++)
|
||||
{
|
||||
float i_I1, j_I1, w00, w01, w10, w11;
|
||||
INIT_BILINEAR_WEIGHTS(cur_U.x, cur_U.y);
|
||||
float4 res = processPatchMeanNorm(
|
||||
I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1,
|
||||
I0x_ptr + i * w + j, I0y_ptr + i * w + j,
|
||||
w, w_ext, w00, w01, w10, w11,
|
||||
x_grad_sum, y_grad_sum);
|
||||
|
||||
float SSD = res.x;
|
||||
float dUx = res.y;
|
||||
float dUy = res.z;
|
||||
float dx = invH11 * dUx + invH12 * dUy;
|
||||
float dy = invH12 * dUx + invH22 * dUy;
|
||||
|
||||
cur_U -= (float2)(dx, dy);
|
||||
|
||||
if (SSD >= prev_SSD)
|
||||
break;
|
||||
prev_SSD = SSD;
|
||||
}
|
||||
|
||||
float2 vec = cur_U - U0;
|
||||
S_ptr[index] = (dot(vec, vec) <= (float)(DIS_PATCH_SIZE * DIS_PATCH_SIZE)) ? cur_U : U0;
|
||||
}
|
||||
|
||||
__attribute__((reqd_work_group_size(8, 1, 1)))
|
||||
__kernel void dis_patch_inverse_search_bwd_1(__global const uchar *I0_ptr, __global const uchar *I1_ptr,
|
||||
int w, int h, int ws, int hs,
|
||||
__global float2 *S_ptr)
|
||||
{
|
||||
int id = get_global_id(0);
|
||||
int is = get_group_id(0);
|
||||
|
||||
is = (hs - 1 - is);
|
||||
int i = is * DIS_PATCH_STRIDE;
|
||||
int j = (ws - 2) * DIS_PATCH_STRIDE;
|
||||
const int w_ext = w + 2 * DIS_BORDER_SIZE;
|
||||
|
||||
const float i_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
const float i_upper_limit = DIS_BORDER_SIZE + h - 1.0f;
|
||||
const float j_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
const float j_upper_limit = DIS_BORDER_SIZE + w - 1.0f;
|
||||
|
||||
#ifdef CV_USE_SUBGROUPS
|
||||
int sid = get_sub_group_local_id();
|
||||
#define EXTRA_ARGS_computeSSDMeanNorm sid
|
||||
#else
|
||||
__local float2 smem[8];
|
||||
int sid = get_local_id(0);
|
||||
#define EXTRA_ARGS_computeSSDMeanNorm sid, smem
|
||||
#endif
|
||||
|
||||
for (int js = (ws - 2); js > -1; js--, j -= DIS_PATCH_STRIDE)
|
||||
{
|
||||
float2 U0 = S_ptr[is * ws + js];
|
||||
float2 U1 = S_ptr[is * ws + js + 1];
|
||||
|
||||
float i_I1, j_I1, w00, w01, w10, w11;
|
||||
|
||||
INIT_BILINEAR_WEIGHTS(U0.x, U0.y);
|
||||
float min_SSD = computeSSDMeanNorm(
|
||||
I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1,
|
||||
w, w_ext, w00, w01, w10, w11, EXTRA_ARGS_computeSSDMeanNorm);
|
||||
|
||||
INIT_BILINEAR_WEIGHTS(U1.x, U1.y);
|
||||
float cur_SSD = computeSSDMeanNorm(
|
||||
I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1,
|
||||
w, w_ext, w00, w01, w10, w11, EXTRA_ARGS_computeSSDMeanNorm);
|
||||
|
||||
S_ptr[is * ws + js] = (cur_SSD < min_SSD) ? U1 : U0;
|
||||
}
|
||||
|
||||
#undef EXTRA_ARGS_computeSSDMeanNorm
|
||||
}
|
||||
|
||||
__kernel void dis_patch_inverse_search_bwd_2(__global const uchar *I0_ptr, __global const uchar *I1_ptr,
|
||||
__global const short *I0x_ptr, __global const short *I0y_ptr,
|
||||
__global const float *xx_ptr, __global const float *yy_ptr,
|
||||
__global const float *xy_ptr,
|
||||
__global const float *x_ptr, __global const float *y_ptr,
|
||||
int w, int h, int ws, int hs, int num_inner_iter,
|
||||
__global float2 *S_ptr)
|
||||
{
|
||||
int js = get_global_id(0);
|
||||
int is = get_global_id(1);
|
||||
if (js >= ws || is >= hs) return;
|
||||
|
||||
js = (ws - 1 - js);
|
||||
is = (hs - 1 - is);
|
||||
|
||||
int j = js * DIS_PATCH_STRIDE;
|
||||
int i = is * DIS_PATCH_STRIDE;
|
||||
int w_ext = w + 2 * DIS_BORDER_SIZE;
|
||||
int index = is * ws + js;
|
||||
|
||||
float2 U0 = S_ptr[index];
|
||||
float2 cur_U = U0;
|
||||
float cur_xx = xx_ptr[index];
|
||||
float cur_yy = yy_ptr[index];
|
||||
float cur_xy = xy_ptr[index];
|
||||
float detH = cur_xx * cur_yy - cur_xy * cur_xy;
|
||||
|
||||
float inv_detH = (fabs(detH) < EPS) ? 1.0 / EPS : 1.0 / detH;
|
||||
float invH11 = cur_yy * inv_detH;
|
||||
float invH12 = -cur_xy * inv_detH;
|
||||
float invH22 = cur_xx * inv_detH;
|
||||
|
||||
float prev_SSD = INF;
|
||||
float x_grad_sum = x_ptr[index];
|
||||
float y_grad_sum = y_ptr[index];
|
||||
|
||||
const float i_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
const float i_upper_limit = DIS_BORDER_SIZE + h - 1.0f;
|
||||
const float j_lower_limit = DIS_BORDER_SIZE - DIS_PATCH_SIZE + 1.0f;
|
||||
const float j_upper_limit = DIS_BORDER_SIZE + w - 1.0f;
|
||||
|
||||
for (int t = 0; t < num_inner_iter; t++)
|
||||
{
|
||||
float i_I1, j_I1, w00, w01, w10, w11;
|
||||
INIT_BILINEAR_WEIGHTS(cur_U.x, cur_U.y);
|
||||
float4 res = processPatchMeanNorm(
|
||||
I0_ptr + i * w + j, I1_ptr + (int)i_I1 * w_ext + (int)j_I1,
|
||||
I0x_ptr + i * w + j, I0y_ptr + i * w + j,
|
||||
w, w_ext, w00, w01, w10, w11,
|
||||
x_grad_sum, y_grad_sum);
|
||||
|
||||
float SSD = res.x;
|
||||
float dUx = res.y;
|
||||
float dUy = res.z;
|
||||
float dx = invH11 * dUx + invH12 * dUy;
|
||||
float dy = invH12 * dUx + invH22 * dUy;
|
||||
|
||||
cur_U -= (float2)(dx, dy);
|
||||
|
||||
if (SSD >= prev_SSD)
|
||||
break;
|
||||
prev_SSD = SSD;
|
||||
}
|
||||
|
||||
float2 vec = cur_U - U0;
|
||||
S_ptr[index] = ((dot(vec, vec)) <= (float)(DIS_PATCH_SIZE * DIS_PATCH_SIZE)) ? cur_U : U0;
|
||||
}
|
||||
#endif // DIS_BORDER_SIZE
|
||||
429
3rdparty/opencv-4.5.4/modules/video/src/opencl/optical_flow_farneback.cl
vendored
Normal file
429
3rdparty/opencv-4.5.4/modules/video/src/opencl/optical_flow_farneback.cl
vendored
Normal file
@@ -0,0 +1,429 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Sen Liu, swjtuls1987@126.com
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors as is and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
|
||||
#define tx (int)get_local_id(0)
|
||||
#define ty get_local_id(1)
|
||||
#define bx get_group_id(0)
|
||||
#define bdx (int)get_local_size(0)
|
||||
|
||||
#define BORDER_SIZE 5
|
||||
#define MAX_KSIZE_HALF 100
|
||||
|
||||
#ifndef polyN
|
||||
#define polyN 5
|
||||
#endif
|
||||
|
||||
#if USE_DOUBLE
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#define TYPE double
|
||||
#define VECTYPE double4
|
||||
#else
|
||||
#define TYPE float
|
||||
#define VECTYPE float4
|
||||
#endif
|
||||
|
||||
__kernel void polynomialExpansion(__global __const float * src, int srcStep,
|
||||
__global float * dst, int dstStep,
|
||||
const int rows, const int cols,
|
||||
__global __const float * c_g,
|
||||
__global __const float * c_xg,
|
||||
__global __const float * c_xxg,
|
||||
__local float * smem,
|
||||
const VECTYPE ig)
|
||||
{
|
||||
const int y = get_global_id(1);
|
||||
const int x = bx * (bdx - 2*polyN) + tx - polyN;
|
||||
|
||||
int xWarped;
|
||||
__local float *row = smem + tx;
|
||||
|
||||
if (y < rows && y >= 0)
|
||||
{
|
||||
xWarped = min(max(x, 0), cols - 1);
|
||||
|
||||
row[0] = src[mad24(y, srcStep, xWarped)] * c_g[0];
|
||||
row[bdx] = 0.f;
|
||||
row[2*bdx] = 0.f;
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 1; k <= polyN; ++k)
|
||||
{
|
||||
float t0 = src[mad24(max(y - k, 0), srcStep, xWarped)];
|
||||
float t1 = src[mad24(min(y + k, rows - 1), srcStep, xWarped)];
|
||||
|
||||
row[0] += c_g[k] * (t0 + t1);
|
||||
row[bdx] += c_xg[k] * (t1 - t0);
|
||||
row[2*bdx] += c_xxg[k] * (t0 + t1);
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (y < rows && y >= 0 && tx >= polyN && tx + polyN < bdx && x < cols)
|
||||
{
|
||||
TYPE b1 = c_g[0] * row[0];
|
||||
TYPE b3 = c_g[0] * row[bdx];
|
||||
TYPE b5 = c_g[0] * row[2*bdx];
|
||||
TYPE b2 = 0, b4 = 0, b6 = 0;
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 1; k <= polyN; ++k)
|
||||
{
|
||||
b1 += (row[k] + row[-k]) * c_g[k];
|
||||
b4 += (row[k] + row[-k]) * c_xxg[k];
|
||||
b2 += (row[k] - row[-k]) * c_xg[k];
|
||||
b3 += (row[k + bdx] + row[-k + bdx]) * c_g[k];
|
||||
b6 += (row[k + bdx] - row[-k + bdx]) * c_xg[k];
|
||||
b5 += (row[k + 2*bdx] + row[-k + 2*bdx]) * c_g[k];
|
||||
}
|
||||
|
||||
dst[mad24(y, dstStep, xWarped)] = (float)(b3*ig.s0);
|
||||
dst[mad24(rows + y, dstStep, xWarped)] = (float)(b2*ig.s0);
|
||||
dst[mad24(2*rows + y, dstStep, xWarped)] = (float)(b1*ig.s1 + b5*ig.s2);
|
||||
dst[mad24(3*rows + y, dstStep, xWarped)] = (float)(b1*ig.s1 + b4*ig.s2);
|
||||
dst[mad24(4*rows + y, dstStep, xWarped)] = (float)(b6*ig.s3);
|
||||
}
|
||||
}
|
||||
|
||||
inline int idx_row_low(const int y, const int last_row)
|
||||
{
|
||||
return abs(y) % (last_row + 1);
|
||||
}
|
||||
|
||||
inline int idx_row_high(const int y, const int last_row)
|
||||
{
|
||||
return abs(last_row - abs(last_row - y)) % (last_row + 1);
|
||||
}
|
||||
|
||||
inline int idx_col_low(const int x, const int last_col)
|
||||
{
|
||||
return abs(x) % (last_col + 1);
|
||||
}
|
||||
|
||||
inline int idx_col_high(const int x, const int last_col)
|
||||
{
|
||||
return abs(last_col - abs(last_col - x)) % (last_col + 1);
|
||||
}
|
||||
|
||||
inline int idx_col(const int x, const int last_col)
|
||||
{
|
||||
return idx_col_low(idx_col_high(x, last_col), last_col);
|
||||
}
|
||||
|
||||
__kernel void gaussianBlur(__global const float * src, int srcStep,
|
||||
__global float * dst, int dstStep, const int rows, const int cols,
|
||||
__global const float * c_gKer, const int ksizeHalf,
|
||||
__local float * smem)
|
||||
{
|
||||
const int y = get_global_id(1);
|
||||
const int x = get_global_id(0);
|
||||
|
||||
__local float *row = smem + ty * (bdx + 2*ksizeHalf);
|
||||
|
||||
if (y < rows)
|
||||
{
|
||||
// Vertical pass
|
||||
for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx)
|
||||
{
|
||||
int xExt = (int)(bx * bdx) + i - ksizeHalf;
|
||||
xExt = idx_col(xExt, cols - 1);
|
||||
row[i] = src[mad24(y, srcStep, xExt)] * c_gKer[0];
|
||||
for (int j = 1; j <= ksizeHalf; ++j)
|
||||
row[i] += (src[mad24(idx_row_low(y - j, rows - 1), srcStep, xExt)]
|
||||
+ src[mad24(idx_row_high(y + j, rows - 1), srcStep, xExt)]) * c_gKer[j];
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (y < rows && y >= 0 && x < cols && x >= 0)
|
||||
{
|
||||
// Horizontal pass
|
||||
row += tx + ksizeHalf;
|
||||
float res = row[0] * c_gKer[0];
|
||||
for (int i = 1; i <= ksizeHalf; ++i)
|
||||
res += (row[-i] + row[i]) * c_gKer[i];
|
||||
|
||||
dst[mad24(y, dstStep, x)] = res;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void gaussianBlur5(__global const float * src, int srcStep,
|
||||
__global float * dst, int dstStep,
|
||||
const int rows, const int cols,
|
||||
__global const float * c_gKer, const int ksizeHalf,
|
||||
__local float * smem)
|
||||
{
|
||||
const int y = get_global_id(1);
|
||||
const int x = get_global_id(0);
|
||||
|
||||
const int smw = bdx + 2*ksizeHalf; // shared memory "cols"
|
||||
__local volatile float *row = smem + 5 * ty * smw;
|
||||
|
||||
if (y < rows)
|
||||
{
|
||||
// Vertical pass
|
||||
for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx)
|
||||
{
|
||||
int xExt = (int)(bx * bdx) + i - ksizeHalf;
|
||||
xExt = idx_col(xExt, cols - 1);
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
row[k*smw + i] = src[mad24(k*rows + y, srcStep, xExt)] * c_gKer[0];
|
||||
|
||||
for (int j = 1; j <= ksizeHalf; ++j)
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
row[k*smw + i] +=
|
||||
(src[mad24(k*rows + idx_row_low(y - j, rows - 1), srcStep, xExt)] +
|
||||
src[mad24(k*rows + idx_row_high(y + j, rows - 1), srcStep, xExt)]) * c_gKer[j];
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (y < rows && y >= 0 && x < cols && x >= 0)
|
||||
{
|
||||
// Horizontal pass
|
||||
|
||||
row += tx + ksizeHalf;
|
||||
float res[5];
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
res[k] = row[k*smw] * c_gKer[0];
|
||||
|
||||
for (int i = 1; i <= ksizeHalf; ++i)
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
res[k] += (row[k*smw - i] + row[k*smw + i]) * c_gKer[i];
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
dst[mad24(k*rows + y, dstStep, x)] = res[k];
|
||||
}
|
||||
}
|
||||
__constant float c_border[BORDER_SIZE + 1] = { 0.14f, 0.14f, 0.4472f, 0.4472f, 0.4472f, 1.f };
|
||||
|
||||
__kernel void updateMatrices(__global const float * flowx, int xStep,
|
||||
__global const float * flowy, int yStep,
|
||||
const int rows, const int cols,
|
||||
__global const float * R0, int R0Step,
|
||||
__global const float * R1, int R1Step,
|
||||
__global float * M, int mStep)
|
||||
{
|
||||
const int y = get_global_id(1);
|
||||
const int x = get_global_id(0);
|
||||
|
||||
if (y < rows && y >= 0 && x < cols && x >= 0)
|
||||
{
|
||||
float dx = flowx[mad24(y, xStep, x)];
|
||||
float dy = flowy[mad24(y, yStep, x)];
|
||||
float fx = x + dx;
|
||||
float fy = y + dy;
|
||||
|
||||
int x1 = convert_int(floor(fx));
|
||||
int y1 = convert_int(floor(fy));
|
||||
fx -= x1;
|
||||
fy -= y1;
|
||||
|
||||
float r2, r3, r4, r5, r6;
|
||||
|
||||
if (x1 >= 0 && y1 >= 0 && x1 < cols - 1 && y1 < rows - 1)
|
||||
{
|
||||
float a00 = (1.f - fx) * (1.f - fy);
|
||||
float a01 = fx * (1.f - fy);
|
||||
float a10 = (1.f - fx) * fy;
|
||||
float a11 = fx * fy;
|
||||
|
||||
r2 = a00 * R1[mad24(y1, R1Step, x1)] +
|
||||
a01 * R1[mad24(y1, R1Step, x1 + 1)] +
|
||||
a10 * R1[mad24(y1 + 1, R1Step, x1)] +
|
||||
a11 * R1[mad24(y1 + 1, R1Step, x1 + 1)];
|
||||
|
||||
r3 = a00 * R1[mad24(rows + y1, R1Step, x1)] +
|
||||
a01 * R1[mad24(rows + y1, R1Step, x1 + 1)] +
|
||||
a10 * R1[mad24(rows + y1 + 1, R1Step, x1)] +
|
||||
a11 * R1[mad24(rows + y1 + 1, R1Step, x1 + 1)];
|
||||
|
||||
r4 = a00 * R1[mad24(2*rows + y1, R1Step, x1)] +
|
||||
a01 * R1[mad24(2*rows + y1, R1Step, x1 + 1)] +
|
||||
a10 * R1[mad24(2*rows + y1 + 1, R1Step, x1)] +
|
||||
a11 * R1[mad24(2*rows + y1 + 1, R1Step, x1 + 1)];
|
||||
|
||||
r5 = a00 * R1[mad24(3*rows + y1, R1Step, x1)] +
|
||||
a01 * R1[mad24(3*rows + y1, R1Step, x1 + 1)] +
|
||||
a10 * R1[mad24(3*rows + y1 + 1, R1Step, x1)] +
|
||||
a11 * R1[mad24(3*rows + y1 + 1, R1Step, x1 + 1)];
|
||||
|
||||
r6 = a00 * R1[mad24(4*rows + y1, R1Step, x1)] +
|
||||
a01 * R1[mad24(4*rows + y1, R1Step, x1 + 1)] +
|
||||
a10 * R1[mad24(4*rows + y1 + 1, R1Step, x1)] +
|
||||
a11 * R1[mad24(4*rows + y1 + 1, R1Step, x1 + 1)];
|
||||
|
||||
r4 = (R0[mad24(2*rows + y, R0Step, x)] + r4) * 0.5f;
|
||||
r5 = (R0[mad24(3*rows + y, R0Step, x)] + r5) * 0.5f;
|
||||
r6 = (R0[mad24(4*rows + y, R0Step, x)] + r6) * 0.25f;
|
||||
}
|
||||
else
|
||||
{
|
||||
r2 = r3 = 0.f;
|
||||
r4 = R0[mad24(2*rows + y, R0Step, x)];
|
||||
r5 = R0[mad24(3*rows + y, R0Step, x)];
|
||||
r6 = R0[mad24(4*rows + y, R0Step, x)] * 0.5f;
|
||||
}
|
||||
|
||||
r2 = (R0[mad24(y, R0Step, x)] - r2) * 0.5f;
|
||||
r3 = (R0[mad24(rows + y, R0Step, x)] - r3) * 0.5f;
|
||||
|
||||
r2 += r4*dy + r6*dx;
|
||||
r3 += r6*dy + r5*dx;
|
||||
|
||||
float scale =
|
||||
c_border[min(x, BORDER_SIZE)] *
|
||||
c_border[min(y, BORDER_SIZE)] *
|
||||
c_border[min(cols - x - 1, BORDER_SIZE)] *
|
||||
c_border[min(rows - y - 1, BORDER_SIZE)];
|
||||
|
||||
r2 *= scale;
|
||||
r3 *= scale;
|
||||
r4 *= scale;
|
||||
r5 *= scale;
|
||||
r6 *= scale;
|
||||
|
||||
M[mad24(y, mStep, x)] = r4*r4 + r6*r6;
|
||||
M[mad24(rows + y, mStep, x)] = (r4 + r5)*r6;
|
||||
M[mad24(2*rows + y, mStep, x)] = r5*r5 + r6*r6;
|
||||
M[mad24(3*rows + y, mStep, x)] = r4*r2 + r6*r3;
|
||||
M[mad24(4*rows + y, mStep, x)] = r6*r2 + r5*r3;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void boxFilter5(__global const float * src, int srcStep,
|
||||
__global float * dst, int dstStep,
|
||||
const int rows, const int cols,
|
||||
const int ksizeHalf,
|
||||
__local float * smem)
|
||||
{
|
||||
const int y = get_global_id(1);
|
||||
const int x = get_global_id(0);
|
||||
|
||||
const float boxAreaInv = 1.f / ((1 + 2*ksizeHalf) * (1 + 2*ksizeHalf));
|
||||
const int smw = bdx + 2*ksizeHalf; // shared memory "width"
|
||||
__local float *row = smem + 5 * ty * smw;
|
||||
|
||||
if (y < rows)
|
||||
{
|
||||
// Vertical pass
|
||||
for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx)
|
||||
{
|
||||
int xExt = (int)(bx * bdx) + i - ksizeHalf;
|
||||
xExt = min(max(xExt, 0), cols - 1);
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
row[k*smw + i] = src[mad24(k*rows + y, srcStep, xExt)];
|
||||
|
||||
for (int j = 1; j <= ksizeHalf; ++j)
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
row[k*smw + i] +=
|
||||
src[mad24(k*rows + max(y - j, 0), srcStep, xExt)] +
|
||||
src[mad24(k*rows + min(y + j, rows - 1), srcStep, xExt)];
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (y < rows && y >= 0 && x < cols && x >= 0)
|
||||
{
|
||||
// Horizontal pass
|
||||
|
||||
row += tx + ksizeHalf;
|
||||
float res[5];
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
res[k] = row[k*smw];
|
||||
|
||||
for (int i = 1; i <= ksizeHalf; ++i)
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
res[k] += row[k*smw - i] + row[k*smw + i];
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 5; ++k)
|
||||
dst[mad24(k*rows + y, dstStep, x)] = res[k] * boxAreaInv;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void updateFlow(__global const float * M, int mStep,
|
||||
__global float * flowx, int xStep,
|
||||
__global float * flowy, int yStep,
|
||||
const int rows, const int cols)
|
||||
{
|
||||
const int y = get_global_id(1);
|
||||
const int x = get_global_id(0);
|
||||
|
||||
if (y < rows && y >= 0 && x < cols && x >= 0)
|
||||
{
|
||||
float g11 = M[mad24(y, mStep, x)];
|
||||
float g12 = M[mad24(rows + y, mStep, x)];
|
||||
float g22 = M[mad24(2*rows + y, mStep, x)];
|
||||
float h1 = M[mad24(3*rows + y, mStep, x)];
|
||||
float h2 = M[mad24(4*rows + y, mStep, x)];
|
||||
|
||||
float detInv = 1.f / (g11*g22 - g12*g12 + 1e-3f);
|
||||
|
||||
flowx[mad24(y, xStep, x)] = (g11*h2 - g12*h1) * detInv;
|
||||
flowy[mad24(y, yStep, x)] = (g22*h1 - g12*h2) * detInv;
|
||||
}
|
||||
}
|
||||
558
3rdparty/opencv-4.5.4/modules/video/src/opencl/pyrlk.cl
vendored
Normal file
558
3rdparty/opencv-4.5.4/modules/video/src/opencl/pyrlk.cl
vendored
Normal file
@@ -0,0 +1,558 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Dachuan Zhao, dachuan@multicorewareinc.com
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
// Xiaopeng Fu, fuxiaopeng2222@163.com
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors as is and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#define GRIDSIZE 3
|
||||
#define LSx 8
|
||||
#define LSy 8
|
||||
// define local memory sizes
|
||||
#define LM_W (LSx*GRIDSIZE+2)
|
||||
#define LM_H (LSy*GRIDSIZE+2)
|
||||
#define BUFFER (LSx*LSy)
|
||||
#define BUFFER2 BUFFER>>1
|
||||
|
||||
#ifdef CPU
|
||||
|
||||
inline void reduce3(float val1, float val2, float val3, __local float* smem1, __local float* smem2, __local float* smem3, int tid)
|
||||
{
|
||||
smem1[tid] = val1;
|
||||
smem2[tid] = val2;
|
||||
smem3[tid] = val3;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for(int i = BUFFER2; i > 0; i >>= 1)
|
||||
{
|
||||
if(tid < i)
|
||||
{
|
||||
smem1[tid] += smem1[tid + i];
|
||||
smem2[tid] += smem2[tid + i];
|
||||
smem3[tid] += smem3[tid + i];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
inline void reduce2(float val1, float val2, __local float* smem1, __local float* smem2, int tid)
|
||||
{
|
||||
smem1[tid] = val1;
|
||||
smem2[tid] = val2;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for(int i = BUFFER2; i > 0; i >>= 1)
|
||||
{
|
||||
if(tid < i)
|
||||
{
|
||||
smem1[tid] += smem1[tid + i];
|
||||
smem2[tid] += smem2[tid + i];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
inline void reduce1(float val1, __local float* smem1, int tid)
|
||||
{
|
||||
smem1[tid] = val1;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for(int i = BUFFER2; i > 0; i >>= 1)
|
||||
{
|
||||
if(tid < i)
|
||||
{
|
||||
smem1[tid] += smem1[tid + i];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
inline void reduce3(float val1, float val2, float val3,
|
||||
__local float* smem1, __local float* smem2, __local float* smem3, int tid)
|
||||
{
|
||||
smem1[tid] = val1;
|
||||
smem2[tid] = val2;
|
||||
smem3[tid] = val3;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 32];
|
||||
smem2[tid] += smem2[tid + 32];
|
||||
smem3[tid] += smem3[tid + 32];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 16)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 16];
|
||||
smem2[tid] += smem2[tid + 16];
|
||||
smem3[tid] += smem3[tid + 16];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 8)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 8];
|
||||
smem2[tid] += smem2[tid + 8];
|
||||
smem3[tid] += smem3[tid + 8];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 4)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 4];
|
||||
smem2[tid] += smem2[tid + 4];
|
||||
smem3[tid] += smem3[tid + 4];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid == 0)
|
||||
{
|
||||
smem1[0] = (smem1[0] + smem1[1]) + (smem1[2] + smem1[3]);
|
||||
smem2[0] = (smem2[0] + smem2[1]) + (smem2[2] + smem2[3]);
|
||||
smem3[0] = (smem3[0] + smem3[1]) + (smem3[2] + smem3[3]);
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
inline void reduce2(float val1, float val2, __local float* smem1, __local float* smem2, int tid)
|
||||
{
|
||||
smem1[tid] = val1;
|
||||
smem2[tid] = val2;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 32];
|
||||
smem2[tid] += smem2[tid + 32];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 16)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 16];
|
||||
smem2[tid] += smem2[tid + 16];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 8)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 8];
|
||||
smem2[tid] += smem2[tid + 8];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 4)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 4];
|
||||
smem2[tid] += smem2[tid + 4];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid == 0)
|
||||
{
|
||||
smem1[0] = (smem1[0] + smem1[1]) + (smem1[2] + smem1[3]);
|
||||
smem2[0] = (smem2[0] + smem2[1]) + (smem2[2] + smem2[3]);
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
inline void reduce1(float val1, __local float* smem1, int tid)
|
||||
{
|
||||
smem1[tid] = val1;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 32];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 16)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 16];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 8)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 8];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid < 4)
|
||||
{
|
||||
smem1[tid] += smem1[tid + 4];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if (tid == 0)
|
||||
{
|
||||
smem1[0] = (smem1[0] + smem1[1]) + (smem1[2] + smem1[3]);
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SCALE (1.0f / (1 << 20))
|
||||
#define THRESHOLD 0.01f
|
||||
|
||||
// Image read mode
|
||||
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
|
||||
|
||||
// macro to get pixel value from local memory
|
||||
|
||||
#define VAL(_y,_x,_yy,_xx) (IPatchLocal[mad24(((_y) + (_yy)), LM_W, ((_x) + (_xx)))])
|
||||
inline void SetPatch(local float* IPatchLocal, int TileY, int TileX,
|
||||
float* Pch, float* Dx, float* Dy,
|
||||
float* A11, float* A12, float* A22, float w)
|
||||
{
|
||||
int xid=get_local_id(0);
|
||||
int yid=get_local_id(1);
|
||||
int xBase = mad24(TileX, LSx, (xid + 1));
|
||||
int yBase = mad24(TileY, LSy, (yid + 1));
|
||||
|
||||
*Pch = VAL(yBase,xBase,0,0);
|
||||
|
||||
*Dx = mad((VAL(yBase,xBase,-1,1) + VAL(yBase,xBase,+1,1) - VAL(yBase,xBase,-1,-1) - VAL(yBase,xBase,+1,-1)), 3.0f, (VAL(yBase,xBase,0,1) - VAL(yBase,xBase,0,-1)) * 10.0f) * w;
|
||||
*Dy = mad((VAL(yBase,xBase,1,-1) + VAL(yBase,xBase,1,+1) - VAL(yBase,xBase,-1,-1) - VAL(yBase,xBase,-1,+1)), 3.0f, (VAL(yBase,xBase,1,0) - VAL(yBase,xBase,-1,0)) * 10.0f) * w;
|
||||
|
||||
*A11 = mad(*Dx, *Dx, *A11);
|
||||
*A12 = mad(*Dx, *Dy, *A12);
|
||||
*A22 = mad(*Dy, *Dy, *A22);
|
||||
}
|
||||
#undef VAL
|
||||
|
||||
inline void GetPatch(image2d_t J, float x, float y,
|
||||
float* Pch, float* Dx, float* Dy,
|
||||
float* b1, float* b2)
|
||||
{
|
||||
float diff = read_imagef(J, sampler, (float2)(x,y)).x-*Pch;
|
||||
*b1 = mad(diff, *Dx, *b1);
|
||||
*b2 = mad(diff, *Dy, *b2);
|
||||
}
|
||||
|
||||
inline void GetError(image2d_t J, const float x, const float y, const float* Pch, float* errval, float w)
|
||||
{
|
||||
float diff = ((((read_imagef(J, sampler, (float2)(x,y)).x * 16384) + 256) / 512) - (((*Pch * 16384) + 256) /512)) * w;
|
||||
*errval += fabs(diff);
|
||||
}
|
||||
|
||||
|
||||
//macro to read pixel value into local memory.
|
||||
#define READI(_y,_x) IPatchLocal[mad24(mad24((_y), LSy, yid), LM_W, mad24((_x), LSx, xid))] = read_imagef(I, sampler, (float2)(mad((float)(_x), (float)LSx, Point.x + xid - 0.5f), mad((float)(_y), (float)LSy, Point.y + yid - 0.5f))).x;
|
||||
void ReadPatchIToLocalMem(image2d_t I, float2 Point, local float* IPatchLocal)
|
||||
{
|
||||
int xid=get_local_id(0);
|
||||
int yid=get_local_id(1);
|
||||
//read (3*LSx)*(3*LSy) window. each macro call read LSx*LSy pixels block
|
||||
READI(0,0);READI(0,1);READI(0,2);
|
||||
READI(1,0);READI(1,1);READI(1,2);
|
||||
READI(2,0);READI(2,1);READI(2,2);
|
||||
if(xid<2)
|
||||
{// read last 2 columns border. each macro call reads 2*LSy pixels block
|
||||
READI(0,3);
|
||||
READI(1,3);
|
||||
READI(2,3);
|
||||
}
|
||||
|
||||
if(yid<2)
|
||||
{// read last 2 row. each macro call reads LSx*2 pixels block
|
||||
READI(3,0);READI(3,1);READI(3,2);
|
||||
}
|
||||
|
||||
if(yid<2 && xid<2)
|
||||
{// read right bottom 2x2 corner. one macro call reads 2*2 pixels block
|
||||
READI(3,3);
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
#undef READI
|
||||
|
||||
__attribute__((reqd_work_group_size(LSx, LSy, 1)))
|
||||
__kernel void lkSparse(image2d_t I, image2d_t J,
|
||||
__global const float2* prevPts, __global float2* nextPts, __global uchar* status, __global float* err,
|
||||
const int level, const int rows, const int cols, int PATCH_X, int PATCH_Y, int c_winSize_x, int c_winSize_y, int c_iters, char calcErr)
|
||||
{
|
||||
__local float smem1[BUFFER];
|
||||
__local float smem2[BUFFER];
|
||||
__local float smem3[BUFFER];
|
||||
|
||||
int xid=get_local_id(0);
|
||||
int yid=get_local_id(1);
|
||||
int gid=get_group_id(0);
|
||||
int xsize=get_local_size(0);
|
||||
int ysize=get_local_size(1);
|
||||
int k;
|
||||
|
||||
#ifdef CPU
|
||||
float wx0 = 1.0f;
|
||||
float wy0 = 1.0f;
|
||||
int xBase = mad24(xsize, 2, xid);
|
||||
int yBase = mad24(ysize, 2, yid);
|
||||
float wx1 = (xBase < c_winSize_x) ? 1 : 0;
|
||||
float wy1 = (yBase < c_winSize_y) ? 1 : 0;
|
||||
#else
|
||||
#if WSX == 1
|
||||
float wx0 = 1.0f;
|
||||
int xBase = mad24(xsize, 2, xid);
|
||||
float wx1 = (xBase < c_winSize_x) ? 1 : 0;
|
||||
#else
|
||||
int xBase = mad24(xsize, 1, xid);
|
||||
float wx0 = (xBase < c_winSize_x) ? 1 : 0;
|
||||
float wx1 = 0.0f;
|
||||
#endif
|
||||
#if WSY == 1
|
||||
float wy0 = 1.0f;
|
||||
int yBase = mad24(ysize, 2, yid);
|
||||
float wy1 = (yBase < c_winSize_y) ? 1 : 0;
|
||||
#else
|
||||
int yBase = mad24(ysize, 1, yid);
|
||||
float wy0 = (yBase < c_winSize_y) ? 1 : 0;
|
||||
float wy1 = 0.0f;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
float2 c_halfWin = (float2)((c_winSize_x - 1)>>1, (c_winSize_y - 1)>>1);
|
||||
|
||||
const int tid = mad24(yid, xsize, xid);
|
||||
|
||||
float2 prevPt = prevPts[gid] / (float2)(1 << level);
|
||||
|
||||
if (prevPt.x < 0 || prevPt.x >= cols || prevPt.y < 0 || prevPt.y >= rows)
|
||||
{
|
||||
if (tid == 0 && level == 0)
|
||||
{
|
||||
status[gid] = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
prevPt -= c_halfWin;
|
||||
|
||||
// extract the patch from the first image, compute covariation matrix of derivatives
|
||||
|
||||
float A11 = 0;
|
||||
float A12 = 0;
|
||||
float A22 = 0;
|
||||
|
||||
float I_patch[GRIDSIZE][GRIDSIZE];
|
||||
float dIdx_patch[GRIDSIZE][GRIDSIZE];
|
||||
float dIdy_patch[GRIDSIZE][GRIDSIZE];
|
||||
|
||||
// local memory to read image with border to calc sobels
|
||||
local float IPatchLocal[LM_W*LM_H];
|
||||
ReadPatchIToLocalMem(I,prevPt,IPatchLocal);
|
||||
|
||||
{
|
||||
SetPatch(IPatchLocal, 0, 0,
|
||||
&I_patch[0][0], &dIdx_patch[0][0], &dIdy_patch[0][0],
|
||||
&A11, &A12, &A22,1);
|
||||
|
||||
|
||||
SetPatch(IPatchLocal, 0, 1,
|
||||
&I_patch[0][1], &dIdx_patch[0][1], &dIdy_patch[0][1],
|
||||
&A11, &A12, &A22,wx0);
|
||||
|
||||
SetPatch(IPatchLocal, 0, 2,
|
||||
&I_patch[0][2], &dIdx_patch[0][2], &dIdy_patch[0][2],
|
||||
&A11, &A12, &A22,wx1);
|
||||
}
|
||||
{
|
||||
SetPatch(IPatchLocal, 1, 0,
|
||||
&I_patch[1][0], &dIdx_patch[1][0], &dIdy_patch[1][0],
|
||||
&A11, &A12, &A22,wy0);
|
||||
|
||||
|
||||
SetPatch(IPatchLocal, 1,1,
|
||||
&I_patch[1][1], &dIdx_patch[1][1], &dIdy_patch[1][1],
|
||||
&A11, &A12, &A22,wx0*wy0);
|
||||
|
||||
SetPatch(IPatchLocal, 1,2,
|
||||
&I_patch[1][2], &dIdx_patch[1][2], &dIdy_patch[1][2],
|
||||
&A11, &A12, &A22,wx1*wy0);
|
||||
}
|
||||
{
|
||||
SetPatch(IPatchLocal, 2,0,
|
||||
&I_patch[2][0], &dIdx_patch[2][0], &dIdy_patch[2][0],
|
||||
&A11, &A12, &A22,wy1);
|
||||
|
||||
|
||||
SetPatch(IPatchLocal, 2,1,
|
||||
&I_patch[2][1], &dIdx_patch[2][1], &dIdy_patch[2][1],
|
||||
&A11, &A12, &A22,wx0*wy1);
|
||||
|
||||
SetPatch(IPatchLocal, 2,2,
|
||||
&I_patch[2][2], &dIdx_patch[2][2], &dIdy_patch[2][2],
|
||||
&A11, &A12, &A22,wx1*wy1);
|
||||
}
|
||||
|
||||
|
||||
reduce3(A11, A12, A22, smem1, smem2, smem3, tid);
|
||||
|
||||
A11 = smem1[0];
|
||||
A12 = smem2[0];
|
||||
A22 = smem3[0];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
float D = mad(A11, A22, - A12 * A12);
|
||||
|
||||
if (D < 1.192092896e-07f)
|
||||
{
|
||||
if (tid == 0 && level == 0)
|
||||
status[gid] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
A11 /= D;
|
||||
A12 /= D;
|
||||
A22 /= D;
|
||||
|
||||
prevPt = mad(nextPts[gid], 2.0f, - c_halfWin);
|
||||
|
||||
float2 offset0 = (float2)(xid + 0.5f, yid + 0.5f);
|
||||
float2 offset1 = (float2)(xsize, ysize);
|
||||
float2 loc0 = prevPt + offset0;
|
||||
float2 loc1 = loc0 + offset1;
|
||||
float2 loc2 = loc1 + offset1;
|
||||
|
||||
for (k = 0; k < c_iters; ++k)
|
||||
{
|
||||
if (prevPt.x < -c_halfWin.x || prevPt.x >= cols || prevPt.y < -c_halfWin.y || prevPt.y >= rows)
|
||||
{
|
||||
if (tid == 0 && level == 0)
|
||||
status[gid] = 0;
|
||||
break;
|
||||
}
|
||||
float b1 = 0;
|
||||
float b2 = 0;
|
||||
|
||||
{
|
||||
GetPatch(J, loc0.x, loc0.y,
|
||||
&I_patch[0][0], &dIdx_patch[0][0], &dIdy_patch[0][0],
|
||||
&b1, &b2);
|
||||
|
||||
|
||||
GetPatch(J, loc1.x, loc0.y,
|
||||
&I_patch[0][1], &dIdx_patch[0][1], &dIdy_patch[0][1],
|
||||
&b1, &b2);
|
||||
|
||||
GetPatch(J, loc2.x, loc0.y,
|
||||
&I_patch[0][2], &dIdx_patch[0][2], &dIdy_patch[0][2],
|
||||
&b1, &b2);
|
||||
}
|
||||
{
|
||||
GetPatch(J, loc0.x, loc1.y,
|
||||
&I_patch[1][0], &dIdx_patch[1][0], &dIdy_patch[1][0],
|
||||
&b1, &b2);
|
||||
|
||||
|
||||
GetPatch(J, loc1.x, loc1.y,
|
||||
&I_patch[1][1], &dIdx_patch[1][1], &dIdy_patch[1][1],
|
||||
&b1, &b2);
|
||||
|
||||
GetPatch(J, loc2.x, loc1.y,
|
||||
&I_patch[1][2], &dIdx_patch[1][2], &dIdy_patch[1][2],
|
||||
&b1, &b2);
|
||||
}
|
||||
{
|
||||
GetPatch(J, loc0.x, loc2.y,
|
||||
&I_patch[2][0], &dIdx_patch[2][0], &dIdy_patch[2][0],
|
||||
&b1, &b2);
|
||||
|
||||
|
||||
GetPatch(J, loc1.x, loc2.y,
|
||||
&I_patch[2][1], &dIdx_patch[2][1], &dIdy_patch[2][1],
|
||||
&b1, &b2);
|
||||
|
||||
GetPatch(J, loc2.x, loc2.y,
|
||||
&I_patch[2][2], &dIdx_patch[2][2], &dIdy_patch[2][2],
|
||||
&b1, &b2);
|
||||
}
|
||||
|
||||
reduce2(b1, b2, smem1, smem2, tid);
|
||||
|
||||
b1 = smem1[0];
|
||||
b2 = smem2[0];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
float2 delta;
|
||||
delta.x = mad(A12, b2, - A22 * b1) * 32.0f;
|
||||
delta.y = mad(A12, b1, - A11 * b2) * 32.0f;
|
||||
|
||||
prevPt += delta;
|
||||
loc0 += delta;
|
||||
loc1 += delta;
|
||||
loc2 += delta;
|
||||
|
||||
if (fabs(delta.x) < THRESHOLD && fabs(delta.y) < THRESHOLD)
|
||||
break;
|
||||
}
|
||||
|
||||
D = 0.0f;
|
||||
if (calcErr)
|
||||
{
|
||||
{
|
||||
GetError(J, loc0.x, loc0.y, &I_patch[0][0], &D, 1);
|
||||
GetError(J, loc1.x, loc0.y, &I_patch[0][1], &D, wx0);
|
||||
}
|
||||
{
|
||||
GetError(J, loc0.x, loc1.y, &I_patch[1][0], &D, wy0);
|
||||
GetError(J, loc1.x, loc1.y, &I_patch[1][1], &D, wx0*wy0);
|
||||
}
|
||||
if(xBase < c_winSize_x)
|
||||
{
|
||||
GetError(J, loc2.x, loc0.y, &I_patch[0][2], &D, wx1);
|
||||
GetError(J, loc2.x, loc1.y, &I_patch[1][2], &D, wx1*wy0);
|
||||
}
|
||||
if(yBase < c_winSize_y)
|
||||
{
|
||||
GetError(J, loc0.x, loc2.y, &I_patch[2][0], &D, wy1);
|
||||
GetError(J, loc1.x, loc2.y, &I_patch[2][1], &D, wx0*wy1);
|
||||
if(xBase < c_winSize_x)
|
||||
GetError(J, loc2.x, loc2.y, &I_patch[2][2], &D, wx1*wy1);
|
||||
}
|
||||
|
||||
reduce1(D, smem1, tid);
|
||||
}
|
||||
|
||||
if (tid == 0)
|
||||
{
|
||||
prevPt += c_halfWin;
|
||||
|
||||
nextPts[gid] = prevPt;
|
||||
|
||||
if (calcErr)
|
||||
err[gid] = smem1[0] / (float)(32 * c_winSize_x * c_winSize_y);
|
||||
}
|
||||
}
|
||||
1211
3rdparty/opencv-4.5.4/modules/video/src/optflowgf.cpp
vendored
Normal file
1211
3rdparty/opencv-4.5.4/modules/video/src/optflowgf.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
129
3rdparty/opencv-4.5.4/modules/video/src/optical_flow_io.cpp
vendored
Normal file
129
3rdparty/opencv-4.5.4/modules/video/src/optical_flow_io.cpp
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
#include<iostream>
|
||||
#include<fstream>
|
||||
|
||||
namespace cv {
|
||||
|
||||
const float FLOW_TAG_FLOAT = 202021.25f;
|
||||
const char *FLOW_TAG_STRING = "PIEH";
|
||||
CV_EXPORTS_W Mat readOpticalFlow( const String& path )
|
||||
{
|
||||
Mat_<Point2f> flow;
|
||||
std::ifstream file(path.c_str(), std::ios_base::binary);
|
||||
if ( !file.good() )
|
||||
return std::move(flow); // no file - return empty matrix
|
||||
|
||||
float tag;
|
||||
file.read((char*) &tag, sizeof(float));
|
||||
if ( tag != FLOW_TAG_FLOAT )
|
||||
return std::move(flow);
|
||||
|
||||
int width, height;
|
||||
|
||||
file.read((char*) &width, 4);
|
||||
file.read((char*) &height, 4);
|
||||
|
||||
flow.create(height, width);
|
||||
|
||||
for ( int i = 0; i < flow.rows; ++i )
|
||||
{
|
||||
for ( int j = 0; j < flow.cols; ++j )
|
||||
{
|
||||
Point2f u;
|
||||
file.read((char*) &u.x, sizeof(float));
|
||||
file.read((char*) &u.y, sizeof(float));
|
||||
if ( !file.good() )
|
||||
{
|
||||
flow.release();
|
||||
return std::move(flow);
|
||||
}
|
||||
|
||||
flow(i, j) = u;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
return std::move(flow);
|
||||
}
|
||||
|
||||
CV_EXPORTS_W bool writeOpticalFlow( const String& path, InputArray flow )
|
||||
{
|
||||
const int nChannels = 2;
|
||||
|
||||
Mat input = flow.getMat();
|
||||
if ( input.channels() != nChannels || input.depth() != CV_32F || path.length() == 0 )
|
||||
return false;
|
||||
|
||||
std::ofstream file(path.c_str(), std::ofstream::binary);
|
||||
if ( !file.good() )
|
||||
return false;
|
||||
|
||||
int nRows, nCols;
|
||||
|
||||
nRows = (int) input.size().height;
|
||||
nCols = (int) input.size().width;
|
||||
|
||||
const int headerSize = 12;
|
||||
char header[headerSize];
|
||||
memcpy(header, FLOW_TAG_STRING, 4);
|
||||
// size of ints is known - has been asserted in the current function
|
||||
memcpy(header + 4, reinterpret_cast<const char*>(&nCols), sizeof(nCols));
|
||||
memcpy(header + 8, reinterpret_cast<const char*>(&nRows), sizeof(nRows));
|
||||
file.write(header, headerSize);
|
||||
if ( !file.good() )
|
||||
return false;
|
||||
|
||||
int row;
|
||||
char* p;
|
||||
for ( row = 0; row < nRows; row++ )
|
||||
{
|
||||
p = input.ptr<char>(row);
|
||||
file.write(p, nCols * nChannels * sizeof(float));
|
||||
if ( !file.good() )
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
52
3rdparty/opencv-4.5.4/modules/video/src/precomp.hpp
vendored
Normal file
52
3rdparty/opencv-4.5.4/modules/video/src/precomp.hpp
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_PRECOMP_H__
|
||||
#define __OPENCV_PRECOMP_H__
|
||||
|
||||
#include "opencv2/video.hpp"
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/core/private.hpp"
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
#endif
|
||||
25
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_feature.cpp
vendored
Normal file
25
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_feature.cpp
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
TrackerFeature::~TrackerFeature()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
void TrackerFeature::compute(const std::vector<Mat>& images, Mat& response)
|
||||
{
|
||||
if (images.empty())
|
||||
return;
|
||||
|
||||
computeImpl(images, response);
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
121
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_feature_haar.impl.hpp
vendored
Normal file
121
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_feature_haar.impl.hpp
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
#include "tracking_feature.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
inline namespace internal {
|
||||
|
||||
class TrackerFeatureHAAR : public TrackerFeature
|
||||
{
|
||||
public:
|
||||
struct Params
|
||||
{
|
||||
Params();
|
||||
int numFeatures; //!< # of rects
|
||||
Size rectSize; //!< rect size
|
||||
bool isIntegral; //!< true if input images are integral, false otherwise
|
||||
};
|
||||
|
||||
TrackerFeatureHAAR(const TrackerFeatureHAAR::Params& parameters = TrackerFeatureHAAR::Params());
|
||||
|
||||
virtual ~TrackerFeatureHAAR() CV_OVERRIDE {}
|
||||
|
||||
protected:
|
||||
bool computeImpl(const std::vector<Mat>& images, Mat& response) CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
Params params;
|
||||
Ptr<CvHaarEvaluator> featureEvaluator;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters
|
||||
*/
|
||||
|
||||
TrackerFeatureHAAR::Params::Params()
|
||||
{
|
||||
numFeatures = 250;
|
||||
rectSize = Size(100, 100);
|
||||
isIntegral = false;
|
||||
}
|
||||
|
||||
TrackerFeatureHAAR::TrackerFeatureHAAR(const TrackerFeatureHAAR::Params& parameters)
|
||||
: params(parameters)
|
||||
{
|
||||
CvHaarFeatureParams haarParams;
|
||||
haarParams.numFeatures = params.numFeatures;
|
||||
haarParams.isIntegral = params.isIntegral;
|
||||
featureEvaluator = makePtr<CvHaarEvaluator>();
|
||||
featureEvaluator->init(&haarParams, 1, params.rectSize);
|
||||
}
|
||||
|
||||
class Parallel_compute : public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
Ptr<CvHaarEvaluator> featureEvaluator;
|
||||
std::vector<Mat> images;
|
||||
Mat response;
|
||||
//std::vector<CvHaarEvaluator::FeatureHaar> features;
|
||||
public:
|
||||
Parallel_compute(Ptr<CvHaarEvaluator>& fe, const std::vector<Mat>& img, Mat& resp)
|
||||
: featureEvaluator(fe)
|
||||
, images(img)
|
||||
, response(resp)
|
||||
{
|
||||
|
||||
//features = featureEvaluator->getFeatures();
|
||||
}
|
||||
|
||||
virtual void operator()(const cv::Range& r) const CV_OVERRIDE
|
||||
{
|
||||
for (int jf = r.start; jf != r.end; ++jf)
|
||||
{
|
||||
int cols = images[jf].cols;
|
||||
int rows = images[jf].rows;
|
||||
for (int j = 0; j < featureEvaluator->getNumFeatures(); j++)
|
||||
{
|
||||
float res = 0;
|
||||
featureEvaluator->getFeatures()[j].eval(images[jf], Rect(0, 0, cols, rows), &res);
|
||||
(Mat_<float>(response))(j, jf) = res;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool TrackerFeatureHAAR::computeImpl(const std::vector<Mat>& images, Mat& response)
|
||||
{
|
||||
if (images.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int numFeatures = featureEvaluator->getNumFeatures();
|
||||
|
||||
response = Mat_<float>(Size((int)images.size(), numFeatures));
|
||||
|
||||
std::vector<CvHaarEvaluator::FeatureHaar> f = featureEvaluator->getFeatures();
|
||||
//for each sample compute #n_feature -> put each feature (n Rect) in response
|
||||
parallel_for_(Range(0, (int)images.size()), Parallel_compute(featureEvaluator, images, response));
|
||||
|
||||
/*for ( size_t i = 0; i < images.size(); i++ )
|
||||
{
|
||||
int c = images[i].cols;
|
||||
int r = images[i].rows;
|
||||
for ( int j = 0; j < numFeatures; j++ )
|
||||
{
|
||||
float res = 0;
|
||||
featureEvaluator->getFeatures( j ).eval( images[i], Rect( 0, 0, c, r ), &res );
|
||||
( Mat_<float>( response ) )( j, i ) = res;
|
||||
}
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}} // namespace cv::detail::tracking::internal
|
||||
60
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_feature_set.cpp
vendored
Normal file
60
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_feature_set.cpp
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
TrackerFeatureSet::TrackerFeatureSet()
|
||||
{
|
||||
blockAddTrackerFeature = false;
|
||||
}
|
||||
|
||||
TrackerFeatureSet::~TrackerFeatureSet()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
void TrackerFeatureSet::extraction(const std::vector<Mat>& images)
|
||||
{
|
||||
blockAddTrackerFeature = true;
|
||||
|
||||
clearResponses();
|
||||
responses.resize(features.size());
|
||||
|
||||
for (size_t i = 0; i < features.size(); i++)
|
||||
{
|
||||
CV_DbgAssert(features[i]);
|
||||
features[i]->compute(images, responses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool TrackerFeatureSet::addTrackerFeature(const Ptr<TrackerFeature>& feature)
|
||||
{
|
||||
CV_Assert(!blockAddTrackerFeature);
|
||||
CV_Assert(feature);
|
||||
|
||||
features.push_back(feature);
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<Ptr<TrackerFeature>>& TrackerFeatureSet::getTrackerFeatures() const
|
||||
{
|
||||
return features;
|
||||
}
|
||||
|
||||
const std::vector<Mat>& TrackerFeatureSet::getResponses() const
|
||||
{
|
||||
return responses;
|
||||
}
|
||||
|
||||
void TrackerFeatureSet::clearResponses()
|
||||
{
|
||||
responses.clear();
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
85
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_model.cpp
vendored
Normal file
85
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_model.cpp
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "tracker_mil_model.hpp"
|
||||
|
||||
/**
|
||||
* TrackerMILModel
|
||||
*/
|
||||
|
||||
namespace cv {
|
||||
inline namespace tracking {
|
||||
namespace impl {
|
||||
|
||||
TrackerMILModel::TrackerMILModel(const Rect& boundingBox)
|
||||
{
|
||||
currentSample.clear();
|
||||
mode = MODE_POSITIVE;
|
||||
width = boundingBox.width;
|
||||
height = boundingBox.height;
|
||||
|
||||
Ptr<TrackerStateEstimatorMILBoosting::TrackerMILTargetState> initState = Ptr<TrackerStateEstimatorMILBoosting::TrackerMILTargetState>(
|
||||
new TrackerStateEstimatorMILBoosting::TrackerMILTargetState(Point2f((float)boundingBox.x, (float)boundingBox.y), boundingBox.width, boundingBox.height,
|
||||
true, Mat()));
|
||||
trajectory.push_back(initState);
|
||||
}
|
||||
|
||||
void TrackerMILModel::responseToConfidenceMap(const std::vector<Mat>& responses, ConfidenceMap& confidenceMap)
|
||||
{
|
||||
if (currentSample.empty())
|
||||
{
|
||||
CV_Error(-1, "The samples in Model estimation are empty");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < responses.size(); i++)
|
||||
{
|
||||
//for each column (one sample) there are #num_feature
|
||||
//get informations from currentSample
|
||||
for (int j = 0; j < responses.at(i).cols; j++)
|
||||
{
|
||||
|
||||
Size currentSize;
|
||||
Point currentOfs;
|
||||
currentSample.at(j).locateROI(currentSize, currentOfs);
|
||||
bool foreground = false;
|
||||
if (mode == MODE_POSITIVE || mode == MODE_ESTIMATON)
|
||||
{
|
||||
foreground = true;
|
||||
}
|
||||
else if (mode == MODE_NEGATIVE)
|
||||
{
|
||||
foreground = false;
|
||||
}
|
||||
|
||||
//get the column of the HAAR responses
|
||||
Mat singleResponse = responses.at(i).col(j);
|
||||
|
||||
//create the state
|
||||
Ptr<TrackerStateEstimatorMILBoosting::TrackerMILTargetState> currentState = Ptr<TrackerStateEstimatorMILBoosting::TrackerMILTargetState>(
|
||||
new TrackerStateEstimatorMILBoosting::TrackerMILTargetState(currentOfs, width, height, foreground, singleResponse));
|
||||
|
||||
confidenceMap.push_back(std::make_pair(currentState, 0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrackerMILModel::modelEstimationImpl(const std::vector<Mat>& responses)
|
||||
{
|
||||
responseToConfidenceMap(responses, currentConfidenceMap);
|
||||
}
|
||||
|
||||
void TrackerMILModel::modelUpdateImpl()
|
||||
{
|
||||
}
|
||||
|
||||
void TrackerMILModel::setMode(int trainingMode, const std::vector<Mat>& samples)
|
||||
{
|
||||
currentSample.clear();
|
||||
currentSample = samples;
|
||||
|
||||
mode = trainingMode;
|
||||
}
|
||||
|
||||
}}} // namespace cv::tracking::impl
|
||||
67
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_model.hpp
vendored
Normal file
67
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_model.hpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef __OPENCV_TRACKER_MIL_MODEL_HPP__
|
||||
#define __OPENCV_TRACKER_MIL_MODEL_HPP__
|
||||
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
#include "tracker_mil_state.hpp"
|
||||
|
||||
namespace cv {
|
||||
inline namespace tracking {
|
||||
namespace impl {
|
||||
|
||||
using namespace cv::detail::tracking;
|
||||
|
||||
/**
|
||||
* \brief Implementation of TrackerModel for MIL algorithm
|
||||
*/
|
||||
class TrackerMILModel : public detail::TrackerModel
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MODE_POSITIVE = 1, // mode for positive features
|
||||
MODE_NEGATIVE = 2, // mode for negative features
|
||||
MODE_ESTIMATON = 3 // mode for estimation step
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param boundingBox The first boundingBox
|
||||
*/
|
||||
TrackerMILModel(const Rect& boundingBox);
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
~TrackerMILModel() {};
|
||||
|
||||
/**
|
||||
* \brief Set the mode
|
||||
*/
|
||||
void setMode(int trainingMode, const std::vector<Mat>& samples);
|
||||
|
||||
/**
|
||||
* \brief Create the ConfidenceMap from a list of responses
|
||||
* \param responses The list of the responses
|
||||
* \param confidenceMap The output
|
||||
*/
|
||||
void responseToConfidenceMap(const std::vector<Mat>& responses, ConfidenceMap& confidenceMap);
|
||||
|
||||
protected:
|
||||
void modelEstimationImpl(const std::vector<Mat>& responses) CV_OVERRIDE;
|
||||
void modelUpdateImpl() CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
int mode;
|
||||
std::vector<Mat> currentSample;
|
||||
|
||||
int width; //initial width of the boundingBox
|
||||
int height; //initial height of the boundingBox
|
||||
};
|
||||
|
||||
}}} // namespace cv::tracking::impl
|
||||
|
||||
#endif
|
||||
159
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_state.cpp
vendored
Normal file
159
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_state.cpp
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
#include "tracker_mil_state.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
/**
|
||||
* TrackerStateEstimatorMILBoosting::TrackerMILTargetState
|
||||
*/
|
||||
TrackerStateEstimatorMILBoosting::TrackerMILTargetState::TrackerMILTargetState(const Point2f& position, int width, int height, bool foreground,
|
||||
const Mat& features)
|
||||
{
|
||||
setTargetPosition(position);
|
||||
setTargetWidth(width);
|
||||
setTargetHeight(height);
|
||||
setTargetFg(foreground);
|
||||
setFeatures(features);
|
||||
}
|
||||
|
||||
void TrackerStateEstimatorMILBoosting::TrackerMILTargetState::setTargetFg(bool foreground)
|
||||
{
|
||||
isTarget = foreground;
|
||||
}
|
||||
|
||||
void TrackerStateEstimatorMILBoosting::TrackerMILTargetState::setFeatures(const Mat& features)
|
||||
{
|
||||
targetFeatures = features;
|
||||
}
|
||||
|
||||
bool TrackerStateEstimatorMILBoosting::TrackerMILTargetState::isTargetFg() const
|
||||
{
|
||||
return isTarget;
|
||||
}
|
||||
|
||||
Mat TrackerStateEstimatorMILBoosting::TrackerMILTargetState::getFeatures() const
|
||||
{
|
||||
return targetFeatures;
|
||||
}
|
||||
|
||||
TrackerStateEstimatorMILBoosting::TrackerStateEstimatorMILBoosting(int nFeatures)
|
||||
{
|
||||
className = "BOOSTING";
|
||||
trained = false;
|
||||
numFeatures = nFeatures;
|
||||
}
|
||||
|
||||
TrackerStateEstimatorMILBoosting::~TrackerStateEstimatorMILBoosting()
|
||||
{
|
||||
}
|
||||
|
||||
void TrackerStateEstimatorMILBoosting::setCurrentConfidenceMap(ConfidenceMap& confidenceMap)
|
||||
{
|
||||
currentConfidenceMap.clear();
|
||||
currentConfidenceMap = confidenceMap;
|
||||
}
|
||||
|
||||
uint TrackerStateEstimatorMILBoosting::max_idx(const std::vector<float>& v)
|
||||
{
|
||||
const float* findPtr = &(*std::max_element(v.begin(), v.end()));
|
||||
const float* beginPtr = &(*v.begin());
|
||||
return (uint)(findPtr - beginPtr);
|
||||
}
|
||||
|
||||
Ptr<TrackerTargetState> TrackerStateEstimatorMILBoosting::estimateImpl(const std::vector<ConfidenceMap>& /*confidenceMaps*/)
|
||||
{
|
||||
//run ClfMilBoost classify in order to compute next location
|
||||
if (currentConfidenceMap.empty())
|
||||
return Ptr<TrackerTargetState>();
|
||||
|
||||
Mat positiveStates;
|
||||
Mat negativeStates;
|
||||
|
||||
prepareData(currentConfidenceMap, positiveStates, negativeStates);
|
||||
|
||||
std::vector<float> prob = boostMILModel.classify(positiveStates);
|
||||
|
||||
int bestind = max_idx(prob);
|
||||
//float resp = prob[bestind];
|
||||
|
||||
return currentConfidenceMap.at(bestind).first;
|
||||
}
|
||||
|
||||
void TrackerStateEstimatorMILBoosting::prepareData(const ConfidenceMap& confidenceMap, Mat& positive, Mat& negative)
|
||||
{
|
||||
|
||||
int posCounter = 0;
|
||||
int negCounter = 0;
|
||||
|
||||
for (size_t i = 0; i < confidenceMap.size(); i++)
|
||||
{
|
||||
Ptr<TrackerMILTargetState> currentTargetState = confidenceMap.at(i).first.staticCast<TrackerMILTargetState>();
|
||||
CV_DbgAssert(currentTargetState);
|
||||
if (currentTargetState->isTargetFg())
|
||||
posCounter++;
|
||||
else
|
||||
negCounter++;
|
||||
}
|
||||
|
||||
positive.create(posCounter, numFeatures, CV_32FC1);
|
||||
negative.create(negCounter, numFeatures, CV_32FC1);
|
||||
|
||||
//TODO change with mat fast access
|
||||
//initialize trainData (positive and negative)
|
||||
|
||||
int pc = 0;
|
||||
int nc = 0;
|
||||
for (size_t i = 0; i < confidenceMap.size(); i++)
|
||||
{
|
||||
Ptr<TrackerMILTargetState> currentTargetState = confidenceMap.at(i).first.staticCast<TrackerMILTargetState>();
|
||||
Mat stateFeatures = currentTargetState->getFeatures();
|
||||
|
||||
if (currentTargetState->isTargetFg())
|
||||
{
|
||||
for (int j = 0; j < stateFeatures.rows; j++)
|
||||
{
|
||||
//fill the positive trainData with the value of the feature j for sample i
|
||||
positive.at<float>(pc, j) = stateFeatures.at<float>(j, 0);
|
||||
}
|
||||
pc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < stateFeatures.rows; j++)
|
||||
{
|
||||
//fill the negative trainData with the value of the feature j for sample i
|
||||
negative.at<float>(nc, j) = stateFeatures.at<float>(j, 0);
|
||||
}
|
||||
nc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrackerStateEstimatorMILBoosting::updateImpl(std::vector<ConfidenceMap>& confidenceMaps)
|
||||
{
|
||||
|
||||
if (!trained)
|
||||
{
|
||||
//this is the first time that the classifier is built
|
||||
//init MIL
|
||||
boostMILModel.init();
|
||||
trained = true;
|
||||
}
|
||||
|
||||
ConfidenceMap lastConfidenceMap = confidenceMaps.back();
|
||||
Mat positiveStates;
|
||||
Mat negativeStates;
|
||||
|
||||
prepareData(lastConfidenceMap, positiveStates, negativeStates);
|
||||
//update MIL
|
||||
boostMILModel.update(positiveStates, negativeStates);
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
87
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_state.hpp
vendored
Normal file
87
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_mil_state.hpp
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_VIDEO_DETAIL_TRACKING_MIL_STATE_HPP
|
||||
#define OPENCV_VIDEO_DETAIL_TRACKING_MIL_STATE_HPP
|
||||
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
#include "tracking_online_mil.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
/** @brief TrackerStateEstimator based on Boosting
|
||||
*/
|
||||
class CV_EXPORTS TrackerStateEstimatorMILBoosting : public TrackerStateEstimator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Implementation of the target state for TrackerStateEstimatorMILBoosting
|
||||
*/
|
||||
class TrackerMILTargetState : public TrackerTargetState
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param position Top left corner of the bounding box
|
||||
* \param width Width of the bounding box
|
||||
* \param height Height of the bounding box
|
||||
* \param foreground label for target or background
|
||||
* \param features features extracted
|
||||
*/
|
||||
TrackerMILTargetState(const Point2f& position, int width, int height, bool foreground, const Mat& features);
|
||||
|
||||
~TrackerMILTargetState() {};
|
||||
|
||||
/** @brief Set label: true for target foreground, false for background
|
||||
@param foreground Label for background/foreground
|
||||
*/
|
||||
void setTargetFg(bool foreground);
|
||||
/** @brief Set the features extracted from TrackerFeatureSet
|
||||
@param features The features extracted
|
||||
*/
|
||||
void setFeatures(const Mat& features);
|
||||
/** @brief Get the label. Return true for target foreground, false for background
|
||||
*/
|
||||
bool isTargetFg() const;
|
||||
/** @brief Get the features extracted
|
||||
*/
|
||||
Mat getFeatures() const;
|
||||
|
||||
private:
|
||||
bool isTarget;
|
||||
Mat targetFeatures;
|
||||
};
|
||||
|
||||
/** @brief Constructor
|
||||
@param nFeatures Number of features for each sample
|
||||
*/
|
||||
TrackerStateEstimatorMILBoosting(int nFeatures = 250);
|
||||
~TrackerStateEstimatorMILBoosting();
|
||||
|
||||
/** @brief Set the current confidenceMap
|
||||
@param confidenceMap The current :cConfidenceMap
|
||||
*/
|
||||
void setCurrentConfidenceMap(ConfidenceMap& confidenceMap);
|
||||
|
||||
protected:
|
||||
Ptr<TrackerTargetState> estimateImpl(const std::vector<ConfidenceMap>& confidenceMaps) CV_OVERRIDE;
|
||||
void updateImpl(std::vector<ConfidenceMap>& confidenceMaps) CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
uint max_idx(const std::vector<float>& v);
|
||||
void prepareData(const ConfidenceMap& confidenceMap, Mat& positive, Mat& negative);
|
||||
|
||||
ClfMilBoost boostMILModel;
|
||||
bool trained;
|
||||
int numFeatures;
|
||||
|
||||
ConfidenceMap currentConfidenceMap;
|
||||
};
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
|
||||
#endif
|
||||
132
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_model.cpp
vendored
Normal file
132
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_model.cpp
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
TrackerModel::TrackerModel()
|
||||
{
|
||||
stateEstimator = Ptr<TrackerStateEstimator>();
|
||||
maxCMLength = 10;
|
||||
}
|
||||
|
||||
TrackerModel::~TrackerModel()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
bool TrackerModel::setTrackerStateEstimator(Ptr<TrackerStateEstimator> trackerStateEstimator)
|
||||
{
|
||||
if (stateEstimator.get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
stateEstimator = trackerStateEstimator;
|
||||
return true;
|
||||
}
|
||||
|
||||
Ptr<TrackerStateEstimator> TrackerModel::getTrackerStateEstimator() const
|
||||
{
|
||||
return stateEstimator;
|
||||
}
|
||||
|
||||
void TrackerModel::modelEstimation(const std::vector<Mat>& responses)
|
||||
{
|
||||
modelEstimationImpl(responses);
|
||||
}
|
||||
|
||||
void TrackerModel::clearCurrentConfidenceMap()
|
||||
{
|
||||
currentConfidenceMap.clear();
|
||||
}
|
||||
|
||||
void TrackerModel::modelUpdate()
|
||||
{
|
||||
modelUpdateImpl();
|
||||
|
||||
if (maxCMLength != -1 && (int)confidenceMaps.size() >= maxCMLength - 1)
|
||||
{
|
||||
int l = maxCMLength / 2;
|
||||
confidenceMaps.erase(confidenceMaps.begin(), confidenceMaps.begin() + l);
|
||||
}
|
||||
if (maxCMLength != -1 && (int)trajectory.size() >= maxCMLength - 1)
|
||||
{
|
||||
int l = maxCMLength / 2;
|
||||
trajectory.erase(trajectory.begin(), trajectory.begin() + l);
|
||||
}
|
||||
confidenceMaps.push_back(currentConfidenceMap);
|
||||
stateEstimator->update(confidenceMaps);
|
||||
|
||||
clearCurrentConfidenceMap();
|
||||
}
|
||||
|
||||
bool TrackerModel::runStateEstimator()
|
||||
{
|
||||
if (!stateEstimator)
|
||||
{
|
||||
CV_Error(-1, "Tracker state estimator is not setted");
|
||||
}
|
||||
Ptr<TrackerTargetState> targetState = stateEstimator->estimate(confidenceMaps);
|
||||
if (!targetState)
|
||||
return false;
|
||||
|
||||
setLastTargetState(targetState);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TrackerModel::setLastTargetState(const Ptr<TrackerTargetState>& lastTargetState)
|
||||
{
|
||||
trajectory.push_back(lastTargetState);
|
||||
}
|
||||
|
||||
Ptr<TrackerTargetState> TrackerModel::getLastTargetState() const
|
||||
{
|
||||
return trajectory.back();
|
||||
}
|
||||
|
||||
const std::vector<ConfidenceMap>& TrackerModel::getConfidenceMaps() const
|
||||
{
|
||||
return confidenceMaps;
|
||||
}
|
||||
|
||||
const ConfidenceMap& TrackerModel::getLastConfidenceMap() const
|
||||
{
|
||||
return confidenceMaps.back();
|
||||
}
|
||||
|
||||
Point2f TrackerTargetState::getTargetPosition() const
|
||||
{
|
||||
return targetPosition;
|
||||
}
|
||||
|
||||
void TrackerTargetState::setTargetPosition(const Point2f& position)
|
||||
{
|
||||
targetPosition = position;
|
||||
}
|
||||
|
||||
int TrackerTargetState::getTargetWidth() const
|
||||
{
|
||||
return targetWidth;
|
||||
}
|
||||
|
||||
void TrackerTargetState::setTargetWidth(int width)
|
||||
{
|
||||
targetWidth = width;
|
||||
}
|
||||
int TrackerTargetState::getTargetHeight() const
|
||||
{
|
||||
return targetHeight;
|
||||
}
|
||||
|
||||
void TrackerTargetState::setTargetHeight(int height)
|
||||
{
|
||||
targetHeight = height;
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
68
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_sampler.cpp
vendored
Normal file
68
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_sampler.cpp
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
TrackerSampler::TrackerSampler()
|
||||
{
|
||||
blockAddTrackerSampler = false;
|
||||
}
|
||||
|
||||
TrackerSampler::~TrackerSampler()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
void TrackerSampler::sampling(const Mat& image, Rect boundingBox)
|
||||
{
|
||||
clearSamples();
|
||||
|
||||
for (size_t i = 0; i < samplers.size(); i++)
|
||||
{
|
||||
CV_DbgAssert(samplers[i]);
|
||||
std::vector<Mat> current_samples;
|
||||
samplers[i]->sampling(image, boundingBox, current_samples);
|
||||
|
||||
//push in samples all current_samples
|
||||
for (size_t j = 0; j < current_samples.size(); j++)
|
||||
{
|
||||
std::vector<Mat>::iterator it = samples.end();
|
||||
samples.insert(it, current_samples.at(j));
|
||||
}
|
||||
}
|
||||
|
||||
blockAddTrackerSampler = true;
|
||||
}
|
||||
|
||||
bool TrackerSampler::addTrackerSamplerAlgorithm(const Ptr<TrackerSamplerAlgorithm>& sampler)
|
||||
{
|
||||
CV_Assert(!blockAddTrackerSampler);
|
||||
CV_Assert(sampler);
|
||||
|
||||
samplers.push_back(sampler);
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<Ptr<TrackerSamplerAlgorithm>>& TrackerSampler::getSamplers() const
|
||||
{
|
||||
return samplers;
|
||||
}
|
||||
|
||||
const std::vector<Mat>& TrackerSampler::getSamples() const
|
||||
{
|
||||
return samples;
|
||||
}
|
||||
|
||||
void TrackerSampler::clearSamples()
|
||||
{
|
||||
samples.clear();
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
124
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_sampler_algorithm.cpp
vendored
Normal file
124
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_sampler_algorithm.cpp
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
TrackerSamplerAlgorithm::~TrackerSamplerAlgorithm()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
TrackerSamplerCSC::Params::Params()
|
||||
{
|
||||
initInRad = 3;
|
||||
initMaxNegNum = 65;
|
||||
searchWinSize = 25;
|
||||
trackInPosRad = 4;
|
||||
trackMaxNegNum = 65;
|
||||
trackMaxPosNum = 100000;
|
||||
}
|
||||
|
||||
TrackerSamplerCSC::TrackerSamplerCSC(const TrackerSamplerCSC::Params& parameters)
|
||||
: params(parameters)
|
||||
{
|
||||
mode = MODE_INIT_POS;
|
||||
rng = theRNG();
|
||||
}
|
||||
|
||||
TrackerSamplerCSC::~TrackerSamplerCSC()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
bool TrackerSamplerCSC::sampling(const Mat& image, const Rect& boundingBox, std::vector<Mat>& sample)
|
||||
{
|
||||
CV_Assert(!image.empty());
|
||||
|
||||
float inrad = 0;
|
||||
float outrad = 0;
|
||||
int maxnum = 0;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_INIT_POS:
|
||||
inrad = params.initInRad;
|
||||
sample = sampleImage(image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad);
|
||||
break;
|
||||
case MODE_INIT_NEG:
|
||||
inrad = 2.0f * params.searchWinSize;
|
||||
outrad = 1.5f * params.initInRad;
|
||||
maxnum = params.initMaxNegNum;
|
||||
sample = sampleImage(image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad, outrad, maxnum);
|
||||
break;
|
||||
case MODE_TRACK_POS:
|
||||
inrad = params.trackInPosRad;
|
||||
outrad = 0;
|
||||
maxnum = params.trackMaxPosNum;
|
||||
sample = sampleImage(image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad, outrad, maxnum);
|
||||
break;
|
||||
case MODE_TRACK_NEG:
|
||||
inrad = 1.5f * params.searchWinSize;
|
||||
outrad = params.trackInPosRad + 5;
|
||||
maxnum = params.trackMaxNegNum;
|
||||
sample = sampleImage(image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad, outrad, maxnum);
|
||||
break;
|
||||
case MODE_DETECT:
|
||||
inrad = params.searchWinSize;
|
||||
sample = sampleImage(image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad);
|
||||
break;
|
||||
default:
|
||||
inrad = params.initInRad;
|
||||
sample = sampleImage(image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TrackerSamplerCSC::setMode(int samplingMode)
|
||||
{
|
||||
mode = samplingMode;
|
||||
}
|
||||
|
||||
std::vector<Mat> TrackerSamplerCSC::sampleImage(const Mat& img, int x, int y, int w, int h, float inrad, float outrad, int maxnum)
|
||||
{
|
||||
int rowsz = img.rows - h - 1;
|
||||
int colsz = img.cols - w - 1;
|
||||
float inradsq = inrad * inrad;
|
||||
float outradsq = outrad * outrad;
|
||||
int dist;
|
||||
|
||||
uint minrow = max(0, (int)y - (int)inrad);
|
||||
uint maxrow = min((int)rowsz - 1, (int)y + (int)inrad);
|
||||
uint mincol = max(0, (int)x - (int)inrad);
|
||||
uint maxcol = min((int)colsz - 1, (int)x + (int)inrad);
|
||||
|
||||
//fprintf(stderr,"inrad=%f minrow=%d maxrow=%d mincol=%d maxcol=%d\n",inrad,minrow,maxrow,mincol,maxcol);
|
||||
|
||||
std::vector<Mat> samples;
|
||||
samples.resize((maxrow - minrow + 1) * (maxcol - mincol + 1));
|
||||
int i = 0;
|
||||
|
||||
float prob = ((float)(maxnum)) / samples.size();
|
||||
|
||||
for (int r = minrow; r <= int(maxrow); r++)
|
||||
for (int c = mincol; c <= int(maxcol); c++)
|
||||
{
|
||||
dist = (y - r) * (y - r) + (x - c) * (x - c);
|
||||
if (float(rng.uniform(0.f, 1.f)) < prob && dist < inradsq && dist >= outradsq)
|
||||
{
|
||||
samples[i] = img(Rect(c, r, w, h));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
samples.resize(min(i, maxnum));
|
||||
return samples;
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
37
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_state_estimator.cpp
vendored
Normal file
37
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracker_state_estimator.cpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
TrackerStateEstimator::~TrackerStateEstimator()
|
||||
{
|
||||
}
|
||||
|
||||
Ptr<TrackerTargetState> TrackerStateEstimator::estimate(const std::vector<ConfidenceMap>& confidenceMaps)
|
||||
{
|
||||
if (confidenceMaps.empty())
|
||||
return Ptr<TrackerTargetState>();
|
||||
|
||||
return estimateImpl(confidenceMaps);
|
||||
}
|
||||
|
||||
void TrackerStateEstimator::update(std::vector<ConfidenceMap>& confidenceMaps)
|
||||
{
|
||||
if (confidenceMaps.empty())
|
||||
return;
|
||||
|
||||
return updateImpl(confidenceMaps);
|
||||
}
|
||||
|
||||
String TrackerStateEstimator::getClassName() const
|
||||
{
|
||||
return className;
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
582
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_feature.cpp
vendored
Normal file
582
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_feature.cpp
vendored
Normal file
@@ -0,0 +1,582 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "opencv2/video/detail/tracking.detail.hpp"
|
||||
#include "tracking_feature.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
/*
|
||||
* TODO This implementation is based on apps/traincascade/
|
||||
* TODO Changed CvHaarEvaluator based on ADABOOSTING implementation (Grabner et al.)
|
||||
*/
|
||||
|
||||
CvParams::CvParams()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
//---------------------------- FeatureParams --------------------------------------
|
||||
|
||||
CvFeatureParams::CvFeatureParams()
|
||||
: maxCatCount(0)
|
||||
, featSize(1)
|
||||
, numFeatures(1)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
//------------------------------------- FeatureEvaluator ---------------------------------------
|
||||
|
||||
void CvFeatureEvaluator::init(const CvFeatureParams* _featureParams, int _maxSampleCount, Size _winSize)
|
||||
{
|
||||
CV_Assert(_featureParams);
|
||||
CV_Assert(_maxSampleCount > 0);
|
||||
featureParams = (CvFeatureParams*)_featureParams;
|
||||
winSize = _winSize;
|
||||
numFeatures = _featureParams->numFeatures;
|
||||
cls.create((int)_maxSampleCount, 1, CV_32FC1);
|
||||
generateFeatures();
|
||||
}
|
||||
|
||||
void CvFeatureEvaluator::setImage(const Mat& img, uchar clsLabel, int idx)
|
||||
{
|
||||
winSize.width = img.cols;
|
||||
winSize.height = img.rows;
|
||||
//CV_Assert( img.cols == winSize.width );
|
||||
//CV_Assert( img.rows == winSize.height );
|
||||
CV_Assert(idx < cls.rows);
|
||||
cls.ptr<float>(idx)[0] = clsLabel;
|
||||
}
|
||||
|
||||
CvHaarFeatureParams::CvHaarFeatureParams()
|
||||
{
|
||||
isIntegral = false;
|
||||
}
|
||||
|
||||
//--------------------- HaarFeatureEvaluator ----------------
|
||||
|
||||
void CvHaarEvaluator::init(const CvFeatureParams* _featureParams, int /*_maxSampleCount*/, Size _winSize)
|
||||
{
|
||||
CV_Assert(_featureParams);
|
||||
int cols = (_winSize.width + 1) * (_winSize.height + 1);
|
||||
sum.create((int)1, cols, CV_32SC1);
|
||||
isIntegral = ((CvHaarFeatureParams*)_featureParams)->isIntegral;
|
||||
CvFeatureEvaluator::init(_featureParams, 1, _winSize);
|
||||
}
|
||||
|
||||
void CvHaarEvaluator::setImage(const Mat& img, uchar /*clsLabel*/, int /*idx*/)
|
||||
{
|
||||
CV_DbgAssert(!sum.empty());
|
||||
|
||||
winSize.width = img.cols;
|
||||
winSize.height = img.rows;
|
||||
|
||||
CvFeatureEvaluator::setImage(img, 1, 0);
|
||||
if (!isIntegral)
|
||||
{
|
||||
std::vector<Mat_<float>> ii_imgs;
|
||||
compute_integral(img, ii_imgs);
|
||||
_ii_img = ii_imgs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
_ii_img = img;
|
||||
}
|
||||
}
|
||||
|
||||
void CvHaarEvaluator::generateFeatures()
|
||||
{
|
||||
generateFeatures(featureParams->numFeatures);
|
||||
}
|
||||
|
||||
void CvHaarEvaluator::generateFeatures(int nFeatures)
|
||||
{
|
||||
for (int i = 0; i < nFeatures; i++)
|
||||
{
|
||||
CvHaarEvaluator::FeatureHaar feature(Size(winSize.width, winSize.height));
|
||||
features.push_back(feature);
|
||||
}
|
||||
}
|
||||
|
||||
#define INITSIGMA(numAreas) (static_cast<float>(sqrt(256.0f * 256.0f / 12.0f * (numAreas))));
|
||||
|
||||
CvHaarEvaluator::FeatureHaar::FeatureHaar(Size patchSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
generateRandomFeature(patchSize);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// FIXIT
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void CvHaarEvaluator::FeatureHaar::generateRandomFeature(Size patchSize)
|
||||
{
|
||||
cv::Point2i position;
|
||||
Size baseDim;
|
||||
Size sizeFactor;
|
||||
int area;
|
||||
|
||||
CV_Assert(!patchSize.empty());
|
||||
|
||||
//Size minSize = Size( 3, 3 );
|
||||
int minArea = 9;
|
||||
|
||||
bool valid = false;
|
||||
while (!valid)
|
||||
{
|
||||
//choose position and scale
|
||||
position.y = rand() % (patchSize.height);
|
||||
position.x = rand() % (patchSize.width);
|
||||
|
||||
baseDim.width = (int)((1 - sqrt(1 - (float)rand() * (float)(1.0 / RAND_MAX))) * patchSize.width);
|
||||
baseDim.height = (int)((1 - sqrt(1 - (float)rand() * (float)(1.0 / RAND_MAX))) * patchSize.height);
|
||||
|
||||
//select types
|
||||
//float probType[11] = {0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0909f, 0.0950f};
|
||||
float probType[11] = { 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
float prob = (float)rand() * (float)(1.0 / RAND_MAX);
|
||||
|
||||
if (prob < probType[0])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 2;
|
||||
sizeFactor.width = 1;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 1;
|
||||
m_numAreas = 2;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x;
|
||||
m_areas[1].y = position.y + baseDim.height;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 1;
|
||||
sizeFactor.width = 2;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 2;
|
||||
m_numAreas = 2;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 4;
|
||||
sizeFactor.width = 1;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 3;
|
||||
m_numAreas = 3;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -2;
|
||||
m_weights[2] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x;
|
||||
m_areas[1].y = position.y + baseDim.height;
|
||||
m_areas[1].height = 2 * baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_areas[2].y = position.y + 3 * baseDim.height;
|
||||
m_areas[2].x = position.x;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2] + probType[3])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 1;
|
||||
sizeFactor.width = 4;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 3;
|
||||
m_numAreas = 3;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -2;
|
||||
m_weights[2] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = 2 * baseDim.width;
|
||||
m_areas[2].y = position.y;
|
||||
m_areas[2].x = position.x + 3 * baseDim.width;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2] + probType[3] + probType[4])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 2;
|
||||
sizeFactor.width = 2;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 5;
|
||||
m_numAreas = 4;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -1;
|
||||
m_weights[2] = -1;
|
||||
m_weights[3] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_areas[2].y = position.y + baseDim.height;
|
||||
m_areas[2].x = position.x;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_areas[3].y = position.y + baseDim.height;
|
||||
m_areas[3].x = position.x + baseDim.width;
|
||||
m_areas[3].height = baseDim.height;
|
||||
m_areas[3].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2] + probType[3] + probType[4] + probType[5])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 3;
|
||||
sizeFactor.width = 3;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 6;
|
||||
m_numAreas = 2;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -9;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = 3 * baseDim.height;
|
||||
m_areas[0].width = 3 * baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y + baseDim.height;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_initMean = -8 * 128;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2] + probType[3] + probType[4] + probType[5] + probType[6])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 3;
|
||||
sizeFactor.width = 1;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 7;
|
||||
m_numAreas = 3;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -2;
|
||||
m_weights[2] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x;
|
||||
m_areas[1].y = position.y + baseDim.height;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_areas[2].y = position.y + baseDim.height * 2;
|
||||
m_areas[2].x = position.x;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2] + probType[3] + probType[4] + probType[5] + probType[6] + probType[7])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 1;
|
||||
sizeFactor.width = 3;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 8;
|
||||
m_numAreas = 3;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -2;
|
||||
m_weights[2] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_areas[2].y = position.y;
|
||||
m_areas[2].x = position.x + 2 * baseDim.width;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob < probType[0] + probType[1] + probType[2] + probType[3] + probType[4] + probType[5] + probType[6] + probType[7] + probType[8])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 3;
|
||||
sizeFactor.width = 3;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 9;
|
||||
m_numAreas = 2;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -2;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = 3 * baseDim.height;
|
||||
m_areas[0].width = 3 * baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y + baseDim.height;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_initMean = 0;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob
|
||||
< probType[0] + probType[1] + probType[2] + probType[3] + probType[4] + probType[5] + probType[6] + probType[7] + probType[8] + probType[9])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 3;
|
||||
sizeFactor.width = 1;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 10;
|
||||
m_numAreas = 3;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -1;
|
||||
m_weights[2] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x;
|
||||
m_areas[1].y = position.y + baseDim.height;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_areas[2].y = position.y + baseDim.height * 2;
|
||||
m_areas[2].x = position.x;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_initMean = 128;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else if (prob
|
||||
< probType[0] + probType[1] + probType[2] + probType[3] + probType[4] + probType[5] + probType[6] + probType[7] + probType[8] + probType[9]
|
||||
+ probType[10])
|
||||
{
|
||||
//check if feature is valid
|
||||
sizeFactor.height = 1;
|
||||
sizeFactor.width = 3;
|
||||
if (position.y + baseDim.height * sizeFactor.height >= patchSize.height || position.x + baseDim.width * sizeFactor.width >= patchSize.width)
|
||||
continue;
|
||||
area = baseDim.height * sizeFactor.height * baseDim.width * sizeFactor.width;
|
||||
if (area < minArea)
|
||||
continue;
|
||||
|
||||
m_type = 11;
|
||||
m_numAreas = 3;
|
||||
m_weights.resize(m_numAreas);
|
||||
m_weights[0] = 1;
|
||||
m_weights[1] = -1;
|
||||
m_weights[2] = 1;
|
||||
m_areas.resize(m_numAreas);
|
||||
m_areas[0].x = position.x;
|
||||
m_areas[0].y = position.y;
|
||||
m_areas[0].height = baseDim.height;
|
||||
m_areas[0].width = baseDim.width;
|
||||
m_areas[1].x = position.x + baseDim.width;
|
||||
m_areas[1].y = position.y;
|
||||
m_areas[1].height = baseDim.height;
|
||||
m_areas[1].width = baseDim.width;
|
||||
m_areas[2].y = position.y;
|
||||
m_areas[2].x = position.x + 2 * baseDim.width;
|
||||
m_areas[2].height = baseDim.height;
|
||||
m_areas[2].width = baseDim.width;
|
||||
m_initMean = 128;
|
||||
m_initSigma = INITSIGMA(m_numAreas);
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsAssert, "");
|
||||
}
|
||||
|
||||
m_initSize = patchSize;
|
||||
m_curSize = m_initSize;
|
||||
m_scaleFactorWidth = m_scaleFactorHeight = 1.0f;
|
||||
m_scaleAreas.resize(m_numAreas);
|
||||
m_scaleWeights.resize(m_numAreas);
|
||||
for (int curArea = 0; curArea < m_numAreas; curArea++)
|
||||
{
|
||||
m_scaleAreas[curArea] = m_areas[curArea];
|
||||
m_scaleWeights[curArea] = (float)m_weights[curArea] / (float)(m_areas[curArea].width * m_areas[curArea].height);
|
||||
}
|
||||
}
|
||||
|
||||
bool CvHaarEvaluator::FeatureHaar::eval(const Mat& image, Rect /*ROI*/, float* result) const
|
||||
{
|
||||
|
||||
*result = 0.0f;
|
||||
|
||||
for (int curArea = 0; curArea < m_numAreas; curArea++)
|
||||
{
|
||||
*result += (float)getSum(image, Rect(m_areas[curArea].x, m_areas[curArea].y, m_areas[curArea].width, m_areas[curArea].height))
|
||||
* m_scaleWeights[curArea];
|
||||
}
|
||||
|
||||
/*
|
||||
if( image->getUseVariance() )
|
||||
{
|
||||
float variance = (float) image->getVariance( ROI );
|
||||
*result /= variance;
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float CvHaarEvaluator::FeatureHaar::getSum(const Mat& image, Rect imageROI) const
|
||||
{
|
||||
// left upper Origin
|
||||
int OriginX = imageROI.x;
|
||||
int OriginY = imageROI.y;
|
||||
|
||||
// Check and fix width and height
|
||||
int Width = imageROI.width;
|
||||
int Height = imageROI.height;
|
||||
|
||||
if (OriginX + Width >= image.cols - 1)
|
||||
Width = (image.cols - 1) - OriginX;
|
||||
if (OriginY + Height >= image.rows - 1)
|
||||
Height = (image.rows - 1) - OriginY;
|
||||
|
||||
float value = 0;
|
||||
int depth = image.depth();
|
||||
|
||||
if (depth == CV_8U || depth == CV_32S)
|
||||
value = static_cast<float>(image.at<int>(OriginY + Height, OriginX + Width) + image.at<int>(OriginY, OriginX) - image.at<int>(OriginY, OriginX + Width)
|
||||
- image.at<int>(OriginY + Height, OriginX));
|
||||
else if (depth == CV_64F)
|
||||
value = static_cast<float>(image.at<double>(OriginY + Height, OriginX + Width) + image.at<double>(OriginY, OriginX)
|
||||
- image.at<double>(OriginY, OriginX + Width) - image.at<double>(OriginY + Height, OriginX));
|
||||
else if (depth == CV_32F)
|
||||
value = static_cast<float>(image.at<float>(OriginY + Height, OriginX + Width) + image.at<float>(OriginY, OriginX) - image.at<float>(OriginY, OriginX + Width)
|
||||
- image.at<float>(OriginY + Height, OriginX));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
168
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_feature.hpp
vendored
Normal file
168
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_feature.hpp
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_VIDEO_DETAIL_TRACKING_FEATURE_HPP
|
||||
#define OPENCV_VIDEO_DETAIL_TRACKING_FEATURE_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
/*
|
||||
* TODO This implementation is based on apps/traincascade/
|
||||
* TODO Changed CvHaarEvaluator based on ADABOOSTING implementation (Grabner et al.)
|
||||
*/
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
//! @addtogroup tracking_detail
|
||||
//! @{
|
||||
|
||||
inline namespace feature {
|
||||
|
||||
class CvParams
|
||||
{
|
||||
public:
|
||||
CvParams();
|
||||
virtual ~CvParams()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class CvFeatureParams : public CvParams
|
||||
{
|
||||
public:
|
||||
enum FeatureType
|
||||
{
|
||||
HAAR = 0,
|
||||
LBP = 1,
|
||||
HOG = 2
|
||||
};
|
||||
|
||||
CvFeatureParams();
|
||||
static Ptr<CvFeatureParams> create(CvFeatureParams::FeatureType featureType);
|
||||
int maxCatCount; // 0 in case of numerical features
|
||||
int featSize; // 1 in case of simple features (HAAR, LBP) and N_BINS(9)*N_CELLS(4) in case of Dalal's HOG features
|
||||
int numFeatures;
|
||||
};
|
||||
|
||||
class CvFeatureEvaluator
|
||||
{
|
||||
public:
|
||||
virtual ~CvFeatureEvaluator()
|
||||
{
|
||||
}
|
||||
virtual void init(const CvFeatureParams* _featureParams, int _maxSampleCount, Size _winSize);
|
||||
virtual void setImage(const Mat& img, uchar clsLabel, int idx);
|
||||
static Ptr<CvFeatureEvaluator> create(CvFeatureParams::FeatureType type);
|
||||
|
||||
int getNumFeatures() const
|
||||
{
|
||||
return numFeatures;
|
||||
}
|
||||
int getMaxCatCount() const
|
||||
{
|
||||
return featureParams->maxCatCount;
|
||||
}
|
||||
int getFeatureSize() const
|
||||
{
|
||||
return featureParams->featSize;
|
||||
}
|
||||
const Mat& getCls() const
|
||||
{
|
||||
return cls;
|
||||
}
|
||||
float getCls(int si) const
|
||||
{
|
||||
return cls.at<float>(si, 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void generateFeatures() = 0;
|
||||
|
||||
int npos, nneg;
|
||||
int numFeatures;
|
||||
Size winSize;
|
||||
CvFeatureParams* featureParams;
|
||||
Mat cls;
|
||||
};
|
||||
|
||||
class CvHaarFeatureParams : public CvFeatureParams
|
||||
{
|
||||
public:
|
||||
CvHaarFeatureParams();
|
||||
bool isIntegral;
|
||||
};
|
||||
|
||||
class CvHaarEvaluator : public CvFeatureEvaluator
|
||||
{
|
||||
public:
|
||||
class FeatureHaar
|
||||
{
|
||||
|
||||
public:
|
||||
FeatureHaar(Size patchSize);
|
||||
bool eval(const Mat& image, Rect ROI, float* result) const;
|
||||
inline int getNumAreas() const { return m_numAreas; }
|
||||
inline const std::vector<float>& getWeights() const { return m_weights; }
|
||||
inline const std::vector<Rect>& getAreas() const { return m_areas; }
|
||||
|
||||
private:
|
||||
int m_type;
|
||||
int m_numAreas;
|
||||
std::vector<float> m_weights;
|
||||
float m_initMean;
|
||||
float m_initSigma;
|
||||
void generateRandomFeature(Size imageSize);
|
||||
float getSum(const Mat& image, Rect imgROI) const;
|
||||
std::vector<Rect> m_areas; // areas within the patch over which to compute the feature
|
||||
cv::Size m_initSize; // size of the patch used during training
|
||||
cv::Size m_curSize; // size of the patches currently under investigation
|
||||
float m_scaleFactorHeight; // scaling factor in vertical direction
|
||||
float m_scaleFactorWidth; // scaling factor in horizontal direction
|
||||
std::vector<Rect> m_scaleAreas; // areas after scaling
|
||||
std::vector<float> m_scaleWeights; // weights after scaling
|
||||
};
|
||||
|
||||
virtual void init(const CvFeatureParams* _featureParams, int _maxSampleCount, Size _winSize) CV_OVERRIDE;
|
||||
virtual void setImage(const Mat& img, uchar clsLabel = 0, int idx = 1) CV_OVERRIDE;
|
||||
inline const std::vector<CvHaarEvaluator::FeatureHaar>& getFeatures() const { return features; }
|
||||
inline CvHaarEvaluator::FeatureHaar& getFeatures(int idx)
|
||||
{
|
||||
return features[idx];
|
||||
}
|
||||
inline void setWinSize(Size patchSize) { winSize = patchSize; }
|
||||
inline Size getWinSize() const { return winSize; }
|
||||
virtual void generateFeatures() CV_OVERRIDE;
|
||||
|
||||
/**
|
||||
* \brief Overload the original generateFeatures in order to limit the number of the features
|
||||
* @param numFeatures Number of the features
|
||||
*/
|
||||
virtual void generateFeatures(int numFeatures);
|
||||
|
||||
protected:
|
||||
bool isIntegral;
|
||||
|
||||
/* TODO Added from MIL implementation */
|
||||
Mat _ii_img;
|
||||
void compute_integral(const cv::Mat& img, std::vector<cv::Mat_<float>>& ii_imgs)
|
||||
{
|
||||
Mat ii_img;
|
||||
integral(img, ii_img, CV_32F);
|
||||
split(ii_img, ii_imgs);
|
||||
}
|
||||
|
||||
std::vector<FeatureHaar> features;
|
||||
Mat sum; /* sum images (each row represents image) */
|
||||
};
|
||||
|
||||
} // namespace feature
|
||||
|
||||
//! @}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
|
||||
#endif
|
||||
356
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_online_mil.cpp
vendored
Normal file
356
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_online_mil.cpp
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "tracking_online_mil.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
#define sign(s) ((s > 0) ? 1 : ((s < 0) ? -1 : 0))
|
||||
|
||||
template <class T>
|
||||
class SortableElementRev
|
||||
{
|
||||
public:
|
||||
T _val;
|
||||
int _ind;
|
||||
SortableElementRev()
|
||||
: _val(), _ind(0)
|
||||
{
|
||||
}
|
||||
SortableElementRev(T val, int ind)
|
||||
{
|
||||
_val = val;
|
||||
_ind = ind;
|
||||
}
|
||||
bool operator<(SortableElementRev<T>& b)
|
||||
{
|
||||
return (_val < b._val);
|
||||
};
|
||||
};
|
||||
|
||||
static bool CompareSortableElementRev(const SortableElementRev<float>& i, const SortableElementRev<float>& j)
|
||||
{
|
||||
return i._val < j._val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sort_order_des(std::vector<T>& v, std::vector<int>& order)
|
||||
{
|
||||
uint n = (uint)v.size();
|
||||
std::vector<SortableElementRev<T>> v2;
|
||||
v2.resize(n);
|
||||
order.clear();
|
||||
order.resize(n);
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
v2[i]._ind = i;
|
||||
v2[i]._val = v[i];
|
||||
}
|
||||
//std::sort( v2.begin(), v2.end() );
|
||||
std::sort(v2.begin(), v2.end(), CompareSortableElementRev);
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
order[i] = v2[i]._ind;
|
||||
v[i] = v2[i]._val;
|
||||
}
|
||||
};
|
||||
|
||||
//implementations for strong classifier
|
||||
|
||||
ClfMilBoost::Params::Params()
|
||||
{
|
||||
_numSel = 50;
|
||||
_numFeat = 250;
|
||||
_lRate = 0.85f;
|
||||
}
|
||||
|
||||
ClfMilBoost::ClfMilBoost()
|
||||
: _numsamples(0)
|
||||
, _counter(0)
|
||||
{
|
||||
_myParams = ClfMilBoost::Params();
|
||||
_numsamples = 0;
|
||||
}
|
||||
|
||||
ClfMilBoost::~ClfMilBoost()
|
||||
{
|
||||
_selectors.clear();
|
||||
for (size_t i = 0; i < _weakclf.size(); i++)
|
||||
delete _weakclf.at(i);
|
||||
}
|
||||
|
||||
void ClfMilBoost::init(const ClfMilBoost::Params& parameters)
|
||||
{
|
||||
_myParams = parameters;
|
||||
_numsamples = 0;
|
||||
|
||||
//_ftrs = Ftr::generate( _myParams->_ftrParams, _myParams->_numFeat );
|
||||
// if( params->_storeFtrHistory )
|
||||
// Ftr::toViz( _ftrs, "haarftrs" );
|
||||
_weakclf.resize(_myParams._numFeat);
|
||||
for (int k = 0; k < _myParams._numFeat; k++)
|
||||
{
|
||||
_weakclf[k] = new ClfOnlineStump(k);
|
||||
_weakclf[k]->_lRate = _myParams._lRate;
|
||||
}
|
||||
_counter = 0;
|
||||
}
|
||||
|
||||
void ClfMilBoost::update(const Mat& posx, const Mat& negx)
|
||||
{
|
||||
int numneg = negx.rows;
|
||||
int numpos = posx.rows;
|
||||
|
||||
// compute ftrs
|
||||
//if( !posx.ftrsComputed() )
|
||||
// Ftr::compute( posx, _ftrs );
|
||||
//if( !negx.ftrsComputed() )
|
||||
// Ftr::compute( negx, _ftrs );
|
||||
|
||||
// initialize H
|
||||
static std::vector<float> Hpos, Hneg;
|
||||
Hpos.clear();
|
||||
Hneg.clear();
|
||||
Hpos.resize(posx.rows, 0.0f), Hneg.resize(negx.rows, 0.0f);
|
||||
|
||||
_selectors.clear();
|
||||
std::vector<float> posw(posx.rows), negw(negx.rows);
|
||||
std::vector<std::vector<float>> pospred(_weakclf.size()), negpred(_weakclf.size());
|
||||
|
||||
// train all weak classifiers without weights
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int m = 0; m < _myParams._numFeat; m++)
|
||||
{
|
||||
_weakclf[m]->update(posx, negx);
|
||||
pospred[m] = _weakclf[m]->classifySetF(posx);
|
||||
negpred[m] = _weakclf[m]->classifySetF(negx);
|
||||
}
|
||||
|
||||
// pick the best features
|
||||
for (int s = 0; s < _myParams._numSel; s++)
|
||||
{
|
||||
|
||||
// compute errors/likl for all weak clfs
|
||||
std::vector<float> poslikl(_weakclf.size(), 1.0f), neglikl(_weakclf.size()), likl(_weakclf.size());
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int w = 0; w < (int)_weakclf.size(); w++)
|
||||
{
|
||||
float lll = 1.0f;
|
||||
for (int j = 0; j < numpos; j++)
|
||||
lll *= (1 - sigmoid(Hpos[j] + pospred[w][j]));
|
||||
poslikl[w] = (float)-log(1 - lll + 1e-5);
|
||||
|
||||
lll = 0.0f;
|
||||
for (int j = 0; j < numneg; j++)
|
||||
lll += (float)-log(1e-5f + 1 - sigmoid(Hneg[j] + negpred[w][j]));
|
||||
neglikl[w] = lll;
|
||||
|
||||
likl[w] = poslikl[w] / numpos + neglikl[w] / numneg;
|
||||
}
|
||||
|
||||
// pick best weak clf
|
||||
std::vector<int> order;
|
||||
sort_order_des(likl, order);
|
||||
|
||||
// find best weakclf that isn't already included
|
||||
for (uint k = 0; k < order.size(); k++)
|
||||
if (std::count(_selectors.begin(), _selectors.end(), order[k]) == 0)
|
||||
{
|
||||
_selectors.push_back(order[k]);
|
||||
break;
|
||||
}
|
||||
|
||||
// update H = H + h_m
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int k = 0; k < posx.rows; k++)
|
||||
Hpos[k] += pospred[_selectors[s]][k];
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int k = 0; k < negx.rows; k++)
|
||||
Hneg[k] += negpred[_selectors[s]][k];
|
||||
}
|
||||
|
||||
//if( _myParams->_storeFtrHistory )
|
||||
//for ( uint j = 0; j < _selectors.size(); j++ )
|
||||
// _ftrHist( _selectors[j], _counter ) = 1.0f / ( j + 1 );
|
||||
|
||||
_counter++;
|
||||
/* */
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<float> ClfMilBoost::classify(const Mat& x, bool logR)
|
||||
{
|
||||
int numsamples = x.rows;
|
||||
std::vector<float> res(numsamples);
|
||||
std::vector<float> tr;
|
||||
|
||||
for (uint w = 0; w < _selectors.size(); w++)
|
||||
{
|
||||
tr = _weakclf[_selectors[w]]->classifySetF(x);
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int j = 0; j < numsamples; j++)
|
||||
{
|
||||
res[j] += tr[j];
|
||||
}
|
||||
}
|
||||
|
||||
// return probabilities or log odds ratio
|
||||
if (!logR)
|
||||
{
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int j = 0; j < (int)res.size(); j++)
|
||||
{
|
||||
res[j] = sigmoid(res[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//implementations for weak classifier
|
||||
|
||||
ClfOnlineStump::ClfOnlineStump()
|
||||
: _mu0(0), _mu1(0), _sig0(0), _sig1(0)
|
||||
, _q(0)
|
||||
, _s(0)
|
||||
, _log_n1(0), _log_n0(0)
|
||||
, _e1(0), _e0(0)
|
||||
, _lRate(0)
|
||||
{
|
||||
_trained = false;
|
||||
_ind = -1;
|
||||
init();
|
||||
}
|
||||
|
||||
ClfOnlineStump::ClfOnlineStump(int ind)
|
||||
: _mu0(0), _mu1(0), _sig0(0), _sig1(0)
|
||||
, _q(0)
|
||||
, _s(0)
|
||||
, _log_n1(0), _log_n0(0)
|
||||
, _e1(0), _e0(0)
|
||||
, _lRate(0)
|
||||
{
|
||||
_trained = false;
|
||||
_ind = ind;
|
||||
init();
|
||||
}
|
||||
void ClfOnlineStump::init()
|
||||
{
|
||||
_mu0 = 0;
|
||||
_mu1 = 0;
|
||||
_sig0 = 1;
|
||||
_sig1 = 1;
|
||||
_lRate = 0.85f;
|
||||
_trained = false;
|
||||
}
|
||||
|
||||
void ClfOnlineStump::update(const Mat& posx, const Mat& negx, const Mat_<float>& /*posw*/, const Mat_<float>& /*negw*/)
|
||||
{
|
||||
//std::cout << " ClfOnlineStump::update" << _ind << std::endl;
|
||||
float posmu = 0.0, negmu = 0.0;
|
||||
if (posx.cols > 0)
|
||||
posmu = float(mean(posx.col(_ind))[0]);
|
||||
if (negx.cols > 0)
|
||||
negmu = float(mean(negx.col(_ind))[0]);
|
||||
|
||||
if (_trained)
|
||||
{
|
||||
if (posx.cols > 0)
|
||||
{
|
||||
_mu1 = (_lRate * _mu1 + (1 - _lRate) * posmu);
|
||||
cv::Mat diff = posx.col(_ind) - _mu1;
|
||||
_sig1 = _lRate * _sig1 + (1 - _lRate) * float(mean(diff.mul(diff))[0]);
|
||||
}
|
||||
if (negx.cols > 0)
|
||||
{
|
||||
_mu0 = (_lRate * _mu0 + (1 - _lRate) * negmu);
|
||||
cv::Mat diff = negx.col(_ind) - _mu0;
|
||||
_sig0 = _lRate * _sig0 + (1 - _lRate) * float(mean(diff.mul(diff))[0]);
|
||||
}
|
||||
|
||||
_q = (_mu1 - _mu0) / 2;
|
||||
_s = sign(_mu1 - _mu0);
|
||||
_log_n0 = std::log(float(1.0f / pow(_sig0, 0.5f)));
|
||||
_log_n1 = std::log(float(1.0f / pow(_sig1, 0.5f)));
|
||||
//_e1 = -1.0f/(2.0f*_sig1+1e-99f);
|
||||
//_e0 = -1.0f/(2.0f*_sig0+1e-99f);
|
||||
_e1 = -1.0f / (2.0f * _sig1 + std::numeric_limits<float>::min());
|
||||
_e0 = -1.0f / (2.0f * _sig0 + std::numeric_limits<float>::min());
|
||||
}
|
||||
else
|
||||
{
|
||||
_trained = true;
|
||||
if (posx.cols > 0)
|
||||
{
|
||||
_mu1 = posmu;
|
||||
cv::Scalar scal_mean, scal_std_dev;
|
||||
cv::meanStdDev(posx.col(_ind), scal_mean, scal_std_dev);
|
||||
_sig1 = float(scal_std_dev[0]) * float(scal_std_dev[0]) + 1e-9f;
|
||||
}
|
||||
|
||||
if (negx.cols > 0)
|
||||
{
|
||||
_mu0 = negmu;
|
||||
cv::Scalar scal_mean, scal_std_dev;
|
||||
cv::meanStdDev(negx.col(_ind), scal_mean, scal_std_dev);
|
||||
_sig0 = float(scal_std_dev[0]) * float(scal_std_dev[0]) + 1e-9f;
|
||||
}
|
||||
|
||||
_q = (_mu1 - _mu0) / 2;
|
||||
_s = sign(_mu1 - _mu0);
|
||||
_log_n0 = std::log(float(1.0f / pow(_sig0, 0.5f)));
|
||||
_log_n1 = std::log(float(1.0f / pow(_sig1, 0.5f)));
|
||||
//_e1 = -1.0f/(2.0f*_sig1+1e-99f);
|
||||
//_e0 = -1.0f/(2.0f*_sig0+1e-99f);
|
||||
_e1 = -1.0f / (2.0f * _sig1 + std::numeric_limits<float>::min());
|
||||
_e0 = -1.0f / (2.0f * _sig0 + std::numeric_limits<float>::min());
|
||||
}
|
||||
}
|
||||
|
||||
bool ClfOnlineStump::classify(const Mat& x, int i)
|
||||
{
|
||||
float xx = x.at<float>(i, _ind);
|
||||
double log_p0 = (xx - _mu0) * (xx - _mu0) * _e0 + _log_n0;
|
||||
double log_p1 = (xx - _mu1) * (xx - _mu1) * _e1 + _log_n1;
|
||||
return log_p1 > log_p0;
|
||||
}
|
||||
|
||||
float ClfOnlineStump::classifyF(const Mat& x, int i)
|
||||
{
|
||||
float xx = x.at<float>(i, _ind);
|
||||
double log_p0 = (xx - _mu0) * (xx - _mu0) * _e0 + _log_n0;
|
||||
double log_p1 = (xx - _mu1) * (xx - _mu1) * _e1 + _log_n1;
|
||||
return float(log_p1 - log_p0);
|
||||
}
|
||||
|
||||
inline std::vector<float> ClfOnlineStump::classifySetF(const Mat& x)
|
||||
{
|
||||
std::vector<float> res(x.rows);
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int k = 0; k < (int)res.size(); k++)
|
||||
{
|
||||
res[k] = classifyF(x, k);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
79
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_online_mil.hpp
vendored
Normal file
79
3rdparty/opencv-4.5.4/modules/video/src/tracking/detail/tracking_online_mil.hpp
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_VIDEO_DETAIL_TRACKING_ONLINE_MIL_HPP
|
||||
#define OPENCV_VIDEO_DETAIL_TRACKING_ONLINE_MIL_HPP
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
inline namespace tracking {
|
||||
|
||||
//! @addtogroup tracking_detail
|
||||
//! @{
|
||||
|
||||
//TODO based on the original implementation
|
||||
//http://vision.ucsd.edu/~bbabenko/project_miltrack.shtml
|
||||
|
||||
class ClfOnlineStump;
|
||||
|
||||
class CV_EXPORTS ClfMilBoost
|
||||
{
|
||||
public:
|
||||
struct CV_EXPORTS Params
|
||||
{
|
||||
Params();
|
||||
int _numSel;
|
||||
int _numFeat;
|
||||
float _lRate;
|
||||
};
|
||||
|
||||
ClfMilBoost();
|
||||
~ClfMilBoost();
|
||||
void init(const ClfMilBoost::Params& parameters = ClfMilBoost::Params());
|
||||
void update(const Mat& posx, const Mat& negx);
|
||||
std::vector<float> classify(const Mat& x, bool logR = true);
|
||||
|
||||
inline float sigmoid(float x)
|
||||
{
|
||||
return 1.0f / (1.0f + exp(-x));
|
||||
}
|
||||
|
||||
private:
|
||||
uint _numsamples;
|
||||
ClfMilBoost::Params _myParams;
|
||||
std::vector<int> _selectors;
|
||||
std::vector<ClfOnlineStump*> _weakclf;
|
||||
uint _counter;
|
||||
};
|
||||
|
||||
class ClfOnlineStump
|
||||
{
|
||||
public:
|
||||
float _mu0, _mu1, _sig0, _sig1;
|
||||
float _q;
|
||||
int _s;
|
||||
float _log_n1, _log_n0;
|
||||
float _e1, _e0;
|
||||
float _lRate;
|
||||
|
||||
ClfOnlineStump();
|
||||
ClfOnlineStump(int ind);
|
||||
void init();
|
||||
void update(const Mat& posx, const Mat& negx, const cv::Mat_<float>& posw = cv::Mat_<float>(), const cv::Mat_<float>& negw = cv::Mat_<float>());
|
||||
bool classify(const Mat& x, int i);
|
||||
float classifyF(const Mat& x, int i);
|
||||
std::vector<float> classifySetF(const Mat& x);
|
||||
|
||||
private:
|
||||
bool _trained;
|
||||
int _ind;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
}}} // namespace cv::detail::tracking
|
||||
|
||||
#endif
|
||||
19
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker.cpp
vendored
Normal file
19
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker.cpp
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
Tracker::Tracker()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
Tracker::~Tracker()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
440
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker_dasiamrpn.cpp
vendored
Normal file
440
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker_dasiamrpn.cpp
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../precomp.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
#include "opencv2/dnn.hpp"
|
||||
#endif
|
||||
|
||||
namespace cv {
|
||||
|
||||
TrackerDaSiamRPN::TrackerDaSiamRPN()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
TrackerDaSiamRPN::~TrackerDaSiamRPN()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
TrackerDaSiamRPN::Params::Params()
|
||||
{
|
||||
model = "dasiamrpn_model.onnx";
|
||||
kernel_cls1 = "dasiamrpn_kernel_cls1.onnx";
|
||||
kernel_r1 = "dasiamrpn_kernel_r1.onnx";
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
backend = dnn::DNN_BACKEND_DEFAULT;
|
||||
target = dnn::DNN_TARGET_CPU;
|
||||
#else
|
||||
backend = -1; // invalid value
|
||||
target = -1; // invalid value
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
|
||||
template <typename T> static
|
||||
T sizeCal(const T& w, const T& h)
|
||||
{
|
||||
T pad = (w + h) * T(0.5);
|
||||
T sz2 = (w + pad) * (h + pad);
|
||||
return sqrt(sz2);
|
||||
}
|
||||
|
||||
template <>
|
||||
Mat sizeCal(const Mat& w, const Mat& h)
|
||||
{
|
||||
Mat pad = (w + h) * 0.5;
|
||||
Mat sz2 = (w + pad).mul((h + pad));
|
||||
|
||||
cv::sqrt(sz2, sz2);
|
||||
return sz2;
|
||||
}
|
||||
|
||||
class TrackerDaSiamRPNImpl : public TrackerDaSiamRPN
|
||||
{
|
||||
public:
|
||||
TrackerDaSiamRPNImpl(const TrackerDaSiamRPN::Params& parameters)
|
||||
: params(parameters)
|
||||
{
|
||||
|
||||
siamRPN = dnn::readNet(params.model);
|
||||
siamKernelCL1 = dnn::readNet(params.kernel_cls1);
|
||||
siamKernelR1 = dnn::readNet(params.kernel_r1);
|
||||
|
||||
CV_Assert(!siamRPN.empty());
|
||||
CV_Assert(!siamKernelCL1.empty());
|
||||
CV_Assert(!siamKernelR1.empty());
|
||||
|
||||
siamRPN.setPreferableBackend(params.backend);
|
||||
siamRPN.setPreferableTarget(params.target);
|
||||
siamKernelR1.setPreferableBackend(params.backend);
|
||||
siamKernelR1.setPreferableTarget(params.target);
|
||||
siamKernelCL1.setPreferableBackend(params.backend);
|
||||
siamKernelCL1.setPreferableTarget(params.target);
|
||||
}
|
||||
|
||||
void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE;
|
||||
bool update(InputArray image, Rect& boundingBox) CV_OVERRIDE;
|
||||
float getTrackingScore() CV_OVERRIDE;
|
||||
|
||||
TrackerDaSiamRPN::Params params;
|
||||
|
||||
protected:
|
||||
dnn::Net siamRPN, siamKernelR1, siamKernelCL1;
|
||||
Rect boundingBox_;
|
||||
Mat image_;
|
||||
struct trackerConfig
|
||||
{
|
||||
float windowInfluence = 0.43f;
|
||||
float lr = 0.4f;
|
||||
int scale = 8;
|
||||
bool swapRB = false;
|
||||
int totalStride = 8;
|
||||
float penaltyK = 0.055f;
|
||||
int exemplarSize = 127;
|
||||
int instanceSize = 271;
|
||||
float contextAmount = 0.5f;
|
||||
std::vector<float> ratios = { 0.33f, 0.5f, 1.0f, 2.0f, 3.0f };
|
||||
int anchorNum = int(ratios.size());
|
||||
Mat anchors;
|
||||
Mat windows;
|
||||
Scalar avgChans;
|
||||
Size imgSize = { 0, 0 };
|
||||
Rect2f targetBox = { 0, 0, 0, 0 };
|
||||
int scoreSize = (instanceSize - exemplarSize) / totalStride + 1;
|
||||
float tracking_score;
|
||||
|
||||
void update_scoreSize()
|
||||
{
|
||||
scoreSize = int((instanceSize - exemplarSize) / totalStride + 1);
|
||||
}
|
||||
};
|
||||
trackerConfig trackState;
|
||||
|
||||
void softmax(const Mat& src, Mat& dst);
|
||||
void elementMax(Mat& src);
|
||||
Mat generateHanningWindow();
|
||||
Mat generateAnchors();
|
||||
Mat getSubwindow(Mat& img, const Rect2f& targetBox, float originalSize, Scalar avgChans);
|
||||
void trackerInit(Mat img);
|
||||
void trackerEval(Mat img);
|
||||
};
|
||||
|
||||
void TrackerDaSiamRPNImpl::init(InputArray image, const Rect& boundingBox)
|
||||
{
|
||||
image_ = image.getMat().clone();
|
||||
|
||||
trackState.update_scoreSize();
|
||||
trackState.targetBox = Rect2f(
|
||||
float(boundingBox.x) + float(boundingBox.width) * 0.5f, // FIXIT don't use center in Rect structures, it is confusing
|
||||
float(boundingBox.y) + float(boundingBox.height) * 0.5f,
|
||||
float(boundingBox.width),
|
||||
float(boundingBox.height)
|
||||
);
|
||||
trackerInit(image_);
|
||||
}
|
||||
|
||||
void TrackerDaSiamRPNImpl::trackerInit(Mat img)
|
||||
{
|
||||
Rect2f targetBox = trackState.targetBox;
|
||||
Mat anchors = generateAnchors();
|
||||
trackState.anchors = anchors;
|
||||
|
||||
Mat windows = generateHanningWindow();
|
||||
|
||||
trackState.windows = windows;
|
||||
trackState.imgSize = img.size();
|
||||
|
||||
trackState.avgChans = mean(img);
|
||||
float wc = targetBox.width + trackState.contextAmount * (targetBox.width + targetBox.height);
|
||||
float hc = targetBox.height + trackState.contextAmount * (targetBox.width + targetBox.height);
|
||||
float sz = (float)cvRound(sqrt(wc * hc));
|
||||
|
||||
Mat zCrop = getSubwindow(img, targetBox, sz, trackState.avgChans);
|
||||
Mat blob;
|
||||
|
||||
dnn::blobFromImage(zCrop, blob, 1.0, Size(trackState.exemplarSize, trackState.exemplarSize), Scalar(), trackState.swapRB, false, CV_32F);
|
||||
siamRPN.setInput(blob);
|
||||
Mat out1;
|
||||
siamRPN.forward(out1, "63");
|
||||
|
||||
siamKernelCL1.setInput(out1);
|
||||
siamKernelR1.setInput(out1);
|
||||
|
||||
Mat cls1 = siamKernelCL1.forward();
|
||||
Mat r1 = siamKernelR1.forward();
|
||||
std::vector<int> r1_shape = { 20, 256, 4, 4 }, cls1_shape = { 10, 256, 4, 4 };
|
||||
|
||||
siamRPN.setParam(siamRPN.getLayerId("65"), 0, r1.reshape(0, r1_shape));
|
||||
siamRPN.setParam(siamRPN.getLayerId("68"), 0, cls1.reshape(0, cls1_shape));
|
||||
}
|
||||
|
||||
bool TrackerDaSiamRPNImpl::update(InputArray image, Rect& boundingBox)
|
||||
{
|
||||
image_ = image.getMat().clone();
|
||||
trackerEval(image_);
|
||||
boundingBox = {
|
||||
int(trackState.targetBox.x - int(trackState.targetBox.width / 2)),
|
||||
int(trackState.targetBox.y - int(trackState.targetBox.height / 2)),
|
||||
int(trackState.targetBox.width),
|
||||
int(trackState.targetBox.height)
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
void TrackerDaSiamRPNImpl::trackerEval(Mat img)
|
||||
{
|
||||
Rect2f targetBox = trackState.targetBox;
|
||||
|
||||
float wc = targetBox.height + trackState.contextAmount * (targetBox.width + targetBox.height);
|
||||
float hc = targetBox.width + trackState.contextAmount * (targetBox.width + targetBox.height);
|
||||
|
||||
float sz = sqrt(wc * hc);
|
||||
float scaleZ = trackState.exemplarSize / sz;
|
||||
|
||||
float searchSize = float((trackState.instanceSize - trackState.exemplarSize) / 2);
|
||||
float pad = searchSize / scaleZ;
|
||||
float sx = sz + 2 * pad;
|
||||
|
||||
Mat xCrop = getSubwindow(img, targetBox, (float)cvRound(sx), trackState.avgChans);
|
||||
|
||||
Mat blob;
|
||||
std::vector<Mat> outs;
|
||||
std::vector<String> outNames;
|
||||
Mat delta, score;
|
||||
Mat sc, rc, penalty, pscore;
|
||||
|
||||
dnn::blobFromImage(xCrop, blob, 1.0, Size(trackState.instanceSize, trackState.instanceSize), Scalar(), trackState.swapRB, false, CV_32F);
|
||||
|
||||
siamRPN.setInput(blob);
|
||||
|
||||
outNames = siamRPN.getUnconnectedOutLayersNames();
|
||||
siamRPN.forward(outs, outNames);
|
||||
|
||||
delta = outs[0];
|
||||
score = outs[1];
|
||||
|
||||
score = score.reshape(0, { 2, trackState.anchorNum, trackState.scoreSize, trackState.scoreSize });
|
||||
delta = delta.reshape(0, { 4, trackState.anchorNum, trackState.scoreSize, trackState.scoreSize });
|
||||
|
||||
softmax(score, score);
|
||||
|
||||
targetBox.width *= scaleZ;
|
||||
targetBox.height *= scaleZ;
|
||||
|
||||
score = score.row(1);
|
||||
score = score.reshape(0, { 5, 19, 19 });
|
||||
|
||||
// Post processing
|
||||
delta.row(0) = delta.row(0).mul(trackState.anchors.row(2)) + trackState.anchors.row(0);
|
||||
delta.row(1) = delta.row(1).mul(trackState.anchors.row(3)) + trackState.anchors.row(1);
|
||||
exp(delta.row(2), delta.row(2));
|
||||
delta.row(2) = delta.row(2).mul(trackState.anchors.row(2));
|
||||
exp(delta.row(3), delta.row(3));
|
||||
delta.row(3) = delta.row(3).mul(trackState.anchors.row(3));
|
||||
|
||||
sc = sizeCal(delta.row(2), delta.row(3)) / sizeCal(targetBox.width, targetBox.height);
|
||||
elementMax(sc);
|
||||
|
||||
rc = delta.row(2).mul(1 / delta.row(3));
|
||||
rc = (targetBox.width / targetBox.height) / rc;
|
||||
elementMax(rc);
|
||||
|
||||
// Calculating the penalty
|
||||
exp(((rc.mul(sc) - 1.) * trackState.penaltyK * (-1.0)), penalty);
|
||||
penalty = penalty.reshape(0, { trackState.anchorNum, trackState.scoreSize, trackState.scoreSize });
|
||||
|
||||
pscore = penalty.mul(score);
|
||||
pscore = pscore * (1.0 - trackState.windowInfluence) + trackState.windows * trackState.windowInfluence;
|
||||
|
||||
int bestID[2] = { 0, 0 };
|
||||
// Find the index of best score.
|
||||
minMaxIdx(pscore.reshape(0, { trackState.anchorNum * trackState.scoreSize * trackState.scoreSize, 1 }), 0, 0, 0, bestID);
|
||||
delta = delta.reshape(0, { 4, trackState.anchorNum * trackState.scoreSize * trackState.scoreSize });
|
||||
penalty = penalty.reshape(0, { trackState.anchorNum * trackState.scoreSize * trackState.scoreSize, 1 });
|
||||
score = score.reshape(0, { trackState.anchorNum * trackState.scoreSize * trackState.scoreSize, 1 });
|
||||
|
||||
int index[2] = { 0, bestID[0] };
|
||||
Rect2f resBox = { 0, 0, 0, 0 };
|
||||
|
||||
resBox.x = delta.at<float>(index) / scaleZ;
|
||||
index[0] = 1;
|
||||
resBox.y = delta.at<float>(index) / scaleZ;
|
||||
index[0] = 2;
|
||||
resBox.width = delta.at<float>(index) / scaleZ;
|
||||
index[0] = 3;
|
||||
resBox.height = delta.at<float>(index) / scaleZ;
|
||||
|
||||
float lr = penalty.at<float>(bestID) * score.at<float>(bestID) * trackState.lr;
|
||||
|
||||
resBox.x = resBox.x + targetBox.x;
|
||||
resBox.y = resBox.y + targetBox.y;
|
||||
targetBox.width /= scaleZ;
|
||||
targetBox.height /= scaleZ;
|
||||
|
||||
resBox.width = targetBox.width * (1 - lr) + resBox.width * lr;
|
||||
resBox.height = targetBox.height * (1 - lr) + resBox.height * lr;
|
||||
|
||||
resBox.x = float(fmax(0., fmin(float(trackState.imgSize.width), resBox.x)));
|
||||
resBox.y = float(fmax(0., fmin(float(trackState.imgSize.height), resBox.y)));
|
||||
resBox.width = float(fmax(10., fmin(float(trackState.imgSize.width), resBox.width)));
|
||||
resBox.height = float(fmax(10., fmin(float(trackState.imgSize.height), resBox.height)));
|
||||
|
||||
trackState.targetBox = resBox;
|
||||
trackState.tracking_score = score.at<float>(bestID);
|
||||
}
|
||||
|
||||
float TrackerDaSiamRPNImpl::getTrackingScore()
|
||||
{
|
||||
return trackState.tracking_score;
|
||||
}
|
||||
|
||||
void TrackerDaSiamRPNImpl::softmax(const Mat& src, Mat& dst)
|
||||
{
|
||||
Mat maxVal;
|
||||
cv::max(src.row(1), src.row(0), maxVal);
|
||||
|
||||
src.row(1) -= maxVal;
|
||||
src.row(0) -= maxVal;
|
||||
|
||||
exp(src, dst);
|
||||
|
||||
Mat sumVal = dst.row(0) + dst.row(1);
|
||||
dst.row(0) = dst.row(0) / sumVal;
|
||||
dst.row(1) = dst.row(1) / sumVal;
|
||||
}
|
||||
|
||||
void TrackerDaSiamRPNImpl::elementMax(Mat& src)
|
||||
{
|
||||
int* p = src.size.p;
|
||||
int index[4] = { 0, 0, 0, 0 };
|
||||
for (int n = 0; n < *p; n++)
|
||||
{
|
||||
for (int k = 0; k < *(p + 1); k++)
|
||||
{
|
||||
for (int i = 0; i < *(p + 2); i++)
|
||||
{
|
||||
for (int j = 0; j < *(p + 3); j++)
|
||||
{
|
||||
index[0] = n, index[1] = k, index[2] = i, index[3] = j;
|
||||
float& v = src.at<float>(index);
|
||||
v = fmax(v, 1.0f / v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mat TrackerDaSiamRPNImpl::generateHanningWindow()
|
||||
{
|
||||
Mat baseWindows, HanningWindows;
|
||||
|
||||
createHanningWindow(baseWindows, Size(trackState.scoreSize, trackState.scoreSize), CV_32F);
|
||||
baseWindows = baseWindows.reshape(0, { 1, trackState.scoreSize, trackState.scoreSize });
|
||||
HanningWindows = baseWindows.clone();
|
||||
for (int i = 1; i < trackState.anchorNum; i++)
|
||||
{
|
||||
HanningWindows.push_back(baseWindows);
|
||||
}
|
||||
|
||||
return HanningWindows;
|
||||
}
|
||||
|
||||
Mat TrackerDaSiamRPNImpl::generateAnchors()
|
||||
{
|
||||
int totalStride = trackState.totalStride, scales = trackState.scale, scoreSize = trackState.scoreSize;
|
||||
std::vector<float> ratios = trackState.ratios;
|
||||
std::vector<Rect2f> baseAnchors;
|
||||
int anchorNum = int(ratios.size());
|
||||
int size = totalStride * totalStride;
|
||||
|
||||
float ori = -(float(scoreSize / 2)) * float(totalStride);
|
||||
|
||||
for (auto i = 0; i < anchorNum; i++)
|
||||
{
|
||||
int ws = int(sqrt(size / ratios[i]));
|
||||
int hs = int(ws * ratios[i]);
|
||||
|
||||
float wws = float(ws) * scales;
|
||||
float hhs = float(hs) * scales;
|
||||
Rect2f anchor = { 0, 0, wws, hhs };
|
||||
baseAnchors.push_back(anchor);
|
||||
}
|
||||
|
||||
int anchorIndex[4] = { 0, 0, 0, 0 };
|
||||
const int sizes[4] = { 4, (int)ratios.size(), scoreSize, scoreSize };
|
||||
Mat anchors(4, sizes, CV_32F);
|
||||
|
||||
for (auto i = 0; i < scoreSize; i++)
|
||||
{
|
||||
for (auto j = 0; j < scoreSize; j++)
|
||||
{
|
||||
for (auto k = 0; k < anchorNum; k++)
|
||||
{
|
||||
anchorIndex[0] = 1, anchorIndex[1] = k, anchorIndex[2] = i, anchorIndex[3] = j;
|
||||
anchors.at<float>(anchorIndex) = ori + totalStride * i;
|
||||
|
||||
anchorIndex[0] = 0;
|
||||
anchors.at<float>(anchorIndex) = ori + totalStride * j;
|
||||
|
||||
anchorIndex[0] = 2;
|
||||
anchors.at<float>(anchorIndex) = baseAnchors[k].width;
|
||||
|
||||
anchorIndex[0] = 3;
|
||||
anchors.at<float>(anchorIndex) = baseAnchors[k].height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return anchors;
|
||||
}
|
||||
|
||||
Mat TrackerDaSiamRPNImpl::getSubwindow(Mat& img, const Rect2f& targetBox, float originalSize, Scalar avgChans)
|
||||
{
|
||||
Mat zCrop, dst;
|
||||
Size imgSize = img.size();
|
||||
float c = (originalSize + 1) / 2;
|
||||
float xMin = (float)cvRound(targetBox.x - c);
|
||||
float xMax = xMin + originalSize - 1;
|
||||
float yMin = (float)cvRound(targetBox.y - c);
|
||||
float yMax = yMin + originalSize - 1;
|
||||
|
||||
int leftPad = (int)(fmax(0., -xMin));
|
||||
int topPad = (int)(fmax(0., -yMin));
|
||||
int rightPad = (int)(fmax(0., xMax - imgSize.width + 1));
|
||||
int bottomPad = (int)(fmax(0., yMax - imgSize.height + 1));
|
||||
|
||||
xMin = xMin + leftPad;
|
||||
xMax = xMax + leftPad;
|
||||
yMax = yMax + topPad;
|
||||
yMin = yMin + topPad;
|
||||
|
||||
if (topPad == 0 && bottomPad == 0 && leftPad == 0 && rightPad == 0)
|
||||
{
|
||||
img(Rect(int(xMin), int(yMin), int(xMax - xMin + 1), int(yMax - yMin + 1))).copyTo(zCrop);
|
||||
}
|
||||
else
|
||||
{
|
||||
copyMakeBorder(img, dst, topPad, bottomPad, leftPad, rightPad, BORDER_CONSTANT, avgChans);
|
||||
dst(Rect(int(xMin), int(yMin), int(xMax - xMin + 1), int(yMax - yMin + 1))).copyTo(zCrop);
|
||||
}
|
||||
|
||||
return zCrop;
|
||||
}
|
||||
Ptr<TrackerDaSiamRPN> TrackerDaSiamRPN::create(const TrackerDaSiamRPN::Params& parameters)
|
||||
{
|
||||
return makePtr<TrackerDaSiamRPNImpl>(parameters);
|
||||
}
|
||||
|
||||
#else // OPENCV_HAVE_DNN
|
||||
Ptr<TrackerDaSiamRPN> TrackerDaSiamRPN::create(const TrackerDaSiamRPN::Params& parameters)
|
||||
{
|
||||
(void)(parameters);
|
||||
CV_Error(cv::Error::StsNotImplemented, "to use GOTURN, the tracking module needs to be built with opencv_dnn !");
|
||||
}
|
||||
#endif // OPENCV_HAVE_DNN
|
||||
}
|
||||
140
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker_goturn.cpp
vendored
Normal file
140
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker_goturn.cpp
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../precomp.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
#include "opencv2/dnn.hpp"
|
||||
#endif
|
||||
|
||||
namespace cv {
|
||||
|
||||
TrackerGOTURN::TrackerGOTURN()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
TrackerGOTURN::~TrackerGOTURN()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
TrackerGOTURN::Params::Params()
|
||||
{
|
||||
modelTxt = "goturn.prototxt";
|
||||
modelBin = "goturn.caffemodel";
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
|
||||
class TrackerGOTURNImpl : public TrackerGOTURN
|
||||
{
|
||||
public:
|
||||
TrackerGOTURNImpl(const TrackerGOTURN::Params& parameters)
|
||||
: params(parameters)
|
||||
{
|
||||
// Load GOTURN architecture from *.prototxt and pretrained weights from *.caffemodel
|
||||
net = dnn::readNetFromCaffe(params.modelTxt, params.modelBin);
|
||||
CV_Assert(!net.empty());
|
||||
}
|
||||
|
||||
void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE;
|
||||
bool update(InputArray image, Rect& boundingBox) CV_OVERRIDE;
|
||||
|
||||
void setBoudingBox(Rect boundingBox)
|
||||
{
|
||||
if (image_.empty())
|
||||
CV_Error(Error::StsInternal, "Set image first");
|
||||
boundingBox_ = boundingBox & Rect(Point(0, 0), image_.size());
|
||||
}
|
||||
|
||||
TrackerGOTURN::Params params;
|
||||
|
||||
dnn::Net net;
|
||||
Rect boundingBox_;
|
||||
Mat image_;
|
||||
};
|
||||
|
||||
void TrackerGOTURNImpl::init(InputArray image, const Rect& boundingBox)
|
||||
{
|
||||
image_ = image.getMat().clone();
|
||||
setBoudingBox(boundingBox);
|
||||
}
|
||||
|
||||
bool TrackerGOTURNImpl::update(InputArray image, Rect& boundingBox)
|
||||
{
|
||||
int INPUT_SIZE = 227;
|
||||
//Using prevFrame & prevBB from model and curFrame GOTURN calculating curBB
|
||||
InputArray curFrame = image;
|
||||
Mat prevFrame = image_;
|
||||
Rect2d prevBB = boundingBox_;
|
||||
Rect curBB;
|
||||
|
||||
float padTargetPatch = 2.0;
|
||||
Rect2f searchPatchRect, targetPatchRect;
|
||||
Point2f currCenter, prevCenter;
|
||||
Mat prevFramePadded, curFramePadded;
|
||||
Mat searchPatch, targetPatch;
|
||||
|
||||
prevCenter.x = (float)(prevBB.x + prevBB.width / 2);
|
||||
prevCenter.y = (float)(prevBB.y + prevBB.height / 2);
|
||||
|
||||
targetPatchRect.width = (float)(prevBB.width * padTargetPatch);
|
||||
targetPatchRect.height = (float)(prevBB.height * padTargetPatch);
|
||||
targetPatchRect.x = (float)(prevCenter.x - prevBB.width * padTargetPatch / 2.0 + targetPatchRect.width);
|
||||
targetPatchRect.y = (float)(prevCenter.y - prevBB.height * padTargetPatch / 2.0 + targetPatchRect.height);
|
||||
|
||||
targetPatchRect.width = std::min(targetPatchRect.width, (float)prevFrame.cols);
|
||||
targetPatchRect.height = std::min(targetPatchRect.height, (float)prevFrame.rows);
|
||||
targetPatchRect.x = std::max(-prevFrame.cols * 0.5f, std::min(targetPatchRect.x, prevFrame.cols * 1.5f));
|
||||
targetPatchRect.y = std::max(-prevFrame.rows * 0.5f, std::min(targetPatchRect.y, prevFrame.rows * 1.5f));
|
||||
|
||||
copyMakeBorder(prevFrame, prevFramePadded, (int)targetPatchRect.height, (int)targetPatchRect.height, (int)targetPatchRect.width, (int)targetPatchRect.width, BORDER_REPLICATE);
|
||||
targetPatch = prevFramePadded(targetPatchRect).clone();
|
||||
|
||||
copyMakeBorder(curFrame, curFramePadded, (int)targetPatchRect.height, (int)targetPatchRect.height, (int)targetPatchRect.width, (int)targetPatchRect.width, BORDER_REPLICATE);
|
||||
searchPatch = curFramePadded(targetPatchRect).clone();
|
||||
|
||||
// Preprocess
|
||||
// Resize
|
||||
resize(targetPatch, targetPatch, Size(INPUT_SIZE, INPUT_SIZE), 0, 0, INTER_LINEAR_EXACT);
|
||||
resize(searchPatch, searchPatch, Size(INPUT_SIZE, INPUT_SIZE), 0, 0, INTER_LINEAR_EXACT);
|
||||
|
||||
// Convert to Float type and subtract mean
|
||||
Mat targetBlob = dnn::blobFromImage(targetPatch, 1.0f, Size(), Scalar::all(128), false);
|
||||
Mat searchBlob = dnn::blobFromImage(searchPatch, 1.0f, Size(), Scalar::all(128), false);
|
||||
|
||||
net.setInput(targetBlob, "data1");
|
||||
net.setInput(searchBlob, "data2");
|
||||
|
||||
Mat resMat = net.forward("scale").reshape(1, 1);
|
||||
|
||||
curBB.x = cvRound(targetPatchRect.x + (resMat.at<float>(0) * targetPatchRect.width / INPUT_SIZE) - targetPatchRect.width);
|
||||
curBB.y = cvRound(targetPatchRect.y + (resMat.at<float>(1) * targetPatchRect.height / INPUT_SIZE) - targetPatchRect.height);
|
||||
curBB.width = cvRound((resMat.at<float>(2) - resMat.at<float>(0)) * targetPatchRect.width / INPUT_SIZE);
|
||||
curBB.height = cvRound((resMat.at<float>(3) - resMat.at<float>(1)) * targetPatchRect.height / INPUT_SIZE);
|
||||
|
||||
// Predicted BB
|
||||
boundingBox = curBB & Rect(Point(0, 0), image_.size());
|
||||
|
||||
// Set new model image and BB from current frame
|
||||
image_ = image.getMat().clone();
|
||||
setBoudingBox(curBB);
|
||||
return true;
|
||||
}
|
||||
|
||||
Ptr<TrackerGOTURN> TrackerGOTURN::create(const TrackerGOTURN::Params& parameters)
|
||||
{
|
||||
return makePtr<TrackerGOTURNImpl>(parameters);
|
||||
}
|
||||
|
||||
#else // OPENCV_HAVE_DNN
|
||||
Ptr<TrackerGOTURN> TrackerGOTURN::create(const TrackerGOTURN::Params& parameters)
|
||||
{
|
||||
(void)(parameters);
|
||||
CV_Error(cv::Error::StsNotImplemented, "to use GOTURN, the tracking module needs to be built with opencv_dnn !");
|
||||
}
|
||||
#endif // OPENCV_HAVE_DNN
|
||||
|
||||
} // namespace cv
|
||||
227
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker_mil.cpp
vendored
Normal file
227
3rdparty/opencv-4.5.4/modules/video/src/tracking/tracker_mil.cpp
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "detail/tracker_mil_model.hpp"
|
||||
|
||||
#include "detail/tracker_feature_haar.impl.hpp"
|
||||
|
||||
namespace cv {
|
||||
inline namespace tracking {
|
||||
namespace impl {
|
||||
|
||||
using cv::detail::tracking::internal::TrackerFeatureHAAR;
|
||||
|
||||
|
||||
class TrackerMILImpl CV_FINAL : public TrackerMIL
|
||||
{
|
||||
public:
|
||||
TrackerMILImpl(const TrackerMIL::Params& parameters);
|
||||
|
||||
virtual void init(InputArray image, const Rect& boundingBox) CV_OVERRIDE;
|
||||
virtual bool update(InputArray image, Rect& boundingBox) CV_OVERRIDE;
|
||||
|
||||
void compute_integral(const Mat& img, Mat& ii_img);
|
||||
|
||||
TrackerMIL::Params params;
|
||||
|
||||
Ptr<TrackerMILModel> model;
|
||||
Ptr<TrackerSampler> sampler;
|
||||
Ptr<TrackerFeatureSet> featureSet;
|
||||
};
|
||||
|
||||
TrackerMILImpl::TrackerMILImpl(const TrackerMIL::Params& parameters)
|
||||
: params(parameters)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
void TrackerMILImpl::compute_integral(const Mat& img, Mat& ii_img)
|
||||
{
|
||||
Mat ii;
|
||||
std::vector<Mat> ii_imgs;
|
||||
integral(img, ii, CV_32F); // FIXIT split first
|
||||
split(ii, ii_imgs);
|
||||
ii_img = ii_imgs[0];
|
||||
}
|
||||
|
||||
void TrackerMILImpl::init(InputArray image, const Rect& boundingBox)
|
||||
{
|
||||
sampler = makePtr<TrackerSampler>();
|
||||
featureSet = makePtr<TrackerFeatureSet>();
|
||||
|
||||
Mat intImage;
|
||||
compute_integral(image.getMat(), intImage);
|
||||
TrackerSamplerCSC::Params CSCparameters;
|
||||
CSCparameters.initInRad = params.samplerInitInRadius;
|
||||
CSCparameters.searchWinSize = params.samplerSearchWinSize;
|
||||
CSCparameters.initMaxNegNum = params.samplerInitMaxNegNum;
|
||||
CSCparameters.trackInPosRad = params.samplerTrackInRadius;
|
||||
CSCparameters.trackMaxPosNum = params.samplerTrackMaxPosNum;
|
||||
CSCparameters.trackMaxNegNum = params.samplerTrackMaxNegNum;
|
||||
|
||||
Ptr<TrackerSamplerAlgorithm> CSCSampler = makePtr<TrackerSamplerCSC>(CSCparameters);
|
||||
CV_Assert(sampler->addTrackerSamplerAlgorithm(CSCSampler));
|
||||
|
||||
//or add CSC sampler with default parameters
|
||||
//sampler->addTrackerSamplerAlgorithm( "CSC" );
|
||||
|
||||
//Positive sampling
|
||||
CSCSampler.staticCast<TrackerSamplerCSC>()->setMode(TrackerSamplerCSC::MODE_INIT_POS);
|
||||
sampler->sampling(intImage, boundingBox);
|
||||
std::vector<Mat> posSamples = sampler->getSamples();
|
||||
|
||||
//Negative sampling
|
||||
CSCSampler.staticCast<TrackerSamplerCSC>()->setMode(TrackerSamplerCSC::MODE_INIT_NEG);
|
||||
sampler->sampling(intImage, boundingBox);
|
||||
std::vector<Mat> negSamples = sampler->getSamples();
|
||||
|
||||
CV_Assert(!posSamples.empty());
|
||||
CV_Assert(!negSamples.empty());
|
||||
|
||||
//compute HAAR features
|
||||
TrackerFeatureHAAR::Params HAARparameters;
|
||||
HAARparameters.numFeatures = params.featureSetNumFeatures;
|
||||
HAARparameters.rectSize = Size((int)boundingBox.width, (int)boundingBox.height);
|
||||
HAARparameters.isIntegral = true;
|
||||
Ptr<TrackerFeature> trackerFeature = makePtr<TrackerFeatureHAAR>(HAARparameters);
|
||||
featureSet->addTrackerFeature(trackerFeature);
|
||||
|
||||
featureSet->extraction(posSamples);
|
||||
const std::vector<Mat> posResponse = featureSet->getResponses();
|
||||
|
||||
featureSet->extraction(negSamples);
|
||||
const std::vector<Mat> negResponse = featureSet->getResponses();
|
||||
|
||||
model = makePtr<TrackerMILModel>(boundingBox);
|
||||
Ptr<TrackerStateEstimatorMILBoosting> stateEstimator = makePtr<TrackerStateEstimatorMILBoosting>(params.featureSetNumFeatures);
|
||||
model->setTrackerStateEstimator(stateEstimator);
|
||||
|
||||
//Run model estimation and update
|
||||
model.staticCast<TrackerMILModel>()->setMode(TrackerMILModel::MODE_POSITIVE, posSamples);
|
||||
model->modelEstimation(posResponse);
|
||||
model.staticCast<TrackerMILModel>()->setMode(TrackerMILModel::MODE_NEGATIVE, negSamples);
|
||||
model->modelEstimation(negResponse);
|
||||
model->modelUpdate();
|
||||
}
|
||||
|
||||
bool TrackerMILImpl::update(InputArray image, Rect& boundingBox)
|
||||
{
|
||||
Mat intImage;
|
||||
compute_integral(image.getMat(), intImage);
|
||||
|
||||
//get the last location [AAM] X(k-1)
|
||||
Ptr<TrackerTargetState> lastLocation = model->getLastTargetState();
|
||||
Rect lastBoundingBox((int)lastLocation->getTargetPosition().x, (int)lastLocation->getTargetPosition().y, lastLocation->getTargetWidth(),
|
||||
lastLocation->getTargetHeight());
|
||||
|
||||
//sampling new frame based on last location
|
||||
auto& samplers = sampler->getSamplers();
|
||||
CV_Assert(!samplers.empty());
|
||||
CV_Assert(samplers[0]);
|
||||
samplers[0].staticCast<TrackerSamplerCSC>()->setMode(TrackerSamplerCSC::MODE_DETECT);
|
||||
sampler->sampling(intImage, lastBoundingBox);
|
||||
std::vector<Mat> detectSamples = sampler->getSamples();
|
||||
if (detectSamples.empty())
|
||||
return false;
|
||||
|
||||
/*//TODO debug samples
|
||||
Mat f;
|
||||
image.copyTo(f);
|
||||
|
||||
for( size_t i = 0; i < detectSamples.size(); i=i+10 )
|
||||
{
|
||||
Size sz;
|
||||
Point off;
|
||||
detectSamples.at(i).locateROI(sz, off);
|
||||
rectangle(f, Rect(off.x,off.y,detectSamples.at(i).cols,detectSamples.at(i).rows), Scalar(255,0,0), 1);
|
||||
}*/
|
||||
|
||||
//extract features from new samples
|
||||
featureSet->extraction(detectSamples);
|
||||
std::vector<Mat> response = featureSet->getResponses();
|
||||
|
||||
//predict new location
|
||||
ConfidenceMap cmap;
|
||||
model.staticCast<TrackerMILModel>()->setMode(TrackerMILModel::MODE_ESTIMATON, detectSamples);
|
||||
model.staticCast<TrackerMILModel>()->responseToConfidenceMap(response, cmap);
|
||||
model->getTrackerStateEstimator().staticCast<TrackerStateEstimatorMILBoosting>()->setCurrentConfidenceMap(cmap);
|
||||
|
||||
if (!model->runStateEstimator())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Ptr<TrackerTargetState> currentState = model->getLastTargetState();
|
||||
boundingBox = Rect((int)currentState->getTargetPosition().x, (int)currentState->getTargetPosition().y, currentState->getTargetWidth(),
|
||||
currentState->getTargetHeight());
|
||||
|
||||
/*//TODO debug
|
||||
rectangle(f, lastBoundingBox, Scalar(0,255,0), 1);
|
||||
rectangle(f, boundingBox, Scalar(0,0,255), 1);
|
||||
imshow("f", f);
|
||||
//waitKey( 0 );*/
|
||||
|
||||
//sampling new frame based on new location
|
||||
//Positive sampling
|
||||
samplers[0].staticCast<TrackerSamplerCSC>()->setMode(TrackerSamplerCSC::MODE_INIT_POS);
|
||||
sampler->sampling(intImage, boundingBox);
|
||||
std::vector<Mat> posSamples = sampler->getSamples();
|
||||
|
||||
//Negative sampling
|
||||
samplers[0].staticCast<TrackerSamplerCSC>()->setMode(TrackerSamplerCSC::MODE_INIT_NEG);
|
||||
sampler->sampling(intImage, boundingBox);
|
||||
std::vector<Mat> negSamples = sampler->getSamples();
|
||||
|
||||
if (posSamples.empty() || negSamples.empty())
|
||||
return false;
|
||||
|
||||
//extract features
|
||||
featureSet->extraction(posSamples);
|
||||
std::vector<Mat> posResponse = featureSet->getResponses();
|
||||
|
||||
featureSet->extraction(negSamples);
|
||||
std::vector<Mat> negResponse = featureSet->getResponses();
|
||||
|
||||
//model estimate
|
||||
model.staticCast<TrackerMILModel>()->setMode(TrackerMILModel::MODE_POSITIVE, posSamples);
|
||||
model->modelEstimation(posResponse);
|
||||
model.staticCast<TrackerMILModel>()->setMode(TrackerMILModel::MODE_NEGATIVE, negSamples);
|
||||
model->modelEstimation(negResponse);
|
||||
|
||||
//model update
|
||||
model->modelUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}} // namespace tracking::impl
|
||||
|
||||
TrackerMIL::Params::Params()
|
||||
{
|
||||
samplerInitInRadius = 3;
|
||||
samplerSearchWinSize = 25;
|
||||
samplerInitMaxNegNum = 65;
|
||||
samplerTrackInRadius = 4;
|
||||
samplerTrackMaxPosNum = 100000;
|
||||
samplerTrackMaxNegNum = 65;
|
||||
featureSetNumFeatures = 250;
|
||||
}
|
||||
|
||||
TrackerMIL::TrackerMIL()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
TrackerMIL::~TrackerMIL()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
Ptr<TrackerMIL> TrackerMIL::create(const TrackerMIL::Params& parameters)
|
||||
{
|
||||
return makePtr<tracking::impl::TrackerMILImpl>(parameters);
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
1242
3rdparty/opencv-4.5.4/modules/video/src/variational_refinement.cpp
vendored
Normal file
1242
3rdparty/opencv-4.5.4/modules/video/src/variational_refinement.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
145
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_bgfg_mog2.cpp
vendored
Normal file
145
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_bgfg_mog2.cpp
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
#include "../test_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
//////////////////////////Mog2_Update///////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
IMPLEMENT_PARAM_CLASS(UseGray, bool)
|
||||
IMPLEMENT_PARAM_CLASS(DetectShadow, bool)
|
||||
IMPLEMENT_PARAM_CLASS(UseFloat, bool)
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(Mog2_Update, UseGray, DetectShadow,UseFloat)
|
||||
{
|
||||
bool useGray;
|
||||
bool detectShadow;
|
||||
bool useFloat;
|
||||
virtual void SetUp()
|
||||
{
|
||||
useGray = GET_PARAM(0);
|
||||
detectShadow = GET_PARAM(1);
|
||||
useFloat = GET_PARAM(2);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Mog2_Update, Accuracy)
|
||||
{
|
||||
string inputFile = string(TS::ptr()->get_data_path()) + "video/768x576.avi";
|
||||
VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
|
||||
Ptr<BackgroundSubtractorMOG2> mog2_cpu = createBackgroundSubtractorMOG2();
|
||||
Ptr<BackgroundSubtractorMOG2> mog2_ocl = createBackgroundSubtractorMOG2();
|
||||
|
||||
mog2_cpu->setDetectShadows(detectShadow);
|
||||
mog2_ocl->setDetectShadows(detectShadow);
|
||||
|
||||
Mat frame, foreground;
|
||||
UMat u_foreground;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
cap >> frame;
|
||||
ASSERT_FALSE(frame.empty());
|
||||
|
||||
if (useGray)
|
||||
{
|
||||
Mat temp;
|
||||
cvtColor(frame, temp, COLOR_BGR2GRAY);
|
||||
swap(temp, frame);
|
||||
}
|
||||
|
||||
if(useFloat)
|
||||
{
|
||||
Mat temp;
|
||||
frame.convertTo(temp,CV_32F);
|
||||
swap(temp,frame);
|
||||
}
|
||||
|
||||
OCL_OFF(mog2_cpu->apply(frame, foreground));
|
||||
OCL_ON (mog2_ocl->apply(frame, u_foreground));
|
||||
|
||||
if (detectShadow)
|
||||
EXPECT_MAT_SIMILAR(foreground, u_foreground, 15e-3);
|
||||
else
|
||||
EXPECT_MAT_NEAR(foreground, u_foreground, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////Mog2_getBackgroundImage///////////////////////////////////
|
||||
|
||||
PARAM_TEST_CASE(Mog2_getBackgroundImage, DetectShadow, UseFloat)
|
||||
{
|
||||
bool detectShadow;
|
||||
bool useFloat;
|
||||
virtual void SetUp()
|
||||
{
|
||||
detectShadow = GET_PARAM(0);
|
||||
useFloat = GET_PARAM(1);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Mog2_getBackgroundImage, Accuracy)
|
||||
{
|
||||
string inputFile = string(TS::ptr()->get_data_path()) + "video/768x576.avi";
|
||||
VideoCapture cap(inputFile);
|
||||
if (!cap.isOpened())
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
|
||||
Ptr<BackgroundSubtractorMOG2> mog2_cpu = createBackgroundSubtractorMOG2();
|
||||
Ptr<BackgroundSubtractorMOG2> mog2_ocl = createBackgroundSubtractorMOG2();
|
||||
|
||||
mog2_cpu->setDetectShadows(detectShadow);
|
||||
mog2_ocl->setDetectShadows(detectShadow);
|
||||
|
||||
Mat frame, foreground;
|
||||
UMat u_foreground;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
cap >> frame;
|
||||
ASSERT_FALSE(frame.empty());
|
||||
|
||||
if(useFloat)
|
||||
{
|
||||
Mat temp;
|
||||
frame.convertTo(temp,CV_32F);
|
||||
swap(temp,frame);
|
||||
}
|
||||
|
||||
OCL_OFF(mog2_cpu->apply(frame, foreground));
|
||||
OCL_ON (mog2_ocl->apply(frame, u_foreground));
|
||||
}
|
||||
|
||||
Mat background;
|
||||
OCL_OFF(mog2_cpu->getBackgroundImage(background));
|
||||
|
||||
UMat u_background;
|
||||
OCL_ON (mog2_ocl->getBackgroundImage(u_background));
|
||||
|
||||
EXPECT_MAT_NEAR(background, u_background, 1.0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2_Update, Combine(
|
||||
Values(UseGray(true),UseGray(false)),
|
||||
Values(DetectShadow(true), DetectShadow(false)),
|
||||
Values(UseFloat(false),UseFloat(true)))
|
||||
);
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2_getBackgroundImage, Combine(
|
||||
Values(DetectShadow(true), DetectShadow(false)),
|
||||
Values(UseFloat(false),UseFloat(true)))
|
||||
);
|
||||
|
||||
}}// namespace opencv_test::ocl
|
||||
|
||||
#endif
|
||||
85
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_dis.cpp
vendored
Normal file
85
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_dis.cpp
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
CV_ENUM(DIS_TestPresets, DISOpticalFlow::PRESET_ULTRAFAST, DISOpticalFlow::PRESET_FAST, DISOpticalFlow::PRESET_MEDIUM);
|
||||
|
||||
typedef ocl::TSTestWithParam<DIS_TestPresets> OCL_DenseOpticalFlow_DIS;
|
||||
|
||||
OCL_TEST_P(OCL_DenseOpticalFlow_DIS, Mat)
|
||||
{
|
||||
int preset = (int)GetParam();
|
||||
Mat frame1, frame2, GT;
|
||||
|
||||
frame1 = imread(TS::ptr()->get_data_path() + "optflow/RubberWhale1.png");
|
||||
frame2 = imread(TS::ptr()->get_data_path() + "optflow/RubberWhale2.png");
|
||||
|
||||
CV_Assert(!frame1.empty() && !frame2.empty());
|
||||
|
||||
cvtColor(frame1, frame1, COLOR_BGR2GRAY);
|
||||
cvtColor(frame2, frame2, COLOR_BGR2GRAY);
|
||||
|
||||
{
|
||||
Mat flow;
|
||||
UMat ocl_flow;
|
||||
|
||||
Ptr<DenseOpticalFlow> algo = DISOpticalFlow::create(preset);
|
||||
OCL_OFF(algo->calc(frame1, frame2, flow));
|
||||
OCL_ON(algo->calc(frame1, frame2, ocl_flow));
|
||||
ASSERT_EQ(flow.rows, ocl_flow.rows);
|
||||
ASSERT_EQ(flow.cols, ocl_flow.cols);
|
||||
|
||||
EXPECT_MAT_SIMILAR(flow, ocl_flow, 6e-3);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Video, OCL_DenseOpticalFlow_DIS,
|
||||
DIS_TestPresets::all());
|
||||
|
||||
}} // namespace
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
120
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_optflow_farneback.cpp
vendored
Normal file
120
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_optflow_farneback.cpp
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FarnebackOpticalFlow
|
||||
namespace
|
||||
{
|
||||
IMPLEMENT_PARAM_CLASS(PyrScale, double)
|
||||
IMPLEMENT_PARAM_CLASS(PolyN, int)
|
||||
CV_FLAGS(FarnebackOptFlowFlags, 0, OPTFLOW_FARNEBACK_GAUSSIAN)
|
||||
IMPLEMENT_PARAM_CLASS(UseInitFlow, bool)
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(FarnebackOpticalFlow, PyrScale, PolyN, FarnebackOptFlowFlags, UseInitFlow)
|
||||
{
|
||||
int numLevels;
|
||||
int winSize;
|
||||
int numIters;
|
||||
double pyrScale;
|
||||
int polyN;
|
||||
int flags;
|
||||
bool useInitFlow;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
numLevels = 5;
|
||||
winSize = 13;
|
||||
numIters = 10;
|
||||
pyrScale = GET_PARAM(0);
|
||||
polyN = GET_PARAM(1);
|
||||
flags = GET_PARAM(2);
|
||||
useInitFlow = GET_PARAM(3);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(FarnebackOpticalFlow, Mat)
|
||||
{
|
||||
cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame0.empty());
|
||||
|
||||
cv::Mat frame1 = readImage("optflow/RubberWhale2.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame1.empty());
|
||||
|
||||
double polySigma = polyN <= 5 ? 1.1 : 1.5;
|
||||
|
||||
cv::Mat flow; cv::UMat uflow;
|
||||
if (useInitFlow)
|
||||
{
|
||||
OCL_ON(cv::calcOpticalFlowFarneback(frame0, frame1, uflow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags));
|
||||
uflow.copyTo(flow);
|
||||
flags |= cv::OPTFLOW_USE_INITIAL_FLOW;
|
||||
}
|
||||
OCL_OFF(cv::calcOpticalFlowFarneback(frame0, frame1, flow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags));
|
||||
OCL_ON(cv::calcOpticalFlowFarneback(frame0, frame1, uflow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags));
|
||||
|
||||
EXPECT_MAT_SIMILAR(flow, uflow, 0.1);
|
||||
}
|
||||
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Video, FarnebackOpticalFlow,
|
||||
Combine(
|
||||
Values(PyrScale(0.3), PyrScale(0.5), PyrScale(0.8)),
|
||||
Values(PolyN(5), PolyN(7)),
|
||||
Values(FarnebackOptFlowFlags(0), FarnebackOptFlowFlags(cv::OPTFLOW_FARNEBACK_GAUSSIAN)),
|
||||
Values(UseInitFlow(false), UseInitFlow(true))
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
} } // namespace opencv_test::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
||||
161
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_optflowpyrlk.cpp
vendored
Normal file
161
3rdparty/opencv-4.5.4/modules/video/test/ocl/test_optflowpyrlk.cpp
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test { namespace ocl {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PyrLKOpticalFlow
|
||||
|
||||
PARAM_TEST_CASE(PyrLKOpticalFlow, int, int)
|
||||
{
|
||||
Size winSize;
|
||||
int maxLevel;
|
||||
TermCriteria criteria;
|
||||
int flags;
|
||||
double minEigThreshold;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
winSize = Size(GET_PARAM(0), GET_PARAM(0));
|
||||
maxLevel = GET_PARAM(1);
|
||||
criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01);
|
||||
flags = 0;
|
||||
minEigThreshold = 1e-4f;
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(PyrLKOpticalFlow, Mat)
|
||||
{
|
||||
static const int npoints = 1000;
|
||||
static const float eps = 0.03f;
|
||||
static const float erreps = 0.1f;
|
||||
|
||||
cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame0.empty());
|
||||
UMat umatFrame0; frame0.copyTo(umatFrame0);
|
||||
|
||||
cv::Mat frame1 = readImage("optflow/RubberWhale2.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame1.empty());
|
||||
UMat umatFrame1; frame1.copyTo(umatFrame1);
|
||||
|
||||
// SKIP unstable tests
|
||||
#ifdef __linux__
|
||||
if (cvtest::skipUnstableTests && ocl::useOpenCL())
|
||||
{
|
||||
if (ocl::Device::getDefault().isIntel())
|
||||
throw cvtest::SkipTestException("Skip unstable test");
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<cv::Point2f> pts;
|
||||
cv::goodFeaturesToTrack(frame0, pts, npoints, 0.01, 0.0);
|
||||
|
||||
std::vector<cv::Point2f> cpuNextPts;
|
||||
std::vector<unsigned char> cpuStatusCPU;
|
||||
std::vector<float> cpuErr;
|
||||
OCL_OFF(cv::calcOpticalFlowPyrLK(frame0, frame1, pts, cpuNextPts, cpuStatusCPU, cpuErr, winSize, maxLevel, criteria, flags, minEigThreshold));
|
||||
|
||||
UMat umatNextPts, umatStatus, umatErr;
|
||||
OCL_ON(cv::calcOpticalFlowPyrLK(umatFrame0, umatFrame1, pts, umatNextPts, umatStatus, umatErr, winSize, maxLevel, criteria, flags, minEigThreshold));
|
||||
std::vector<cv::Point2f> nextPts; umatNextPts.reshape(2, 1).copyTo(nextPts);
|
||||
std::vector<unsigned char> status; umatStatus.reshape(1, 1).copyTo(status);
|
||||
std::vector<float> err; umatErr.reshape(1, 1).copyTo(err);
|
||||
|
||||
ASSERT_EQ(cpuNextPts.size(), nextPts.size());
|
||||
ASSERT_EQ(cpuStatusCPU.size(), status.size());
|
||||
|
||||
size_t mistmatch = 0;
|
||||
size_t errmatch = 0;
|
||||
|
||||
for (size_t i = 0; i < nextPts.size(); ++i)
|
||||
{
|
||||
if (status[i] != cpuStatusCPU[i])
|
||||
{
|
||||
++mistmatch;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status[i])
|
||||
{
|
||||
cv::Point2i a = nextPts[i];
|
||||
cv::Point2i b = cpuNextPts[i];
|
||||
|
||||
bool eq = std::abs(a.x - b.x) < 1 && std::abs(a.y - b.y) < 1;
|
||||
float errdiff = 0.0f;
|
||||
|
||||
if (!eq || errdiff > 1e-1)
|
||||
{
|
||||
++mistmatch;
|
||||
continue;
|
||||
}
|
||||
|
||||
eq = std::abs(cpuErr[i] - err[i]) <= (0.01 * std::max(1.0f, cpuErr[i]));
|
||||
if(!eq)
|
||||
++errmatch;
|
||||
}
|
||||
}
|
||||
|
||||
double bad_ratio = static_cast<double>(mistmatch) / (nextPts.size());
|
||||
double err_ratio = static_cast<double>(errmatch) / (nextPts.size());
|
||||
|
||||
ASSERT_LE(bad_ratio, eps);
|
||||
ASSERT_LE(err_ratio, erreps);
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Video, PyrLKOpticalFlow,
|
||||
Combine(
|
||||
Values(11, 15, 21, 25),
|
||||
Values(3, 5)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_OPENCL
|
||||
175
3rdparty/opencv-4.5.4/modules/video/test/test_OF_accuracy.cpp
vendored
Normal file
175
3rdparty/opencv-4.5.4/modules/video/test/test_OF_accuracy.cpp
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static string getDataDir() { return TS::ptr()->get_data_path(); }
|
||||
|
||||
static string getRubberWhaleFrame1() { return getDataDir() + "optflow/RubberWhale1.png"; }
|
||||
|
||||
static string getRubberWhaleFrame2() { return getDataDir() + "optflow/RubberWhale2.png"; }
|
||||
|
||||
static string getRubberWhaleGroundTruth() { return getDataDir() + "optflow/RubberWhale.flo"; }
|
||||
|
||||
static bool isFlowCorrect(float u) { return !cvIsNaN(u) && (fabs(u) < 1e9); }
|
||||
|
||||
static float calcRMSE(Mat flow1, Mat flow2)
|
||||
{
|
||||
float sum = 0;
|
||||
int counter = 0;
|
||||
const int rows = flow1.rows;
|
||||
const int cols = flow1.cols;
|
||||
|
||||
for (int y = 0; y < rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < cols; ++x)
|
||||
{
|
||||
Vec2f flow1_at_point = flow1.at<Vec2f>(y, x);
|
||||
Vec2f flow2_at_point = flow2.at<Vec2f>(y, x);
|
||||
|
||||
float u1 = flow1_at_point[0];
|
||||
float v1 = flow1_at_point[1];
|
||||
float u2 = flow2_at_point[0];
|
||||
float v2 = flow2_at_point[1];
|
||||
|
||||
if (isFlowCorrect(u1) && isFlowCorrect(u2) && isFlowCorrect(v1) && isFlowCorrect(v2))
|
||||
{
|
||||
sum += (u1 - u2) * (u1 - u2) + (v1 - v2) * (v1 - v2);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (float)sqrt(sum / (1e-9 + counter));
|
||||
}
|
||||
|
||||
bool readRubberWhale(Mat &dst_frame_1, Mat &dst_frame_2, Mat &dst_GT)
|
||||
{
|
||||
const string frame1_path = getRubberWhaleFrame1();
|
||||
const string frame2_path = getRubberWhaleFrame2();
|
||||
const string gt_flow_path = getRubberWhaleGroundTruth();
|
||||
|
||||
dst_frame_1 = imread(frame1_path);
|
||||
dst_frame_2 = imread(frame2_path);
|
||||
dst_GT = readOpticalFlow(gt_flow_path);
|
||||
|
||||
if (dst_frame_1.empty() || dst_frame_2.empty() || dst_GT.empty())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(DenseOpticalFlow_DIS, ReferenceAccuracy)
|
||||
{
|
||||
Mat frame1, frame2, GT;
|
||||
ASSERT_TRUE(readRubberWhale(frame1, frame2, GT));
|
||||
int presets[] = {DISOpticalFlow::PRESET_ULTRAFAST, DISOpticalFlow::PRESET_FAST, DISOpticalFlow::PRESET_MEDIUM};
|
||||
float target_RMSE[] = {0.86f, 0.74f, 0.49f};
|
||||
cvtColor(frame1, frame1, COLOR_BGR2GRAY);
|
||||
cvtColor(frame2, frame2, COLOR_BGR2GRAY);
|
||||
|
||||
Ptr<DenseOpticalFlow> algo;
|
||||
|
||||
// iterate over presets:
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Mat flow;
|
||||
algo = DISOpticalFlow::create(presets[i]);
|
||||
algo->calc(frame1, frame2, flow);
|
||||
ASSERT_EQ(GT.rows, flow.rows);
|
||||
ASSERT_EQ(GT.cols, flow.cols);
|
||||
EXPECT_LE(calcRMSE(GT, flow), target_RMSE[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DenseOpticalFlow_DIS, InvalidImgSize_CoarsestLevelLessThanZero)
|
||||
{
|
||||
cv::Ptr<cv::DISOpticalFlow> of = cv::DISOpticalFlow::create();
|
||||
const int mat_size = 10;
|
||||
|
||||
cv::Mat x(mat_size, mat_size, CV_8UC1, 42);
|
||||
cv::Mat y(mat_size, mat_size, CV_8UC1, 42);
|
||||
cv::Mat flow;
|
||||
|
||||
ASSERT_THROW(of->calc(x, y, flow), cv::Exception);
|
||||
}
|
||||
|
||||
// make sure that autoSelectPatchSizeAndScales() works properly.
|
||||
TEST(DenseOpticalFlow_DIS, InvalidImgSize_CoarsestLevelLessThanFinestLevel)
|
||||
{
|
||||
cv::Ptr<cv::DISOpticalFlow> of = cv::DISOpticalFlow::create();
|
||||
const int mat_size = 80;
|
||||
|
||||
cv::Mat x(mat_size, mat_size, CV_8UC1, 42);
|
||||
cv::Mat y(mat_size, mat_size, CV_8UC1, 42);
|
||||
cv::Mat flow;
|
||||
|
||||
of->calc(x, y, flow);
|
||||
|
||||
ASSERT_EQ(flow.rows, mat_size);
|
||||
ASSERT_EQ(flow.cols, mat_size);
|
||||
}
|
||||
|
||||
TEST(DenseOpticalFlow_VariationalRefinement, ReferenceAccuracy)
|
||||
{
|
||||
Mat frame1, frame2, GT;
|
||||
ASSERT_TRUE(readRubberWhale(frame1, frame2, GT));
|
||||
float target_RMSE = 0.86f;
|
||||
cvtColor(frame1, frame1, COLOR_BGR2GRAY);
|
||||
cvtColor(frame2, frame2, COLOR_BGR2GRAY);
|
||||
|
||||
Ptr<VariationalRefinement> var_ref;
|
||||
var_ref = VariationalRefinement::create();
|
||||
var_ref->setAlpha(20.0f);
|
||||
var_ref->setDelta(5.0f);
|
||||
var_ref->setGamma(10.0f);
|
||||
var_ref->setSorIterations(25);
|
||||
var_ref->setFixedPointIterations(25);
|
||||
Mat flow(frame1.size(), CV_32FC2);
|
||||
flow.setTo(0.0f);
|
||||
var_ref->calc(frame1, frame2, flow);
|
||||
ASSERT_EQ(GT.rows, flow.rows);
|
||||
ASSERT_EQ(GT.cols, flow.cols);
|
||||
EXPECT_LE(calcRMSE(GT, flow), target_RMSE);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
160
3rdparty/opencv-4.5.4/modules/video/test/test_OF_reproducibility.cpp
vendored
Normal file
160
3rdparty/opencv-4.5.4/modules/video/test/test_OF_reproducibility.cpp
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef tuple<Size> OFParams;
|
||||
typedef TestWithParam<OFParams> DenseOpticalFlow_DIS;
|
||||
typedef TestWithParam<OFParams> DenseOpticalFlow_VariationalRefinement;
|
||||
|
||||
TEST_P(DenseOpticalFlow_DIS, MultithreadReproducibility)
|
||||
{
|
||||
double MAX_DIF = 0.01;
|
||||
double MAX_MEAN_DIF = 0.001;
|
||||
int loopsCount = 2;
|
||||
RNG rng(0);
|
||||
|
||||
OFParams params = GetParam();
|
||||
Size size = get<0>(params);
|
||||
|
||||
int nThreads = cv::getNumThreads();
|
||||
if (nThreads == 1)
|
||||
throw SkipTestException("Single thread environment");
|
||||
for (int iter = 0; iter <= loopsCount; iter++)
|
||||
{
|
||||
Mat frame1(size, CV_8U);
|
||||
randu(frame1, 0, 255);
|
||||
Mat frame2(size, CV_8U);
|
||||
randu(frame2, 0, 255);
|
||||
|
||||
Ptr<DISOpticalFlow> algo = DISOpticalFlow::create();
|
||||
int psz = rng.uniform(4, 16);
|
||||
int pstr = rng.uniform(1, psz - 1);
|
||||
int grad_iter = rng.uniform(1, 64);
|
||||
int var_iter = rng.uniform(0, 10);
|
||||
bool use_mean_normalization = !!rng.uniform(0, 2);
|
||||
bool use_spatial_propagation = !!rng.uniform(0, 2);
|
||||
algo->setFinestScale(0);
|
||||
algo->setPatchSize(psz);
|
||||
algo->setPatchStride(pstr);
|
||||
algo->setGradientDescentIterations(grad_iter);
|
||||
algo->setVariationalRefinementIterations(var_iter);
|
||||
algo->setUseMeanNormalization(use_mean_normalization);
|
||||
algo->setUseSpatialPropagation(use_spatial_propagation);
|
||||
|
||||
cv::setNumThreads(nThreads);
|
||||
Mat resMultiThread;
|
||||
algo->calc(frame1, frame2, resMultiThread);
|
||||
|
||||
cv::setNumThreads(1);
|
||||
Mat resSingleThread;
|
||||
algo->calc(frame1, frame2, resSingleThread);
|
||||
|
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_INF), MAX_DIF);
|
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_L1), MAX_MEAN_DIF * frame1.total());
|
||||
|
||||
// resulting flow should be within the frame bounds:
|
||||
double min_val, max_val;
|
||||
minMaxLoc(resMultiThread, &min_val, &max_val);
|
||||
EXPECT_LE(abs(min_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) );
|
||||
EXPECT_LE(abs(max_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) );
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FullSet, DenseOpticalFlow_DIS, Values(szODD, szQVGA));
|
||||
|
||||
TEST_P(DenseOpticalFlow_VariationalRefinement, MultithreadReproducibility)
|
||||
{
|
||||
double MAX_DIF = 0.01;
|
||||
double MAX_MEAN_DIF = 0.001;
|
||||
float input_flow_rad = 5.0;
|
||||
int loopsCount = 2;
|
||||
RNG rng(0);
|
||||
|
||||
OFParams params = GetParam();
|
||||
Size size = get<0>(params);
|
||||
|
||||
int nThreads = cv::getNumThreads();
|
||||
if (nThreads == 1)
|
||||
throw SkipTestException("Single thread environment");
|
||||
for (int iter = 0; iter <= loopsCount; iter++)
|
||||
{
|
||||
Mat frame1(size, CV_8U);
|
||||
randu(frame1, 0, 255);
|
||||
Mat frame2(size, CV_8U);
|
||||
randu(frame2, 0, 255);
|
||||
Mat flow(size, CV_32FC2);
|
||||
randu(flow, -input_flow_rad, input_flow_rad);
|
||||
|
||||
Ptr<VariationalRefinement> var = VariationalRefinement::create();
|
||||
var->setAlpha(rng.uniform(1.0f, 100.0f));
|
||||
var->setGamma(rng.uniform(0.1f, 10.0f));
|
||||
var->setDelta(rng.uniform(0.1f, 10.0f));
|
||||
var->setSorIterations(rng.uniform(1, 20));
|
||||
var->setFixedPointIterations(rng.uniform(1, 20));
|
||||
var->setOmega(rng.uniform(1.01f, 1.99f));
|
||||
|
||||
cv::setNumThreads(nThreads);
|
||||
Mat resMultiThread;
|
||||
flow.copyTo(resMultiThread);
|
||||
var->calc(frame1, frame2, resMultiThread);
|
||||
|
||||
cv::setNumThreads(1);
|
||||
Mat resSingleThread;
|
||||
flow.copyTo(resSingleThread);
|
||||
var->calc(frame1, frame2, resSingleThread);
|
||||
|
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_INF), MAX_DIF);
|
||||
EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_L1), MAX_MEAN_DIF * frame1.total());
|
||||
|
||||
// resulting flow should be within the frame bounds:
|
||||
double min_val, max_val;
|
||||
minMaxLoc(resMultiThread, &min_val, &max_val);
|
||||
EXPECT_LE(abs(min_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) );
|
||||
EXPECT_LE(abs(max_val), sqrt( static_cast<double>(size.height * size.height + size.width * size.width)) );
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FullSet, DenseOpticalFlow_VariationalRefinement, Values(szODD, szQVGA));
|
||||
|
||||
}} // namespace
|
||||
249
3rdparty/opencv-4.5.4/modules/video/test/test_accum.cpp
vendored
Normal file
249
3rdparty/opencv-4.5.4/modules/video/test/test_accum.cpp
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_AccumBaseTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_AccumBaseTest();
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
double alpha;
|
||||
};
|
||||
|
||||
|
||||
CV_AccumBaseTest::CV_AccumBaseTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[INPUT_OUTPUT].push_back(NULL);
|
||||
test_array[REF_INPUT_OUTPUT].push_back(NULL);
|
||||
test_array[MASK].push_back(NULL);
|
||||
optional_mask = true;
|
||||
element_wise_relative_error = false;
|
||||
} // ctor
|
||||
|
||||
|
||||
void CV_AccumBaseTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int depth = cvtest::randInt(rng) % 4, cn = cvtest::randInt(rng) & 1 ? 3 : 1;
|
||||
int accdepth = (int)(cvtest::randInt(rng) % 2 + 1);
|
||||
int i, input_count = (int)test_array[INPUT].size();
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_32F : CV_64F;
|
||||
accdepth = accdepth == 1 ? CV_32F : CV_64F;
|
||||
accdepth = MAX(accdepth, depth);
|
||||
|
||||
for( i = 0; i < input_count; i++ )
|
||||
types[INPUT][i] = CV_MAKETYPE(depth,cn);
|
||||
|
||||
types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(accdepth,cn);
|
||||
|
||||
alpha = cvtest::randReal(rng);
|
||||
}
|
||||
|
||||
|
||||
double CV_AccumBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return test_mat[INPUT_OUTPUT][0].depth() < CV_64F ||
|
||||
test_mat[INPUT][0].depth() == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
|
||||
}
|
||||
|
||||
|
||||
/// acc
|
||||
class CV_AccTest : public CV_AccumBaseTest
|
||||
{
|
||||
public:
|
||||
CV_AccTest() { }
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
};
|
||||
|
||||
|
||||
void CV_AccTest::run_func(void)
|
||||
{
|
||||
cvAcc( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
|
||||
}
|
||||
|
||||
|
||||
void CV_AccTest::prepare_to_validation( int )
|
||||
{
|
||||
const Mat& src = test_mat[INPUT][0];
|
||||
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
|
||||
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
|
||||
Mat temp;
|
||||
cvtest::add( src, 1, dst, 1, cvScalarAll(0.), temp, dst.type() );
|
||||
cvtest::copy( temp, dst, mask );
|
||||
}
|
||||
|
||||
|
||||
/// square acc
|
||||
class CV_SquareAccTest : public CV_AccumBaseTest
|
||||
{
|
||||
public:
|
||||
CV_SquareAccTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
};
|
||||
|
||||
|
||||
CV_SquareAccTest::CV_SquareAccTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CV_SquareAccTest::run_func()
|
||||
{
|
||||
cvSquareAcc( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
|
||||
}
|
||||
|
||||
|
||||
void CV_SquareAccTest::prepare_to_validation( int )
|
||||
{
|
||||
const Mat& src = test_mat[INPUT][0];
|
||||
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
|
||||
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
|
||||
Mat temp;
|
||||
|
||||
cvtest::convert( src, temp, dst.type() );
|
||||
cvtest::multiply( temp, temp, temp, 1 );
|
||||
cvtest::add( temp, 1, dst, 1, cvScalarAll(0.), temp, dst.depth() );
|
||||
cvtest::copy( temp, dst, mask );
|
||||
}
|
||||
|
||||
|
||||
/// multiply acc
|
||||
class CV_MultiplyAccTest : public CV_AccumBaseTest
|
||||
{
|
||||
public:
|
||||
CV_MultiplyAccTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
};
|
||||
|
||||
|
||||
CV_MultiplyAccTest::CV_MultiplyAccTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
}
|
||||
|
||||
|
||||
void CV_MultiplyAccTest::run_func()
|
||||
{
|
||||
cvMultiplyAcc( test_array[INPUT][0], test_array[INPUT][1],
|
||||
test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
|
||||
}
|
||||
|
||||
|
||||
void CV_MultiplyAccTest::prepare_to_validation( int )
|
||||
{
|
||||
const Mat& src1 = test_mat[INPUT][0];
|
||||
const Mat& src2 = test_mat[INPUT][1];
|
||||
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
|
||||
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
|
||||
Mat temp1, temp2;
|
||||
|
||||
cvtest::convert( src1, temp1, dst.type() );
|
||||
cvtest::convert( src2, temp2, dst.type() );
|
||||
|
||||
cvtest::multiply( temp1, temp2, temp1, 1 );
|
||||
cvtest::add( temp1, 1, dst, 1, cvScalarAll(0.), temp1, dst.depth() );
|
||||
cvtest::copy( temp1, dst, mask );
|
||||
}
|
||||
|
||||
|
||||
/// running average
|
||||
class CV_RunningAvgTest : public CV_AccumBaseTest
|
||||
{
|
||||
public:
|
||||
CV_RunningAvgTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
};
|
||||
|
||||
|
||||
CV_RunningAvgTest::CV_RunningAvgTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CV_RunningAvgTest::run_func()
|
||||
{
|
||||
cvRunningAvg( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
|
||||
alpha, test_array[MASK][0] );
|
||||
}
|
||||
|
||||
|
||||
void CV_RunningAvgTest::prepare_to_validation( int )
|
||||
{
|
||||
const Mat& src = test_mat[INPUT][0];
|
||||
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
|
||||
Mat temp;
|
||||
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
|
||||
double a[1], b[1];
|
||||
int accdepth = test_mat[INPUT_OUTPUT][0].depth();
|
||||
CvMat A = cvMat(1,1,accdepth,a), B = cvMat(1,1,accdepth,b);
|
||||
cvSetReal1D( &A, 0, alpha);
|
||||
cvSetReal1D( &B, 0, 1 - cvGetReal1D(&A, 0));
|
||||
|
||||
cvtest::convert( src, temp, dst.type() );
|
||||
cvtest::add( src, cvGetReal1D(&A, 0), dst, cvGetReal1D(&B, 0), cvScalarAll(0.), temp, temp.depth() );
|
||||
cvtest::copy( temp, dst, mask );
|
||||
}
|
||||
|
||||
|
||||
TEST(Video_Acc, accuracy) { CV_AccTest test; test.safe_run(); }
|
||||
TEST(Video_AccSquared, accuracy) { CV_SquareAccTest test; test.safe_run(); }
|
||||
TEST(Video_AccProduct, accuracy) { CV_MultiplyAccTest test; test.safe_run(); }
|
||||
TEST(Video_RunningAvg, accuracy) { CV_RunningAvgTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
||||
466
3rdparty/opencv-4.5.4/modules/video/test/test_camshift.cpp
vendored
Normal file
466
3rdparty/opencv-4.5.4/modules/video/test/test_camshift.cpp
vendored
Normal file
@@ -0,0 +1,466 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class CV_TrackBaseTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_TrackBaseTest();
|
||||
virtual ~CV_TrackBaseTest();
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
int read_params( const cv::FileStorage& fs );
|
||||
void run_func(void);
|
||||
int prepare_test_case( int test_case_idx );
|
||||
int validate_test_results( int test_case_idx );
|
||||
void generate_object();
|
||||
|
||||
int min_log_size, max_log_size;
|
||||
Mat img;
|
||||
RotatedRect box0;
|
||||
Size img_size;
|
||||
TermCriteria criteria;
|
||||
int img_type;
|
||||
};
|
||||
|
||||
|
||||
CV_TrackBaseTest::CV_TrackBaseTest()
|
||||
{
|
||||
img = 0;
|
||||
test_case_count = 100;
|
||||
min_log_size = 5;
|
||||
max_log_size = 8;
|
||||
}
|
||||
|
||||
|
||||
CV_TrackBaseTest::~CV_TrackBaseTest()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void CV_TrackBaseTest::clear()
|
||||
{
|
||||
img.release();
|
||||
cvtest::BaseTest::clear();
|
||||
}
|
||||
|
||||
|
||||
int CV_TrackBaseTest::read_params( const cv::FileStorage& fs )
|
||||
{
|
||||
int code = cvtest::BaseTest::read_params( fs );
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
read( find_param( fs, "test_case_count" ), test_case_count, test_case_count );
|
||||
read( find_param( fs, "min_log_size" ), min_log_size, min_log_size );
|
||||
read( find_param( fs, "max_log_size" ), max_log_size, max_log_size );
|
||||
|
||||
min_log_size = cvtest::clipInt( min_log_size, 1, 10 );
|
||||
max_log_size = cvtest::clipInt( max_log_size, 1, 10 );
|
||||
if( min_log_size > max_log_size )
|
||||
{
|
||||
std::swap( min_log_size, max_log_size );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CV_TrackBaseTest::generate_object()
|
||||
{
|
||||
int x, y;
|
||||
double cx = box0.center.x;
|
||||
double cy = box0.center.y;
|
||||
double width = box0.size.width*0.5;
|
||||
double height = box0.size.height*0.5;
|
||||
double angle = box0.angle*CV_PI/180.;
|
||||
double a = sin(angle), b = -cos(angle);
|
||||
double inv_ww = 1./(width*width), inv_hh = 1./(height*height);
|
||||
|
||||
img = Mat::zeros( img_size.height, img_size.width, img_type );
|
||||
|
||||
// use the straightforward algorithm: for every pixel check if it is inside the ellipse
|
||||
for( y = 0; y < img_size.height; y++ )
|
||||
{
|
||||
uchar* ptr = img.ptr(y);
|
||||
float* fl = (float*)ptr;
|
||||
double x_ = (y - cy)*b, y_ = (y - cy)*a;
|
||||
|
||||
for( x = 0; x < img_size.width; x++ )
|
||||
{
|
||||
double x1 = (x - cx)*a - x_;
|
||||
double y1 = (x - cx)*b + y_;
|
||||
|
||||
if( x1*x1*inv_hh + y1*y1*inv_ww <= 1. )
|
||||
{
|
||||
if( img_type == CV_8U )
|
||||
ptr[x] = (uchar)1;
|
||||
else
|
||||
fl[x] = (float)1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CV_TrackBaseTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
cvtest::BaseTest::prepare_test_case( test_case_idx );
|
||||
float m;
|
||||
|
||||
clear();
|
||||
|
||||
box0.size.width = (float)exp((cvtest::randReal(rng) * (max_log_size - min_log_size) + min_log_size)*CV_LOG2);
|
||||
box0.size.height = (float)exp((cvtest::randReal(rng) * (max_log_size - min_log_size) + min_log_size)*CV_LOG2);
|
||||
box0.angle = (float)(cvtest::randReal(rng)*180.);
|
||||
|
||||
if( box0.size.width > box0.size.height )
|
||||
{
|
||||
std::swap( box0.size.width, box0.size.height );
|
||||
}
|
||||
|
||||
m = MAX( box0.size.width, box0.size.height );
|
||||
img_size.width = cvRound(cvtest::randReal(rng)*m*0.5 + m + 1);
|
||||
img_size.height = cvRound(cvtest::randReal(rng)*m*0.5 + m + 1);
|
||||
img_type = cvtest::randInt(rng) % 2 ? CV_32F : CV_8U;
|
||||
img_type = CV_8U;
|
||||
|
||||
box0.center.x = (float)(img_size.width*0.5 + (cvtest::randReal(rng)-0.5)*(img_size.width - m));
|
||||
box0.center.y = (float)(img_size.height*0.5 + (cvtest::randReal(rng)-0.5)*(img_size.height - m));
|
||||
|
||||
criteria = TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 10, 0.1 );
|
||||
|
||||
generate_object();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CV_TrackBaseTest::run_func(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int CV_TrackBaseTest::validate_test_results( int /*test_case_idx*/ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////// CamShift //////////////////////////////
|
||||
|
||||
class CV_CamShiftTest : public CV_TrackBaseTest
|
||||
{
|
||||
public:
|
||||
CV_CamShiftTest();
|
||||
|
||||
protected:
|
||||
void run_func(void);
|
||||
int prepare_test_case( int test_case_idx );
|
||||
int validate_test_results( int test_case_idx );
|
||||
void generate_object();
|
||||
|
||||
RotatedRect box;
|
||||
Rect init_rect;
|
||||
int area0;
|
||||
};
|
||||
|
||||
|
||||
CV_CamShiftTest::CV_CamShiftTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int CV_CamShiftTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
double m;
|
||||
int code = CV_TrackBaseTest::prepare_test_case( test_case_idx );
|
||||
int i, area;
|
||||
|
||||
if( code <= 0 )
|
||||
return code;
|
||||
|
||||
area0 = countNonZero(img);
|
||||
|
||||
for(i = 0; i < 100; i++)
|
||||
{
|
||||
m = MAX(box0.size.width,box0.size.height)*0.8;
|
||||
init_rect.x = cvFloor(box0.center.x - m*(0.45 + cvtest::randReal(rng)*0.2));
|
||||
init_rect.y = cvFloor(box0.center.y - m*(0.45 + cvtest::randReal(rng)*0.2));
|
||||
init_rect.width = cvCeil(box0.center.x + m*(0.45 + cvtest::randReal(rng)*0.2) - init_rect.x);
|
||||
init_rect.height = cvCeil(box0.center.y + m*(0.45 + cvtest::randReal(rng)*0.2) - init_rect.y);
|
||||
|
||||
if( init_rect.x < 0 || init_rect.y < 0 ||
|
||||
init_rect.x + init_rect.width >= img_size.width ||
|
||||
init_rect.y + init_rect.height >= img_size.height )
|
||||
continue;
|
||||
|
||||
Mat temp = img(init_rect);
|
||||
area = countNonZero( temp );
|
||||
|
||||
if( area >= 0.1*area0 )
|
||||
break;
|
||||
}
|
||||
|
||||
return i < 100 ? code : 0;
|
||||
}
|
||||
|
||||
|
||||
void CV_CamShiftTest::run_func(void)
|
||||
{
|
||||
box = CamShift( img, init_rect, criteria );
|
||||
}
|
||||
|
||||
|
||||
int CV_CamShiftTest::validate_test_results( int /*test_case_idx*/ )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
double m = MAX(box0.size.width, box0.size.height);
|
||||
double diff_angle;
|
||||
|
||||
if( cvIsNaN(box.size.width) || cvIsInf(box.size.width) || box.size.width <= 0 ||
|
||||
cvIsNaN(box.size.height) || cvIsInf(box.size.height) || box.size.height <= 0 ||
|
||||
cvIsNaN(box.center.x) || cvIsInf(box.center.x) ||
|
||||
cvIsNaN(box.center.y) || cvIsInf(box.center.y) ||
|
||||
cvIsNaN(box.angle) || cvIsInf(box.angle) || box.angle < -180 || box.angle > 180 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Invalid CvBox2D or CvConnectedComp was returned by cvCamShift\n" );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
box.angle = (float)(180 - box.angle);
|
||||
|
||||
if( fabs(box.size.width - box0.size.width) > box0.size.width*0.2 ||
|
||||
fabs(box.size.height - box0.size.height) > box0.size.height*0.3 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D size (=%.1f x %.1f, should be %.1f x %.1f)\n",
|
||||
box.size.width, box.size.height, box0.size.width, box0.size.height );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
if( fabs(box.center.x - box0.center.x) > m*0.1 ||
|
||||
fabs(box.center.y - box0.center.y) > m*0.1 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D position (=(%.1f, %.1f), should be (%.1f, %.1f))\n",
|
||||
box.center.x, box.center.y, box0.center.x, box0.center.y );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
if( box.angle < 0 )
|
||||
box.angle += 180;
|
||||
|
||||
diff_angle = fabs(box0.angle - box.angle);
|
||||
diff_angle = MIN( diff_angle, fabs(box0.angle - box.angle + 180));
|
||||
|
||||
if( fabs(diff_angle) > 30 && box0.size.height > box0.size.width*1.2 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D angle (=%1.f, should be %1.f)\n",
|
||||
box.angle, box0.angle );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
_exit_:
|
||||
|
||||
if( code < 0 )
|
||||
{
|
||||
#if 0 //defined _DEBUG && defined _WIN32
|
||||
IplImage* dst = cvCreateImage( img_size, 8, 3 );
|
||||
cvNamedWindow( "test", 1 );
|
||||
cvCmpS( img, 0, img, CV_CMP_GT );
|
||||
cvCvtColor( img, dst, CV_GRAY2BGR );
|
||||
cvRectangle( dst, cvPoint(init_rect.x, init_rect.y),
|
||||
cvPoint(init_rect.x + init_rect.width, init_rect.y + init_rect.height),
|
||||
CV_RGB(255,0,0), 3, 8, 0 );
|
||||
cvEllipseBox( dst, box, CV_RGB(0,255,0), 3, 8, 0 );
|
||||
cvShowImage( "test", dst );
|
||||
cvReleaseImage( &dst );
|
||||
cvWaitKey();
|
||||
#endif
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////// MeanShift //////////////////////////////
|
||||
|
||||
class CV_MeanShiftTest : public CV_TrackBaseTest
|
||||
{
|
||||
public:
|
||||
CV_MeanShiftTest();
|
||||
|
||||
protected:
|
||||
void run_func(void);
|
||||
int prepare_test_case( int test_case_idx );
|
||||
int validate_test_results( int test_case_idx );
|
||||
void generate_object();
|
||||
|
||||
Rect init_rect, rect;
|
||||
int area0, area;
|
||||
};
|
||||
|
||||
|
||||
CV_MeanShiftTest::CV_MeanShiftTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int CV_MeanShiftTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
double m;
|
||||
int code = CV_TrackBaseTest::prepare_test_case( test_case_idx );
|
||||
int i;
|
||||
|
||||
if( code <= 0 )
|
||||
return code;
|
||||
|
||||
area0 = countNonZero(img);
|
||||
|
||||
for(i = 0; i < 100; i++)
|
||||
{
|
||||
m = (box0.size.width + box0.size.height)*0.5;
|
||||
init_rect.x = cvFloor(box0.center.x - m*(0.4 + cvtest::randReal(rng)*0.2));
|
||||
init_rect.y = cvFloor(box0.center.y - m*(0.4 + cvtest::randReal(rng)*0.2));
|
||||
init_rect.width = cvCeil(box0.center.x + m*(0.4 + cvtest::randReal(rng)*0.2) - init_rect.x);
|
||||
init_rect.height = cvCeil(box0.center.y + m*(0.4 + cvtest::randReal(rng)*0.2) - init_rect.y);
|
||||
|
||||
if( init_rect.x < 0 || init_rect.y < 0 ||
|
||||
init_rect.x + init_rect.width >= img_size.width ||
|
||||
init_rect.y + init_rect.height >= img_size.height )
|
||||
continue;
|
||||
|
||||
Mat temp = img(init_rect);
|
||||
area = countNonZero( temp );
|
||||
|
||||
if( area >= 0.5*area0 )
|
||||
break;
|
||||
}
|
||||
|
||||
return i < 100 ? code : 0;
|
||||
}
|
||||
|
||||
|
||||
void CV_MeanShiftTest::run_func(void)
|
||||
{
|
||||
rect = init_rect;
|
||||
meanShift( img, rect, criteria );
|
||||
}
|
||||
|
||||
|
||||
int CV_MeanShiftTest::validate_test_results( int /*test_case_idx*/ )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
Point2f c;
|
||||
double m = MAX(box0.size.width, box0.size.height), delta;
|
||||
|
||||
c.x = (float)(rect.x + rect.width*0.5);
|
||||
c.y = (float)(rect.y + rect.height*0.5);
|
||||
|
||||
if( fabs(c.x - box0.center.x) > m*0.1 ||
|
||||
fabs(c.y - box0.center.y) > m*0.1 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D position (=(%.1f, %.1f), should be (%.1f, %.1f))\n",
|
||||
c.x, c.y, box0.center.x, box0.center.y );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
delta = m*0.7;
|
||||
|
||||
if( rect.x < box0.center.x - delta ||
|
||||
rect.y < box0.center.y - delta ||
|
||||
rect.x + rect.width > box0.center.x + delta ||
|
||||
rect.y + rect.height > box0.center.y + delta )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"Incorrect CvConnectedComp ((%d,%d,%d,%d) is not within (%.1f,%.1f,%.1f,%.1f))\n",
|
||||
rect.x, rect.y, rect.x + rect.width, rect.y + rect.height,
|
||||
box0.center.x - delta, box0.center.y - delta, box0.center.x + delta, box0.center.y + delta );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
_exit_:
|
||||
|
||||
if( code < 0 )
|
||||
{
|
||||
#if 0// defined _DEBUG && defined _WIN32
|
||||
IplImage* dst = cvCreateImage( img_size, 8, 3 );
|
||||
cvNamedWindow( "test", 1 );
|
||||
cvCmpS( img, 0, img, CV_CMP_GT );
|
||||
cvCvtColor( img, dst, CV_GRAY2BGR );
|
||||
cvRectangle( dst, cvPoint(init_rect.x, init_rect.y),
|
||||
cvPoint(init_rect.x + init_rect.width, init_rect.y + init_rect.height),
|
||||
CV_RGB(255,0,0), 3, 8, 0 );
|
||||
cvRectangle( dst, cvPoint(comp.rect.x, comp.rect.y),
|
||||
cvPoint(comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height),
|
||||
CV_RGB(0,255,0), 3, 8, 0 );
|
||||
cvShowImage( "test", dst );
|
||||
cvReleaseImage( &dst );
|
||||
cvWaitKey();
|
||||
#endif
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
TEST(Video_CAMShift, accuracy) { CV_CamShiftTest test; test.safe_run(); }
|
||||
TEST(Video_MeanShift, accuracy) { CV_MeanShiftTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
522
3rdparty/opencv-4.5.4/modules/video/test/test_ecc.cpp
vendored
Normal file
522
3rdparty/opencv-4.5.4/modules/video/test/test_ecc.cpp
vendored
Normal file
@@ -0,0 +1,522 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_ECC_BaseTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ECC_BaseTest();
|
||||
|
||||
protected:
|
||||
|
||||
double computeRMS(const Mat& mat1, const Mat& mat2);
|
||||
bool isMapCorrect(const Mat& mat);
|
||||
|
||||
|
||||
double MAX_RMS_ECC;//upper bound for RMS error
|
||||
int ntests;//number of tests per motion type
|
||||
int ECC_iterations;//number of iterations for ECC
|
||||
double ECC_epsilon; //we choose a negative value, so that
|
||||
// ECC_iterations are always executed
|
||||
};
|
||||
|
||||
CV_ECC_BaseTest::CV_ECC_BaseTest()
|
||||
{
|
||||
MAX_RMS_ECC=0.1;
|
||||
ntests = 3;
|
||||
ECC_iterations = 50;
|
||||
ECC_epsilon = -1; //-> negative value means that ECC_Iterations will be executed
|
||||
}
|
||||
|
||||
|
||||
bool CV_ECC_BaseTest::isMapCorrect(const Mat& map)
|
||||
{
|
||||
bool tr = true;
|
||||
float mapVal;
|
||||
for(int i =0; i<map.rows; i++)
|
||||
for(int j=0; j<map.cols; j++){
|
||||
mapVal = map.at<float>(i, j);
|
||||
tr = tr & (!cvIsNaN(mapVal) && (fabs(mapVal) < 1e9));
|
||||
}
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
double CV_ECC_BaseTest::computeRMS(const Mat& mat1, const Mat& mat2){
|
||||
|
||||
CV_Assert(mat1.rows == mat2.rows);
|
||||
CV_Assert(mat1.cols == mat2.cols);
|
||||
|
||||
Mat errorMat;
|
||||
subtract(mat1, mat2, errorMat);
|
||||
|
||||
return sqrt(errorMat.dot(errorMat)/(mat1.rows*mat1.cols));
|
||||
}
|
||||
|
||||
class CV_ECC_Test_Translation : public CV_ECC_BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ECC_Test_Translation();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool testTranslation(int);
|
||||
};
|
||||
|
||||
CV_ECC_Test_Translation::CV_ECC_Test_Translation(){}
|
||||
|
||||
bool CV_ECC_Test_Translation::testTranslation(int from)
|
||||
{
|
||||
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
|
||||
|
||||
|
||||
if (img.empty())
|
||||
{
|
||||
ts->printf( ts->LOG, "test image can not be read");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
Mat testImg;
|
||||
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
|
||||
|
||||
cv::RNG rng = ts->get_rng();
|
||||
|
||||
int progress=0;
|
||||
|
||||
for (int k=from; k<ntests; k++){
|
||||
|
||||
ts->update_context( this, k, true );
|
||||
progress = update_progress(progress, k, ntests, 0);
|
||||
|
||||
Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
|
||||
0, 1, (rng.uniform(10.f, 20.f)));
|
||||
|
||||
Mat warpedImage;
|
||||
|
||||
warpAffine(testImg, warpedImage, translationGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
|
||||
Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
|
||||
|
||||
findTransformECC(warpedImage, testImg, mapTranslation, 0,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
|
||||
|
||||
if (!isMapCorrect(mapTranslation)){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( ts->LOG, "RMS = %f",
|
||||
computeRMS(mapTranslation, translationGround));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CV_ECC_Test_Translation::run(int from)
|
||||
{
|
||||
|
||||
if (!testTranslation(from))
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CV_ECC_Test_Euclidean : public CV_ECC_BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ECC_Test_Euclidean();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool testEuclidean(int);
|
||||
};
|
||||
|
||||
CV_ECC_Test_Euclidean::CV_ECC_Test_Euclidean() { }
|
||||
|
||||
bool CV_ECC_Test_Euclidean::testEuclidean(int from)
|
||||
{
|
||||
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
|
||||
|
||||
|
||||
if (img.empty())
|
||||
{
|
||||
ts->printf( ts->LOG, "test image can not be read");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
Mat testImg;
|
||||
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
|
||||
|
||||
cv::RNG rng = ts->get_rng();
|
||||
|
||||
int progress = 0;
|
||||
for (int k=from; k<ntests; k++){
|
||||
ts->update_context( this, k, true );
|
||||
progress = update_progress(progress, k, ntests, 0);
|
||||
|
||||
double angle = CV_PI/30 + CV_PI*rng.uniform((double)-2.f, (double)2.f)/180;
|
||||
|
||||
Mat euclideanGround = (Mat_<float>(2,3) << cos(angle), -sin(angle), (rng.uniform(10.f, 20.f)),
|
||||
sin(angle), cos(angle), (rng.uniform(10.f, 20.f)));
|
||||
|
||||
Mat warpedImage;
|
||||
|
||||
warpAffine(testImg, warpedImage, euclideanGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
|
||||
Mat mapEuclidean = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
|
||||
|
||||
findTransformECC(warpedImage, testImg, mapEuclidean, 1,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
|
||||
|
||||
if (!isMapCorrect(mapEuclidean)){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (computeRMS(mapEuclidean, euclideanGround)>MAX_RMS_ECC){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( ts->LOG, "RMS = %f",
|
||||
computeRMS(mapEuclidean, euclideanGround));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CV_ECC_Test_Euclidean::run(int from)
|
||||
{
|
||||
|
||||
if (!testEuclidean(from))
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
class CV_ECC_Test_Affine : public CV_ECC_BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ECC_Test_Affine();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool testAffine(int);
|
||||
};
|
||||
|
||||
CV_ECC_Test_Affine::CV_ECC_Test_Affine(){}
|
||||
|
||||
|
||||
bool CV_ECC_Test_Affine::testAffine(int from)
|
||||
{
|
||||
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
|
||||
|
||||
if (img.empty())
|
||||
{
|
||||
ts->printf( ts->LOG, "test image can not be read");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
Mat testImg;
|
||||
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
|
||||
|
||||
cv::RNG rng = ts->get_rng();
|
||||
|
||||
int progress = 0;
|
||||
for (int k=from; k<ntests; k++){
|
||||
ts->update_context( this, k, true );
|
||||
progress = update_progress(progress, k, ntests, 0);
|
||||
|
||||
|
||||
Mat affineGround = (Mat_<float>(2,3) << (1-rng.uniform(-0.05f, 0.05f)),
|
||||
(rng.uniform(-0.03f, 0.03f)), (rng.uniform(10.f, 20.f)),
|
||||
(rng.uniform(-0.03f, 0.03f)), (1-rng.uniform(-0.05f, 0.05f)),
|
||||
(rng.uniform(10.f, 20.f)));
|
||||
|
||||
Mat warpedImage;
|
||||
|
||||
warpAffine(testImg, warpedImage, affineGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
|
||||
Mat mapAffine = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
|
||||
|
||||
findTransformECC(warpedImage, testImg, mapAffine, 2,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
|
||||
|
||||
if (!isMapCorrect(mapAffine)){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (computeRMS(mapAffine, affineGround)>MAX_RMS_ECC){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( ts->LOG, "RMS = %f",
|
||||
computeRMS(mapAffine, affineGround));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CV_ECC_Test_Affine::run(int from)
|
||||
{
|
||||
|
||||
if (!testAffine(from))
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
class CV_ECC_Test_Homography : public CV_ECC_BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ECC_Test_Homography();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool testHomography(int);
|
||||
};
|
||||
|
||||
CV_ECC_Test_Homography::CV_ECC_Test_Homography(){}
|
||||
|
||||
bool CV_ECC_Test_Homography::testHomography(int from)
|
||||
{
|
||||
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
|
||||
|
||||
|
||||
if (img.empty())
|
||||
{
|
||||
ts->printf( ts->LOG, "test image can not be read");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
Mat testImg;
|
||||
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
|
||||
|
||||
cv::RNG rng = ts->get_rng();
|
||||
|
||||
int progress = 0;
|
||||
for (int k=from; k<ntests; k++){
|
||||
ts->update_context( this, k, true );
|
||||
progress = update_progress(progress, k, ntests, 0);
|
||||
|
||||
Mat homoGround = (Mat_<float>(3,3) << (1-rng.uniform(-0.05f, 0.05f)),
|
||||
(rng.uniform(-0.03f, 0.03f)), (rng.uniform(10.f, 20.f)),
|
||||
(rng.uniform(-0.03f, 0.03f)), (1-rng.uniform(-0.05f, 0.05f)),(rng.uniform(10.f, 20.f)),
|
||||
(rng.uniform(0.0001f, 0.0003f)), (rng.uniform(0.0001f, 0.0003f)), 1.f);
|
||||
|
||||
Mat warpedImage;
|
||||
|
||||
warpPerspective(testImg, warpedImage, homoGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
|
||||
Mat mapHomography = Mat::eye(3, 3, CV_32F);
|
||||
|
||||
findTransformECC(warpedImage, testImg, mapHomography, 3,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
|
||||
|
||||
if (!isMapCorrect(mapHomography)){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (computeRMS(mapHomography, homoGround)>MAX_RMS_ECC){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( ts->LOG, "RMS = %f",
|
||||
computeRMS(mapHomography, homoGround));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CV_ECC_Test_Homography::run(int from)
|
||||
{
|
||||
if (!testHomography(from))
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
class CV_ECC_Test_Mask : public CV_ECC_BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ECC_Test_Mask();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool testMask(int);
|
||||
};
|
||||
|
||||
CV_ECC_Test_Mask::CV_ECC_Test_Mask(){}
|
||||
|
||||
bool CV_ECC_Test_Mask::testMask(int from)
|
||||
{
|
||||
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
|
||||
|
||||
|
||||
if (img.empty())
|
||||
{
|
||||
ts->printf( ts->LOG, "test image can not be read");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
Mat scaledImage;
|
||||
resize(img, scaledImage, Size(216, 216), 0, 0, INTER_LINEAR_EXACT );
|
||||
|
||||
Mat_<float> testImg;
|
||||
scaledImage.convertTo(testImg, testImg.type());
|
||||
|
||||
cv::RNG rng = ts->get_rng();
|
||||
|
||||
int progress=0;
|
||||
|
||||
for (int k=from; k<ntests; k++){
|
||||
|
||||
ts->update_context( this, k, true );
|
||||
progress = update_progress(progress, k, ntests, 0);
|
||||
|
||||
Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
|
||||
0, 1, (rng.uniform(10.f, 20.f)));
|
||||
|
||||
Mat warpedImage;
|
||||
|
||||
warpAffine(testImg, warpedImage, translationGround,
|
||||
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
|
||||
|
||||
Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
|
||||
|
||||
Mat_<unsigned char> mask = Mat_<unsigned char>::ones(testImg.rows, testImg.cols);
|
||||
for (int i=testImg.rows*2/3; i<testImg.rows; i++) {
|
||||
for (int j=testImg.cols*2/3; j<testImg.cols; j++) {
|
||||
testImg(i, j) = 0;
|
||||
mask(i, j) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
findTransformECC(warpedImage, testImg, mapTranslation, 0,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon), mask);
|
||||
|
||||
if (!isMapCorrect(mapTranslation)){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( ts->LOG, "RMS = %f",
|
||||
computeRMS(mapTranslation, translationGround));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test with non-default gaussian blur.
|
||||
findTransformECC(warpedImage, testImg, mapTranslation, 0,
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon), mask, 1);
|
||||
|
||||
if (!isMapCorrect(mapTranslation)){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( ts->LOG, "RMS = %f",
|
||||
computeRMS(mapTranslation, translationGround));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CV_ECC_Test_Mask::run(int from)
|
||||
{
|
||||
if (!testMask(from))
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Video_ECC_Test_Compute, accuracy)
|
||||
{
|
||||
Mat testImg = (Mat_<float>(3, 3) << 1, 0, 0, 1, 0, 0, 1, 0, 0);
|
||||
Mat warpedImage = (Mat_<float>(3, 3) << 0, 1, 0, 0, 1, 0, 0, 1, 0);
|
||||
Mat_<unsigned char> mask = Mat_<unsigned char>::ones(testImg.rows, testImg.cols);
|
||||
double ecc = computeECC(warpedImage, testImg, mask);
|
||||
|
||||
EXPECT_NEAR(ecc, -0.5f, 1e-5f);
|
||||
}
|
||||
|
||||
TEST(Video_ECC_Test_Compute, bug_14657)
|
||||
{
|
||||
/*
|
||||
* Simple test case - a 2 x 2 matrix with 10, 10, 10, 6. When the mean (36 / 4 = 9) is subtracted,
|
||||
* it results in 1, 1, 1, 0 for the unsigned int case - compare to 1, 1, 1, -3 in the signed case.
|
||||
* For this reason, when the same matrix was provided as the input and the template, we didn't get 1 as expected.
|
||||
*/
|
||||
Mat img = (Mat_<uint8_t>(2, 2) << 10, 10, 10, 6);
|
||||
EXPECT_NEAR(computeECC(img, img), 1.0f, 1e-5f);
|
||||
}
|
||||
|
||||
|
||||
TEST(Video_ECC_Translation, accuracy) { CV_ECC_Test_Translation test; test.safe_run();}
|
||||
TEST(Video_ECC_Euclidean, accuracy) { CV_ECC_Test_Euclidean test; test.safe_run(); }
|
||||
TEST(Video_ECC_Affine, accuracy) { CV_ECC_Test_Affine test; test.safe_run(); }
|
||||
TEST(Video_ECC_Homography, accuracy) { CV_ECC_Test_Homography test; test.safe_run(); }
|
||||
TEST(Video_ECC_Mask, accuracy) { CV_ECC_Test_Mask test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
||||
184
3rdparty/opencv-4.5.4/modules/video/test/test_estimaterigid.cpp
vendored
Normal file
184
3rdparty/opencv-4.5.4/modules/video/test/test_estimaterigid.cpp
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
// this is test for a deprecated function. let's ignore deprecated warnings in this file
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning( disable : 4996)
|
||||
#endif
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_RigidTransform_Test : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_RigidTransform_Test();
|
||||
~CV_RigidTransform_Test();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool testNPoints(int);
|
||||
bool testImage();
|
||||
};
|
||||
|
||||
CV_RigidTransform_Test::CV_RigidTransform_Test()
|
||||
{
|
||||
}
|
||||
CV_RigidTransform_Test::~CV_RigidTransform_Test() {}
|
||||
|
||||
struct WrapAff2D
|
||||
{
|
||||
const double *F;
|
||||
WrapAff2D(const Mat& aff) : F(aff.ptr<double>()) {}
|
||||
Point2f operator()(const Point2f& p)
|
||||
{
|
||||
return Point2f( (float)(p.x * F[0] + p.y * F[1] + F[2]),
|
||||
(float)(p.x * F[3] + p.y * F[4] + F[5]) );
|
||||
}
|
||||
};
|
||||
|
||||
bool CV_RigidTransform_Test::testNPoints(int from)
|
||||
{
|
||||
cv::RNG rng = ts->get_rng();
|
||||
|
||||
int progress = 0;
|
||||
int k, ntests = 10000;
|
||||
|
||||
for( k = from; k < ntests; k++ )
|
||||
{
|
||||
ts->update_context( this, k, true );
|
||||
progress = update_progress(progress, k, ntests, 0);
|
||||
|
||||
Mat aff(2, 3, CV_64F);
|
||||
rng.fill(aff, RNG::UNIFORM, Scalar(-2), Scalar(2));
|
||||
|
||||
int n = (unsigned)rng % 100 + 10;
|
||||
|
||||
Mat fpts(1, n, CV_32FC2);
|
||||
Mat tpts(1, n, CV_32FC2);
|
||||
|
||||
rng.fill(fpts, RNG::UNIFORM, Scalar(0,0), Scalar(10,10));
|
||||
std::transform(fpts.ptr<Point2f>(), fpts.ptr<Point2f>() + n, tpts.ptr<Point2f>(), WrapAff2D(aff));
|
||||
|
||||
Mat noise(1, n, CV_32FC2);
|
||||
rng.fill(noise, RNG::NORMAL, Scalar::all(0), Scalar::all(0.001*(n<=7 ? 0 : n <= 30 ? 1 : 10)));
|
||||
tpts += noise;
|
||||
|
||||
Mat aff_est = estimateRigidTransform(fpts, tpts, true);
|
||||
|
||||
double thres = 0.1*cvtest::norm(aff, NORM_L2);
|
||||
double d = cvtest::norm(aff_est, aff, NORM_L2);
|
||||
if (d > thres)
|
||||
{
|
||||
double dB=0, nB=0;
|
||||
if (n <= 4)
|
||||
{
|
||||
Mat A = fpts.reshape(1, 3);
|
||||
Mat B = A - repeat(A.row(0), 3, 1), Bt = B.t();
|
||||
B = Bt*B;
|
||||
dB = cv::determinant(B);
|
||||
nB = cvtest::norm(B, NORM_L2);
|
||||
if( fabs(dB) < 0.01*nB )
|
||||
continue;
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( cvtest::TS::LOG, "Threshold = %f, norm of difference = %f", thres, d );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CV_RigidTransform_Test::testImage()
|
||||
{
|
||||
Mat img;
|
||||
Mat testImg = imread( string(ts->get_data_path()) + "shared/graffiti.png", 1);
|
||||
if (testImg.empty())
|
||||
{
|
||||
ts->printf( ts->LOG, "test image can not be read");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
pyrDown(testImg, img);
|
||||
|
||||
Mat aff = cv::getRotationMatrix2D(Point(img.cols/2, img.rows/2), 1, 0.99);
|
||||
aff.ptr<double>()[2]+=3;
|
||||
aff.ptr<double>()[5]+=3;
|
||||
|
||||
Mat rotated;
|
||||
warpAffine(img, rotated, aff, img.size());
|
||||
|
||||
Mat aff_est = estimateRigidTransform(img, rotated, true);
|
||||
|
||||
const double thres = 0.033;
|
||||
if (cvtest::norm(aff_est, aff, NORM_INF) > thres)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( cvtest::TS::LOG, "Threshold = %f, norm of difference = %f", thres,
|
||||
cvtest::norm(aff_est, aff, NORM_INF) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CV_RigidTransform_Test::run( int start_from )
|
||||
{
|
||||
cvtest::DefaultRngAuto dra;
|
||||
|
||||
if (!testNPoints(start_from))
|
||||
return;
|
||||
|
||||
if (!testImage())
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Video_RigidFlow, accuracy) { CV_RigidTransform_Test test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
||||
113
3rdparty/opencv-4.5.4/modules/video/test/test_kalman.cpp
vendored
Normal file
113
3rdparty/opencv-4.5.4/modules/video/test/test_kalman.cpp
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_KalmanTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_KalmanTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
CV_KalmanTest::CV_KalmanTest()
|
||||
{
|
||||
}
|
||||
|
||||
void CV_KalmanTest::run( int )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
const int Dim = 7;
|
||||
const int Steps = 100;
|
||||
const double max_init = 1;
|
||||
const double max_noise = 0.1;
|
||||
|
||||
const double EPSILON = 1.000;
|
||||
RNG& rng = ts->get_rng();
|
||||
int i, j;
|
||||
|
||||
cv::Mat Sample(Dim,1,CV_32F);
|
||||
cv::Mat Temp(Dim,1,CV_32F);
|
||||
|
||||
cv::KalmanFilter Kalm(Dim, Dim);
|
||||
Kalm.transitionMatrix = cv::Mat::eye(Dim, Dim, CV_32F);
|
||||
Kalm.measurementMatrix = cv::Mat::eye(Dim, Dim, CV_32F);
|
||||
Kalm.processNoiseCov = cv::Mat::eye(Dim, Dim, CV_32F);
|
||||
Kalm.errorCovPre = cv::Mat::eye(Dim, Dim, CV_32F);
|
||||
Kalm.errorCovPost = cv::Mat::eye(Dim, Dim, CV_32F);
|
||||
Kalm.measurementNoiseCov = cv::Mat::zeros(Dim, Dim, CV_32F);
|
||||
Kalm.statePre = cv::Mat::zeros(Dim, 1, CV_32F);
|
||||
Kalm.statePost = cv::Mat::zeros(Dim, 1, CV_32F);
|
||||
cvtest::randUni(rng, Sample, Scalar::all(-max_init), Scalar::all(max_init));
|
||||
Kalm.correct(Sample);
|
||||
for(i = 0; i<Steps; i++)
|
||||
{
|
||||
Kalm.predict();
|
||||
const Mat& Dyn = Kalm.transitionMatrix;
|
||||
for(j = 0; j<Dim; j++)
|
||||
{
|
||||
float t = 0;
|
||||
for(int k=0; k<Dim; k++)
|
||||
{
|
||||
t += Dyn.at<float>(j,k)*Sample.at<float>(k);
|
||||
}
|
||||
Temp.at<float>(j) = (float)(t+(cvtest::randReal(rng)*2-1)*max_noise);
|
||||
}
|
||||
Temp.copyTo(Sample);
|
||||
Kalm.correct(Temp);
|
||||
}
|
||||
|
||||
Mat _state_post = Kalm.statePost;
|
||||
code = cvtest::cmpEps2( ts, Sample, _state_post, EPSILON, false, "The final estimated state" );
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(Video_Kalman, accuracy) { CV_KalmanTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
25
3rdparty/opencv-4.5.4/modules/video/test/test_main.cpp
vendored
Normal file
25
3rdparty/opencv-4.5.4/modules/video/test/test_main.cpp
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
static
|
||||
void initTests()
|
||||
{
|
||||
const char* extraTestDataPath =
|
||||
#ifdef WINRT
|
||||
NULL;
|
||||
#else
|
||||
getenv("OPENCV_DNN_TEST_DATA_PATH");
|
||||
#endif
|
||||
if (extraTestDataPath)
|
||||
cvtest::addDataSearchPath(extraTestDataPath);
|
||||
|
||||
cvtest::addDataSearchSubDirectory(""); // override "cv" prefix below to access without "../dnn" hacks
|
||||
}
|
||||
|
||||
CV_TEST_MAIN("cv", initTests())
|
||||
257
3rdparty/opencv-4.5.4/modules/video/test/test_optflowpyrlk.cpp
vendored
Normal file
257
3rdparty/opencv-4.5.4/modules/video/test/test_optflowpyrlk.cpp
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/* ///////////////////// pyrlk_test ///////////////////////// */
|
||||
|
||||
class CV_OptFlowPyrLKTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_OptFlowPyrLKTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
CV_OptFlowPyrLKTest::CV_OptFlowPyrLKTest() {}
|
||||
|
||||
void CV_OptFlowPyrLKTest::run( int )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
const double success_error_level = 0.3;
|
||||
const int bad_points_max = 8;
|
||||
|
||||
/* test parameters */
|
||||
double max_err = 0., sum_err = 0;
|
||||
int pt_cmpd = 0;
|
||||
int pt_exceed = 0;
|
||||
int merr_i = 0, merr_j = 0, merr_k = 0, merr_nan = 0;
|
||||
char filename[1000];
|
||||
|
||||
cv::Point2f *v = 0, *v2 = 0;
|
||||
cv::Mat _u, _v, _v2;
|
||||
|
||||
cv::Mat imgI, imgJ;
|
||||
|
||||
int n = 0, i = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "lk_prev.dat" );
|
||||
|
||||
{
|
||||
FileStorage fs(filename, FileStorage::READ);
|
||||
fs["points"] >> _u;
|
||||
if( _u.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "lk_next.dat" );
|
||||
|
||||
{
|
||||
FileStorage fs(filename, FileStorage::READ);
|
||||
fs["points"] >> _v;
|
||||
if( _v.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( _u.cols != 2 || _u.type() != CV_32F ||
|
||||
_v.cols != 2 || _v.type() != CV_32F ||
|
||||
_v.rows != _u.rows )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the loaded matrices of points are not valid\n" );
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* read first image */
|
||||
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "rock_1.bmp" );
|
||||
imgI = cv::imread( filename, cv::IMREAD_UNCHANGED );
|
||||
|
||||
if( imgI.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
/* read second image */
|
||||
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "rock_2.bmp" );
|
||||
imgJ = cv::imread( filename, cv::IMREAD_UNCHANGED );
|
||||
|
||||
if( imgJ.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
n = _u.rows;
|
||||
std::vector<uchar> status(n, (uchar)0);
|
||||
|
||||
/* calculate flow */
|
||||
calcOpticalFlowPyrLK(imgI, imgJ, _u, _v2, status, cv::noArray(), Size( 41, 41 ), 4,
|
||||
TermCriteria( TermCriteria::MAX_ITER + TermCriteria::EPS, 30, 0.01f ), 0 );
|
||||
|
||||
v = (cv::Point2f*)_v.ptr();
|
||||
v2 = (cv::Point2f*)_v2.ptr();
|
||||
|
||||
/* compare results */
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
if( status[i] != 0 )
|
||||
{
|
||||
double err;
|
||||
if( cvIsNaN(v[i].x) || cvIsNaN(v[i].y) )
|
||||
{
|
||||
merr_j++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( cvIsNaN(v2[i].x) || cvIsNaN(v2[i].y) )
|
||||
{
|
||||
merr_nan++;
|
||||
continue;
|
||||
}
|
||||
|
||||
err = fabs(v2[i].x - v[i].x) + fabs(v2[i].y - v[i].y);
|
||||
if( err > max_err )
|
||||
{
|
||||
max_err = err;
|
||||
merr_i = i;
|
||||
}
|
||||
|
||||
pt_exceed += err > success_error_level;
|
||||
sum_err += err;
|
||||
pt_cmpd++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !cvIsNaN( v[i].x ))
|
||||
{
|
||||
merr_i = i;
|
||||
merr_k++;
|
||||
ts->printf( cvtest::TS::LOG, "The algorithm lost the point #%d\n", i );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( i < n )
|
||||
break;
|
||||
|
||||
if( pt_exceed > bad_points_max )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"The number of poorly tracked points is too big (>=%d)\n", pt_exceed );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
break;
|
||||
}
|
||||
|
||||
if( max_err > 1 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Maximum tracking error is too big (=%g) at %d\n", max_err, merr_i );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
break;
|
||||
}
|
||||
|
||||
if( merr_nan > 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "NAN tracking result with status != 0 (%d times)\n", merr_nan );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
|
||||
TEST(Video_OpticalFlowPyrLK, accuracy) { CV_OptFlowPyrLKTest test; test.safe_run(); }
|
||||
|
||||
TEST(Video_OpticalFlowPyrLK, submat)
|
||||
{
|
||||
// see bug #2075
|
||||
std::string path = cvtest::TS::ptr()->get_data_path() + "../cv/shared/lena.png";
|
||||
|
||||
cv::Mat lenaImg = cv::imread(path);
|
||||
ASSERT_FALSE(lenaImg.empty());
|
||||
|
||||
cv::Mat wholeImage;
|
||||
cv::resize(lenaImg, wholeImage, cv::Size(1024, 1024), 0, 0, cv::INTER_LINEAR_EXACT);
|
||||
|
||||
cv::Mat img1 = wholeImage(cv::Rect(0, 0, 640, 360)).clone();
|
||||
cv::Mat img2 = wholeImage(cv::Rect(40, 60, 640, 360));
|
||||
|
||||
std::vector<uchar> status;
|
||||
std::vector<float> error;
|
||||
std::vector<cv::Point2f> prev;
|
||||
std::vector<cv::Point2f> next;
|
||||
|
||||
cv::RNG rng(123123);
|
||||
|
||||
for(int i = 0; i < 50; ++i)
|
||||
{
|
||||
int x = rng.uniform(0, 640);
|
||||
int y = rng.uniform(0, 360);
|
||||
|
||||
prev.push_back(cv::Point2f((float)x, (float)y));
|
||||
}
|
||||
|
||||
ASSERT_NO_THROW(cv::calcOpticalFlowPyrLK(img1, img2, prev, next, status, error));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
15
3rdparty/opencv-4.5.4/modules/video/test/test_precomp.hpp
vendored
Normal file
15
3rdparty/opencv-4.5.4/modules/video/test/test_precomp.hpp
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/video.hpp"
|
||||
#include <opencv2/ts/ts_perf.hpp>
|
||||
|
||||
namespace opencv_test {
|
||||
using namespace perf;
|
||||
}
|
||||
|
||||
#endif
|
||||
129
3rdparty/opencv-4.5.4/modules/video/test/test_trackers.cpp
vendored
Normal file
129
3rdparty/opencv-4.5.4/modules/video/test/test_trackers.cpp
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
//#define DEBUG_TEST
|
||||
#ifdef DEBUG_TEST
|
||||
#include <opencv2/highgui.hpp>
|
||||
#endif
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
//using namespace cv::tracking;
|
||||
|
||||
#define TESTSET_NAMES testing::Values("david", "dudek", "faceocc2")
|
||||
|
||||
const string TRACKING_DIR = "tracking";
|
||||
const string FOLDER_IMG = "data";
|
||||
const string FOLDER_OMIT_INIT = "initOmit";
|
||||
|
||||
#include "test_trackers.impl.hpp"
|
||||
|
||||
//[TESTDATA]
|
||||
PARAM_TEST_CASE(DistanceAndOverlap, string)
|
||||
{
|
||||
string dataset;
|
||||
virtual void SetUp()
|
||||
{
|
||||
dataset = GET_PARAM(0);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(DistanceAndOverlap, MIL)
|
||||
{
|
||||
TrackerTest<Tracker, Rect> test(TrackerMIL::create(), dataset, 30, .65f, NoTransform);
|
||||
test.run();
|
||||
}
|
||||
|
||||
TEST_P(DistanceAndOverlap, Shifted_Data_MIL)
|
||||
{
|
||||
TrackerTest<Tracker, Rect> test(TrackerMIL::create(), dataset, 30, .6f, CenterShiftLeft);
|
||||
test.run();
|
||||
}
|
||||
|
||||
/***************************************************************************************/
|
||||
//Tests with scaled initial window
|
||||
|
||||
TEST_P(DistanceAndOverlap, Scaled_Data_MIL)
|
||||
{
|
||||
TrackerTest<Tracker, Rect> test(TrackerMIL::create(), dataset, 30, .7f, Scale_1_1);
|
||||
test.run();
|
||||
}
|
||||
|
||||
TEST_P(DistanceAndOverlap, GOTURN)
|
||||
{
|
||||
std::string model = cvtest::findDataFile("dnn/gsoc2016-goturn/goturn.prototxt");
|
||||
std::string weights = cvtest::findDataFile("dnn/gsoc2016-goturn/goturn.caffemodel", false);
|
||||
cv::TrackerGOTURN::Params params;
|
||||
params.modelTxt = model;
|
||||
params.modelBin = weights;
|
||||
TrackerTest<Tracker, Rect> test(TrackerGOTURN::create(params), dataset, 35, .35f, NoTransform);
|
||||
test.run();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Tracking, DistanceAndOverlap, TESTSET_NAMES);
|
||||
|
||||
TEST(GOTURN, memory_usage)
|
||||
{
|
||||
cv::Rect roi(145, 70, 85, 85);
|
||||
|
||||
std::string model = cvtest::findDataFile("dnn/gsoc2016-goturn/goturn.prototxt");
|
||||
std::string weights = cvtest::findDataFile("dnn/gsoc2016-goturn/goturn.caffemodel", false);
|
||||
cv::TrackerGOTURN::Params params;
|
||||
params.modelTxt = model;
|
||||
params.modelBin = weights;
|
||||
cv::Ptr<Tracker> tracker = TrackerGOTURN::create(params);
|
||||
|
||||
string inputVideo = cvtest::findDataFile("tracking/david/data/david.webm");
|
||||
cv::VideoCapture video(inputVideo);
|
||||
ASSERT_TRUE(video.isOpened()) << inputVideo;
|
||||
|
||||
cv::Mat frame;
|
||||
video >> frame;
|
||||
ASSERT_FALSE(frame.empty()) << inputVideo;
|
||||
tracker->init(frame, roi);
|
||||
string ground_truth_bb;
|
||||
for (int nframes = 0; nframes < 15; ++nframes)
|
||||
{
|
||||
std::cout << "Frame: " << nframes << std::endl;
|
||||
video >> frame;
|
||||
bool res = tracker->update(frame, roi);
|
||||
ASSERT_TRUE(res);
|
||||
std::cout << "Predicted ROI: " << roi << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DaSiamRPN, memory_usage)
|
||||
{
|
||||
cv::Rect roi(145, 70, 85, 85);
|
||||
|
||||
std::string model = cvtest::findDataFile("dnn/onnx/models/dasiamrpn_model.onnx", false);
|
||||
std::string kernel_r1 = cvtest::findDataFile("dnn/onnx/models/dasiamrpn_kernel_r1.onnx", false);
|
||||
std::string kernel_cls1 = cvtest::findDataFile("dnn/onnx/models/dasiamrpn_kernel_cls1.onnx", false);
|
||||
cv::TrackerDaSiamRPN::Params params;
|
||||
params.model = model;
|
||||
params.kernel_r1 = kernel_r1;
|
||||
params.kernel_cls1 = kernel_cls1;
|
||||
cv::Ptr<Tracker> tracker = TrackerDaSiamRPN::create(params);
|
||||
|
||||
string inputVideo = cvtest::findDataFile("tracking/david/data/david.webm");
|
||||
cv::VideoCapture video(inputVideo);
|
||||
ASSERT_TRUE(video.isOpened()) << inputVideo;
|
||||
|
||||
cv::Mat frame;
|
||||
video >> frame;
|
||||
ASSERT_FALSE(frame.empty()) << inputVideo;
|
||||
tracker->init(frame, roi);
|
||||
string ground_truth_bb;
|
||||
for (int nframes = 0; nframes < 15; ++nframes)
|
||||
{
|
||||
std::cout << "Frame: " << nframes << std::endl;
|
||||
video >> frame;
|
||||
bool res = tracker->update(frame, roi);
|
||||
ASSERT_TRUE(res);
|
||||
std::cout << "Predicted ROI: " << roi << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace opencv_test::
|
||||
369
3rdparty/opencv-4.5.4/modules/video/test/test_trackers.impl.hpp
vendored
Normal file
369
3rdparty/opencv-4.5.4/modules/video/test/test_trackers.impl.hpp
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/*
|
||||
* The Evaluation Methodologies are partially based on:
|
||||
* ====================================================================================================================
|
||||
* [OTB] Y. Wu, J. Lim, and M.-H. Yang, "Online object tracking: A benchmark," in Computer Vision and Pattern Recognition (CVPR), 2013
|
||||
*
|
||||
*/
|
||||
|
||||
enum BBTransformations
|
||||
{
|
||||
NoTransform = 0,
|
||||
CenterShiftLeft = 1,
|
||||
CenterShiftRight = 2,
|
||||
CenterShiftUp = 3,
|
||||
CenterShiftDown = 4,
|
||||
CornerShiftTopLeft = 5,
|
||||
CornerShiftTopRight = 6,
|
||||
CornerShiftBottomLeft = 7,
|
||||
CornerShiftBottomRight = 8,
|
||||
Scale_0_8 = 9,
|
||||
Scale_0_9 = 10,
|
||||
Scale_1_1 = 11,
|
||||
Scale_1_2 = 12
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<std::string> splitString(const std::string& s_, const std::string& delimiter)
|
||||
{
|
||||
std::string s = s_;
|
||||
std::vector<string> token;
|
||||
size_t pos = 0;
|
||||
while ((pos = s.find(delimiter)) != std::string::npos)
|
||||
{
|
||||
token.push_back(s.substr(0, pos));
|
||||
s.erase(0, pos + delimiter.length());
|
||||
}
|
||||
token.push_back(s);
|
||||
return token;
|
||||
}
|
||||
|
||||
float calcDistance(const Rect& a, const Rect& b)
|
||||
{
|
||||
Point2f p_a((float)(a.x + a.width / 2), (float)(a.y + a.height / 2));
|
||||
Point2f p_b((float)(b.x + b.width / 2), (float)(b.y + b.height / 2));
|
||||
Point2f diff = p_a - p_b;
|
||||
return sqrt(diff.dot(diff));
|
||||
}
|
||||
|
||||
float calcOverlap(const Rect& a, const Rect& b)
|
||||
{
|
||||
float rectIntersectionArea = (float)(a & b).area();
|
||||
return rectIntersectionArea / (a.area() + b.area() - rectIntersectionArea);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename Tracker, typename ROI_t = Rect2d>
|
||||
class TrackerTest
|
||||
{
|
||||
public:
|
||||
TrackerTest(const Ptr<Tracker>& tracker, const string& video, float distanceThreshold,
|
||||
float overlapThreshold, int shift = NoTransform, int segmentIdx = 1, int numSegments = 10);
|
||||
~TrackerTest() {}
|
||||
void run();
|
||||
|
||||
protected:
|
||||
void checkDataTest();
|
||||
|
||||
void distanceAndOverlapTest();
|
||||
|
||||
Ptr<Tracker> tracker;
|
||||
string video;
|
||||
std::vector<Rect> bbs;
|
||||
int startFrame;
|
||||
string suffix;
|
||||
string prefix;
|
||||
float overlapThreshold;
|
||||
float distanceThreshold;
|
||||
int segmentIdx;
|
||||
int shift;
|
||||
int numSegments;
|
||||
|
||||
int gtStartFrame;
|
||||
int endFrame;
|
||||
vector<int> validSequence;
|
||||
|
||||
private:
|
||||
Rect applyShift(const Rect& bb);
|
||||
};
|
||||
|
||||
template <typename Tracker, typename ROI_t>
|
||||
TrackerTest<Tracker, ROI_t>::TrackerTest(const Ptr<Tracker>& _tracker, const string& _video, float _distanceThreshold,
|
||||
float _overlapThreshold, int _shift, int _segmentIdx, int _numSegments)
|
||||
: tracker(_tracker)
|
||||
, video(_video)
|
||||
, overlapThreshold(_overlapThreshold)
|
||||
, distanceThreshold(_distanceThreshold)
|
||||
, segmentIdx(_segmentIdx)
|
||||
, shift(_shift)
|
||||
, numSegments(_numSegments)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
template <typename Tracker, typename ROI_t>
|
||||
Rect TrackerTest<Tracker, ROI_t>::applyShift(const Rect& bb_)
|
||||
{
|
||||
Rect bb = bb_;
|
||||
Point center(bb.x + (bb.width / 2), bb.y + (bb.height / 2));
|
||||
|
||||
int xLimit = bb.x + bb.width - 1;
|
||||
int yLimit = bb.y + bb.height - 1;
|
||||
|
||||
int h = 0;
|
||||
int w = 0;
|
||||
float ratio = 1.0;
|
||||
|
||||
switch (shift)
|
||||
{
|
||||
case CenterShiftLeft:
|
||||
bb.x = bb.x - (int)ceil(0.1 * bb.width);
|
||||
break;
|
||||
case CenterShiftRight:
|
||||
bb.x = bb.x + (int)ceil(0.1 * bb.width);
|
||||
break;
|
||||
case CenterShiftUp:
|
||||
bb.y = bb.y - (int)ceil(0.1 * bb.height);
|
||||
break;
|
||||
case CenterShiftDown:
|
||||
bb.y = bb.y + (int)ceil(0.1 * bb.height);
|
||||
break;
|
||||
case CornerShiftTopLeft:
|
||||
bb.x = (int)cvRound(bb.x - 0.1 * bb.width);
|
||||
bb.y = (int)cvRound(bb.y - 0.1 * bb.height);
|
||||
|
||||
bb.width = xLimit - bb.x + 1;
|
||||
bb.height = yLimit - bb.y + 1;
|
||||
break;
|
||||
case CornerShiftTopRight:
|
||||
xLimit = (int)cvRound(xLimit + 0.1 * bb.width);
|
||||
|
||||
bb.y = (int)cvRound(bb.y - 0.1 * bb.height);
|
||||
bb.width = xLimit - bb.x + 1;
|
||||
bb.height = yLimit - bb.y + 1;
|
||||
break;
|
||||
case CornerShiftBottomLeft:
|
||||
bb.x = (int)cvRound(bb.x - 0.1 * bb.width);
|
||||
yLimit = (int)cvRound(yLimit + 0.1 * bb.height);
|
||||
|
||||
bb.width = xLimit - bb.x + 1;
|
||||
bb.height = yLimit - bb.y + 1;
|
||||
break;
|
||||
case CornerShiftBottomRight:
|
||||
xLimit = (int)cvRound(xLimit + 0.1 * bb.width);
|
||||
yLimit = (int)cvRound(yLimit + 0.1 * bb.height);
|
||||
|
||||
bb.width = xLimit - bb.x + 1;
|
||||
bb.height = yLimit - bb.y + 1;
|
||||
break;
|
||||
case Scale_0_8:
|
||||
ratio = 0.8f;
|
||||
w = (int)(ratio * bb.width);
|
||||
h = (int)(ratio * bb.height);
|
||||
|
||||
bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
|
||||
break;
|
||||
case Scale_0_9:
|
||||
ratio = 0.9f;
|
||||
w = (int)(ratio * bb.width);
|
||||
h = (int)(ratio * bb.height);
|
||||
|
||||
bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
|
||||
break;
|
||||
case 11:
|
||||
//scale 1.1
|
||||
ratio = 1.1f;
|
||||
w = (int)(ratio * bb.width);
|
||||
h = (int)(ratio * bb.height);
|
||||
|
||||
bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
|
||||
break;
|
||||
case 12:
|
||||
//scale 1.2
|
||||
ratio = 1.2f;
|
||||
w = (int)(ratio * bb.width);
|
||||
h = (int)(ratio * bb.height);
|
||||
|
||||
bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return bb;
|
||||
}
|
||||
|
||||
template <typename Tracker, typename ROI_t>
|
||||
void TrackerTest<Tracker, ROI_t>::distanceAndOverlapTest()
|
||||
{
|
||||
bool initialized = false;
|
||||
|
||||
int fc = (startFrame - gtStartFrame);
|
||||
|
||||
bbs.at(fc) = applyShift(bbs.at(fc));
|
||||
Rect currentBBi = bbs.at(fc);
|
||||
ROI_t currentBB(currentBBi);
|
||||
float sumDistance = 0;
|
||||
float sumOverlap = 0;
|
||||
|
||||
string folder = cvtest::TS::ptr()->get_data_path() + "/" + TRACKING_DIR + "/" + video + "/" + FOLDER_IMG;
|
||||
string videoPath = folder + "/" + video + ".webm";
|
||||
|
||||
VideoCapture c;
|
||||
c.open(videoPath);
|
||||
if (!c.isOpened())
|
||||
throw SkipTestException("Can't open video file");
|
||||
#if 0
|
||||
c.set(CAP_PROP_POS_FRAMES, startFrame);
|
||||
#else
|
||||
if (startFrame)
|
||||
std::cout << "startFrame = " << startFrame << std::endl;
|
||||
for (int i = 0; i < startFrame; i++)
|
||||
{
|
||||
Mat dummy_frame;
|
||||
c >> dummy_frame;
|
||||
ASSERT_FALSE(dummy_frame.empty()) << i << ": " << videoPath;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int frameCounter = startFrame; frameCounter < endFrame; frameCounter++)
|
||||
{
|
||||
Mat frame;
|
||||
c >> frame;
|
||||
|
||||
ASSERT_FALSE(frame.empty()) << "frameCounter=" << frameCounter << " video=" << videoPath;
|
||||
if (!initialized)
|
||||
{
|
||||
tracker->init(frame, currentBB);
|
||||
std::cout << "frame size = " << frame.size() << std::endl;
|
||||
initialized = true;
|
||||
}
|
||||
else if (initialized)
|
||||
{
|
||||
if (frameCounter >= (int)bbs.size())
|
||||
break;
|
||||
tracker->update(frame, currentBB);
|
||||
}
|
||||
float curDistance = calcDistance(currentBB, bbs.at(fc));
|
||||
float curOverlap = calcOverlap(currentBB, bbs.at(fc));
|
||||
|
||||
#ifdef DEBUG_TEST
|
||||
Mat result;
|
||||
repeat(frame, 1, 2, result);
|
||||
rectangle(result, currentBB, Scalar(0, 255, 0), 1);
|
||||
Rect roi2(frame.cols, 0, frame.cols, frame.rows);
|
||||
rectangle(result(roi2), bbs.at(fc), Scalar(0, 0, 255), 1);
|
||||
imshow("result", result);
|
||||
waitKey(1);
|
||||
#endif
|
||||
|
||||
sumDistance += curDistance;
|
||||
sumOverlap += curOverlap;
|
||||
fc++;
|
||||
}
|
||||
|
||||
float meanDistance = sumDistance / (endFrame - startFrame);
|
||||
float meanOverlap = sumOverlap / (endFrame - startFrame);
|
||||
|
||||
EXPECT_LE(meanDistance, distanceThreshold);
|
||||
EXPECT_GE(meanOverlap, overlapThreshold);
|
||||
}
|
||||
|
||||
template <typename Tracker, typename ROI_t>
|
||||
void TrackerTest<Tracker, ROI_t>::checkDataTest()
|
||||
{
|
||||
|
||||
FileStorage fs;
|
||||
fs.open(cvtest::TS::ptr()->get_data_path() + TRACKING_DIR + "/" + video + "/" + video + ".yml", FileStorage::READ);
|
||||
fs["start"] >> startFrame;
|
||||
fs["prefix"] >> prefix;
|
||||
fs["suffix"] >> suffix;
|
||||
fs.release();
|
||||
|
||||
string gtFile = cvtest::TS::ptr()->get_data_path() + TRACKING_DIR + "/" + video + "/gt.txt";
|
||||
std::ifstream gt;
|
||||
//open the ground truth
|
||||
gt.open(gtFile.c_str());
|
||||
ASSERT_TRUE(gt.is_open()) << gtFile;
|
||||
string line;
|
||||
int bbCounter = 0;
|
||||
while (getline(gt, line))
|
||||
{
|
||||
bbCounter++;
|
||||
}
|
||||
gt.close();
|
||||
|
||||
int seqLength = bbCounter;
|
||||
for (int i = startFrame; i < seqLength; i++)
|
||||
{
|
||||
validSequence.push_back(i);
|
||||
}
|
||||
|
||||
//exclude from the images sequence, the frames where the target is occluded or out of view
|
||||
string omitFile = cvtest::TS::ptr()->get_data_path() + TRACKING_DIR + "/" + video + "/" + FOLDER_OMIT_INIT + "/" + video + ".txt";
|
||||
std::ifstream omit;
|
||||
omit.open(omitFile.c_str());
|
||||
if (omit.is_open())
|
||||
{
|
||||
string omitLine;
|
||||
while (getline(omit, omitLine))
|
||||
{
|
||||
vector<string> tokens = splitString(omitLine, " ");
|
||||
int s_start = atoi(tokens.at(0).c_str());
|
||||
int s_end = atoi(tokens.at(1).c_str());
|
||||
for (int k = s_start; k <= s_end; k++)
|
||||
{
|
||||
std::vector<int>::iterator position = std::find(validSequence.begin(), validSequence.end(), k);
|
||||
if (position != validSequence.end())
|
||||
validSequence.erase(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
omit.close();
|
||||
gtStartFrame = startFrame;
|
||||
//compute the start and the and for each segment
|
||||
int numFrame = (int)(validSequence.size() / numSegments);
|
||||
startFrame += (segmentIdx - 1) * numFrame;
|
||||
endFrame = startFrame + numFrame;
|
||||
|
||||
std::ifstream gt2;
|
||||
//open the ground truth
|
||||
gt2.open(gtFile.c_str());
|
||||
ASSERT_TRUE(gt2.is_open()) << gtFile;
|
||||
string line2;
|
||||
int bbCounter2 = 0;
|
||||
while (getline(gt2, line2))
|
||||
{
|
||||
vector<string> tokens = splitString(line2, ",");
|
||||
Rect bb(atoi(tokens.at(0).c_str()), atoi(tokens.at(1).c_str()), atoi(tokens.at(2).c_str()), atoi(tokens.at(3).c_str()));
|
||||
ASSERT_EQ((size_t)4, tokens.size()) << "Incorrect ground truth file " << gtFile;
|
||||
|
||||
bbs.push_back(bb);
|
||||
bbCounter2++;
|
||||
}
|
||||
gt2.close();
|
||||
|
||||
if (segmentIdx == numSegments)
|
||||
endFrame = (int)bbs.size();
|
||||
}
|
||||
|
||||
template <typename Tracker, typename ROI_t>
|
||||
void TrackerTest<Tracker, ROI_t>::run()
|
||||
{
|
||||
srand(1); // FIXIT remove that, ensure that there is no "rand()" in implementation
|
||||
|
||||
ASSERT_TRUE(tracker);
|
||||
|
||||
checkDataTest();
|
||||
|
||||
//check for failure
|
||||
if (::testing::Test::HasFatalFailure())
|
||||
return;
|
||||
|
||||
distanceAndOverlapTest();
|
||||
}
|
||||
Reference in New Issue
Block a user