mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge remote-tracking branch 'itseez/opencv'
Conflicts: modules/video/src/simpleflow.cpp modules/video/test/test_simpleflow.cpp
This commit is contained in:
@@ -6,10 +6,15 @@
|
||||
#include "camera_activity.hpp"
|
||||
#include "camera_wrapper.h"
|
||||
|
||||
#define LOG_TAG "CAMERA_ACTIVITY"
|
||||
#undef LOG_TAG
|
||||
#undef LOGE
|
||||
#undef LOGD
|
||||
#undef LOGI
|
||||
|
||||
#define LOG_TAG "OpenCV::camera"
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
|
||||
///////
|
||||
// Debug
|
||||
|
||||
@@ -9,3 +9,4 @@ The module contains some recently added functionality that has not been stabiliz
|
||||
|
||||
stereo
|
||||
FaceRecognizer Documentation <facerec/index>
|
||||
Retina Documentation <retina/index>
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
openFABMAP
|
||||
========================================
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
The openFABMAP package has been integrated into OpenCV from the openFABMAP <http://code.google.com/p/openfabmap/> project. OpenFABMAP is an open and modifiable code-source which implements the Fast Appearance-based Mapping algorithm (FAB-MAP) developed by Mark Cummins and Paul Newman. The algorithms used in openFABMAP were developed using only the relevant FAB-MAP publications.
|
||||
|
||||
FAB-MAP is an approach to appearance-based place recognition. FAB-MAP compares images of locations that have been visited and determines the probability of re-visiting a location, as well as providing a measure of the probability of being at a new, previously unvisited location. Camera images form the sole input to the system, from which visual bag-of-words models are formed through the extraction of appearance-based (e.g. SURF) features.
|
||||
|
||||
openFABMAP requires training data (e.g. a collection of images from a similar but not identical environment) to construct a visual vocabulary for the visual bag-of-words model, along with a Chow-Liu tree representation of feature likelihood and for use in the Sampled new place method (see below).
|
||||
|
||||
FabMap
|
||||
--------------------
|
||||
|
||||
.. ocv:class:: FabMap
|
||||
|
||||
The main FabMap class performs the comparison between visual bags-of-words extracted from one or more images. The FabMap class is instantiated as one of the four inherited FabMap classes (FabMap1, FabMapLUT, FabMapFBO, FabMap2). Each inherited class performs the comparison differently based on algorithm iterations as published (see each class below for specifics). A Chow-Liu tree, detector model parameters and some option flags are common to all Fabmap variants and are supplied on class creation. Training data (visual bag-of-words) is supplied to the class if using the SAMPLED new place method. Test data (visual bag-of-words) is supplied as images to which query bag-of-words are compared against. The common flags are listed below: ::
|
||||
|
||||
enum {
|
||||
MEAN_FIELD,
|
||||
SAMPLED,
|
||||
NAIVE_BAYES,
|
||||
CHOW_LIU,
|
||||
MOTION_MODEL
|
||||
};
|
||||
|
||||
#. MEAN_FIELD: Use the Mean Field approximation to determine the new place likelihood (cannot be used for FabMap2).
|
||||
#. SAMPLED: Use the Sampled approximation to determine the new place likelihood. Requires training data (see below).
|
||||
#. NAIVE_BAYES: Assume a naive Bayes approximation to feature distribution (i.e. all features are independent). Note that a Chow-Liu tree is still required but only the absolute word probabilities are used, feature co-occurrance information is discarded.
|
||||
#. CHOW_LIU: Use the full Chow-Liu tree to approximate feature distribution.
|
||||
#. MOTION_MODEL: Update the location distribution using the previous distribution as a (weak) prior. Used for matching in sequences (i.e. successive video frames).
|
||||
|
||||
Training Data
|
||||
++++++++++++++++++++
|
||||
|
||||
Training data is required to use the SAMPLED new place method. The SAMPLED method was shown to have improved performance over the alternative MEAN_FIELD method. Training data can be added singularly or as a batch.
|
||||
|
||||
.. ocv:function:: virtual void addTraining(const Mat& queryImgDescriptor)
|
||||
|
||||
:param queryImgDescriptor: bag-of-words image descriptors stored as rows in a Mat
|
||||
|
||||
.. ocv:function:: virtual void addTraining(const vector<Mat>& queryImgDescriptors)
|
||||
|
||||
:param queryImgDescriptors: a vector containing multiple bag-of-words image descriptors
|
||||
|
||||
.. ocv:function:: const vector<Mat>& getTrainingImgDescriptors() const
|
||||
|
||||
Returns a vector containing multiple bag-of-words image descriptors
|
||||
|
||||
Test Data
|
||||
++++++++++++++++++++
|
||||
|
||||
Test Data is the database of images represented using bag-of-words models. When a compare function is called, each query point is compared to the test data.
|
||||
|
||||
.. ocv:function:: virtual void add(const Mat& queryImgDescriptor)
|
||||
|
||||
:param queryImgDescriptor: bag-of-words image descriptors stored as rows in a Mat
|
||||
|
||||
.. ocv:function:: virtual void add(const vector<Mat>& queryImgDescriptors)
|
||||
|
||||
:param queryImgDescriptors: a vector containing multiple bag-of-words image descriptors
|
||||
|
||||
.. ocv:function:: const vector<Mat>& getTestImgDescriptors() const
|
||||
|
||||
Returns a vector containing multiple bag-of-words image descriptors
|
||||
|
||||
Image Comparison
|
||||
++++++++++++++++++++
|
||||
|
||||
Image matching is performed calling the compare function. Query bag-of-words image descriptors are provided and compared to test data added to the FabMap class. Alternatively test data can be provided with the call to compare to which the comparison is performed. Results are written to the 'matches' argument.
|
||||
|
||||
.. ocv:function:: void compare(const Mat& queryImgDescriptor, vector<IMatch>& matches, bool addQuery = false, const Mat& mask = Mat())
|
||||
|
||||
:param queryImgDescriptor: bag-of-words image descriptors stored as rows in a Mat
|
||||
|
||||
:param matches: a vector of image match probabilities
|
||||
|
||||
:param addQuery: if true the queryImg Descriptor is added to the test data after the comparison is performed.
|
||||
|
||||
:param mask: *not implemented*
|
||||
|
||||
.. ocv:function:: void compare(const Mat& queryImgDescriptor, const Mat& testImgDescriptors, vector<IMatch>& matches, const Mat& mask = Mat())
|
||||
|
||||
:param testImgDescriptors: bag-of-words image descriptors stored as rows in a Mat
|
||||
|
||||
.. ocv:function:: void compare(const Mat& queryImgDescriptor, const vector<Mat>& testImgDescriptors, vector<IMatch>& matches, const Mat& mask = Mat())
|
||||
|
||||
:param testImgDescriptors: a vector of multiple bag-of-words image descriptors
|
||||
|
||||
.. ocv:function:: void compare(const vector<Mat>& queryImgDescriptors, vector<IMatch>& matches, bool addQuery = false, const Mat& mask = Mat())
|
||||
|
||||
:param queryImgDescriptors: a vector of multiple bag-of-words image descriptors
|
||||
|
||||
.. ocv:function:: void compare(const vector<Mat>& queryImgDescriptors, const vector<Mat>& testImgDescriptors, vector<IMatch>& matches, const Mat& mask = Mat())
|
||||
|
||||
|
||||
|
||||
FabMap classes
|
||||
++++++++++++++++++++
|
||||
|
||||
.. ocv:class:: FabMap1 : public FabMap
|
||||
|
||||
The original FAB-MAP algorithm without any computational improvements as published in [IJRR2008]_
|
||||
|
||||
.. ocv:function:: FabMap1::FabMap1(const Mat& clTree, double PzGe, double PzGNe, int flags, int numSamples = 0)
|
||||
|
||||
:param clTree: a Chow-Liu tree class
|
||||
|
||||
:param PzGe: the dector model recall. The probability of the feature detector extracting a feature from an object given it is in the scene. This is used to account for detector noise.
|
||||
|
||||
:param PzGNe: the dector model precision. The probability of the feature detector falsing extracting a feature representing an object that is not in the scene.
|
||||
|
||||
:param numSamples: the number of samples to use for the SAMPLED new place calculation
|
||||
|
||||
.. ocv:class:: FabMapLUT : public FabMap
|
||||
|
||||
The original FAB-MAP algorithm implemented as a look-up table for speed enhancements [ICRA2011]_
|
||||
|
||||
.. ocv:function:: FabMapLUT::FabMapLUT(const Mat& clTree, double PzGe, double PzGNe, int flags, int numSamples = 0, int precision = 6)
|
||||
|
||||
:param precision: the precision with which to store the pre-computed likelihoods
|
||||
|
||||
.. ocv:class:: FabMapFBO : public FabMap
|
||||
|
||||
The accelerated FAB-MAP using a 'fast bail-out' approach as in [TRO2010]_
|
||||
|
||||
.. ocv:function:: FabMapFBO::FabMapFBO(const Mat& clTree, double PzGe, double PzGNe, int flags, int numSamples = 0, double rejectionThreshold = 1e-8, double PsGd = 1e-8, int bisectionStart = 512, int bisectionIts = 9)
|
||||
|
||||
:param rejectionThreshold: images are not considered a match when the likelihood falls below the Bennett bound by the amount given by the rejectionThreshold. The threshold provides a speed/accuracy trade-off. A lower bound will be more accurate
|
||||
|
||||
:param PsGd: used to calculate the Bennett bound. Provides a speed/accuracy trade-off. A lower bound will be more accurate
|
||||
|
||||
:param bisectionStart: Used to estimate the bound using the bisection method. Must be larger than the largest expected difference between maximum and minimum image likelihoods
|
||||
|
||||
:param bisectionIts: The number of iterations for which to perform the bisection method
|
||||
|
||||
|
||||
.. ocv:class:: FabMap2 : public FabMap
|
||||
|
||||
The inverted index FAB-MAP as in [IJRR2010]_. This version of FAB-MAP is the fastest without any loss of accuracy.
|
||||
|
||||
.. ocv:function:: FabMap2::FabMap2(const Mat& clTree, double PzGe, double PzGNe, int flags)
|
||||
|
||||
.. [IJRR2008] M. Cummins and P. Newman, "FAB-MAP: Probabilistic Localization and Mapping in the Space of Appearance," The International Journal of Robotics Research, vol. 27(6), pp. 647-665, 2008
|
||||
|
||||
.. [TRO2010] M. Cummins and P. Newman, "Accelerating FAB-MAP with concentration inequalities," IEEE Transactions on Robotics, vol. 26(6), pp. 1042-1050, 2010
|
||||
|
||||
.. [IJRR2010] M. Cummins and P. Newman, "Appearance-only SLAM at large scale with FAB-MAP 2.0," The International Journal of Robotics Research, vol. 30(9), pp. 1100-1123, 2010
|
||||
|
||||
.. [ICRA2011] A. Glover, et al., "OpenFABMAP: An Open Source Toolbox for Appearance-based Loop Closure Detection," in IEEE International Conference on Robotics and Automation, St Paul, Minnesota, 2011
|
||||
|
||||
ImageMatch
|
||||
--------------------
|
||||
|
||||
.. ocv:struct:: IMatch
|
||||
|
||||
FAB-MAP comparison results are stored in a vector of IMatch structs. Each IMatch structure provides the index of the provided query bag-of-words, the index of the test bag-of-words, the raw log-likelihood of the match (independent of other comparisons), and the match probability (normalised over other comparison likelihoods).
|
||||
|
||||
::
|
||||
|
||||
struct IMatch {
|
||||
|
||||
IMatch() :
|
||||
queryIdx(-1), imgIdx(-1), likelihood(-DBL_MAX), match(-DBL_MAX) {
|
||||
}
|
||||
IMatch(int _queryIdx, int _imgIdx, double _likelihood, double _match) :
|
||||
queryIdx(_queryIdx), imgIdx(_imgIdx), likelihood(_likelihood), match(
|
||||
_match) {
|
||||
}
|
||||
|
||||
int queryIdx; //query index
|
||||
int imgIdx; //test index
|
||||
|
||||
double likelihood; //raw loglikelihood
|
||||
double match; //normalised probability
|
||||
|
||||
bool operator<(const IMatch& m) const {
|
||||
return match < m.match;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Chow-Liu Tree
|
||||
--------------------
|
||||
|
||||
.. ocv:class:: ChowLiuTree
|
||||
|
||||
The Chow-Liu tree is a probabilistic model of the environment in terms of feature occurance and co-occurance. The Chow-Liu tree is a form of Bayesian network. FAB-MAP uses the model when calculating bag-of-words similarity by taking into account feature saliency. Training data is provided to the ChowLiuTree class in the form of bag-of-words image descriptors. The make function produces a cv::Mat that encodes the tree structure.
|
||||
|
||||
.. ocv:function:: ChowLiuTree::ChowLiuTree()
|
||||
|
||||
.. ocv:function:: void add(const Mat& imgDescriptor)
|
||||
|
||||
:param imgDescriptor: bag-of-words image descriptors stored as rows in a Mat
|
||||
|
||||
.. ocv:function:: void add(const vector<Mat>& imgDescriptors)
|
||||
|
||||
:param imgDescriptors: a vector containing multiple bag-of-words image descriptors
|
||||
|
||||
.. ocv:function:: const vector<Mat>& getImgDescriptors() const
|
||||
|
||||
Returns a vector containing multiple bag-of-words image descriptors
|
||||
|
||||
.. ocv:function:: Mat make(double infoThreshold = 0.0)
|
||||
|
||||
:param infoThreshold: a threshold can be set to reduce the amount of memory used when making the Chow-Liu tree, which can occur with large vocabulary sizes. This function can fail if the threshold is set too high. If memory is an issue the value must be set by trial and error (~0.0005)
|
||||
|
||||
|
||||
BOWMSCTrainer
|
||||
--------------------
|
||||
|
||||
.. ocv:class:: BOWMSCTrainer : public BOWTrainer
|
||||
|
||||
BOWMSCTrainer is a custom clustering algorithm used to produce the feature vocabulary required to create bag-of-words representations. The algorithm is an implementation of [AVC2007]_. Arguments against using K-means for the FAB-MAP algorithm are discussed in [IJRR2010]_. The BOWMSCTrainer inherits from the cv::BOWTrainer class, overwriting the cluster function.
|
||||
|
||||
.. ocv:function:: BOWMSCTrainer::BOWMSCTrainer(double clusterSize = 0.4)
|
||||
|
||||
:param clusterSize: the specificity of the vocabulary produced. A smaller cluster size will instigate a larger vocabulary.
|
||||
|
||||
.. ocv:function:: virtual Mat cluster() const
|
||||
|
||||
Cluster using features added to the class
|
||||
|
||||
.. ocv:function:: virtual Mat cluster(const Mat& descriptors) const
|
||||
|
||||
:param descriptors: feature descriptors provided as rows of the Mat.
|
||||
|
||||
.. [AVC2007] Alexandra Teynor and Hans Burkhardt, "Fast Codebook Generation by Sequential Data Analysis for Object Classification", in Advances in Visual Computing, pp. 610-620, 2007
|
||||
@@ -0,0 +1,353 @@
|
||||
Retina : a Bio mimetic human retina model
|
||||
*****************************************
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
Retina
|
||||
======
|
||||
|
||||
.. ocv:class:: Retina
|
||||
|
||||
Class which provides the main controls to the Gipsa/Listic labs human retina model. Spatio-temporal filtering modelling the two main retina information channels :
|
||||
|
||||
* foveal vision for detailled color vision : the parvocellular pathway).
|
||||
|
||||
* periphearal vision for sensitive transient signals detection (motion and events) : the magnocellular pathway.
|
||||
|
||||
The retina can be settled up with various parameters, by default, the retina cancels mean luminance and enforces all details of the visual scene. In order to use your own parameters, you can use at least one time the *write(std::string fs)* method which will write a proper XML file with all default parameters. Then, tweak it on your own and reload them at any time using method *setup(std::string fs)*. These methods update a *cv::Retina::RetinaParameters* member structure that is described hereafter. ::
|
||||
|
||||
class Retina
|
||||
{
|
||||
public:
|
||||
// parameters setup instance
|
||||
struct RetinaParameters; // this class is detailled later
|
||||
|
||||
// constructors
|
||||
Retina (Size inputSize);
|
||||
Retina (Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
|
||||
|
||||
// main method for input frame processing
|
||||
void run (const Mat &inputImage);
|
||||
|
||||
// output buffers retreival methods
|
||||
// -> foveal color vision details channel with luminance and noise correction
|
||||
void getParvo (Mat &retinaOutput_parvo);
|
||||
void getParvo (std::valarray< float > &retinaOutput_parvo);
|
||||
const std::valarray< float > & getParvo () const;
|
||||
// -> peripheral monochrome motion and events (transient information) channel
|
||||
void getMagno (Mat &retinaOutput_magno);
|
||||
void getMagno (std::valarray< float > &retinaOutput_magno);
|
||||
const std::valarray< float > & getMagno () const;
|
||||
|
||||
// reset retina buffers... equivalent to closing your eyes for some seconds
|
||||
void clearBuffers ();
|
||||
|
||||
// retreive input and output buffers sizes
|
||||
Size inputSize ();
|
||||
Size outputSize ();
|
||||
|
||||
// setup methods with specific parameters specification of global xml config file loading/write
|
||||
void setup (std::string retinaParameterFile="", const bool applyDefaultSetupOnFailure=true);
|
||||
void setup (cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true);
|
||||
void setup (RetinaParameters newParameters);
|
||||
struct Retina::RetinaParameters getParameters ();
|
||||
const std::string printSetup ();
|
||||
virtual void write (std::string fs) const;
|
||||
virtual void write (FileStorage &fs) const;
|
||||
void setupOPLandIPLParvoChannel (const bool colorMode=true, const bool normaliseOutput=true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7);
|
||||
void setupIPLMagnoChannel (const bool normaliseOutput=true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7);
|
||||
void setColorSaturation (const bool saturateColors=true, const float colorSaturationValue=4.0);
|
||||
void activateMovingContoursProcessing (const bool activate);
|
||||
void activateContoursProcessing (const bool activate);
|
||||
};
|
||||
|
||||
|
||||
Description
|
||||
+++++++++++
|
||||
|
||||
Class which allows the `Gipsa <http://www.gipsa-lab.inpg.fr>`_ (preliminary work) / `Listic <http://www.listic.univ-savoie.fr>`_ (code maintainer) labs retina model to be used. This class allows human retina spatio-temporal image processing to be applied on still images, images sequences and video sequences. Briefly, here are the main human retina model properties:
|
||||
|
||||
* spectral whithening (mid-frequency details enhancement)
|
||||
|
||||
* high frequency spatio-temporal noise reduction (temporal noise and high frequency spatial noise are minimized)
|
||||
|
||||
* low frequency luminance reduction (luminance range compression) : high luminance regions do not hide details in darker regions anymore
|
||||
|
||||
* local logarithmic luminance compression allows details to be enhanced even in low light conditions
|
||||
|
||||
Use : this model can be used basically for spatio-temporal video effects but also in the aim of :
|
||||
|
||||
* performing texture analysis with enhanced signal to noise ratio and enhanced details robust against input images luminance ranges (check out the parvocellular retina channel output, by using the provided **getParvo** methods)
|
||||
|
||||
* performing motion analysis also taking benefit of the previously cited properties (check out the magnocellular retina channel output, by using the provided **getMagno** methods)
|
||||
|
||||
For more information, refer to the following papers :
|
||||
|
||||
* Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI <http://dx.doi.org/10.1016/j.cviu.2010.01.011>
|
||||
|
||||
* Please have a look at the reference work of Jeanny Herault that you can read in his book :
|
||||
|
||||
Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891.
|
||||
|
||||
This retina filter code includes the research contributions of phd/research collegues from which code has been redrawn by the author :
|
||||
|
||||
* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
|
||||
|
||||
* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. ====> more informations in the above cited Jeanny Heraults's book.
|
||||
|
||||
Demos and experiments !
|
||||
=======================
|
||||
|
||||
Take a look at the C++ examples provided with OpenCV :
|
||||
|
||||
* **samples/cpp/retinademo.cpp** shows how to use the retina module for details enhancement (Parvo channel output) and transient maps observation (Magno channel output). You can play with images, video sequences and webcam video.
|
||||
Typical uses are (provided your OpenCV installation is situated in folder *OpenCVReleaseFolder*)
|
||||
|
||||
* image processing : **OpenCVReleaseFolder/bin/retinademo -image myPicture.jpg**
|
||||
|
||||
* video processing : **OpenCVReleaseFolder/bin/retinademo -video myMovie.avi**
|
||||
|
||||
* webcam processing: **OpenCVReleaseFolder/bin/retinademo -video**
|
||||
|
||||
**Note :** This demo generates the file *RetinaDefaultParameters.xml* which contains the default parameters of the retina. Then, rename this as *RetinaSpecificParameters.xml*, adjust the parameters the way you want and reload the program to check the effect.
|
||||
|
||||
|
||||
* **samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cpp** shows how to use the retina to perform High Dynamic Range (HDR) luminance compression
|
||||
|
||||
Then, take a HDR image using bracketing with your camera and generate an OpenEXR image and then process it using the demo.
|
||||
|
||||
Typical use, supposing that you have the OpenEXR image *memorial.exr* (present in the samples/cpp/ folder)
|
||||
|
||||
**OpenCVReleaseFolder/bin/OpenEXRimages_HighDynamicRange_Retina_toneMapping memorial.exr**
|
||||
|
||||
Note that some sliders are made available to allow you to play with luminance compression.
|
||||
|
||||
Methods description
|
||||
===================
|
||||
|
||||
Here are detailled the main methods to control the retina model
|
||||
|
||||
Retina::Retina
|
||||
++++++++++++++
|
||||
|
||||
.. ocv:function:: Retina::Retina(Size inputSize)
|
||||
.. ocv:function:: Retina::Retina(Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0 )
|
||||
|
||||
Constructors
|
||||
|
||||
:param inputSize: the input frame size
|
||||
:param colorMode: the chosen processing mode : with or without color processing
|
||||
:param colorSamplingMethod: specifies which kind of color sampling will be used
|
||||
* RETINA_COLOR_RANDOM: each pixel position is either R, G or B in a random choice
|
||||
* RETINA_COLOR_DIAGONAL: color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR...
|
||||
* RETINA_COLOR_BAYER: standard bayer sampling
|
||||
:param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used
|
||||
:param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak
|
||||
:param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied
|
||||
|
||||
Retina::activateContoursProcessing
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::activateContoursProcessing(const bool activate)
|
||||
|
||||
Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated
|
||||
|
||||
:param activate: true if Parvocellular (contours information extraction) output should be activated, false if not... if activated, the Parvocellular output can be retrieved using the **getParvo** methods
|
||||
|
||||
Retina::activateMovingContoursProcessing
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::activateMovingContoursProcessing(const bool activate)
|
||||
|
||||
Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated
|
||||
|
||||
:param activate: true if Magnocellular output should be activated, false if not... if activated, the Magnocellular output can be retrieved using the **getMagno** methods
|
||||
|
||||
Retina::clearBuffers
|
||||
++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::clearBuffers()
|
||||
|
||||
Clears all retina buffers (equivalent to opening the eyes after a long period of eye close ;o) whatchout the temporal transition occuring just after this method call.
|
||||
|
||||
Retina::getParvo
|
||||
++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::getParvo(Mat & retinaOutput_parvo)
|
||||
.. ocv:function:: void cv::Retina::getParvo(std::valarray< float > & retinaOutput_parvo )
|
||||
|
||||
Accessor of the details channel of the retina (models foveal vision)
|
||||
|
||||
:param retinaOutput_parvo: the output buffer (reallocated if necessary), format can be :
|
||||
|
||||
* a cv::Mat, this output is rescaled for standard 8bits image processing use in OpenCV
|
||||
|
||||
* a 1D std::valarray Buffer (encoding is R1, R2, ... Rn), this output is the original retina filter model output, without any quantification or rescaling
|
||||
|
||||
Retina::getMagno
|
||||
++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::getMagno(Mat & retinaOutput_magno)
|
||||
.. ocv:function:: void cv::Retina::getMagno(std::valarray< float > & retinaOutput_magno)
|
||||
|
||||
Accessor of the motion channel of the retina (models peripheral vision)
|
||||
|
||||
:param retinaOutput_magno: the output buffer (reallocated if necessary), format can be :
|
||||
|
||||
* a cv::Mat, this output is rescaled for standard 8bits image processing use in OpenCV
|
||||
|
||||
* a 1D std::valarray Buffer (encoding is R1, R2, ... Rn), this output is the original retina filter model output, without any quantification or rescaling
|
||||
|
||||
Retina::getParameters
|
||||
+++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: struct Retina::RetinaParameters cv::Retina::getParameters()
|
||||
|
||||
Retrieve the current parameters values in a *Retina::RetinaParameters* structure
|
||||
|
||||
:return: the current parameters setup
|
||||
|
||||
Retina::inputSize
|
||||
+++++++++++++++++
|
||||
|
||||
.. ocv:function:: Size cv::Retina::inputSize()
|
||||
|
||||
Retreive retina input buffer size
|
||||
|
||||
:return: the retina input buffer size
|
||||
|
||||
Retina::outputSize
|
||||
++++++++++++++++++
|
||||
|
||||
.. ocv:function:: Size cv::Retina::outputSize()
|
||||
|
||||
Retreive retina output buffer size that can be different from the input if a spatial log transformation is applied
|
||||
|
||||
:return: the retina output buffer size
|
||||
|
||||
Retina::printSetup
|
||||
++++++++++++++++++
|
||||
|
||||
.. ocv:function:: const std::string cv::Retina::printSetup()
|
||||
|
||||
Outputs a string showing the used parameters setup
|
||||
|
||||
:return: a string which contains formatted parameters information
|
||||
|
||||
Retina::run
|
||||
+++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::run(const Mat & inputImage)
|
||||
|
||||
Method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods
|
||||
|
||||
:param inputImage: the input cv::Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits)
|
||||
|
||||
Retina::setColorSaturation
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0 )
|
||||
|
||||
Activate color saturation as the final step of the color demultiplexing process -> this saturation is a sigmoide function applied to each channel of the demultiplexed image.
|
||||
|
||||
:param saturateColors: boolean that activates color saturation (if true) or desactivate (if false)
|
||||
:param colorSaturationValue: the saturation factor : a simple factor applied on the chrominance buffers
|
||||
|
||||
|
||||
Retina::setup
|
||||
+++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::setup(std::string retinaParameterFile = "", const bool applyDefaultSetupOnFailure = true )
|
||||
.. ocv:function:: void cv::Retina::setup(cv::FileStorage & fs, const bool applyDefaultSetupOnFailure = true )
|
||||
.. ocv:function:: void cv::Retina::setup(RetinaParameters newParameters)
|
||||
|
||||
Try to open an XML retina parameters file to adjust current retina instance setup => if the xml file does not exist, then default setup is applied => warning, Exceptions are thrown if read XML file is not valid
|
||||
|
||||
:param retinaParameterFile: the parameters filename
|
||||
:param applyDefaultSetupOnFailure: set to true if an error must be thrown on error
|
||||
:param fs: the open Filestorage which contains retina parameters
|
||||
:param newParameters: a parameters structures updated with the new target configuration
|
||||
|
||||
Retina::write
|
||||
+++++++++++++
|
||||
|
||||
.. ocv:function:: virtual void cv::Retina::write(std::string fs) const
|
||||
.. ocv:function:: virtual void cv::Retina::write(FileStorage & fs) const
|
||||
|
||||
Write xml/yml formated parameters information
|
||||
|
||||
:param fs: the filename of the xml file that will be open and writen with formatted parameters information
|
||||
|
||||
Retina::setupIPLMagnoChannel
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta = 0, const float parasolCells_tau = 0, const float parasolCells_k = 7, const float amacrinCellsTemporalCutFrequency = 1.2, const float V0CompressionParameter = 0.95, const float localAdaptintegration_tau = 0, const float localAdaptintegration_k = 7 )
|
||||
|
||||
Set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel this channel processes signals output from OPL processing stage in peripheral vision, it allows motion information enhancement. It is decorrelated from the details channel. See reference papers for more details.
|
||||
|
||||
:param normaliseOutput: specifies if (true) output is rescaled between 0 and 255 of not (false)
|
||||
:param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0
|
||||
:param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response)
|
||||
:param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5
|
||||
:param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, typical value is 1.2
|
||||
:param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.95
|
||||
:param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
:param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
|
||||
Retina::setupOPLandIPLParvoChannel
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. ocv:function:: void cv::Retina::setupOPLandIPLParvoChannel(const bool colorMode = true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity = 0.7, const float photoreceptorsTemporalConstant = 0.5, const float photoreceptorsSpatialConstant = 0.53, const float horizontalCellsGain = 0, const float HcellsTemporalConstant = 1, const float HcellsSpatialConstant = 7, const float ganglionCellsSensitivity = 0.7 )
|
||||
|
||||
Setup the OPL and IPL parvo channels (see biologocal model) OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy) IPL parvo is the OPL next processing stage, it refers to a part of the Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision. See reference papers for more informations.
|
||||
|
||||
:param colorMode: specifies if (true) color is processed of not (false) to then processing gray level image
|
||||
:param normaliseOutput: specifies if (true) output is rescaled between 0 and 255 of not (false)
|
||||
:param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases)
|
||||
:param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame
|
||||
:param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel
|
||||
:param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0
|
||||
:param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors
|
||||
:param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model)
|
||||
:param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.7
|
||||
|
||||
|
||||
Retina::RetinaParameters
|
||||
========================
|
||||
|
||||
.. ocv:class:: RetinaParameters
|
||||
This structure merges all the parameters that can be adjusted threw the **cv::Retina::setup()**, **cv::Retina::setupOPLandIPLParvoChannel** and **cv::Retina::setupIPLMagnoChannel** setup methods
|
||||
Parameters structure for better clarity, check explenations on the comments of methods : setupOPLandIPLParvoChannel and setupIPLMagnoChannel. ::
|
||||
|
||||
class RetinaParameters{
|
||||
struct OPLandIplParvoParameters{ // Outer Plexiform Layer (OPL) and Inner Plexiform Layer Parvocellular (IplParvo) parameters
|
||||
OPLandIplParvoParameters():colorMode(true),
|
||||
normaliseOutput(true), // specifies if (true) output is rescaled between 0 and 255 of not (false)
|
||||
photoreceptorsLocalAdaptationSensitivity(0.7f), // the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases)
|
||||
photoreceptorsTemporalConstant(0.5f),// the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame
|
||||
photoreceptorsSpatialConstant(0.53f),// the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel
|
||||
horizontalCellsGain(0.0f),//gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0
|
||||
hcellsTemporalConstant(1.f),// the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors
|
||||
hcellsSpatialConstant(7.f),//the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model)
|
||||
ganglionCellsSensitivity(0.7f)//the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.7
|
||||
{};// default setup
|
||||
bool colorMode, normaliseOutput;
|
||||
float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity;
|
||||
};
|
||||
struct IplMagnoParameters{ // Inner Plexiform Layer Magnocellular channel (IplMagno)
|
||||
IplMagnoParameters():
|
||||
normaliseOutput(true), //specifies if (true) output is rescaled between 0 and 255 of not (false)
|
||||
parasolCells_beta(0.f), // the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0
|
||||
parasolCells_tau(0.f), //the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response)
|
||||
parasolCells_k(7.f), //the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5
|
||||
amacrinCellsTemporalCutFrequency(1.2f), //the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, typical value is 1.2
|
||||
V0CompressionParameter(0.95f), the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.95
|
||||
localAdaptintegration_tau(0.f), // specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
localAdaptintegration_k(7.f) // specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
{};// default setup
|
||||
bool normaliseOutput;
|
||||
float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k;
|
||||
};
|
||||
struct OPLandIplParvoParameters OPLandIplParvo;
|
||||
struct IplMagnoParameters IplMagno;
|
||||
};
|
||||
@@ -967,6 +967,8 @@ namespace cv
|
||||
|
||||
#include "opencv2/contrib/retina.hpp"
|
||||
|
||||
#include "opencv2/contrib/openfabmap.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
/*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.
|
||||
//
|
||||
// This file originates from the openFABMAP project:
|
||||
// [http://code.google.com/p/openfabmap/]
|
||||
//
|
||||
// For published work which uses all or part of OpenFABMAP, please cite:
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
|
||||
//
|
||||
// Original Algorithm by Mark Cummins and Paul Newman:
|
||||
// [http://ijr.sagepub.com/content/27/6/647.short]
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
|
||||
// [http://ijr.sagepub.com/content/30/9/1100.abstract]
|
||||
//
|
||||
// License Agreement
|
||||
//
|
||||
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
|
||||
// Will Maddern [w.maddern@qut.edu.au], all rights reserved.
|
||||
//
|
||||
//
|
||||
// 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_OPENFABMAP_H_
|
||||
#define __OPENCV_OPENFABMAP_H_
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <valarray>
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace of2 {
|
||||
|
||||
using std::list;
|
||||
using std::map;
|
||||
using std::multiset;
|
||||
|
||||
/*
|
||||
Return data format of a FABMAP compare call
|
||||
*/
|
||||
struct CV_EXPORTS IMatch {
|
||||
|
||||
IMatch() :
|
||||
queryIdx(-1), imgIdx(-1), likelihood(-DBL_MAX), match(-DBL_MAX) {
|
||||
}
|
||||
IMatch(int _queryIdx, int _imgIdx, double _likelihood, double _match) :
|
||||
queryIdx(_queryIdx), imgIdx(_imgIdx), likelihood(_likelihood), match(
|
||||
_match) {
|
||||
}
|
||||
|
||||
int queryIdx; //query index
|
||||
int imgIdx; //test index
|
||||
|
||||
double likelihood; //raw loglikelihood
|
||||
double match; //normalised probability
|
||||
|
||||
bool operator<(const IMatch& m) const {
|
||||
return match < m.match;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
Base FabMap class. Each FabMap method inherits from this class.
|
||||
*/
|
||||
class CV_EXPORTS FabMap {
|
||||
public:
|
||||
|
||||
//FabMap options
|
||||
enum {
|
||||
MEAN_FIELD = 1,
|
||||
SAMPLED = 2,
|
||||
NAIVE_BAYES = 4,
|
||||
CHOW_LIU = 8,
|
||||
MOTION_MODEL = 16
|
||||
};
|
||||
|
||||
FabMap(const Mat& clTree, double PzGe, double PzGNe, int flags,
|
||||
int numSamples = 0);
|
||||
virtual ~FabMap();
|
||||
|
||||
//methods to add training data for sampling method
|
||||
virtual void addTraining(const Mat& queryImgDescriptor);
|
||||
virtual void addTraining(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
//methods to add to the test data
|
||||
virtual void add(const Mat& queryImgDescriptor);
|
||||
virtual void add(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
//accessors
|
||||
const vector<Mat>& getTrainingImgDescriptors() const;
|
||||
const vector<Mat>& getTestImgDescriptors() const;
|
||||
|
||||
//Main FabMap image comparison
|
||||
void compare(const Mat& queryImgDescriptor,
|
||||
vector<IMatch>& matches, bool addQuery = false,
|
||||
const Mat& mask = Mat());
|
||||
void compare(const Mat& queryImgDescriptor,
|
||||
const Mat& testImgDescriptors, vector<IMatch>& matches,
|
||||
const Mat& mask = Mat());
|
||||
void compare(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches, const Mat& mask = Mat());
|
||||
void compare(const vector<Mat>& queryImgDescriptors, vector<
|
||||
IMatch>& matches, bool addQuery = false, const Mat& mask =
|
||||
Mat());
|
||||
void compare(const vector<Mat>& queryImgDescriptors,
|
||||
const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches, const Mat& mask = Mat());
|
||||
|
||||
protected:
|
||||
|
||||
void compareImgDescriptor(const Mat& queryImgDescriptor,
|
||||
int queryIndex, const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches);
|
||||
|
||||
void addImgDescriptor(const Mat& queryImgDescriptor);
|
||||
|
||||
//the getLikelihoods method is overwritten for each different FabMap
|
||||
//method.
|
||||
virtual void getLikelihoods(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches);
|
||||
virtual double getNewPlaceLikelihood(const Mat& queryImgDescriptor);
|
||||
|
||||
//turn likelihoods into probabilities (also add in motion model if used)
|
||||
void normaliseDistribution(vector<IMatch>& matches);
|
||||
|
||||
//Chow-Liu Tree
|
||||
int pq(int q);
|
||||
double Pzq(int q, bool zq);
|
||||
double PzqGzpq(int q, bool zq, bool zpq);
|
||||
|
||||
//FAB-MAP Core
|
||||
double PzqGeq(bool zq, bool eq);
|
||||
double PeqGL(int q, bool Lzq, bool eq);
|
||||
double PzqGL(int q, bool zq, bool zpq, bool Lzq);
|
||||
double PzqGzpqL(int q, bool zq, bool zpq, bool Lzq);
|
||||
double (FabMap::*PzGL)(int q, bool zq, bool zpq, bool Lzq);
|
||||
|
||||
//data
|
||||
Mat clTree;
|
||||
vector<Mat> trainingImgDescriptors;
|
||||
vector<Mat> testImgDescriptors;
|
||||
vector<IMatch> priorMatches;
|
||||
|
||||
//parameters
|
||||
double PzGe;
|
||||
double PzGNe;
|
||||
double Pnew;
|
||||
|
||||
double mBias;
|
||||
double sFactor;
|
||||
|
||||
int flags;
|
||||
int numSamples;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
The original FAB-MAP algorithm, developed based on:
|
||||
http://ijr.sagepub.com/content/27/6/647.short
|
||||
*/
|
||||
class CV_EXPORTS FabMap1: public FabMap {
|
||||
public:
|
||||
FabMap1(const Mat& clTree, double PzGe, double PzGNe, int flags,
|
||||
int numSamples = 0);
|
||||
virtual ~FabMap1();
|
||||
protected:
|
||||
|
||||
//FabMap1 implementation of likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
};
|
||||
|
||||
/*
|
||||
A computationally faster version of the original FAB-MAP algorithm. A look-
|
||||
up-table is used to precompute many of the reoccuring calculations
|
||||
*/
|
||||
class CV_EXPORTS FabMapLUT: public FabMap {
|
||||
public:
|
||||
FabMapLUT(const Mat& clTree, double PzGe, double PzGNe,
|
||||
int flags, int numSamples = 0, int precision = 6);
|
||||
virtual ~FabMapLUT();
|
||||
protected:
|
||||
|
||||
//FabMap look-up-table implementation of the likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
|
||||
//procomputed data
|
||||
int (*table)[8];
|
||||
|
||||
//data precision
|
||||
int precision;
|
||||
};
|
||||
|
||||
/*
|
||||
The Accelerated FAB-MAP algorithm, developed based on:
|
||||
http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942
|
||||
*/
|
||||
class CV_EXPORTS FabMapFBO: public FabMap {
|
||||
public:
|
||||
FabMapFBO(const Mat& clTree, double PzGe, double PzGNe, int flags,
|
||||
int numSamples = 0, double rejectionThreshold = 1e-8, double PsGd =
|
||||
1e-8, int bisectionStart = 512, int bisectionIts = 9);
|
||||
virtual ~FabMapFBO();
|
||||
|
||||
protected:
|
||||
|
||||
//FabMap Fast Bail-out implementation of the likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
|
||||
//stucture used to determine word comparison order
|
||||
struct WordStats {
|
||||
WordStats() :
|
||||
q(0), info(0), V(0), M(0) {
|
||||
}
|
||||
|
||||
WordStats(int _q, double _info) :
|
||||
q(_q), info(_info), V(0), M(0) {
|
||||
}
|
||||
|
||||
int q;
|
||||
double info;
|
||||
mutable double V;
|
||||
mutable double M;
|
||||
|
||||
bool operator<(const WordStats& w) const {
|
||||
return info < w.info;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//private fast bail-out necessary functions
|
||||
void setWordStatistics(const Mat& queryImgDescriptor, multiset<WordStats>& wordData);
|
||||
double limitbisection(double v, double m);
|
||||
double bennettInequality(double v, double m, double delta);
|
||||
static bool compInfo(const WordStats& first, const WordStats& second);
|
||||
|
||||
//parameters
|
||||
double PsGd;
|
||||
double rejectionThreshold;
|
||||
int bisectionStart;
|
||||
int bisectionIts;
|
||||
};
|
||||
|
||||
/*
|
||||
The FAB-MAP2.0 algorithm, developed based on:
|
||||
http://ijr.sagepub.com/content/30/9/1100.abstract
|
||||
*/
|
||||
class CV_EXPORTS FabMap2: public FabMap {
|
||||
public:
|
||||
|
||||
FabMap2(const Mat& clTree, double PzGe, double PzGNe, int flags);
|
||||
virtual ~FabMap2();
|
||||
|
||||
//FabMap2 builds the inverted index and requires an additional training/test
|
||||
//add function
|
||||
void addTraining(const Mat& queryImgDescriptors) {
|
||||
FabMap::addTraining(queryImgDescriptors);
|
||||
}
|
||||
void addTraining(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
void add(const Mat& queryImgDescriptors) {
|
||||
FabMap::add(queryImgDescriptors);
|
||||
}
|
||||
void add(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
protected:
|
||||
|
||||
//FabMap2 implementation of the likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
double getNewPlaceLikelihood(const Mat& queryImgDescriptor);
|
||||
|
||||
//the likelihood function using the inverted index
|
||||
void getIndexLikelihoods(const Mat& queryImgDescriptor, vector<
|
||||
double>& defaults, map<int, vector<int> >& invertedMap,
|
||||
vector<IMatch>& matches);
|
||||
void addToIndex(const Mat& queryImgDescriptor,
|
||||
vector<double>& defaults,
|
||||
map<int, vector<int> >& invertedMap);
|
||||
|
||||
//data
|
||||
vector<double> d1, d2, d3, d4;
|
||||
vector<vector<int> > children;
|
||||
|
||||
// TODO: inverted map a vector?
|
||||
|
||||
vector<double> trainingDefaults;
|
||||
map<int, vector<int> > trainingInvertedMap;
|
||||
|
||||
vector<double> testDefaults;
|
||||
map<int, vector<int> > testInvertedMap;
|
||||
|
||||
};
|
||||
/*
|
||||
A Chow-Liu tree is required by FAB-MAP. The Chow-Liu tree provides an
|
||||
estimate of the full distribution of visual words using a minimum spanning
|
||||
tree. The tree is generated through training data.
|
||||
*/
|
||||
class CV_EXPORTS ChowLiuTree {
|
||||
public:
|
||||
ChowLiuTree();
|
||||
virtual ~ChowLiuTree();
|
||||
|
||||
//add data to the chow-liu tree before calling make
|
||||
void add(const Mat& imgDescriptor);
|
||||
void add(const vector<Mat>& imgDescriptors);
|
||||
|
||||
const vector<Mat>& getImgDescriptors() const;
|
||||
|
||||
Mat make(double infoThreshold = 0.0);
|
||||
|
||||
private:
|
||||
vector<Mat> imgDescriptors;
|
||||
Mat mergedImgDescriptors;
|
||||
|
||||
typedef struct info {
|
||||
float score;
|
||||
short word1;
|
||||
short word2;
|
||||
} info;
|
||||
|
||||
//probabilities extracted from mergedImgDescriptors
|
||||
double P(int a, bool za);
|
||||
double JP(int a, bool za, int b, bool zb); //a & b
|
||||
double CP(int a, bool za, int b, bool zb); // a | b
|
||||
|
||||
//calculating mutual information of all edges
|
||||
void createBaseEdges(list<info>& edges, double infoThreshold);
|
||||
double calcMutInfo(int word1, int word2);
|
||||
static bool sortInfoScores(const info& first, const info& second);
|
||||
|
||||
//selecting minimum spanning egdges with maximum information
|
||||
bool reduceEdgesToMinSpan(list<info>& edges);
|
||||
|
||||
//building the tree sctructure
|
||||
Mat buildTree(int root_word, list<info> &edges);
|
||||
void recAddToTree(Mat &cltree, int q, int pq,
|
||||
list<info> &remaining_edges);
|
||||
vector<int> extractChildren(list<info> &remaining_edges, int q);
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
A custom vocabulary training method based on:
|
||||
http://www.springerlink.com/content/d1h6j8x552532003/
|
||||
*/
|
||||
class CV_EXPORTS BOWMSCTrainer: public BOWTrainer {
|
||||
public:
|
||||
BOWMSCTrainer(double clusterSize = 0.4);
|
||||
virtual ~BOWMSCTrainer();
|
||||
|
||||
// Returns trained vocabulary (i.e. cluster centers).
|
||||
virtual Mat cluster() const;
|
||||
virtual Mat cluster(const Mat& descriptors) const;
|
||||
|
||||
protected:
|
||||
|
||||
double clusterSize;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENFABMAP_H_ */
|
||||
@@ -316,28 +316,50 @@ void BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const std::valarray
|
||||
_spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0]);
|
||||
_localLuminanceAdaptation(get_data(inputFrame), &_filterOutput[0], &outputFrame[0]);
|
||||
}
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer
|
||||
void BasicRetinaFilter::_localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame)
|
||||
{
|
||||
float meanLuminance=0;
|
||||
const float *luminancePTR=inputFrame;
|
||||
for (unsigned int i=0;i<_filterOutput.getNBpixels();++i)
|
||||
meanLuminance+=*(luminancePTR++);
|
||||
meanLuminance/=_filterOutput.getNBpixels();
|
||||
//float tempMeanValue=meanLuminance+_meanInputValue*_tau;
|
||||
|
||||
updateCompressionParameter(meanLuminance);
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output
|
||||
void BasicRetinaFilter::_localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance)
|
||||
{
|
||||
_localLuminanceAdaptation(inputOutputFrame, localLuminance, inputOutputFrame, false);
|
||||
|
||||
/* const float *localLuminancePTR=localLuminance;
|
||||
float *inputOutputFramePTR=inputOutputFrame;
|
||||
|
||||
for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputOutputFramePTR)
|
||||
{
|
||||
float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon;
|
||||
*(inputOutputFramePTR) = (_maxInputValue+X0)**inputOutputFramePTR/(*inputOutputFramePTR +X0+0.00000000001);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer
|
||||
void BasicRetinaFilter::_localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame, const bool updateLuminanceMean)
|
||||
{
|
||||
if (updateLuminanceMean)
|
||||
{ float meanLuminance=0;
|
||||
const float *luminancePTR=inputFrame;
|
||||
for (unsigned int i=0;i<_filterOutput.getNBpixels();++i)
|
||||
meanLuminance+=*(luminancePTR++);
|
||||
meanLuminance/=_filterOutput.getNBpixels();
|
||||
//float tempMeanValue=meanLuminance+_meanInputValue*_tau;
|
||||
updateCompressionParameter(meanLuminance);
|
||||
}
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(0,_filterOutput.getNBpixels()), Parallel_localAdaptation(localLuminance, inputFrame, outputFrame, _localLuminanceFactor, _localLuminanceAddon, _maxInputValue));
|
||||
#else
|
||||
//std::cout<<meanLuminance<<std::endl;
|
||||
const float *localLuminancePTR=localLuminance;
|
||||
const float *inputFramePTR=inputFrame;
|
||||
float *outputFramePTR=outputFrame;
|
||||
for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputFramePTR)
|
||||
for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputFramePTR, ++outputFramePTR)
|
||||
{
|
||||
float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon;
|
||||
// TODO : the following line can lead to a divide by zero ! A small offset is added, take care if the offset is too large in case of High Dynamic Range images which can use very small values...
|
||||
*(outputFramePTR++) = (_maxInputValue+X0)**inputFramePTR/(*inputFramePTR +X0+0.00000000001f);
|
||||
*(outputFramePTR) = (_maxInputValue+X0)**inputFramePTR/(*inputFramePTR +X0+0.00000000001);
|
||||
//std::cout<<"BasicRetinaFilter::inputFrame[IDpixel]=%f, X0=%f, outputFrame[IDpixel]=%f\n", inputFrame[IDpixel], X0, outputFrame[IDpixel]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// local adaptation applied on a range of values which can be positive and negative
|
||||
@@ -355,27 +377,6 @@ void BasicRetinaFilter::_localLuminanceAdaptationPosNegValues(const float *input
|
||||
}
|
||||
}
|
||||
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output
|
||||
void BasicRetinaFilter::_localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance)
|
||||
{
|
||||
/*float meanLuminance=0;
|
||||
const float *luminancePTR=inputOutputFrame;
|
||||
for (unsigned int i=0;i<_filterOutput.getNBpixels();++i)
|
||||
meanLuminance+=*(luminancePTR++);
|
||||
meanLuminance/=_filterOutput.getNBpixels();
|
||||
//float tempMeanValue=meanLuminance+_meanInputValue*_tau;
|
||||
|
||||
updateCompressionParameter(meanLuminance);
|
||||
*/
|
||||
const float *localLuminancePTR=localLuminance;
|
||||
float *inputOutputFramePTR=inputOutputFrame;
|
||||
|
||||
for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputOutputFramePTR)
|
||||
{
|
||||
float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon;
|
||||
*(inputOutputFramePTR) = (_maxInputValue+X0)**inputOutputFramePTR/(*inputOutputFramePTR +X0);
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// Spatio temporal Low Pass filter functions
|
||||
// run LP filter and save result in the basic retina element buffer
|
||||
@@ -465,7 +466,9 @@ void BasicRetinaFilter::_horizontalCausalFilter(float *outputFrame, unsigned int
|
||||
// horizontal causal filter which adds the input inside
|
||||
void BasicRetinaFilter::_horizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
|
||||
{
|
||||
//#pragma omp parallel for
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_horizontalCausalFilter_addInput(inputFrame, outputFrame, IDrowStart, _filterOutput.getNBcolumns(), _a, _tau));
|
||||
#else
|
||||
for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
|
||||
{
|
||||
register float* outputPTR=outputFrame+(IDrowStart+IDrow)*_filterOutput.getNBcolumns();
|
||||
@@ -477,14 +480,16 @@ void BasicRetinaFilter::_horizontalCausalFilter_addInput(const float *inputFrame
|
||||
*(outputPTR++) = result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// horizontal anticausal filter (basic way, no add on)
|
||||
void BasicRetinaFilter::_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
|
||||
{
|
||||
|
||||
//#pragma omp parallel for
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_horizontalAnticausalFilter(outputFrame, IDrowEnd, _filterOutput.getNBcolumns(), _a ));
|
||||
#else
|
||||
for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
|
||||
{
|
||||
register float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(_filterOutput.getNBcolumns())-1;
|
||||
@@ -495,9 +500,9 @@ void BasicRetinaFilter::_horizontalAnticausalFilter(float *outputFrame, unsigned
|
||||
*(outputPTR--) = result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// horizontal anticausal filter which multiplies the output by _gain
|
||||
void BasicRetinaFilter::_horizontalAnticausalFilter_multGain(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
|
||||
{
|
||||
@@ -518,8 +523,10 @@ void BasicRetinaFilter::_horizontalAnticausalFilter_multGain(float *outputFrame,
|
||||
// vertical anticausal filter
|
||||
void BasicRetinaFilter::_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
|
||||
{
|
||||
//#pragma omp parallel for
|
||||
for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(IDcolumnStart,IDcolumnEnd), Parallel_verticalCausalFilter(outputFrame, _filterOutput.getNBrows(), _filterOutput.getNBcolumns(), _a ));
|
||||
#else
|
||||
for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
|
||||
{
|
||||
register float result=0;
|
||||
register float *outputPTR=outputFrame+IDcolumn;
|
||||
@@ -532,6 +539,7 @@ void BasicRetinaFilter::_verticalCausalFilter(float *outputFrame, unsigned int I
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -558,7 +566,10 @@ void BasicRetinaFilter::_verticalAnticausalFilter(float *outputFrame, unsigned i
|
||||
// vertical anticausal filter which multiplies the output by _gain
|
||||
void BasicRetinaFilter::_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
|
||||
{
|
||||
float* offset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(IDcolumnStart,IDcolumnEnd), Parallel_verticalAnticausalFilter_multGain(outputFrame, _filterOutput.getNBrows(), _filterOutput.getNBcolumns(), _a, _gain ));
|
||||
#else
|
||||
float* offset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
|
||||
//#pragma omp parallel for
|
||||
for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
|
||||
{
|
||||
@@ -573,7 +584,7 @@ void BasicRetinaFilter::_verticalAnticausalFilter_multGain(float *outputFrame, u
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
@@ -745,8 +756,8 @@ void BasicRetinaFilter::_spatiotemporalLPfilter_Irregular(float *inputOutputFram
|
||||
|
||||
// launch the serie of 1D directional filters in order to compute the 2D low pass filter
|
||||
_horizontalCausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBrows());
|
||||
_horizontalAnticausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBrows());
|
||||
_verticalCausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBcolumns());
|
||||
_horizontalAnticausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBrows(), &_progressiveSpatialConstant[0]);
|
||||
_verticalCausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBcolumns(), &_progressiveSpatialConstant[0]);
|
||||
_verticalAnticausalFilter_Irregular_multGain(inputOutputFrame, 0, (int)_filterOutput.getNBcolumns());
|
||||
|
||||
}
|
||||
@@ -765,8 +776,8 @@ void BasicRetinaFilter::_spatiotemporalLPfilter_Irregular(const float *inputFram
|
||||
|
||||
// launch the serie of 1D directional filters in order to compute the 2D low pass filter
|
||||
_horizontalCausalFilter_Irregular_addInput(inputFrame, outputFrame, 0, (int)_filterOutput.getNBrows());
|
||||
_horizontalAnticausalFilter_Irregular(outputFrame, 0, (int)_filterOutput.getNBrows());
|
||||
_verticalCausalFilter_Irregular(outputFrame, 0, (int)_filterOutput.getNBcolumns());
|
||||
_horizontalAnticausalFilter_Irregular(outputFrame, 0, (int)_filterOutput.getNBrows(), &_progressiveSpatialConstant[0]);
|
||||
_verticalCausalFilter_Irregular(outputFrame, 0, (int)_filterOutput.getNBcolumns(), &_progressiveSpatialConstant[0]);
|
||||
_verticalAnticausalFilter_Irregular_multGain(outputFrame, 0, (int)_filterOutput.getNBcolumns());
|
||||
|
||||
}
|
||||
@@ -806,10 +817,13 @@ void BasicRetinaFilter::_horizontalCausalFilter_Irregular_addInput(const float *
|
||||
}
|
||||
|
||||
// horizontal anticausal filter (basic way, no add on)
|
||||
void BasicRetinaFilter::_horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
|
||||
void BasicRetinaFilter::_horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const float *spatialConstantBuffer)
|
||||
{
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_horizontalAnticausalFilter_Irregular(outputFrame, spatialConstantBuffer, IDrowEnd, _filterOutput.getNBcolumns()));
|
||||
#else
|
||||
register float* outputPTR=outputFrame+IDrowEnd*(_filterOutput.getNBcolumns())-1;
|
||||
register const float* spatialConstantPTR=&_progressiveSpatialConstant[0]+IDrowEnd*(_filterOutput.getNBcolumns())-1;
|
||||
register const float* spatialConstantPTR=spatialConstantBuffer+IDrowEnd*(_filterOutput.getNBcolumns())-1;
|
||||
|
||||
for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
|
||||
{
|
||||
@@ -820,18 +834,21 @@ void BasicRetinaFilter::_horizontalAnticausalFilter_Irregular(float *outputFrame
|
||||
*(outputPTR--) = result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// vertical anticausal filter
|
||||
void BasicRetinaFilter::_verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
|
||||
void BasicRetinaFilter::_verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const float *spatialConstantBuffer)
|
||||
{
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(IDcolumnStart,IDcolumnEnd), Parallel_verticalCausalFilter_Irregular(outputFrame, spatialConstantBuffer, _filterOutput.getNBrows(), _filterOutput.getNBcolumns()));
|
||||
#else
|
||||
for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
|
||||
{
|
||||
register float result=0;
|
||||
register float *outputPTR=outputFrame+IDcolumn;
|
||||
register const float *spatialConstantPTR=&_progressiveSpatialConstant[0]+IDcolumn;
|
||||
register const float *spatialConstantPTR=spatialConstantBuffer+IDcolumn;
|
||||
for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
|
||||
{
|
||||
result = *(outputPTR) + *(spatialConstantPTR) * result;
|
||||
@@ -840,6 +857,7 @@ void BasicRetinaFilter::_verticalCausalFilter_Irregular(float *outputFrame, unsi
|
||||
spatialConstantPTR+=_filterOutput.getNBcolumns();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// vertical anticausal filter which multiplies the output by _gain
|
||||
|
||||
@@ -115,328 +115,541 @@
|
||||
//using namespace std;
|
||||
namespace cv
|
||||
{
|
||||
class BasicRetinaFilter
|
||||
{
|
||||
public:
|
||||
class BasicRetinaFilter
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* constructor of the base bio-inspired toolbox, parameters are only linked to imae input size and number of filtering capabilities of the object
|
||||
* @param NBrows: number of rows of the input image
|
||||
* @param NBcolumns: number of columns of the input image
|
||||
* @param parametersListSize: specifies the number of parameters set (each parameters set represents a specific low pass spatio-temporal filter)
|
||||
* @param useProgressiveFilter: specifies if the filter has irreguar (progressive) filtering capabilities (this can be activated later using setProgressiveFilterConstants_xxx methods)
|
||||
*/
|
||||
BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize=1, const bool useProgressiveFilter=false);
|
||||
/**
|
||||
* constructor of the base bio-inspired toolbox, parameters are only linked to imae input size and number of filtering capabilities of the object
|
||||
* @param NBrows: number of rows of the input image
|
||||
* @param NBcolumns: number of columns of the input image
|
||||
* @param parametersListSize: specifies the number of parameters set (each parameters set represents a specific low pass spatio-temporal filter)
|
||||
* @param useProgressiveFilter: specifies if the filter has irreguar (progressive) filtering capabilities (this can be activated later using setProgressiveFilterConstants_xxx methods)
|
||||
*/
|
||||
BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize=1, const bool useProgressiveFilter=false);
|
||||
|
||||
/**
|
||||
* standrad destructore
|
||||
*/
|
||||
~BasicRetinaFilter();
|
||||
/**
|
||||
* standrad destructore
|
||||
*/
|
||||
~BasicRetinaFilter();
|
||||
|
||||
/**
|
||||
* function which clears the output buffer of the object
|
||||
*/
|
||||
inline void clearOutputBuffer(){_filterOutput=0;};
|
||||
/**
|
||||
* function which clears the output buffer of the object
|
||||
*/
|
||||
inline void clearOutputBuffer(){_filterOutput=0;};
|
||||
|
||||
/**
|
||||
* function which clears the secondary buffer of the object
|
||||
*/
|
||||
inline void clearSecondaryBuffer(){_localBuffer=0;};
|
||||
/**
|
||||
* function which clears the secondary buffer of the object
|
||||
*/
|
||||
inline void clearSecondaryBuffer(){_localBuffer=0;};
|
||||
|
||||
/**
|
||||
* function which clears the output and the secondary buffer of the object
|
||||
*/
|
||||
inline void clearAllBuffers(){clearOutputBuffer();clearSecondaryBuffer();};
|
||||
/**
|
||||
* function which clears the output and the secondary buffer of the object
|
||||
*/
|
||||
inline void clearAllBuffers(){clearOutputBuffer();clearSecondaryBuffer();};
|
||||
|
||||
/**
|
||||
* resize basic retina filter object (resize all allocated buffers
|
||||
* @param NBrows: the new height size
|
||||
* @param NBcolumns: the new width size
|
||||
*/
|
||||
void resize(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
/**
|
||||
* resize basic retina filter object (resize all allocated buffers
|
||||
* @param NBrows: the new height size
|
||||
* @param NBcolumns: the new width size
|
||||
*/
|
||||
void resize(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
|
||||
/**
|
||||
* forbiden method inherited from parent std::valarray
|
||||
* prefer not to use this method since the filter matrix become vectors
|
||||
*/
|
||||
void resize(const unsigned int){std::cerr<<"error, not accessible method"<<std::endl;};
|
||||
/**
|
||||
* forbiden method inherited from parent std::valarray
|
||||
* prefer not to use this method since the filter matrix become vectors
|
||||
*/
|
||||
void resize(const unsigned int){std::cerr<<"error, not accessible method"<<std::endl;};
|
||||
|
||||
/**
|
||||
* low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param filterIndex: the offset which specifies the parameter set that should be used for the filtering
|
||||
* @return the processed image, the output is reachable later by using function getOutput()
|
||||
*/
|
||||
const std::valarray<float> &runFilter_LPfilter(const std::valarray<float> &inputFrame, const unsigned int filterIndex=0); // run the LP filter for a new frame input and save result in _filterOutput
|
||||
/**
|
||||
* low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param filterIndex: the offset which specifies the parameter set that should be used for the filtering
|
||||
* @return the processed image, the output is reachable later by using function getOutput()
|
||||
*/
|
||||
const std::valarray<float> &runFilter_LPfilter(const std::valarray<float> &inputFrame, const unsigned int filterIndex=0); // run the LP filter for a new frame input and save result in _filterOutput
|
||||
|
||||
/**
|
||||
* low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param outputFrame: the output buffer in which the result is writed
|
||||
* @param filterIndex: the offset which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void runFilter_LPfilter(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const unsigned int filterIndex=0); // run LP filter on a specific output adress
|
||||
/**
|
||||
* low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param outputFrame: the output buffer in which the result is writed
|
||||
* @param filterIndex: the offset which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void runFilter_LPfilter(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const unsigned int filterIndex=0); // run LP filter on a specific output adress
|
||||
|
||||
/**
|
||||
* low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors)
|
||||
* @param inputOutputFrame: the input image to be processed on which the result is rewrited
|
||||
* @param filterIndex: the offset which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void runFilter_LPfilter_Autonomous(std::valarray<float> &inputOutputFrame, const unsigned int filterIndex=0);// run LP filter on the input data and rewrite it
|
||||
/**
|
||||
* low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors)
|
||||
* @param inputOutputFrame: the input image to be processed on which the result is rewrited
|
||||
* @param filterIndex: the offset which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void runFilter_LPfilter_Autonomous(std::valarray<float> &inputOutputFrame, const unsigned int filterIndex=0);// run LP filter on the input data and rewrite it
|
||||
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputOutputFrame: the input image to be processed
|
||||
* @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering
|
||||
* @return the processed image, the output is reachable later by using function getOutput()
|
||||
*/
|
||||
const std::valarray<float> &runFilter_LocalAdapdation(const std::valarray<float> &inputOutputFrame, const std::valarray<float> &localLuminance);// run local adaptation filter and save result in _filterOutput
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputOutputFrame: the input image to be processed
|
||||
* @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering
|
||||
* @return the processed image, the output is reachable later by using function getOutput()
|
||||
*/
|
||||
const std::valarray<float> &runFilter_LocalAdapdation(const std::valarray<float> &inputOutputFrame, const std::valarray<float> &localLuminance);// run local adaptation filter and save result in _filterOutput
|
||||
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering
|
||||
* @param outputFrame: the output buffer in which the result is writed
|
||||
*/
|
||||
void runFilter_LocalAdapdation(const std::valarray<float> &inputFrame, const std::valarray<float> &localLuminance, std::valarray<float> &outputFrame); // run local adaptation filter on a specific output adress
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering
|
||||
* @param outputFrame: the output buffer in which the result is writed
|
||||
*/
|
||||
void runFilter_LocalAdapdation(const std::valarray<float> &inputFrame, const std::valarray<float> &localLuminance, std::valarray<float> &outputFrame); // run local adaptation filter on a specific output adress
|
||||
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @return the processed image, the output is reachable later by using function getOutput()
|
||||
*/
|
||||
const std::valarray<float> &runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame);// run local adaptation filter and save result in _filterOutput
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @return the processed image, the output is reachable later by using function getOutput()
|
||||
*/
|
||||
const std::valarray<float> &runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame);// run local adaptation filter and save result in _filterOutput
|
||||
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param outputFrame: the output buffer in which the result is writen
|
||||
*/
|
||||
void runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame); // run local adaptation filter on a specific output adress
|
||||
/**
|
||||
* local luminance adaptation call and run (contrast enhancement property of the photoreceptors)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param outputFrame: the output buffer in which the result is writen
|
||||
*/
|
||||
void runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame); // run local adaptation filter on a specific output adress
|
||||
|
||||
/**
|
||||
* run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
* @return the processed image, the output is reachable later by using function getOutput() if outputFrame is NULL
|
||||
*/
|
||||
inline void runProgressiveFilter(std::valarray<float> &inputFrame, const unsigned int filterIndex=0){_spatiotemporalLPfilter_Irregular(&inputFrame[0], filterIndex);};
|
||||
/**
|
||||
* run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
* @return the processed image, the output is reachable later by using function getOutput() if outputFrame is NULL
|
||||
*/
|
||||
inline void runProgressiveFilter(std::valarray<float> &inputFrame, const unsigned int filterIndex=0){_spatiotemporalLPfilter_Irregular(&inputFrame[0], filterIndex);};
|
||||
|
||||
/**
|
||||
* run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param outputFrame: the output buffer in which the result is writen
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
inline void runProgressiveFilter(const std::valarray<float> &inputFrame,
|
||||
std::valarray<float> &outputFrame,
|
||||
const unsigned int filterIndex=0)
|
||||
{_spatiotemporalLPfilter_Irregular(get_data(inputFrame), &outputFrame[0], filterIndex);};
|
||||
/**
|
||||
* run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners)
|
||||
* @param inputFrame: the input image to be processed
|
||||
* @param outputFrame: the output buffer in which the result is writen
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
inline void runProgressiveFilter(const std::valarray<float> &inputFrame,
|
||||
std::valarray<float> &outputFrame,
|
||||
const unsigned int filterIndex=0)
|
||||
{_spatiotemporalLPfilter_Irregular(get_data(inputFrame), &outputFrame[0], filterIndex);};
|
||||
|
||||
/**
|
||||
* first order spatio-temporal low pass filter setup function
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing)
|
||||
* @param k: spatial constant of the filter (unit is pixels)
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void setLPfilterParameters(const float beta, const float tau, const float k, const unsigned int filterIndex=0); // change the parameters of the filter
|
||||
/**
|
||||
* first order spatio-temporal low pass filter setup function
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing)
|
||||
* @param k: spatial constant of the filter (unit is pixels)
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void setLPfilterParameters(const float beta, const float tau, const float k, const unsigned int filterIndex=0); // change the parameters of the filter
|
||||
|
||||
/**
|
||||
* first order spatio-temporal low pass filter setup function
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing)
|
||||
* @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void setProgressiveFilterConstants_CentredAccuracy(const float beta, const float tau, const float alpha0, const unsigned int filterIndex=0);
|
||||
/**
|
||||
* first order spatio-temporal low pass filter setup function
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing)
|
||||
* @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void setProgressiveFilterConstants_CentredAccuracy(const float beta, const float tau, const float alpha0, const unsigned int filterIndex=0);
|
||||
|
||||
/**
|
||||
* first order spatio-temporal low pass filter setup function
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing)
|
||||
* @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image
|
||||
* @param accuracyMap an image (float format) which values range is between 0 and 1, where 0 means, apply no filtering and 1 means apply the filtering as specified in the parameters set, intermediate values allow to smooth variations of the filtering strenght
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void setProgressiveFilterConstants_CustomAccuracy(const float beta, const float tau, const float alpha0, const std::valarray<float> &accuracyMap, const unsigned int filterIndex=0);
|
||||
/**
|
||||
* first order spatio-temporal low pass filter setup function
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing)
|
||||
* @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image
|
||||
* @param accuracyMap an image (float format) which values range is between 0 and 1, where 0 means, apply no filtering and 1 means apply the filtering as specified in the parameters set, intermediate values allow to smooth variations of the filtering strenght
|
||||
* @param filterIndex: the index which specifies the parameter set that should be used for the filtering
|
||||
*/
|
||||
void setProgressiveFilterConstants_CustomAccuracy(const float beta, const float tau, const float alpha0, const std::valarray<float> &accuracyMap, const unsigned int filterIndex=0);
|
||||
|
||||
/**
|
||||
* local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation)
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
* @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous)
|
||||
* @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI)
|
||||
*/
|
||||
void setV0CompressionParameter(const float v0, const float maxInputValue, const float){ _v0=v0*maxInputValue; _localLuminanceFactor=v0; _localLuminanceAddon=maxInputValue*(1.0f-v0); _maxInputValue=maxInputValue;};
|
||||
/**
|
||||
* local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation)
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
* @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous)
|
||||
* @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI)
|
||||
*/
|
||||
void setV0CompressionParameter(const float v0, const float maxInputValue, const float){ _v0=v0*maxInputValue; _localLuminanceFactor=v0; _localLuminanceAddon=maxInputValue*(1.0f-v0); _maxInputValue=maxInputValue;};
|
||||
|
||||
/**
|
||||
* update local luminance adaptation setup, initial maxInputValue is kept. This function should be applied for normal local adaptation (not for tone mapping operation)
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
* @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI)
|
||||
*/
|
||||
void setV0CompressionParameter(const float v0, const float meanLuminance){ this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance);};
|
||||
/**
|
||||
* update local luminance adaptation setup, initial maxInputValue is kept. This function should be applied for normal local adaptation (not for tone mapping operation)
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
* @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI)
|
||||
*/
|
||||
void setV0CompressionParameter(const float v0, const float meanLuminance){ this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance);};
|
||||
|
||||
/**
|
||||
* local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation)
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
*/
|
||||
void setV0CompressionParameter(const float v0){ _v0=v0*_maxInputValue; _localLuminanceFactor=v0; _localLuminanceAddon=_maxInputValue*(1.0f-v0);};
|
||||
/**
|
||||
* local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation)
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
*/
|
||||
void setV0CompressionParameter(const float v0){ _v0=v0*_maxInputValue; _localLuminanceFactor=v0; _localLuminanceAddon=_maxInputValue*(1.0f-v0);};
|
||||
|
||||
/**
|
||||
* local luminance adaptation setup, this function should be applied for local adaptation applied to tone mapping operation
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
* @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous)
|
||||
* @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI)
|
||||
*/
|
||||
void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f){ _v0=v0*maxInputValue; _localLuminanceFactor=1.0f; _localLuminanceAddon=meanLuminance*_v0; _maxInputValue=maxInputValue;};
|
||||
/**
|
||||
* local luminance adaptation setup, this function should be applied for local adaptation applied to tone mapping operation
|
||||
* @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect
|
||||
* @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous)
|
||||
* @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI)
|
||||
*/
|
||||
void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f){ _v0=v0*maxInputValue; _localLuminanceFactor=1.0f; _localLuminanceAddon=meanLuminance*_v0; _maxInputValue=maxInputValue;};
|
||||
|
||||
/**
|
||||
* update compression parameters while keeping v0 parameter value
|
||||
* @param meanLuminance the input frame mean luminance
|
||||
*/
|
||||
inline void updateCompressionParameter(const float meanLuminance){_localLuminanceFactor=1; _localLuminanceAddon=meanLuminance*_v0;};
|
||||
/**
|
||||
* update compression parameters while keeping v0 parameter value
|
||||
* @param meanLuminance the input frame mean luminance
|
||||
*/
|
||||
inline void updateCompressionParameter(const float meanLuminance){_localLuminanceFactor=1; _localLuminanceAddon=meanLuminance*_v0;};
|
||||
|
||||
/**
|
||||
* @return the v0 compression parameter used to compute the local adaptation
|
||||
*/
|
||||
float getV0CompressionParameter(){ return _v0/_maxInputValue;};
|
||||
/**
|
||||
* @return the v0 compression parameter used to compute the local adaptation
|
||||
*/
|
||||
float getV0CompressionParameter(){ return _v0/_maxInputValue;};
|
||||
|
||||
/**
|
||||
* @return the output result of the object
|
||||
*/
|
||||
inline const std::valarray<float> &getOutput() const {return _filterOutput;};
|
||||
/**
|
||||
* @return the output result of the object
|
||||
*/
|
||||
inline const std::valarray<float> &getOutput() const {return _filterOutput;};
|
||||
|
||||
/**
|
||||
* @return number of rows of the filter
|
||||
*/
|
||||
inline unsigned int getNBrows(){return _filterOutput.getNBrows();};
|
||||
/**
|
||||
* @return number of rows of the filter
|
||||
*/
|
||||
inline unsigned int getNBrows(){return _filterOutput.getNBrows();};
|
||||
|
||||
/**
|
||||
* @return number of columns of the filter
|
||||
*/
|
||||
inline unsigned int getNBcolumns(){return _filterOutput.getNBcolumns();};
|
||||
/**
|
||||
* @return number of columns of the filter
|
||||
*/
|
||||
inline unsigned int getNBcolumns(){return _filterOutput.getNBcolumns();};
|
||||
|
||||
/**
|
||||
* @return number of pixels of the filter
|
||||
*/
|
||||
inline unsigned int getNBpixels(){return _filterOutput.getNBpixels();};
|
||||
/**
|
||||
* @return number of pixels of the filter
|
||||
*/
|
||||
inline unsigned int getNBpixels(){return _filterOutput.getNBpixels();};
|
||||
|
||||
/**
|
||||
* force filter output to be normalized between 0 and maxValue
|
||||
* @param maxValue: the maximum output value that is required
|
||||
*/
|
||||
inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue){_filterOutput.normalizeGrayOutput_0_maxOutputValue(maxValue);};
|
||||
/**
|
||||
* force filter output to be normalized between 0 and maxValue
|
||||
* @param maxValue: the maximum output value that is required
|
||||
*/
|
||||
inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue){_filterOutput.normalizeGrayOutput_0_maxOutputValue(maxValue);};
|
||||
|
||||
/**
|
||||
* force filter output to be normalized around 0 and rescaled with a sigmoide effect (extrem values saturation)
|
||||
* @param maxValue: the maximum output value that is required
|
||||
*/
|
||||
inline void normalizeGrayOutputCentredSigmoide(){_filterOutput.normalizeGrayOutputCentredSigmoide();};
|
||||
/**
|
||||
* force filter output to be normalized around 0 and rescaled with a sigmoide effect (extrem values saturation)
|
||||
* @param maxValue: the maximum output value that is required
|
||||
*/
|
||||
inline void normalizeGrayOutputCentredSigmoide(){_filterOutput.normalizeGrayOutputCentredSigmoide();};
|
||||
|
||||
/**
|
||||
* force filter output to be normalized : data centering and std normalisation
|
||||
* @param maxValue: the maximum output value that is required
|
||||
*/
|
||||
inline void centerReductImageLuminance(){_filterOutput.centerReductImageLuminance();};
|
||||
/**
|
||||
* force filter output to be normalized : data centering and std normalisation
|
||||
* @param maxValue: the maximum output value that is required
|
||||
*/
|
||||
inline void centerReductImageLuminance(){_filterOutput.centerReductImageLuminance();};
|
||||
|
||||
/**
|
||||
* @return the maximum input buffer value
|
||||
*/
|
||||
inline float getMaxInputValue(){return this->_maxInputValue;};
|
||||
/**
|
||||
* @return the maximum input buffer value
|
||||
*/
|
||||
inline float getMaxInputValue(){return this->_maxInputValue;};
|
||||
|
||||
/**
|
||||
* @return the maximum input buffer value
|
||||
*/
|
||||
inline void setMaxInputValue(const float newMaxInputValue){this->_maxInputValue=newMaxInputValue;};
|
||||
/**
|
||||
* @return the maximum input buffer value
|
||||
*/
|
||||
inline void setMaxInputValue(const float newMaxInputValue){this->_maxInputValue=newMaxInputValue;};
|
||||
|
||||
protected:
|
||||
protected:
|
||||
|
||||
/////////////////////////
|
||||
// data buffers
|
||||
TemplateBuffer<float> _filterOutput; // primary buffer (contains processing outputs)
|
||||
std::valarray<float> _localBuffer; // local secondary buffer
|
||||
/////////////////////////
|
||||
// PARAMETERS
|
||||
unsigned int _halfNBrows;
|
||||
unsigned int _halfNBcolumns;
|
||||
/////////////////////////
|
||||
// data buffers
|
||||
TemplateBuffer<float> _filterOutput; // primary buffer (contains processing outputs)
|
||||
std::valarray<float> _localBuffer; // local secondary buffer
|
||||
/////////////////////////
|
||||
// PARAMETERS
|
||||
unsigned int _halfNBrows;
|
||||
unsigned int _halfNBcolumns;
|
||||
|
||||
// parameters buffers
|
||||
std::valarray <float>_filteringCoeficientsTable;
|
||||
std::valarray <float>_progressiveSpatialConstant;// pointer to a local table containing local spatial constant (allocated with the object)
|
||||
std::valarray <float>_progressiveGain;// pointer to a local table containing local spatial constant (allocated with the object)
|
||||
// parameters buffers
|
||||
std::valarray <float>_filteringCoeficientsTable;
|
||||
std::valarray <float>_progressiveSpatialConstant;// pointer to a local table containing local spatial constant (allocated with the object)
|
||||
std::valarray <float>_progressiveGain;// pointer to a local table containing local spatial constant (allocated with the object)
|
||||
|
||||
// local adaptation filtering parameters
|
||||
float _v0; //value used for local luminance adaptation function
|
||||
float _maxInputValue;
|
||||
float _meanInputValue;
|
||||
float _localLuminanceFactor;
|
||||
float _localLuminanceAddon;
|
||||
// local adaptation filtering parameters
|
||||
float _v0; //value used for local luminance adaptation function
|
||||
float _maxInputValue;
|
||||
float _meanInputValue;
|
||||
float _localLuminanceFactor;
|
||||
float _localLuminanceAddon;
|
||||
|
||||
// protected data related to standard low pass filters parameters
|
||||
float _a;
|
||||
float _tau;
|
||||
float _gain;
|
||||
// protected data related to standard low pass filters parameters
|
||||
float _a;
|
||||
float _tau;
|
||||
float _gain;
|
||||
|
||||
/////////////////////////
|
||||
// FILTERS METHODS
|
||||
/////////////////////////
|
||||
// FILTERS METHODS
|
||||
|
||||
// Basic low pass spation temporal low pass filter used by each retina filters
|
||||
void _spatiotemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int coefTableOffset=0);
|
||||
float _squaringSpatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0);
|
||||
// Basic low pass spation temporal low pass filter used by each retina filters
|
||||
void _spatiotemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int coefTableOffset=0);
|
||||
float _squaringSpatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0);
|
||||
|
||||
// LP filter with an irregular spatial filtering
|
||||
// LP filter with an irregular spatial filtering
|
||||
|
||||
// -> rewrites the input buffer
|
||||
void _spatiotemporalLPfilter_Irregular(float *inputOutputFrame, const unsigned int filterIndex=0);
|
||||
// writes the output on another buffer
|
||||
void _spatiotemporalLPfilter_Irregular(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0);
|
||||
// LP filter that squares the input and computes the output ONLY on the areas where the integrationAreas map are TRUE
|
||||
void _localSquaringSpatioTemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex=0);
|
||||
// -> rewrites the input buffer
|
||||
void _spatiotemporalLPfilter_Irregular(float *inputOutputFrame, const unsigned int filterIndex=0);
|
||||
// writes the output on another buffer
|
||||
void _spatiotemporalLPfilter_Irregular(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0);
|
||||
// LP filter that squares the input and computes the output ONLY on the areas where the integrationAreas map are TRUE
|
||||
void _localSquaringSpatioTemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex=0);
|
||||
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer
|
||||
void _localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame);
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output
|
||||
void _localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance);
|
||||
// local adaptation applied on a range of values which can be positive and negative
|
||||
void _localLuminanceAdaptationPosNegValues(const float *inputFrame, const float *localLuminance, float *outputFrame);
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer
|
||||
void _localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame, const bool updateLuminanceMean=true);
|
||||
// local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output
|
||||
void _localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance);
|
||||
// local adaptation applied on a range of values which can be positive and negative
|
||||
void _localLuminanceAdaptationPosNegValues(const float *inputFrame, const float *localLuminance, float *outputFrame);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// 1D directional filters used for the 2D low pass filtering
|
||||
//////////////////////////////////////////////////////////////
|
||||
// 1D directional filters used for the 2D low pass filtering
|
||||
|
||||
// 1D filters with image input
|
||||
void _horizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
// 1D filters with image input that is squared in the function
|
||||
void _squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
// vertical anticausal filter that returns the mean value of its result
|
||||
float _verticalAnticausalFilter_returnMeanValue(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
// 1D filters with image input
|
||||
void _horizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
// 1D filters with image input that is squared in the function // parallelized with TBB
|
||||
void _squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
// vertical anticausal filter that returns the mean value of its result
|
||||
float _verticalAnticausalFilter_returnMeanValue(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
|
||||
// most simple functions: only perform 1D filtering with output=input (no add on)
|
||||
void _horizontalCausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
void _verticalAnticausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
// most simple functions: only perform 1D filtering with output=input (no add on)
|
||||
void _horizontalCausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); // parallelized with TBB
|
||||
void _verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // parallelized with TBB
|
||||
void _verticalAnticausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
|
||||
// perform 1D filtering with output with varrying spatial coefficient
|
||||
void _horizontalCausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _horizontalCausalFilter_Irregular_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
void _verticalAnticausalFilter_Irregular_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
// perform 1D filtering with output with varrying spatial coefficient
|
||||
void _horizontalCausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _horizontalCausalFilter_Irregular_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd);
|
||||
void _horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const float *spatialConstantBuffer); // parallelized with TBB
|
||||
void _verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const float *spatialConstantBuffer); // parallelized with TBB
|
||||
void _verticalAnticausalFilter_Irregular_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd);
|
||||
|
||||
|
||||
// 1D filters in which the output is multiplied by _gain
|
||||
void _verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output
|
||||
void _horizontalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output
|
||||
// 1D filters in which the output is multiplied by _gain
|
||||
void _verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output // parallelized with TBB
|
||||
void _horizontalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output
|
||||
|
||||
// LP filter on specific parts of the picture instead of all the image
|
||||
// same functions (some of them) but take a binary flag to allow integration, false flag means, 0 at the output...
|
||||
void _local_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas);
|
||||
void _local_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas);
|
||||
void _local_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas);
|
||||
void _local_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas); // this functions affects _gain at the output
|
||||
// LP filter on specific parts of the picture instead of all the image
|
||||
// same functions (some of them) but take a binary flag to allow integration, false flag means, 0 at the output...
|
||||
void _local_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas);
|
||||
void _local_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas);
|
||||
void _local_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas);
|
||||
void _local_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas); // this functions affects _gain at the output
|
||||
|
||||
};
|
||||
#ifdef MAKE_PARALLEL
|
||||
/******************************************************
|
||||
** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors
|
||||
** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary
|
||||
** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised
|
||||
** ==> functors constructors can differ from the parameters used with their related serial functions
|
||||
*/
|
||||
|
||||
#define _DEBUG_TBB // define DEBUG_TBB in order to display additionnal data on stdout
|
||||
class Parallel_horizontalAnticausalFilter: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
unsigned int IDrowEnd, nbColumns;
|
||||
float filterParam_a;
|
||||
public:
|
||||
// constructor which takes the input image pointer reference reference and limits
|
||||
Parallel_horizontalAnticausalFilter(float *bufferToProcess, const unsigned int idEnd, const unsigned int nbCols, const float a )
|
||||
:outputFrame(bufferToProcess), IDrowEnd(idEnd), nbColumns(nbCols), filterParam_a(a)
|
||||
{
|
||||
#ifdef DEBUG_TBB
|
||||
std::cout<<"Parallel_horizontalAnticausalFilter::Parallel_horizontalAnticausalFilter :"
|
||||
<<"\n\t idEnd="<<IDrowEnd
|
||||
<<"\n\t nbCols="<<nbColumns
|
||||
<<"\n\t filterParam="<<filterParam_a
|
||||
<<std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
|
||||
#ifdef DEBUG_TBB
|
||||
std::cout<<"Parallel_horizontalAnticausalFilter::operator() :"
|
||||
<<"\n\t range size="<<r.size()
|
||||
<<"\n\t first index="<<r.start
|
||||
//<<"\n\t last index="<<filterParam
|
||||
<<std::endl;
|
||||
#endif
|
||||
for (int IDrow=r.start; IDrow!=r.end; ++IDrow)
|
||||
{
|
||||
register float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(nbColumns)-1;
|
||||
register float result=0;
|
||||
for (unsigned int index=0; index<nbColumns; ++index)
|
||||
{
|
||||
result = *(outputPTR)+ filterParam_a* result;
|
||||
*(outputPTR--) = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Parallel_horizontalCausalFilter_addInput: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
const float *inputFrame;
|
||||
float *outputFrame;
|
||||
unsigned int IDrowStart, nbColumns;
|
||||
float filterParam_a, filterParam_tau;
|
||||
public:
|
||||
Parallel_horizontalCausalFilter_addInput(const float *bufferToAddAsInputProcess, float *bufferToProcess, const unsigned int idStart, const unsigned int nbCols, const float a, const float tau)
|
||||
:inputFrame(bufferToAddAsInputProcess), outputFrame(bufferToProcess), IDrowStart(idStart), nbColumns(nbCols), filterParam_a(a), filterParam_tau(tau){}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
for (int IDrow=r.start; IDrow!=r.end; ++IDrow)
|
||||
{
|
||||
register float* outputPTR=outputFrame+(IDrowStart+IDrow)*nbColumns;
|
||||
register const float* inputPTR=inputFrame+(IDrowStart+IDrow)*nbColumns;
|
||||
register float result=0;
|
||||
for (unsigned int index=0; index<nbColumns; ++index)
|
||||
{
|
||||
result = *(inputPTR++) + filterParam_tau**(outputPTR)+ filterParam_a* result;
|
||||
*(outputPTR++) = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Parallel_verticalCausalFilter: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
unsigned int nbRows, nbColumns;
|
||||
float filterParam_a;
|
||||
public:
|
||||
Parallel_verticalCausalFilter(float *bufferToProcess, const unsigned int nbRws, const unsigned int nbCols, const float a )
|
||||
:outputFrame(bufferToProcess), nbRows(nbRws), nbColumns(nbCols), filterParam_a(a){}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn)
|
||||
{
|
||||
register float result=0;
|
||||
register float *outputPTR=outputFrame+IDcolumn;
|
||||
|
||||
for (unsigned int index=0; index<nbRows; ++index)
|
||||
{
|
||||
result = *(outputPTR) + filterParam_a * result;
|
||||
*(outputPTR) = result;
|
||||
outputPTR+=nbColumns;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Parallel_verticalAnticausalFilter_multGain: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
unsigned int nbRows, nbColumns;
|
||||
float filterParam_a, filterParam_gain;
|
||||
public:
|
||||
Parallel_verticalAnticausalFilter_multGain(float *bufferToProcess, const unsigned int nbRws, const unsigned int nbCols, const float a, const float gain)
|
||||
:outputFrame(bufferToProcess), nbRows(nbRws), nbColumns(nbCols), filterParam_a(a), filterParam_gain(gain){}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
float* offset=outputFrame+nbColumns*nbRows-nbColumns;
|
||||
for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn)
|
||||
{
|
||||
register float result=0;
|
||||
register float *outputPTR=offset+IDcolumn;
|
||||
|
||||
for (unsigned int index=0; index<nbRows; ++index)
|
||||
{
|
||||
result = *(outputPTR) + filterParam_a * result;
|
||||
*(outputPTR) = filterParam_gain*result;
|
||||
outputPTR-=nbColumns;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Parallel_localAdaptation: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
const float *localLuminance, *inputFrame;
|
||||
float *outputFrame;
|
||||
float localLuminanceFactor, localLuminanceAddon, maxInputValue;
|
||||
public:
|
||||
Parallel_localAdaptation(const float *localLum, const float *inputImg, float *bufferToProcess, const float localLuminanceFact, const float localLuminanceAdd, const float maxInputVal)
|
||||
:localLuminance(localLum), inputFrame(inputImg),outputFrame(bufferToProcess), localLuminanceFactor(localLuminanceFact), localLuminanceAddon(localLuminanceAdd), maxInputValue(maxInputVal) {};
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
const float *localLuminancePTR=localLuminance+r.start;
|
||||
const float *inputFramePTR=inputFrame+r.start;
|
||||
float *outputFramePTR=outputFrame+r.start;
|
||||
for (register int IDpixel=r.start ; IDpixel!=r.end ; ++IDpixel, ++inputFramePTR, ++outputFramePTR)
|
||||
{
|
||||
float X0=*(localLuminancePTR++)*localLuminanceFactor+localLuminanceAddon;
|
||||
// TODO : the following line can lead to a divide by zero ! A small offset is added, take care if the offset is too large in case of High Dynamic Range images which can use very small values...
|
||||
*(outputFramePTR) = (maxInputValue+X0)**inputFramePTR/(*inputFramePTR +X0+0.00000000001f);
|
||||
//std::cout<<"BasicRetinaFilter::inputFrame[IDpixel]=%f, X0=%f, outputFrame[IDpixel]=%f\n", inputFrame[IDpixel], X0, outputFrame[IDpixel]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////
|
||||
/// Specific filtering methods which manage non const spatial filtering parameter (used By retinacolor and LogProjectors)
|
||||
class Parallel_horizontalAnticausalFilter_Irregular: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
const float *spatialConstantBuffer;
|
||||
unsigned int IDrowEnd, nbColumns;
|
||||
public:
|
||||
Parallel_horizontalAnticausalFilter_Irregular(float *bufferToProcess, const float *spatialConst, const unsigned int idEnd, const unsigned int nbCols)
|
||||
:outputFrame(bufferToProcess), spatialConstantBuffer(spatialConst), IDrowEnd(idEnd), nbColumns(nbCols){}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
|
||||
for (int IDrow=r.start; IDrow!=r.end; ++IDrow)
|
||||
{
|
||||
register float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(nbColumns)-1;
|
||||
register const float* spatialConstantPTR=spatialConstantBuffer+(IDrowEnd-IDrow)*(nbColumns)-1;
|
||||
register float result=0;
|
||||
for (unsigned int index=0; index<nbColumns; ++index)
|
||||
{
|
||||
result = *(outputPTR)+ *(spatialConstantPTR--)* result;
|
||||
*(outputPTR--) = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Parallel_verticalCausalFilter_Irregular: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
const float *spatialConstantBuffer;
|
||||
unsigned int nbRows, nbColumns;
|
||||
public:
|
||||
Parallel_verticalCausalFilter_Irregular(float *bufferToProcess, const float *spatialConst, const unsigned int nbRws, const unsigned int nbCols)
|
||||
:outputFrame(bufferToProcess), spatialConstantBuffer(spatialConst), nbRows(nbRws), nbColumns(nbCols){}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn)
|
||||
{
|
||||
register float result=0;
|
||||
register float *outputPTR=outputFrame+IDcolumn;
|
||||
register const float* spatialConstantPTR=spatialConstantBuffer+IDcolumn;
|
||||
for (unsigned int index=0; index<nbRows; ++index)
|
||||
{
|
||||
result = *(outputPTR) + *(spatialConstantPTR) * result;
|
||||
*(outputPTR) = result;
|
||||
outputPTR+=nbColumns;
|
||||
spatialConstantPTR+=nbColumns;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*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.
|
||||
//
|
||||
// This file originates from the openFABMAP project:
|
||||
// [http://code.google.com/p/openfabmap/]
|
||||
//
|
||||
// For published work which uses all or part of OpenFABMAP, please cite:
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
|
||||
//
|
||||
// Original Algorithm by Mark Cummins and Paul Newman:
|
||||
// [http://ijr.sagepub.com/content/27/6/647.short]
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
|
||||
// [http://ijr.sagepub.com/content/30/9/1100.abstract]
|
||||
//
|
||||
// License Agreement
|
||||
//
|
||||
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
|
||||
// Will Maddern [w.maddern@qut.edu.au], all rights reserved.
|
||||
//
|
||||
//
|
||||
// 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 "opencv2/contrib/openfabmap.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace of2 {
|
||||
|
||||
BOWMSCTrainer::BOWMSCTrainer(double _clusterSize) :
|
||||
clusterSize(_clusterSize) {
|
||||
}
|
||||
|
||||
BOWMSCTrainer::~BOWMSCTrainer() {
|
||||
}
|
||||
|
||||
Mat BOWMSCTrainer::cluster() const {
|
||||
CV_Assert(!descriptors.empty());
|
||||
int descCount = 0;
|
||||
for(size_t i = 0; i < descriptors.size(); i++)
|
||||
descCount += descriptors[i].rows;
|
||||
|
||||
Mat mergedDescriptors(descCount, descriptors[0].cols,
|
||||
descriptors[0].type());
|
||||
for(size_t i = 0, start = 0; i < descriptors.size(); i++)
|
||||
{
|
||||
Mat submut = mergedDescriptors.rowRange((int)start,
|
||||
(int)(start + descriptors[i].rows));
|
||||
descriptors[i].copyTo(submut);
|
||||
start += descriptors[i].rows;
|
||||
}
|
||||
return cluster(mergedDescriptors);
|
||||
}
|
||||
|
||||
Mat BOWMSCTrainer::cluster(const Mat& _descriptors) const {
|
||||
|
||||
CV_Assert(!_descriptors.empty());
|
||||
|
||||
// TODO: sort the descriptors before clustering.
|
||||
|
||||
|
||||
Mat icovar = Mat::eye(_descriptors.cols,_descriptors.cols,_descriptors.type());
|
||||
|
||||
vector<Mat> initialCentres;
|
||||
initialCentres.push_back(_descriptors.row(0));
|
||||
for (int i = 1; i < _descriptors.rows; i++) {
|
||||
double minDist = DBL_MAX;
|
||||
for (size_t j = 0; j < initialCentres.size(); j++) {
|
||||
minDist = std::min(minDist,
|
||||
cv::Mahalanobis(_descriptors.row(i),initialCentres[j],
|
||||
icovar));
|
||||
}
|
||||
if (minDist > clusterSize)
|
||||
initialCentres.push_back(_descriptors.row(i));
|
||||
}
|
||||
|
||||
std::vector<std::list<cv::Mat> > clusters;
|
||||
clusters.resize(initialCentres.size());
|
||||
for (int i = 0; i < _descriptors.rows; i++) {
|
||||
int index = 0; double dist = 0, minDist = DBL_MAX;
|
||||
for (size_t j = 0; j < initialCentres.size(); j++) {
|
||||
dist = cv::Mahalanobis(_descriptors.row(i),initialCentres[j],icovar);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
index = (int)j;
|
||||
}
|
||||
}
|
||||
clusters[index].push_back(_descriptors.row(i));
|
||||
}
|
||||
|
||||
// TODO: throw away small clusters.
|
||||
|
||||
Mat vocabulary;
|
||||
Mat centre = Mat::zeros(1,_descriptors.cols,_descriptors.type());
|
||||
for (size_t i = 0; i < clusters.size(); i++) {
|
||||
centre.setTo(0);
|
||||
for (std::list<cv::Mat>::iterator Ci = clusters[i].begin(); Ci != clusters[i].end(); Ci++) {
|
||||
centre += *Ci;
|
||||
}
|
||||
centre /= (double)clusters[i].size();
|
||||
vocabulary.push_back(centre);
|
||||
}
|
||||
|
||||
return vocabulary;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ private:
|
||||
float max_scale_;
|
||||
|
||||
public:
|
||||
SlidingWindowImageRange(int width, int height, int x_step = 3, int y_step = 3, int scales = 5, float min_scale = 0.6, float max_scale = 1.6) :
|
||||
width_(width), height_(height), x_step_(x_step),y_step_(y_step), scales_(scales), min_scale_(min_scale), max_scale_(max_scale)
|
||||
SlidingWindowImageRange(int width, int height, int x_step = 3, int y_step = 3, int _scales = 5, float min_scale = 0.6, float max_scale = 1.6) :
|
||||
width_(width), height_(height), x_step_(x_step),y_step_(y_step), scales_(_scales), min_scale_(min_scale), max_scale_(max_scale)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ private:
|
||||
LocationImageRange& operator=(const LocationImageRange&);
|
||||
|
||||
public:
|
||||
LocationImageRange(const std::vector<Point>& locations, int scales = 5, float min_scale = 0.6, float max_scale = 1.6) :
|
||||
locations_(locations), scales_(scales), min_scale_(min_scale), max_scale_(max_scale)
|
||||
LocationImageRange(const std::vector<Point>& locations, int _scales = 5, float min_scale = 0.6, float max_scale = 1.6) :
|
||||
locations_(locations), scales_(_scales), min_scale_(min_scale), max_scale_(max_scale)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -141,10 +141,10 @@ private:
|
||||
LocationScaleImageRange(const LocationScaleImageRange&);
|
||||
LocationScaleImageRange& operator=(const LocationScaleImageRange&);
|
||||
public:
|
||||
LocationScaleImageRange(const std::vector<Point>& locations, const std::vector<float>& scales) :
|
||||
locations_(locations), scales_(scales)
|
||||
LocationScaleImageRange(const std::vector<Point>& locations, const std::vector<float>& _scales) :
|
||||
locations_(locations), scales_(_scales)
|
||||
{
|
||||
assert(locations.size()==scales.size());
|
||||
assert(locations.size()==_scales.size());
|
||||
}
|
||||
|
||||
ImageIterator* iterator() const
|
||||
@@ -237,7 +237,7 @@ private:
|
||||
|
||||
std::vector<Template*> templates;
|
||||
public:
|
||||
Matching(bool use_orientation = true, float truncate = 10) : truncate_(truncate), use_orientation_(use_orientation)
|
||||
Matching(bool use_orientation = true, float _truncate = 10) : truncate_(_truncate), use_orientation_(use_orientation)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ private:
|
||||
LocationImageIterator& operator=(const LocationImageIterator&);
|
||||
|
||||
public:
|
||||
LocationImageIterator(const std::vector<Point>& locations, int scales, float min_scale, float max_scale);
|
||||
LocationImageIterator(const std::vector<Point>& locations, int _scales, float min_scale, float max_scale);
|
||||
|
||||
bool hasNext() const {
|
||||
return has_next_;
|
||||
@@ -392,10 +392,10 @@ private:
|
||||
LocationScaleImageIterator& operator=(const LocationScaleImageIterator&);
|
||||
|
||||
public:
|
||||
LocationScaleImageIterator(const std::vector<Point>& locations, const std::vector<float>& scales) :
|
||||
locations_(locations), scales_(scales)
|
||||
LocationScaleImageIterator(const std::vector<Point>& locations, const std::vector<float>& _scales) :
|
||||
locations_(locations), scales_(_scales)
|
||||
{
|
||||
assert(locations.size()==scales.size());
|
||||
assert(locations.size()==_scales.size());
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -494,7 +494,7 @@ ChamferMatcher::SlidingWindowImageIterator::SlidingWindowImageIterator( int widt
|
||||
int height,
|
||||
int x_step = 3,
|
||||
int y_step = 3,
|
||||
int scales = 5,
|
||||
int _scales = 5,
|
||||
float min_scale = 0.6,
|
||||
float max_scale = 1.6) :
|
||||
|
||||
@@ -502,7 +502,7 @@ ChamferMatcher::SlidingWindowImageIterator::SlidingWindowImageIterator( int widt
|
||||
height_(height),
|
||||
x_step_(x_step),
|
||||
y_step_(y_step),
|
||||
scales_(scales),
|
||||
scales_(_scales),
|
||||
min_scale_(min_scale),
|
||||
max_scale_(max_scale)
|
||||
{
|
||||
@@ -550,11 +550,11 @@ ChamferMatcher::ImageIterator* ChamferMatcher::SlidingWindowImageRange::iterator
|
||||
|
||||
|
||||
ChamferMatcher::LocationImageIterator::LocationImageIterator(const std::vector<Point>& locations,
|
||||
int scales = 5,
|
||||
int _scales = 5,
|
||||
float min_scale = 0.6,
|
||||
float max_scale = 1.6) :
|
||||
locations_(locations),
|
||||
scales_(scales),
|
||||
scales_(_scales),
|
||||
min_scale_(min_scale),
|
||||
max_scale_(max_scale)
|
||||
{
|
||||
@@ -1138,10 +1138,10 @@ ChamferMatcher::Match* ChamferMatcher::Matching::localChamferDistance(Point offs
|
||||
}
|
||||
|
||||
|
||||
ChamferMatcher::Matches* ChamferMatcher::Matching::matchTemplates(Mat& dist_img, Mat& orientation_img, const ImageRange& range, float orientation_weight)
|
||||
ChamferMatcher::Matches* ChamferMatcher::Matching::matchTemplates(Mat& dist_img, Mat& orientation_img, const ImageRange& range, float _orientation_weight)
|
||||
{
|
||||
|
||||
ChamferMatcher::Matches* matches(new Matches());
|
||||
ChamferMatcher::Matches* pmatches(new Matches());
|
||||
// try each template
|
||||
for(size_t i = 0; i < templates.size(); i++) {
|
||||
ImageIterator* it = range.iterator();
|
||||
@@ -1156,17 +1156,17 @@ ChamferMatcher::Matches* ChamferMatcher::Matching::matchTemplates(Mat& dist_img,
|
||||
if (loc.x-tpl->center.x<0 || loc.x+tpl->size.width/2>=dist_img.cols) continue;
|
||||
if (loc.y-tpl->center.y<0 || loc.y+tpl->size.height/2>=dist_img.rows) continue;
|
||||
|
||||
ChamferMatcher::Match* is = localChamferDistance(loc, dist_img, orientation_img, tpl, orientation_weight);
|
||||
ChamferMatcher::Match* is = localChamferDistance(loc, dist_img, orientation_img, tpl, _orientation_weight);
|
||||
if(is)
|
||||
{
|
||||
matches->push_back(*is);
|
||||
pmatches->push_back(*is);
|
||||
delete is;
|
||||
}
|
||||
}
|
||||
|
||||
delete it;
|
||||
}
|
||||
return matches;
|
||||
return pmatches;
|
||||
}
|
||||
|
||||
|
||||
@@ -1176,7 +1176,8 @@ ChamferMatcher::Matches* ChamferMatcher::Matching::matchTemplates(Mat& dist_img,
|
||||
* @param edge_img Edge image
|
||||
* @return a match object
|
||||
*/
|
||||
ChamferMatcher::Matches* ChamferMatcher::Matching::matchEdgeImage(Mat& edge_img, const ImageRange& range, float orientation_weight, int /*max_matches*/, float /*min_match_distance*/)
|
||||
ChamferMatcher::Matches* ChamferMatcher::Matching::matchEdgeImage(Mat& edge_img, const ImageRange& range,
|
||||
float _orientation_weight, int /*max_matches*/, float /*min_match_distance*/)
|
||||
{
|
||||
CV_Assert(edge_img.channels()==1);
|
||||
|
||||
@@ -1203,10 +1204,10 @@ ChamferMatcher::Matches* ChamferMatcher::Matching::matchEdgeImage(Mat& edge_img,
|
||||
|
||||
|
||||
// Template matching
|
||||
ChamferMatcher::Matches* matches = matchTemplates( dist_img,
|
||||
ChamferMatcher::Matches* pmatches = matchTemplates( dist_img,
|
||||
orientation_img,
|
||||
range,
|
||||
orientation_weight);
|
||||
_orientation_weight);
|
||||
|
||||
|
||||
if (use_orientation_) {
|
||||
@@ -1215,7 +1216,7 @@ ChamferMatcher::Matches* ChamferMatcher::Matching::matchEdgeImage(Mat& edge_img,
|
||||
dist_img.release();
|
||||
annotated_img.release();
|
||||
|
||||
return matches;
|
||||
return pmatches;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
/*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.
|
||||
//
|
||||
// This file originates from the openFABMAP project:
|
||||
// [http://code.google.com/p/openfabmap/]
|
||||
//
|
||||
// For published work which uses all or part of OpenFABMAP, please cite:
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
|
||||
//
|
||||
// Original Algorithm by Mark Cummins and Paul Newman:
|
||||
// [http://ijr.sagepub.com/content/27/6/647.short]
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
|
||||
// [http://ijr.sagepub.com/content/30/9/1100.abstract]
|
||||
//
|
||||
// License Agreement
|
||||
//
|
||||
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
|
||||
// Will Maddern [w.maddern@qut.edu.au], all rights reserved.
|
||||
//
|
||||
//
|
||||
// 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 "opencv2/contrib/openfabmap.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace of2 {
|
||||
|
||||
ChowLiuTree::ChowLiuTree() {
|
||||
}
|
||||
|
||||
ChowLiuTree::~ChowLiuTree() {
|
||||
}
|
||||
|
||||
void ChowLiuTree::add(const Mat& imgDescriptor) {
|
||||
CV_Assert(!imgDescriptor.empty());
|
||||
if (!imgDescriptors.empty()) {
|
||||
CV_Assert(imgDescriptors[0].cols == imgDescriptor.cols);
|
||||
CV_Assert(imgDescriptors[0].type() == imgDescriptor.type());
|
||||
}
|
||||
|
||||
imgDescriptors.push_back(imgDescriptor);
|
||||
|
||||
}
|
||||
|
||||
void ChowLiuTree::add(const vector<Mat>& _imgDescriptors) {
|
||||
for (size_t i = 0; i < _imgDescriptors.size(); i++) {
|
||||
add(_imgDescriptors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<cv::Mat>& ChowLiuTree::getImgDescriptors() const {
|
||||
return imgDescriptors;
|
||||
}
|
||||
|
||||
Mat ChowLiuTree::make(double infoThreshold) {
|
||||
CV_Assert(!imgDescriptors.empty());
|
||||
|
||||
unsigned int descCount = 0;
|
||||
for (size_t i = 0; i < imgDescriptors.size(); i++)
|
||||
descCount += imgDescriptors[i].rows;
|
||||
|
||||
mergedImgDescriptors = cv::Mat(descCount, imgDescriptors[0].cols,
|
||||
imgDescriptors[0].type());
|
||||
for (size_t i = 0, start = 0; i < imgDescriptors.size(); i++)
|
||||
{
|
||||
Mat submut = mergedImgDescriptors.rowRange((int)start,
|
||||
(int)(start + imgDescriptors[i].rows));
|
||||
imgDescriptors[i].copyTo(submut);
|
||||
start += imgDescriptors[i].rows;
|
||||
}
|
||||
|
||||
std::list<info> edges;
|
||||
createBaseEdges(edges, infoThreshold);
|
||||
|
||||
// TODO: if it cv_asserts here they really won't know why.
|
||||
|
||||
CV_Assert(reduceEdgesToMinSpan(edges));
|
||||
|
||||
return buildTree(edges.front().word1, edges);
|
||||
}
|
||||
|
||||
double ChowLiuTree::P(int a, bool za) {
|
||||
|
||||
if(za) {
|
||||
return (0.98 * cv::countNonZero(mergedImgDescriptors.col(a)) /
|
||||
mergedImgDescriptors.rows) + 0.01;
|
||||
} else {
|
||||
return 1 - ((0.98 * cv::countNonZero(mergedImgDescriptors.col(a)) /
|
||||
mergedImgDescriptors.rows) + 0.01);
|
||||
}
|
||||
|
||||
}
|
||||
double ChowLiuTree::JP(int a, bool za, int b, bool zb) {
|
||||
|
||||
double count = 0;
|
||||
for(int i = 0; i < mergedImgDescriptors.rows; i++) {
|
||||
if((mergedImgDescriptors.at<float>(i,a) > 0) == za &&
|
||||
(mergedImgDescriptors.at<float>(i,b) > 0) == zb) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count / mergedImgDescriptors.rows;
|
||||
|
||||
}
|
||||
double ChowLiuTree::CP(int a, bool za, int b, bool zb){
|
||||
|
||||
int count = 0, total = 0;
|
||||
for(int i = 0; i < mergedImgDescriptors.rows; i++) {
|
||||
if((mergedImgDescriptors.at<float>(i,b) > 0) == zb) {
|
||||
total++;
|
||||
if((mergedImgDescriptors.at<float>(i,a) > 0) == za) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(total) {
|
||||
return (double)(0.98 * count)/total + 0.01;
|
||||
} else {
|
||||
return (za) ? 0.01 : 0.99;
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat ChowLiuTree::buildTree(int root_word, std::list<info> &edges) {
|
||||
|
||||
int q = root_word;
|
||||
cv::Mat cltree(4, (int)edges.size()+1, CV_64F);
|
||||
|
||||
cltree.at<double>(0, q) = q;
|
||||
cltree.at<double>(1, q) = P(q, true);
|
||||
cltree.at<double>(2, q) = P(q, true);
|
||||
cltree.at<double>(3, q) = P(q, true);
|
||||
//setting P(zq|zpq) to P(zq) gives the root node of the chow-liu
|
||||
//independence from a parent node.
|
||||
|
||||
//find all children and do the same
|
||||
vector<int> nextqs = extractChildren(edges, q);
|
||||
|
||||
int pq = q;
|
||||
vector<int>::iterator nextq;
|
||||
for(nextq = nextqs.begin(); nextq != nextqs.end(); nextq++) {
|
||||
recAddToTree(cltree, *nextq, pq, edges);
|
||||
}
|
||||
|
||||
return cltree;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ChowLiuTree::recAddToTree(cv::Mat &cltree, int q, int pq,
|
||||
std::list<info>& remaining_edges) {
|
||||
|
||||
cltree.at<double>(0, q) = pq;
|
||||
cltree.at<double>(1, q) = P(q, true);
|
||||
cltree.at<double>(2, q) = CP(q, true, pq, true);
|
||||
cltree.at<double>(3, q) = CP(q, true, pq, false);
|
||||
|
||||
//find all children and do the same
|
||||
vector<int> nextqs = extractChildren(remaining_edges, q);
|
||||
|
||||
pq = q;
|
||||
vector<int>::iterator nextq;
|
||||
for(nextq = nextqs.begin(); nextq != nextqs.end(); nextq++) {
|
||||
recAddToTree(cltree, *nextq, pq, remaining_edges);
|
||||
}
|
||||
}
|
||||
|
||||
vector<int> ChowLiuTree::extractChildren(std::list<info> &remaining_edges, int q) {
|
||||
|
||||
std::vector<int> children;
|
||||
std::list<info>::iterator edge = remaining_edges.begin();
|
||||
|
||||
while(edge != remaining_edges.end()) {
|
||||
if(edge->word1 == q) {
|
||||
children.push_back(edge->word2);
|
||||
edge = remaining_edges.erase(edge);
|
||||
continue;
|
||||
}
|
||||
if(edge->word2 == q) {
|
||||
children.push_back(edge->word1);
|
||||
edge = remaining_edges.erase(edge);
|
||||
continue;
|
||||
}
|
||||
edge++;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
bool ChowLiuTree::sortInfoScores(const info& first, const info& second) {
|
||||
return first.score > second.score;
|
||||
}
|
||||
|
||||
double ChowLiuTree::calcMutInfo(int word1, int word2) {
|
||||
double accumulation = 0;
|
||||
|
||||
double P00 = JP(word1, false, word2, false);
|
||||
if(P00) accumulation += P00 * log(P00 / (P(word1, false)*P(word2, false)));
|
||||
|
||||
double P01 = JP(word1, false, word2, true);
|
||||
if(P01) accumulation += P01 * log(P01 / (P(word1, false)*P(word2, true)));
|
||||
|
||||
double P10 = JP(word1, true, word2, false);
|
||||
if(P10) accumulation += P10 * log(P10 / (P(word1, true)*P(word2, false)));
|
||||
|
||||
double P11 = JP(word1, true, word2, true);
|
||||
if(P11) accumulation += P11 * log(P11 / (P(word1, true)*P(word2, true)));
|
||||
|
||||
return accumulation;
|
||||
}
|
||||
|
||||
void ChowLiuTree::createBaseEdges(std::list<info>& edges, double infoThreshold) {
|
||||
|
||||
int nWords = imgDescriptors[0].cols;
|
||||
info mutInfo;
|
||||
|
||||
for(int word1 = 0; word1 < nWords; word1++) {
|
||||
for(int word2 = word1 + 1; word2 < nWords; word2++) {
|
||||
mutInfo.word1 = (short)word1;
|
||||
mutInfo.word2 = (short)word2;
|
||||
mutInfo.score = (float)calcMutInfo(word1, word2);
|
||||
if(mutInfo.score >= infoThreshold)
|
||||
edges.push_back(mutInfo);
|
||||
}
|
||||
}
|
||||
edges.sort(sortInfoScores);
|
||||
}
|
||||
|
||||
bool ChowLiuTree::reduceEdgesToMinSpan(std::list<info>& edges) {
|
||||
|
||||
std::map<int, int> groups;
|
||||
std::map<int, int>::iterator groupIt;
|
||||
for(int i = 0; i < imgDescriptors[0].cols; i++) groups[i] = i;
|
||||
int group1, group2;
|
||||
|
||||
std::list<info>::iterator edge = edges.begin();
|
||||
while(edge != edges.end()) {
|
||||
if(groups[edge->word1] != groups[edge->word2]) {
|
||||
group1 = groups[edge->word1];
|
||||
group2 = groups[edge->word2];
|
||||
for(groupIt = groups.begin(); groupIt != groups.end(); groupIt++)
|
||||
if(groupIt->second == group2) groupIt->second = group1;
|
||||
edge++;
|
||||
} else {
|
||||
edge = edges.erase(edge);
|
||||
}
|
||||
}
|
||||
|
||||
if(edges.size() != (unsigned int)imgDescriptors[0].cols - 1) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -153,6 +153,9 @@ void MagnoRetinaFilter::setCoefficientsTable(const float parasolCells_beta, cons
|
||||
|
||||
void MagnoRetinaFilter::_amacrineCellsComputing(const float *OPL_ON, const float *OPL_OFF)
|
||||
{
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(0,_filterOutput.getNBpixels()), Parallel_amacrineCellsComputing(OPL_ON, OPL_OFF, &_previousInput_ON[0], &_previousInput_OFF[0], &_amacrinCellsTempOutput_ON[0], &_amacrinCellsTempOutput_OFF[0], _temporalCoefficient));
|
||||
#else
|
||||
register const float *OPL_ON_PTR=OPL_ON;
|
||||
register const float *OPL_OFF_PTR=OPL_OFF;
|
||||
register float *previousInput_ON_PTR= &_previousInput_ON[0];
|
||||
@@ -175,6 +178,7 @@ void MagnoRetinaFilter::_amacrineCellsComputing(const float *OPL_ON, const float
|
||||
*(previousInput_OFF_PTR++)=*(OPL_OFF_PTR++);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// launch filter that runs all the IPL filter
|
||||
|
||||
@@ -100,101 +100,143 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class MagnoRetinaFilter: public BasicRetinaFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* constructor parameters are only linked to image input size
|
||||
* @param NBrows: number of rows of the input image
|
||||
* @param NBcolumns: number of columns of the input image
|
||||
*/
|
||||
MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
class MagnoRetinaFilter: public BasicRetinaFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* constructor parameters are only linked to image input size
|
||||
* @param NBrows: number of rows of the input image
|
||||
* @param NBcolumns: number of columns of the input image
|
||||
*/
|
||||
MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
|
||||
|
||||
/**
|
||||
* destructor
|
||||
*/
|
||||
virtual ~MagnoRetinaFilter();
|
||||
/**
|
||||
* destructor
|
||||
*/
|
||||
virtual ~MagnoRetinaFilter();
|
||||
|
||||
/**
|
||||
* function that clears all buffers of the object
|
||||
*/
|
||||
void clearAllBuffers();
|
||||
/**
|
||||
* function that clears all buffers of the object
|
||||
*/
|
||||
void clearAllBuffers();
|
||||
|
||||
/**
|
||||
* resize retina magno filter object (resize all allocated buffers)
|
||||
* @param NBrows: the new height size
|
||||
* @param NBcolumns: the new width size
|
||||
*/
|
||||
void resize(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
/**
|
||||
* resize retina magno filter object (resize all allocated buffers)
|
||||
* @param NBrows: the new height size
|
||||
* @param NBcolumns: the new width size
|
||||
*/
|
||||
void resize(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
|
||||
/**
|
||||
* set parameters values
|
||||
* @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0
|
||||
* @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response)
|
||||
* @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5
|
||||
* @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5
|
||||
* @param localAdaptIntegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
* @param localAdaptIntegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
*/
|
||||
void setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k);
|
||||
/**
|
||||
* set parameters values
|
||||
* @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0
|
||||
* @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response)
|
||||
* @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5
|
||||
* @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5
|
||||
* @param localAdaptIntegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
* @param localAdaptIntegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
*/
|
||||
void setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k);
|
||||
|
||||
/**
|
||||
* launch filter that runs all the IPL magno filter (model of the magnocellular channel of the Inner Plexiform Layer of the retina)
|
||||
* @param OPL_ON: the output of the bipolar ON cells of the retina (available from the ParvoRetinaFilter class (getBipolarCellsON() function)
|
||||
* @param OPL_OFF: the output of the bipolar OFF cells of the retina (available from the ParvoRetinaFilter class (getBipolarCellsOFF() function)
|
||||
* @return the processed result without post-processing
|
||||
*/
|
||||
const std::valarray<float> &runFilter(const std::valarray<float> &OPL_ON, const std::valarray<float> &OPL_OFF);
|
||||
/**
|
||||
* launch filter that runs all the IPL magno filter (model of the magnocellular channel of the Inner Plexiform Layer of the retina)
|
||||
* @param OPL_ON: the output of the bipolar ON cells of the retina (available from the ParvoRetinaFilter class (getBipolarCellsON() function)
|
||||
* @param OPL_OFF: the output of the bipolar OFF cells of the retina (available from the ParvoRetinaFilter class (getBipolarCellsOFF() function)
|
||||
* @return the processed result without post-processing
|
||||
*/
|
||||
const std::valarray<float> &runFilter(const std::valarray<float> &OPL_ON, const std::valarray<float> &OPL_OFF);
|
||||
|
||||
/**
|
||||
* @return the Magnocellular ON channel filtering output
|
||||
*/
|
||||
inline const std::valarray<float> &getMagnoON() const {return _magnoXOutputON;};
|
||||
/**
|
||||
* @return the Magnocellular ON channel filtering output
|
||||
*/
|
||||
inline const std::valarray<float> &getMagnoON() const {return _magnoXOutputON;};
|
||||
|
||||
/**
|
||||
* @return the Magnocellular OFF channel filtering output
|
||||
*/
|
||||
inline const std::valarray<float> &getMagnoOFF() const {return _magnoXOutputOFF;};
|
||||
/**
|
||||
* @return the Magnocellular OFF channel filtering output
|
||||
*/
|
||||
inline const std::valarray<float> &getMagnoOFF() const {return _magnoXOutputOFF;};
|
||||
|
||||
/**
|
||||
* @return the Magnocellular Y (sum of the ON and OFF magno channels) filtering output
|
||||
*/
|
||||
inline const std::valarray<float> &getMagnoYsaturated() const {return *_magnoYsaturated;};
|
||||
/**
|
||||
* @return the Magnocellular Y (sum of the ON and OFF magno channels) filtering output
|
||||
*/
|
||||
inline const std::valarray<float> &getMagnoYsaturated() const {return *_magnoYsaturated;};
|
||||
|
||||
/**
|
||||
* applies an image normalization which saturates the high output values by the use of an assymetric sigmoide
|
||||
*/
|
||||
inline void normalizeGrayOutputNearZeroCentreredSigmoide(){_filterOutput.normalizeGrayOutputNearZeroCentreredSigmoide(&(*_magnoYOutput)[0], &(*_magnoYsaturated)[0]);};
|
||||
/**
|
||||
* applies an image normalization which saturates the high output values by the use of an assymetric sigmoide
|
||||
*/
|
||||
inline void normalizeGrayOutputNearZeroCentreredSigmoide(){_filterOutput.normalizeGrayOutputNearZeroCentreredSigmoide(&(*_magnoYOutput)[0], &(*_magnoYsaturated)[0]);};
|
||||
|
||||
/**
|
||||
* @return the horizontal cells' temporal constant
|
||||
*/
|
||||
inline float getTemporalConstant(){return this->_filteringCoeficientsTable[2];};
|
||||
/**
|
||||
* @return the horizontal cells' temporal constant
|
||||
*/
|
||||
inline float getTemporalConstant(){return this->_filteringCoeficientsTable[2];};
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
// related pointers to these buffers
|
||||
std::valarray<float> _previousInput_ON;
|
||||
std::valarray<float> _previousInput_OFF;
|
||||
std::valarray<float> _amacrinCellsTempOutput_ON;
|
||||
std::valarray<float> _amacrinCellsTempOutput_OFF;
|
||||
std::valarray<float> _magnoXOutputON;
|
||||
std::valarray<float> _magnoXOutputOFF;
|
||||
std::valarray<float> _localProcessBufferON;
|
||||
std::valarray<float> _localProcessBufferOFF;
|
||||
// reference to parent buffers and allow better readability
|
||||
TemplateBuffer<float> *_magnoYOutput;
|
||||
std::valarray<float> *_magnoYsaturated;
|
||||
// related pointers to these buffers
|
||||
std::valarray<float> _previousInput_ON;
|
||||
std::valarray<float> _previousInput_OFF;
|
||||
std::valarray<float> _amacrinCellsTempOutput_ON;
|
||||
std::valarray<float> _amacrinCellsTempOutput_OFF;
|
||||
std::valarray<float> _magnoXOutputON;
|
||||
std::valarray<float> _magnoXOutputOFF;
|
||||
std::valarray<float> _localProcessBufferON;
|
||||
std::valarray<float> _localProcessBufferOFF;
|
||||
// reference to parent buffers and allow better readability
|
||||
TemplateBuffer<float> *_magnoYOutput;
|
||||
std::valarray<float> *_magnoYsaturated;
|
||||
|
||||
// varialbles
|
||||
float _temporalCoefficient;
|
||||
// varialbles
|
||||
float _temporalCoefficient;
|
||||
|
||||
// amacrine cells filter : high pass temporal filter
|
||||
void _amacrineCellsComputing(const float *ONinput, const float *OFFinput);
|
||||
// amacrine cells filter : high pass temporal filter
|
||||
void _amacrineCellsComputing(const float *ONinput, const float *OFFinput);
|
||||
#ifdef MAKE_PARALLEL
|
||||
/******************************************************
|
||||
** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors
|
||||
** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary
|
||||
** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised
|
||||
** ==> functors constructors can differ from the parameters used with their related serial functions
|
||||
*/
|
||||
class Parallel_amacrineCellsComputing: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
const float *OPL_ON, *OPL_OFF;
|
||||
float *previousInput_ON, *previousInput_OFF, *amacrinCellsTempOutput_ON, *amacrinCellsTempOutput_OFF;
|
||||
float temporalCoefficient;
|
||||
public:
|
||||
Parallel_amacrineCellsComputing(const float *OPL_ON_PTR, const float *OPL_OFF_PTR, float *previousInput_ON_PTR, float *previousInput_OFF_PTR, float *amacrinCellsTempOutput_ON_PTR, float *amacrinCellsTempOutput_OFF_PTR, float temporalCoefficientVal)
|
||||
:OPL_ON(OPL_ON_PTR), OPL_OFF(OPL_OFF_PTR), previousInput_ON(previousInput_ON_PTR), previousInput_OFF(previousInput_OFF_PTR), amacrinCellsTempOutput_ON(amacrinCellsTempOutput_ON_PTR), amacrinCellsTempOutput_OFF(amacrinCellsTempOutput_OFF_PTR), temporalCoefficient(temporalCoefficientVal) {}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
register const float *OPL_ON_PTR=OPL_ON+r.start;
|
||||
register const float *OPL_OFF_PTR=OPL_OFF+r.start;
|
||||
register float *previousInput_ON_PTR= previousInput_ON+r.start;
|
||||
register float *previousInput_OFF_PTR= previousInput_OFF+r.start;
|
||||
register float *amacrinCellsTempOutput_ON_PTR= amacrinCellsTempOutput_ON+r.start;
|
||||
register float *amacrinCellsTempOutput_OFF_PTR= amacrinCellsTempOutput_OFF+r.start;
|
||||
|
||||
};
|
||||
for (int IDpixel=r.start ; IDpixel!=r.end; ++IDpixel)
|
||||
{
|
||||
|
||||
/* Compute ON and OFF amacrin cells high pass temporal filter */
|
||||
float magnoXonPixelResult = temporalCoefficient*(*amacrinCellsTempOutput_ON_PTR+ *OPL_ON_PTR-*previousInput_ON_PTR);
|
||||
*(amacrinCellsTempOutput_ON_PTR++)=((float)(magnoXonPixelResult>0))*magnoXonPixelResult;
|
||||
|
||||
float magnoXoffPixelResult = temporalCoefficient*(*amacrinCellsTempOutput_OFF_PTR+ *OPL_OFF_PTR-*previousInput_OFF_PTR);
|
||||
*(amacrinCellsTempOutput_OFF_PTR++)=((float)(magnoXoffPixelResult>0))*magnoXoffPixelResult;
|
||||
|
||||
/* prepare next loop */
|
||||
*(previousInput_ON_PTR++)=*(OPL_ON_PTR++);
|
||||
*(previousInput_OFF_PTR++)=*(OPL_OFF_PTR++);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,779 @@
|
||||
/*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.
|
||||
//
|
||||
// This file originates from the openFABMAP project:
|
||||
// [http://code.google.com/p/openfabmap/]
|
||||
//
|
||||
// For published work which uses all or part of OpenFABMAP, please cite:
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
|
||||
//
|
||||
// Original Algorithm by Mark Cummins and Paul Newman:
|
||||
// [http://ijr.sagepub.com/content/27/6/647.short]
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
|
||||
// [http://ijr.sagepub.com/content/30/9/1100.abstract]
|
||||
//
|
||||
// License Agreement
|
||||
//
|
||||
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
|
||||
// Will Maddern [w.maddern@qut.edu.au], all rights reserved.
|
||||
//
|
||||
//
|
||||
// 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 "opencv2/contrib/openfabmap.hpp"
|
||||
|
||||
|
||||
/*
|
||||
Calculate the sum of two log likelihoods
|
||||
*/
|
||||
namespace cv {
|
||||
|
||||
namespace of2 {
|
||||
|
||||
static double logsumexp(double a, double b) {
|
||||
return a > b ? log(1 + exp(b - a)) + a : log(1 + exp(a - b)) + b;
|
||||
}
|
||||
|
||||
FabMap::FabMap(const Mat& _clTree, double _PzGe,
|
||||
double _PzGNe, int _flags, int _numSamples) :
|
||||
clTree(_clTree), PzGe(_PzGe), PzGNe(_PzGNe), flags(
|
||||
_flags), numSamples(_numSamples) {
|
||||
|
||||
CV_Assert(flags & MEAN_FIELD || flags & SAMPLED);
|
||||
CV_Assert(flags & NAIVE_BAYES || flags & CHOW_LIU);
|
||||
if (flags & NAIVE_BAYES) {
|
||||
PzGL = &FabMap::PzqGL;
|
||||
} else {
|
||||
PzGL = &FabMap::PzqGzpqL;
|
||||
}
|
||||
|
||||
//check for a valid Chow-Liu tree
|
||||
CV_Assert(clTree.type() == CV_64FC1);
|
||||
cv::checkRange(clTree.row(0), false, NULL, 0, clTree.cols);
|
||||
cv::checkRange(clTree.row(1), false, NULL, DBL_MIN, 1);
|
||||
cv::checkRange(clTree.row(2), false, NULL, DBL_MIN, 1);
|
||||
cv::checkRange(clTree.row(3), false, NULL, DBL_MIN, 1);
|
||||
|
||||
// TODO: Add default values for member variables
|
||||
Pnew = 0.9;
|
||||
sFactor = 0.99;
|
||||
mBias = 0.5;
|
||||
}
|
||||
|
||||
FabMap::~FabMap() {
|
||||
}
|
||||
|
||||
const std::vector<cv::Mat>& FabMap::getTrainingImgDescriptors() const {
|
||||
return trainingImgDescriptors;
|
||||
}
|
||||
|
||||
const std::vector<cv::Mat>& FabMap::getTestImgDescriptors() const {
|
||||
return testImgDescriptors;
|
||||
}
|
||||
|
||||
void FabMap::addTraining(const Mat& queryImgDescriptor) {
|
||||
CV_Assert(!queryImgDescriptor.empty());
|
||||
vector<Mat> queryImgDescriptors;
|
||||
for (int i = 0; i < queryImgDescriptor.rows; i++) {
|
||||
queryImgDescriptors.push_back(queryImgDescriptor.row(i));
|
||||
}
|
||||
addTraining(queryImgDescriptors);
|
||||
}
|
||||
|
||||
void FabMap::addTraining(const vector<Mat>& queryImgDescriptors) {
|
||||
for (size_t i = 0; i < queryImgDescriptors.size(); i++) {
|
||||
CV_Assert(!queryImgDescriptors[i].empty());
|
||||
CV_Assert(queryImgDescriptors[i].rows == 1);
|
||||
CV_Assert(queryImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(queryImgDescriptors[i].type() == CV_32F);
|
||||
trainingImgDescriptors.push_back(queryImgDescriptors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FabMap::add(const cv::Mat& queryImgDescriptor) {
|
||||
CV_Assert(!queryImgDescriptor.empty());
|
||||
vector<Mat> queryImgDescriptors;
|
||||
for (int i = 0; i < queryImgDescriptor.rows; i++) {
|
||||
queryImgDescriptors.push_back(queryImgDescriptor.row(i));
|
||||
}
|
||||
add(queryImgDescriptors);
|
||||
}
|
||||
|
||||
void FabMap::add(const std::vector<cv::Mat>& queryImgDescriptors) {
|
||||
for (size_t i = 0; i < queryImgDescriptors.size(); i++) {
|
||||
CV_Assert(!queryImgDescriptors[i].empty());
|
||||
CV_Assert(queryImgDescriptors[i].rows == 1);
|
||||
CV_Assert(queryImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(queryImgDescriptors[i].type() == CV_32F);
|
||||
testImgDescriptors.push_back(queryImgDescriptors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FabMap::compare(const Mat& queryImgDescriptor,
|
||||
vector<IMatch>& matches, bool addQuery,
|
||||
const Mat& mask) {
|
||||
CV_Assert(!queryImgDescriptor.empty());
|
||||
vector<Mat> queryImgDescriptors;
|
||||
for (int i = 0; i < queryImgDescriptor.rows; i++) {
|
||||
queryImgDescriptors.push_back(queryImgDescriptor.row(i));
|
||||
}
|
||||
compare(queryImgDescriptors,matches,addQuery,mask);
|
||||
}
|
||||
|
||||
void FabMap::compare(const Mat& queryImgDescriptor,
|
||||
const Mat& testImgDescriptor, vector<IMatch>& matches,
|
||||
const Mat& mask) {
|
||||
CV_Assert(!queryImgDescriptor.empty());
|
||||
vector<Mat> queryImgDescriptors;
|
||||
for (int i = 0; i < queryImgDescriptor.rows; i++) {
|
||||
queryImgDescriptors.push_back(queryImgDescriptor.row(i));
|
||||
}
|
||||
|
||||
CV_Assert(!testImgDescriptor.empty());
|
||||
vector<Mat> _testImgDescriptors;
|
||||
for (int i = 0; i < testImgDescriptor.rows; i++) {
|
||||
_testImgDescriptors.push_back(testImgDescriptor.row(i));
|
||||
}
|
||||
compare(queryImgDescriptors,_testImgDescriptors,matches,mask);
|
||||
|
||||
}
|
||||
|
||||
void FabMap::compare(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& _testImgDescriptors,
|
||||
vector<IMatch>& matches, const Mat& mask) {
|
||||
CV_Assert(!queryImgDescriptor.empty());
|
||||
vector<Mat> queryImgDescriptors;
|
||||
for (int i = 0; i < queryImgDescriptor.rows; i++) {
|
||||
queryImgDescriptors.push_back(queryImgDescriptor.row(i));
|
||||
}
|
||||
compare(queryImgDescriptors,_testImgDescriptors,matches,mask);
|
||||
}
|
||||
|
||||
void FabMap::compare(const vector<Mat>& queryImgDescriptors,
|
||||
vector<IMatch>& matches, bool addQuery, const Mat& /*mask*/) {
|
||||
|
||||
// TODO: add first query if empty (is this necessary)
|
||||
|
||||
for (size_t i = 0; i < queryImgDescriptors.size(); i++) {
|
||||
CV_Assert(!queryImgDescriptors[i].empty());
|
||||
CV_Assert(queryImgDescriptors[i].rows == 1);
|
||||
CV_Assert(queryImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(queryImgDescriptors[i].type() == CV_32F);
|
||||
|
||||
// TODO: add mask
|
||||
|
||||
compareImgDescriptor(queryImgDescriptors[i],
|
||||
(int)i, testImgDescriptors, matches);
|
||||
if (addQuery)
|
||||
add(queryImgDescriptors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FabMap::compare(const vector<Mat>& queryImgDescriptors,
|
||||
const vector<Mat>& _testImgDescriptors,
|
||||
vector<IMatch>& matches, const Mat& /*mask*/) {
|
||||
if (_testImgDescriptors[0].data != this->testImgDescriptors[0].data) {
|
||||
CV_Assert(!(flags & MOTION_MODEL));
|
||||
for (size_t i = 0; i < _testImgDescriptors.size(); i++) {
|
||||
CV_Assert(!_testImgDescriptors[i].empty());
|
||||
CV_Assert(_testImgDescriptors[i].rows == 1);
|
||||
CV_Assert(_testImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(_testImgDescriptors[i].type() == CV_32F);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < queryImgDescriptors.size(); i++) {
|
||||
CV_Assert(!queryImgDescriptors[i].empty());
|
||||
CV_Assert(queryImgDescriptors[i].rows == 1);
|
||||
CV_Assert(queryImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(queryImgDescriptors[i].type() == CV_32F);
|
||||
|
||||
// TODO: add mask
|
||||
|
||||
compareImgDescriptor(queryImgDescriptors[i],
|
||||
(int)i, _testImgDescriptors, matches);
|
||||
}
|
||||
}
|
||||
|
||||
void FabMap::compareImgDescriptor(const Mat& queryImgDescriptor,
|
||||
int queryIndex, const vector<Mat>& _testImgDescriptors,
|
||||
vector<IMatch>& matches) {
|
||||
|
||||
vector<IMatch> queryMatches;
|
||||
queryMatches.push_back(IMatch(queryIndex,-1,
|
||||
getNewPlaceLikelihood(queryImgDescriptor),0));
|
||||
getLikelihoods(queryImgDescriptor,_testImgDescriptors,queryMatches);
|
||||
normaliseDistribution(queryMatches);
|
||||
for (size_t j = 1; j < queryMatches.size(); j++) {
|
||||
queryMatches[j].queryIdx = queryIndex;
|
||||
}
|
||||
matches.insert(matches.end(), queryMatches.begin(), queryMatches.end());
|
||||
}
|
||||
|
||||
void FabMap::getLikelihoods(const Mat& /*queryImgDescriptor*/,
|
||||
const vector<Mat>& /*testImgDescriptors*/, vector<IMatch>& /*matches*/) {
|
||||
|
||||
}
|
||||
|
||||
double FabMap::getNewPlaceLikelihood(const Mat& queryImgDescriptor) {
|
||||
if (flags & MEAN_FIELD) {
|
||||
double logP = 0;
|
||||
bool zq, zpq;
|
||||
if(flags & NAIVE_BAYES) {
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
zq = queryImgDescriptor.at<float>(0,q) > 0;
|
||||
|
||||
logP += log(Pzq(q, false) * PzqGeq(zq, false) +
|
||||
Pzq(q, true) * PzqGeq(zq, true));
|
||||
}
|
||||
} else {
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
zq = queryImgDescriptor.at<float>(0,q) > 0;
|
||||
zpq = queryImgDescriptor.at<float>(0,pq(q)) > 0;
|
||||
|
||||
double alpha, beta, p;
|
||||
alpha = Pzq(q, zq) * PzqGeq(!zq, false) * PzqGzpq(q, !zq, zpq);
|
||||
beta = Pzq(q, !zq) * PzqGeq(zq, false) * PzqGzpq(q, zq, zpq);
|
||||
p = Pzq(q, false) * beta / (alpha + beta);
|
||||
|
||||
alpha = Pzq(q, zq) * PzqGeq(!zq, true) * PzqGzpq(q, !zq, zpq);
|
||||
beta = Pzq(q, !zq) * PzqGeq(zq, true) * PzqGzpq(q, zq, zpq);
|
||||
p += Pzq(q, true) * beta / (alpha + beta);
|
||||
|
||||
logP += log(p);
|
||||
}
|
||||
}
|
||||
return logP;
|
||||
}
|
||||
|
||||
if (flags & SAMPLED) {
|
||||
CV_Assert(!trainingImgDescriptors.empty());
|
||||
CV_Assert(numSamples > 0);
|
||||
|
||||
vector<Mat> sampledImgDescriptors;
|
||||
|
||||
// TODO: this method can result in the same sample being added
|
||||
// multiple times. Is this desired?
|
||||
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
int index = rand() % trainingImgDescriptors.size();
|
||||
sampledImgDescriptors.push_back(trainingImgDescriptors[index]);
|
||||
}
|
||||
|
||||
vector<IMatch> matches;
|
||||
getLikelihoods(queryImgDescriptor,sampledImgDescriptors,matches);
|
||||
|
||||
double averageLogLikelihood = -DBL_MAX + matches.front().likelihood + 1;
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
averageLogLikelihood =
|
||||
logsumexp(matches[i].likelihood, averageLogLikelihood);
|
||||
}
|
||||
|
||||
return averageLogLikelihood - log((double)numSamples);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FabMap::normaliseDistribution(vector<IMatch>& matches) {
|
||||
CV_Assert(!matches.empty());
|
||||
|
||||
if (flags & MOTION_MODEL) {
|
||||
|
||||
matches[0].match = matches[0].likelihood + log(Pnew);
|
||||
|
||||
if (priorMatches.size() > 2) {
|
||||
matches[1].match = matches[1].likelihood;
|
||||
matches[1].match += log(
|
||||
(2 * (1-mBias) * priorMatches[1].match +
|
||||
priorMatches[1].match +
|
||||
2 * mBias * priorMatches[2].match) / 3);
|
||||
for (size_t i = 2; i < priorMatches.size()-1; i++) {
|
||||
matches[i].match = matches[i].likelihood;
|
||||
matches[i].match += log(
|
||||
(2 * (1-mBias) * priorMatches[i-1].match +
|
||||
priorMatches[i].match +
|
||||
2 * mBias * priorMatches[i+1].match)/3);
|
||||
}
|
||||
matches[priorMatches.size()-1].match =
|
||||
matches[priorMatches.size()-1].likelihood;
|
||||
matches[priorMatches.size()-1].match += log(
|
||||
(2 * (1-mBias) * priorMatches[priorMatches.size()-2].match +
|
||||
priorMatches[priorMatches.size()-1].match +
|
||||
2 * mBias * priorMatches[priorMatches.size()-1].match)/3);
|
||||
|
||||
for(size_t i = priorMatches.size(); i < matches.size(); i++) {
|
||||
matches[i].match = matches[i].likelihood;
|
||||
}
|
||||
} else {
|
||||
for(size_t i = 1; i < matches.size(); i++) {
|
||||
matches[i].match = matches[i].likelihood;
|
||||
}
|
||||
}
|
||||
|
||||
double logsum = -DBL_MAX + matches.front().match + 1;
|
||||
|
||||
//calculate the normalising constant
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
logsum = logsumexp(logsum, matches[i].match);
|
||||
}
|
||||
|
||||
//normalise
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
matches[i].match = exp(matches[i].match - logsum);
|
||||
}
|
||||
|
||||
//smooth final probabilities
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
matches[i].match = sFactor*matches[i].match +
|
||||
(1 - sFactor)/matches.size();
|
||||
}
|
||||
|
||||
//update our location priors
|
||||
priorMatches = matches;
|
||||
|
||||
} else {
|
||||
|
||||
double logsum = -DBL_MAX + matches.front().likelihood + 1;
|
||||
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
logsum = logsumexp(logsum, matches[i].likelihood);
|
||||
}
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
matches[i].match = exp(matches[i].likelihood - logsum);
|
||||
}
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
matches[i].match = sFactor*matches[i].match +
|
||||
(1 - sFactor)/matches.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FabMap::pq(int q) {
|
||||
return (int)clTree.at<double>(0,q);
|
||||
}
|
||||
|
||||
double FabMap::Pzq(int q, bool zq) {
|
||||
return (zq) ? clTree.at<double>(1,q) : 1 - clTree.at<double>(1,q);
|
||||
}
|
||||
|
||||
double FabMap::PzqGzpq(int q, bool zq, bool zpq) {
|
||||
if (zpq) {
|
||||
return (zq) ? clTree.at<double>(2,q) : 1 - clTree.at<double>(2,q);
|
||||
} else {
|
||||
return (zq) ? clTree.at<double>(3,q) : 1 - clTree.at<double>(3,q);
|
||||
}
|
||||
}
|
||||
|
||||
double FabMap::PzqGeq(bool zq, bool eq) {
|
||||
if (eq) {
|
||||
return (zq) ? PzGe : 1 - PzGe;
|
||||
} else {
|
||||
return (zq) ? PzGNe : 1 - PzGNe;
|
||||
}
|
||||
}
|
||||
|
||||
double FabMap::PeqGL(int q, bool Lzq, bool eq) {
|
||||
double alpha, beta;
|
||||
alpha = PzqGeq(Lzq, true) * Pzq(q, true);
|
||||
beta = PzqGeq(Lzq, false) * Pzq(q, false);
|
||||
|
||||
if (eq) {
|
||||
return alpha / (alpha + beta);
|
||||
} else {
|
||||
return 1 - (alpha / (alpha + beta));
|
||||
}
|
||||
}
|
||||
|
||||
double FabMap::PzqGL(int q, bool zq, bool /*zpq*/, bool Lzq) {
|
||||
return PeqGL(q, Lzq, false) * PzqGeq(zq, false) +
|
||||
PeqGL(q, Lzq, true) * PzqGeq(zq, true);
|
||||
}
|
||||
|
||||
|
||||
double FabMap::PzqGzpqL(int q, bool zq, bool zpq, bool Lzq) {
|
||||
double p;
|
||||
double alpha, beta;
|
||||
|
||||
alpha = Pzq(q, zq) * PzqGeq(!zq, false) * PzqGzpq(q, !zq, zpq);
|
||||
beta = Pzq(q, !zq) * PzqGeq( zq, false) * PzqGzpq(q, zq, zpq);
|
||||
p = PeqGL(q, Lzq, false) * beta / (alpha + beta);
|
||||
|
||||
alpha = Pzq(q, zq) * PzqGeq(!zq, true) * PzqGzpq(q, !zq, zpq);
|
||||
beta = Pzq(q, !zq) * PzqGeq( zq, true) * PzqGzpq(q, zq, zpq);
|
||||
p += PeqGL(q, Lzq, true) * beta / (alpha + beta);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
FabMap1::FabMap1(const Mat& _clTree, double _PzGe, double _PzGNe, int _flags,
|
||||
int _numSamples) : FabMap(_clTree, _PzGe, _PzGNe, _flags,
|
||||
_numSamples) {
|
||||
}
|
||||
|
||||
FabMap1::~FabMap1() {
|
||||
}
|
||||
|
||||
void FabMap1::getLikelihoods(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImageDescriptors, vector<IMatch>& matches) {
|
||||
|
||||
for (size_t i = 0; i < testImageDescriptors.size(); i++) {
|
||||
bool zq, zpq, Lzq;
|
||||
double logP = 0;
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
|
||||
zq = queryImgDescriptor.at<float>(0,q) > 0;
|
||||
zpq = queryImgDescriptor.at<float>(0,pq(q)) > 0;
|
||||
Lzq = testImageDescriptors[i].at<float>(0,q) > 0;
|
||||
|
||||
logP += log((this->*PzGL)(q, zq, zpq, Lzq));
|
||||
|
||||
}
|
||||
matches.push_back(IMatch(0,(int)i,logP,0));
|
||||
}
|
||||
}
|
||||
|
||||
FabMapLUT::FabMapLUT(const Mat& _clTree, double _PzGe, double _PzGNe,
|
||||
int _flags, int _numSamples, int _precision) :
|
||||
FabMap(_clTree, _PzGe, _PzGNe, _flags, _numSamples), precision(_precision) {
|
||||
|
||||
int nWords = clTree.cols;
|
||||
double precFactor = (double)pow(10.0, precision);
|
||||
|
||||
table = new int[nWords][8];
|
||||
|
||||
for (int q = 0; q < nWords; q++) {
|
||||
for (unsigned char i = 0; i < 8; i++) {
|
||||
|
||||
bool Lzq = (bool) ((i >> 2) & 0x01);
|
||||
bool zq = (bool) ((i >> 1) & 0x01);
|
||||
bool zpq = (bool) (i & 1);
|
||||
|
||||
table[q][i] = -(int)(log((this->*PzGL)(q, zq, zpq, Lzq))
|
||||
* precFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FabMapLUT::~FabMapLUT() {
|
||||
delete[] table;
|
||||
}
|
||||
|
||||
void FabMapLUT::getLikelihoods(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImageDescriptors, vector<IMatch>& matches) {
|
||||
|
||||
double precFactor = (double)pow(10.0, -precision);
|
||||
|
||||
for (size_t i = 0; i < testImageDescriptors.size(); i++) {
|
||||
unsigned long long int logP = 0;
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
logP += table[q][(queryImgDescriptor.at<float>(0,pq(q)) > 0) +
|
||||
((queryImgDescriptor.at<float>(0, q) > 0) << 1) +
|
||||
((testImageDescriptors[i].at<float>(0,q) > 0) << 2)];
|
||||
}
|
||||
matches.push_back(IMatch(0,(int)i,-precFactor*(double)logP,0));
|
||||
}
|
||||
}
|
||||
|
||||
FabMapFBO::FabMapFBO(const Mat& _clTree, double _PzGe, double _PzGNe,
|
||||
int _flags, int _numSamples, double _rejectionThreshold,
|
||||
double _PsGd, int _bisectionStart, int _bisectionIts) :
|
||||
FabMap(_clTree, _PzGe, _PzGNe, _flags, _numSamples), PsGd(_PsGd),
|
||||
rejectionThreshold(_rejectionThreshold), bisectionStart(_bisectionStart),
|
||||
bisectionIts(_bisectionIts) {
|
||||
}
|
||||
|
||||
|
||||
FabMapFBO::~FabMapFBO() {
|
||||
}
|
||||
|
||||
void FabMapFBO::getLikelihoods(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImageDescriptors, vector<IMatch>& matches) {
|
||||
|
||||
std::multiset<WordStats> wordData;
|
||||
setWordStatistics(queryImgDescriptor, wordData);
|
||||
|
||||
vector<int> matchIndices;
|
||||
vector<IMatch> queryMatches;
|
||||
|
||||
for (size_t i = 0; i < testImageDescriptors.size(); i++) {
|
||||
queryMatches.push_back(IMatch(0,(int)i,0,0));
|
||||
matchIndices.push_back((int)i);
|
||||
}
|
||||
|
||||
double currBest = -DBL_MAX;
|
||||
double bailedOut = DBL_MAX;
|
||||
|
||||
for (std::multiset<WordStats>::iterator wordIter = wordData.begin();
|
||||
wordIter != wordData.end(); wordIter++) {
|
||||
bool zq = queryImgDescriptor.at<float>(0,wordIter->q) > 0;
|
||||
bool zpq = queryImgDescriptor.at<float>(0,pq(wordIter->q)) > 0;
|
||||
|
||||
currBest = -DBL_MAX;
|
||||
|
||||
for (size_t i = 0; i < matchIndices.size(); i++) {
|
||||
bool Lzq =
|
||||
testImageDescriptors[matchIndices[i]].at<float>(0,wordIter->q) > 0;
|
||||
queryMatches[matchIndices[i]].likelihood +=
|
||||
log((this->*PzGL)(wordIter->q,zq,zpq,Lzq));
|
||||
currBest =
|
||||
std::max(queryMatches[matchIndices[i]].likelihood, currBest);
|
||||
}
|
||||
|
||||
if (matchIndices.size() == 1)
|
||||
continue;
|
||||
|
||||
double delta = std::max(limitbisection(wordIter->V, wordIter->M),
|
||||
-log(rejectionThreshold));
|
||||
|
||||
vector<int>::iterator matchIter = matchIndices.begin();
|
||||
while (matchIter != matchIndices.end()) {
|
||||
if (currBest - queryMatches[*matchIter].likelihood > delta) {
|
||||
queryMatches[*matchIter].likelihood = bailedOut;
|
||||
matchIter = matchIndices.erase(matchIter);
|
||||
} else {
|
||||
matchIter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < queryMatches.size(); i++) {
|
||||
if (queryMatches[i].likelihood == bailedOut) {
|
||||
queryMatches[i].likelihood = currBest + log(rejectionThreshold);
|
||||
}
|
||||
}
|
||||
matches.insert(matches.end(), queryMatches.begin(), queryMatches.end());
|
||||
|
||||
}
|
||||
|
||||
void FabMapFBO::setWordStatistics(const Mat& queryImgDescriptor,
|
||||
std::multiset<WordStats>& wordData) {
|
||||
//words are sorted according to information = -ln(P(zq|zpq))
|
||||
//in non-log format this is lowest probability first
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
wordData.insert(WordStats(q,PzqGzpq(q,
|
||||
queryImgDescriptor.at<float>(0,q) > 0,
|
||||
queryImgDescriptor.at<float>(0,pq(q)) > 0)));
|
||||
}
|
||||
|
||||
double d = 0, V = 0, M = 0;
|
||||
bool zq, zpq;
|
||||
|
||||
for (std::multiset<WordStats>::reverse_iterator wordIter =
|
||||
wordData.rbegin();
|
||||
wordIter != wordData.rend(); wordIter++) {
|
||||
|
||||
zq = queryImgDescriptor.at<float>(0,wordIter->q) > 0;
|
||||
zpq = queryImgDescriptor.at<float>(0,pq(wordIter->q)) > 0;
|
||||
|
||||
d = log((this->*PzGL)(wordIter->q, zq, zpq, true)) -
|
||||
log((this->*PzGL)(wordIter->q, zq, zpq, false));
|
||||
|
||||
V += pow(d, 2.0) * 2 *
|
||||
(Pzq(wordIter->q, true) - pow(Pzq(wordIter->q, true), 2.0));
|
||||
M = std::max(M, fabs(d));
|
||||
|
||||
wordIter->V = V;
|
||||
wordIter->M = M;
|
||||
}
|
||||
}
|
||||
|
||||
double FabMapFBO::limitbisection(double v, double m) {
|
||||
double midpoint, left_val, mid_val;
|
||||
double left = 0, right = bisectionStart;
|
||||
|
||||
left_val = bennettInequality(v, m, left) - PsGd;
|
||||
|
||||
for(int i = 0; i < bisectionIts; i++) {
|
||||
|
||||
midpoint = (left + right)*0.5;
|
||||
mid_val = bennettInequality(v, m, midpoint)- PsGd;
|
||||
|
||||
if(left_val * mid_val > 0) {
|
||||
left = midpoint;
|
||||
left_val = mid_val;
|
||||
} else {
|
||||
right = midpoint;
|
||||
}
|
||||
}
|
||||
|
||||
return (right + left) * 0.5;
|
||||
}
|
||||
|
||||
double FabMapFBO::bennettInequality(double v, double m, double delta) {
|
||||
double DMonV = delta * m / v;
|
||||
double f_delta = log(DMonV + sqrt(pow(DMonV, 2.0) + 1));
|
||||
return exp((v / pow(m, 2.0))*(cosh(f_delta) - 1 - DMonV * f_delta));
|
||||
}
|
||||
|
||||
bool FabMapFBO::compInfo(const WordStats& first, const WordStats& second) {
|
||||
return first.info < second.info;
|
||||
}
|
||||
|
||||
FabMap2::FabMap2(const Mat& _clTree, double _PzGe, double _PzGNe,
|
||||
int _flags) :
|
||||
FabMap(_clTree, _PzGe, _PzGNe, _flags) {
|
||||
CV_Assert(flags & SAMPLED);
|
||||
|
||||
children.resize(clTree.cols);
|
||||
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
d1.push_back(log((this->*PzGL)(q, false, false, true) /
|
||||
(this->*PzGL)(q, false, false, false)));
|
||||
d2.push_back(log((this->*PzGL)(q, false, true, true) /
|
||||
(this->*PzGL)(q, false, true, false)) - d1[q]);
|
||||
d3.push_back(log((this->*PzGL)(q, true, false, true) /
|
||||
(this->*PzGL)(q, true, false, false))- d1[q]);
|
||||
d4.push_back(log((this->*PzGL)(q, true, true, true) /
|
||||
(this->*PzGL)(q, true, true, false))- d1[q]);
|
||||
children[pq(q)].push_back(q);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FabMap2::~FabMap2() {
|
||||
}
|
||||
|
||||
|
||||
void FabMap2::addTraining(const vector<Mat>& queryImgDescriptors) {
|
||||
for (size_t i = 0; i < queryImgDescriptors.size(); i++) {
|
||||
CV_Assert(!queryImgDescriptors[i].empty());
|
||||
CV_Assert(queryImgDescriptors[i].rows == 1);
|
||||
CV_Assert(queryImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(queryImgDescriptors[i].type() == CV_32F);
|
||||
trainingImgDescriptors.push_back(queryImgDescriptors[i]);
|
||||
addToIndex(queryImgDescriptors[i], trainingDefaults, trainingInvertedMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FabMap2::add(const vector<Mat>& queryImgDescriptors) {
|
||||
for (size_t i = 0; i < queryImgDescriptors.size(); i++) {
|
||||
CV_Assert(!queryImgDescriptors[i].empty());
|
||||
CV_Assert(queryImgDescriptors[i].rows == 1);
|
||||
CV_Assert(queryImgDescriptors[i].cols == clTree.cols);
|
||||
CV_Assert(queryImgDescriptors[i].type() == CV_32F);
|
||||
testImgDescriptors.push_back(queryImgDescriptors[i]);
|
||||
addToIndex(queryImgDescriptors[i], testDefaults, testInvertedMap);
|
||||
}
|
||||
}
|
||||
|
||||
void FabMap2::getLikelihoods(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImageDescriptors, vector<IMatch>& matches) {
|
||||
|
||||
if (&testImageDescriptors == &testImgDescriptors) {
|
||||
getIndexLikelihoods(queryImgDescriptor, testDefaults, testInvertedMap,
|
||||
matches);
|
||||
} else {
|
||||
CV_Assert(!(flags & MOTION_MODEL));
|
||||
vector<double> defaults;
|
||||
std::map<int, vector<int> > invertedMap;
|
||||
for (size_t i = 0; i < testImageDescriptors.size(); i++) {
|
||||
addToIndex(testImageDescriptors[i],defaults,invertedMap);
|
||||
}
|
||||
getIndexLikelihoods(queryImgDescriptor, defaults, invertedMap, matches);
|
||||
}
|
||||
}
|
||||
|
||||
double FabMap2::getNewPlaceLikelihood(const Mat& queryImgDescriptor) {
|
||||
|
||||
CV_Assert(!trainingImgDescriptors.empty());
|
||||
|
||||
vector<IMatch> matches;
|
||||
getIndexLikelihoods(queryImgDescriptor, trainingDefaults,
|
||||
trainingInvertedMap, matches);
|
||||
|
||||
double averageLogLikelihood = -DBL_MAX + matches.front().likelihood + 1;
|
||||
for (size_t i = 0; i < matches.size(); i++) {
|
||||
averageLogLikelihood =
|
||||
logsumexp(matches[i].likelihood, averageLogLikelihood);
|
||||
}
|
||||
|
||||
return averageLogLikelihood - log((double)trainingDefaults.size());
|
||||
|
||||
}
|
||||
|
||||
void FabMap2::addToIndex(const Mat& queryImgDescriptor,
|
||||
vector<double>& defaults,
|
||||
std::map<int, vector<int> >& invertedMap) {
|
||||
defaults.push_back(0);
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
if (queryImgDescriptor.at<float>(0,q) > 0) {
|
||||
defaults.back() += d1[q];
|
||||
invertedMap[q].push_back((int)defaults.size()-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FabMap2::getIndexLikelihoods(const Mat& queryImgDescriptor,
|
||||
std::vector<double>& defaults,
|
||||
std::map<int, vector<int> >& invertedMap,
|
||||
std::vector<IMatch>& matches) {
|
||||
|
||||
vector<int>::iterator LwithI, child;
|
||||
|
||||
std::vector<double> likelihoods = defaults;
|
||||
|
||||
for (int q = 0; q < clTree.cols; q++) {
|
||||
if (queryImgDescriptor.at<float>(0,q) > 0) {
|
||||
for (LwithI = invertedMap[q].begin();
|
||||
LwithI != invertedMap[q].end(); LwithI++) {
|
||||
|
||||
if (queryImgDescriptor.at<float>(0,pq(q)) > 0) {
|
||||
likelihoods[*LwithI] += d4[q];
|
||||
} else {
|
||||
likelihoods[*LwithI] += d3[q];
|
||||
}
|
||||
}
|
||||
for (child = children[q].begin(); child != children[q].end();
|
||||
child++) {
|
||||
|
||||
if (queryImgDescriptor.at<float>(0,*child) == 0) {
|
||||
for (LwithI = invertedMap[*child].begin();
|
||||
LwithI != invertedMap[*child].end(); LwithI++) {
|
||||
|
||||
likelihoods[*LwithI] += d2[*child];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < likelihoods.size(); i++) {
|
||||
matches.push_back(IMatch(0,(int)i,likelihoods[i],0));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -199,17 +199,20 @@ const std::valarray<float> &ParvoRetinaFilter::runFilter(const std::valarray<flo
|
||||
return (*_parvocellularOutputONminusOFF);
|
||||
}
|
||||
|
||||
void ParvoRetinaFilter::_OPL_OnOffWaysComputing()
|
||||
void ParvoRetinaFilter::_OPL_OnOffWaysComputing() // WARNING : this method requires many buffer accesses, parallelizing can increase bandwith & core efficacy
|
||||
{
|
||||
// loop that makes the difference between photoreceptor cells output and horizontal cells
|
||||
// positive part goes on the ON way, negative pat goes on the OFF way
|
||||
register float *photoreceptorsOutput_PTR= &_photoreceptorsOutput[0];
|
||||
register float *horizontalCellsOutput_PTR= &_horizontalCellsOutput[0];
|
||||
register float *bipolarCellsON_PTR = &_bipolarCellsOutputON[0];
|
||||
register float *bipolarCellsOFF_PTR = &_bipolarCellsOutputOFF[0];
|
||||
register float *parvocellularOutputON_PTR= &_parvocellularOutputON[0];
|
||||
register float *parvocellularOutputOFF_PTR= &_parvocellularOutputOFF[0];
|
||||
|
||||
#ifdef MAKE_PARALLEL
|
||||
cv::parallel_for_(cv::Range(0,_filterOutput.getNBpixels()), Parallel_OPL_OnOffWaysComputing(&_photoreceptorsOutput[0], &_horizontalCellsOutput[0], &_bipolarCellsOutputON[0], &_bipolarCellsOutputOFF[0], &_parvocellularOutputON[0], &_parvocellularOutputOFF[0]));
|
||||
#else
|
||||
float *photoreceptorsOutput_PTR= &_photoreceptorsOutput[0];
|
||||
float *horizontalCellsOutput_PTR= &_horizontalCellsOutput[0];
|
||||
float *bipolarCellsON_PTR = &_bipolarCellsOutputON[0];
|
||||
float *bipolarCellsOFF_PTR = &_bipolarCellsOutputOFF[0];
|
||||
float *parvocellularOutputON_PTR= &_parvocellularOutputON[0];
|
||||
float *parvocellularOutputOFF_PTR= &_parvocellularOutputOFF[0];
|
||||
// compute bipolar cells response equal to photoreceptors minus horizontal cells response
|
||||
// and copy the result on parvo cellular outputs... keeping time before their local contrast adaptation for final result
|
||||
for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel)
|
||||
@@ -222,6 +225,7 @@ void ParvoRetinaFilter::_OPL_OnOffWaysComputing()
|
||||
*(parvocellularOutputON_PTR++)=*(bipolarCellsON_PTR++) = isPositive*pixelDifference;
|
||||
*(parvocellularOutputOFF_PTR++)=*(bipolarCellsOFF_PTR++)= (isPositive-1.0f)*pixelDifference;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -216,6 +216,45 @@ private:
|
||||
// private functions
|
||||
void _OPL_OnOffWaysComputing();
|
||||
|
||||
#ifdef MAKE_PARALLEL
|
||||
/******************************************************
|
||||
** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors
|
||||
** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary
|
||||
** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised
|
||||
** ==> functors constructors can differ from the parameters used with their related serial functions
|
||||
*/
|
||||
class Parallel_OPL_OnOffWaysComputing: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *photoreceptorsOutput, *horizontalCellsOutput, *bipolarCellsON, *bipolarCellsOFF, *parvocellularOutputON, *parvocellularOutputOFF;
|
||||
public:
|
||||
Parallel_OPL_OnOffWaysComputing(float *photoreceptorsOutput_PTR, float *horizontalCellsOutput_PTR, float *bipolarCellsON_PTR, float *bipolarCellsOFF_PTR, float *parvocellularOutputON_PTR, float *parvocellularOutputOFF_PTR)
|
||||
:photoreceptorsOutput(photoreceptorsOutput_PTR), horizontalCellsOutput(horizontalCellsOutput_PTR), bipolarCellsON(bipolarCellsON_PTR), bipolarCellsOFF(bipolarCellsOFF_PTR), parvocellularOutputON(parvocellularOutputON_PTR), parvocellularOutputOFF(parvocellularOutputOFF_PTR) {}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
// compute bipolar cells response equal to photoreceptors minus horizontal cells response
|
||||
// and copy the result on parvo cellular outputs... keeping time before their local contrast adaptation for final result
|
||||
float *photoreceptorsOutput_PTR= photoreceptorsOutput+r.start;
|
||||
float *horizontalCellsOutput_PTR= horizontalCellsOutput+r.start;
|
||||
float *bipolarCellsON_PTR = bipolarCellsON+r.start;
|
||||
float *bipolarCellsOFF_PTR = bipolarCellsOFF+r.start;
|
||||
float *parvocellularOutputON_PTR= parvocellularOutputON+r.start;
|
||||
float *parvocellularOutputOFF_PTR= parvocellularOutputOFF+r.start;
|
||||
|
||||
for (register int IDpixel=r.start ; IDpixel!=r.end ; ++IDpixel)
|
||||
{
|
||||
float pixelDifference = *(photoreceptorsOutput_PTR++) -*(horizontalCellsOutput_PTR++);
|
||||
// test condition to allow write pixelDifference in ON or OFF buffer and 0 in the over
|
||||
float isPositive=(float) (pixelDifference>0.0f);
|
||||
|
||||
// ON and OFF channels writing step
|
||||
*(parvocellularOutputON_PTR++)=*(bipolarCellsON_PTR++) = isPositive*pixelDifference;
|
||||
*(parvocellularOutputOFF_PTR++)=*(bipolarCellsOFF_PTR++)= (isPositive-1.0f)*pixelDifference;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
+476
-500
File diff suppressed because it is too large
Load Diff
+223
-147
@@ -86,179 +86,255 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class RetinaColor: public BasicRetinaFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @typedef which allows to select the type of photoreceptors color sampling
|
||||
*/
|
||||
class RetinaColor: public BasicRetinaFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @typedef which allows to select the type of photoreceptors color sampling
|
||||
*/
|
||||
|
||||
/**
|
||||
* constructor of the retina color processing model
|
||||
* @param NBrows: number of rows of the input image
|
||||
* @param NBcolumns: number of columns of the input image
|
||||
* @param samplingMethod: the chosen color sampling method
|
||||
*/
|
||||
RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const RETINA_COLORSAMPLINGMETHOD samplingMethod=RETINA_COLOR_DIAGONAL);
|
||||
/**
|
||||
* constructor of the retina color processing model
|
||||
* @param NBrows: number of rows of the input image
|
||||
* @param NBcolumns: number of columns of the input image
|
||||
* @param samplingMethod: the chosen color sampling method
|
||||
*/
|
||||
RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const RETINA_COLORSAMPLINGMETHOD samplingMethod=RETINA_COLOR_DIAGONAL);
|
||||
|
||||
/**
|
||||
* standard destructor
|
||||
*/
|
||||
virtual ~RetinaColor();
|
||||
/**
|
||||
* standard destructor
|
||||
*/
|
||||
virtual ~RetinaColor();
|
||||
|
||||
/**
|
||||
* function that clears all buffers of the object
|
||||
*/
|
||||
void clearAllBuffers();
|
||||
/**
|
||||
* function that clears all buffers of the object
|
||||
*/
|
||||
void clearAllBuffers();
|
||||
|
||||
/**
|
||||
* resize retina color filter object (resize all allocated buffers)
|
||||
* @param NBrows: the new height size
|
||||
* @param NBcolumns: the new width size
|
||||
*/
|
||||
void resize(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
/**
|
||||
* resize retina color filter object (resize all allocated buffers)
|
||||
* @param NBrows: the new height size
|
||||
* @param NBcolumns: the new width size
|
||||
*/
|
||||
void resize(const unsigned int NBrows, const unsigned int NBcolumns);
|
||||
|
||||
|
||||
/**
|
||||
* color multiplexing function: a demultiplexed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue
|
||||
* @param inputRGBFrame: the input RGB frame to be processed
|
||||
* @return, nothing but the multiplexed frame is available by the use of the getMultiplexedFrame() function
|
||||
*/
|
||||
inline void runColorMultiplexing(const std::valarray<float> &inputRGBFrame){runColorMultiplexing(inputRGBFrame, *_multiplexedFrame);};
|
||||
/**
|
||||
* color multiplexing function: a demultiplexed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue
|
||||
* @param inputRGBFrame: the input RGB frame to be processed
|
||||
* @return, nothing but the multiplexed frame is available by the use of the getMultiplexedFrame() function
|
||||
*/
|
||||
inline void runColorMultiplexing(const std::valarray<float> &inputRGBFrame){runColorMultiplexing(inputRGBFrame, *_multiplexedFrame);};
|
||||
|
||||
/**
|
||||
* color multiplexing function: a demultipleed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue if using RGB images
|
||||
* @param demultiplexedInputFrame: the demultiplexed input frame to be processed of size M*N*3
|
||||
* @param multiplexedFrame: the resulting multiplexed frame
|
||||
*/
|
||||
void runColorMultiplexing(const std::valarray<float> &demultiplexedInputFrame, std::valarray<float> &multiplexedFrame);
|
||||
/**
|
||||
* color multiplexing function: a demultipleed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue if using RGB images
|
||||
* @param demultiplexedInputFrame: the demultiplexed input frame to be processed of size M*N*3
|
||||
* @param multiplexedFrame: the resulting multiplexed frame
|
||||
*/
|
||||
void runColorMultiplexing(const std::valarray<float> &demultiplexedInputFrame, std::valarray<float> &multiplexedFrame);
|
||||
|
||||
/**
|
||||
* color demultiplexing function: a multiplexed frame of size M*N*1 pixels is transformed into a RGB demultiplexed M*N*3 pixels frame
|
||||
* @param multiplexedColorFrame: the input multiplexed frame to be processed
|
||||
* @param adaptiveFiltering: specifies if an adaptive filtering has to be perform rather than standard filtering (adaptive filtering allows a better rendering)
|
||||
* @param maxInputValue: the maximum input data value (should be 255 for 8 bits images but it can change in the case of High Dynamic Range Images (HDRI)
|
||||
* @return, nothing but the output demultiplexed frame is available by the use of the getDemultiplexedColorFrame() function, also use getLuminance() and getChrominance() in order to retreive either luminance or chrominance
|
||||
*/
|
||||
void runColorDemultiplexing(const std::valarray<float> &multiplexedColorFrame, const bool adaptiveFiltering=false, const float maxInputValue=255.0);
|
||||
/**
|
||||
* color demultiplexing function: a multiplexed frame of size M*N*1 pixels is transformed into a RGB demultiplexed M*N*3 pixels frame
|
||||
* @param multiplexedColorFrame: the input multiplexed frame to be processed
|
||||
* @param adaptiveFiltering: specifies if an adaptive filtering has to be perform rather than standard filtering (adaptive filtering allows a better rendering)
|
||||
* @param maxInputValue: the maximum input data value (should be 255 for 8 bits images but it can change in the case of High Dynamic Range Images (HDRI)
|
||||
* @return, nothing but the output demultiplexed frame is available by the use of the getDemultiplexedColorFrame() function, also use getLuminance() and getChrominance() in order to retreive either luminance or chrominance
|
||||
*/
|
||||
void runColorDemultiplexing(const std::valarray<float> &multiplexedColorFrame, const bool adaptiveFiltering=false, const float maxInputValue=255.0);
|
||||
|
||||
/**
|
||||
* activate color saturation as the final step of the color demultiplexing process
|
||||
* -> this saturation is a sigmoide function applied to each channel of the demultiplexed image.
|
||||
* @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false)
|
||||
* @param colorSaturationValue: the saturation factor
|
||||
* */
|
||||
void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0){_saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue;};
|
||||
/**
|
||||
* activate color saturation as the final step of the color demultiplexing process
|
||||
* -> this saturation is a sigmoide function applied to each channel of the demultiplexed image.
|
||||
* @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false)
|
||||
* @param colorSaturationValue: the saturation factor
|
||||
* */
|
||||
void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0){_saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue;};
|
||||
|
||||
/**
|
||||
* set parameters of the low pass spatio-temporal filter used to retreive the low chrominance
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing), typically 0 when considering static processing, 1 or more if a temporal smoothing effect is required
|
||||
* @param k: spatial constant of the filter (unit is pixels), typical value is 2.5
|
||||
*/
|
||||
void setChrominanceLPfilterParameters(const float beta, const float tau, const float k){setLPfilterParameters(beta, tau, k);};
|
||||
/**
|
||||
* set parameters of the low pass spatio-temporal filter used to retreive the low chrominance
|
||||
* @param beta: gain of the filter (generally set to zero)
|
||||
* @param tau: time constant of the filter (unit is frame for video processing), typically 0 when considering static processing, 1 or more if a temporal smoothing effect is required
|
||||
* @param k: spatial constant of the filter (unit is pixels), typical value is 2.5
|
||||
*/
|
||||
void setChrominanceLPfilterParameters(const float beta, const float tau, const float k){setLPfilterParameters(beta, tau, k);};
|
||||
|
||||
/**
|
||||
* apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space
|
||||
* @param result: the input buffer to fill with the transformed colorspace retina output
|
||||
* @return true if process ended successfully
|
||||
*/
|
||||
bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray<float> &result);
|
||||
/**
|
||||
* apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space
|
||||
* @param result: the input buffer to fill with the transformed colorspace retina output
|
||||
* @return true if process ended successfully
|
||||
*/
|
||||
bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray<float> &result);
|
||||
|
||||
/**
|
||||
* apply to the retina color output the CIE Lab color transformation
|
||||
* @param result: the input buffer to fill with the transformed colorspace retina output
|
||||
* @return true if process ended successfully
|
||||
*/
|
||||
bool applyLMS2LabTransform(std::valarray<float> &result);
|
||||
/**
|
||||
* apply to the retina color output the CIE Lab color transformation
|
||||
* @param result: the input buffer to fill with the transformed colorspace retina output
|
||||
* @return true if process ended successfully
|
||||
*/
|
||||
bool applyLMS2LabTransform(std::valarray<float> &result);
|
||||
|
||||
/**
|
||||
* @return the multiplexed frame result (use this after function runColorMultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getMultiplexedFrame() const {return *_multiplexedFrame;};
|
||||
/**
|
||||
* @return the multiplexed frame result (use this after function runColorMultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getMultiplexedFrame() const {return *_multiplexedFrame;};
|
||||
|
||||
/**
|
||||
* @return the demultiplexed frame result (use this after function runColorDemultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getDemultiplexedColorFrame() const {return _demultiplexedColorFrame;};
|
||||
/**
|
||||
* @return the demultiplexed frame result (use this after function runColorDemultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getDemultiplexedColorFrame() const {return _demultiplexedColorFrame;};
|
||||
|
||||
/**
|
||||
* @return the luminance of the processed frame (use this after function runColorDemultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getLuminance() const {return *_luminance;};
|
||||
/**
|
||||
* @return the luminance of the processed frame (use this after function runColorDemultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getLuminance() const {return *_luminance;};
|
||||
|
||||
/**
|
||||
* @return the chrominance of the processed frame (use this after function runColorDemultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getChrominance() const {return _chrominance;};
|
||||
/**
|
||||
* @return the chrominance of the processed frame (use this after function runColorDemultiplexing)
|
||||
*/
|
||||
inline const std::valarray<float> &getChrominance() const {return _chrominance;};
|
||||
|
||||
/**
|
||||
* standard 0 to 255 image clipping function appled to RGB images (of size M*N*3 pixels)
|
||||
* @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped
|
||||
*/
|
||||
void clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxOutputValue=255.0);
|
||||
/**
|
||||
* standard 0 to 255 image clipping function appled to RGB images (of size M*N*3 pixels)
|
||||
* @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped
|
||||
*/
|
||||
void clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxOutputValue=255.0);
|
||||
|
||||
/**
|
||||
* standard 0 to 255 image normalization function appled to RGB images (of size M*N*3 pixels)
|
||||
* @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped
|
||||
*/
|
||||
void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue=255.0);
|
||||
/**
|
||||
* standard 0 to 255 image normalization function appled to RGB images (of size M*N*3 pixels)
|
||||
* @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped
|
||||
*/
|
||||
void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue=255.0);
|
||||
|
||||
/**
|
||||
* return the color sampling map: a Nrows*Mcolumns image in which each pixel value is the ofsset adress which gives the adress of the sampled pixel on an Nrows*Mcolumns*3 color image ordered by layers: layer1, layer2, layer3
|
||||
*/
|
||||
inline const std::valarray<unsigned int> &getSamplingMap() const {return _colorSampling;};
|
||||
/**
|
||||
* return the color sampling map: a Nrows*Mcolumns image in which each pixel value is the ofsset adress which gives the adress of the sampled pixel on an Nrows*Mcolumns*3 color image ordered by layers: layer1, layer2, layer3
|
||||
*/
|
||||
inline const std::valarray<unsigned int> &getSamplingMap() const {return _colorSampling;};
|
||||
|
||||
/**
|
||||
* function used (to bypass processing) to manually set the color output
|
||||
* @param demultiplexedImage: the color image (luminance+chrominance) which has to be written in the object buffer
|
||||
*/
|
||||
inline void setDemultiplexedColorFrame(const std::valarray<float> &demultiplexedImage){_demultiplexedColorFrame=demultiplexedImage;};
|
||||
/**
|
||||
* function used (to bypass processing) to manually set the color output
|
||||
* @param demultiplexedImage: the color image (luminance+chrominance) which has to be written in the object buffer
|
||||
*/
|
||||
inline void setDemultiplexedColorFrame(const std::valarray<float> &demultiplexedImage){_demultiplexedColorFrame=demultiplexedImage;};
|
||||
|
||||
protected:
|
||||
protected:
|
||||
|
||||
// private functions
|
||||
RETINA_COLORSAMPLINGMETHOD _samplingMethod;
|
||||
bool _saturateColors;
|
||||
float _colorSaturationValue;
|
||||
// links to parent buffers (more convienient names
|
||||
TemplateBuffer<float> *_luminance;
|
||||
std::valarray<float> *_multiplexedFrame;
|
||||
// instance buffers
|
||||
std::valarray<unsigned int> _colorSampling; // table (size (_nbRows*_nbColumns) which specifies the color of each pixel
|
||||
std::valarray<float> _RGBmosaic;
|
||||
std::valarray<float> _tempMultiplexedFrame;
|
||||
std::valarray<float> _demultiplexedTempBuffer;
|
||||
std::valarray<float> _demultiplexedColorFrame;
|
||||
std::valarray<float> _chrominance;
|
||||
std::valarray<float> _colorLocalDensity;// buffer which contains the local density of the R, G and B photoreceptors for a normalization use
|
||||
std::valarray<float> _imageGradient;
|
||||
// private functions
|
||||
RETINA_COLORSAMPLINGMETHOD _samplingMethod;
|
||||
bool _saturateColors;
|
||||
float _colorSaturationValue;
|
||||
// links to parent buffers (more convienient names
|
||||
TemplateBuffer<float> *_luminance;
|
||||
std::valarray<float> *_multiplexedFrame;
|
||||
// instance buffers
|
||||
std::valarray<unsigned int> _colorSampling; // table (size (_nbRows*_nbColumns) which specifies the color of each pixel
|
||||
std::valarray<float> _RGBmosaic;
|
||||
std::valarray<float> _tempMultiplexedFrame;
|
||||
std::valarray<float> _demultiplexedTempBuffer;
|
||||
std::valarray<float> _demultiplexedColorFrame;
|
||||
std::valarray<float> _chrominance;
|
||||
std::valarray<float> _colorLocalDensity;// buffer which contains the local density of the R, G and B photoreceptors for a normalization use
|
||||
std::valarray<float> _imageGradient;
|
||||
|
||||
// variables
|
||||
float _pR, _pG, _pB; // probabilities of color R, G and B
|
||||
bool _objectInit;
|
||||
// variables
|
||||
float _pR, _pG, _pB; // probabilities of color R, G and B
|
||||
bool _objectInit;
|
||||
|
||||
// protected functions
|
||||
void _initColorSampling();
|
||||
void _interpolateImageDemultiplexedImage(float *inputOutputBuffer);
|
||||
void _interpolateSingleChannelImage111(float *inputOutputBuffer);
|
||||
void _interpolateBayerRGBchannels(float *inputOutputBuffer);
|
||||
void _applyRIFfilter(const float *sourceBuffer, float *destinationBuffer);
|
||||
void _getNormalizedContoursImage(const float *inputFrame, float *outputFrame);
|
||||
// -> special adaptive filters dedicated to low pass filtering on the chrominance (skeeps filtering on the edges)
|
||||
void _adaptiveSpatialLPfilter(const float *inputFrame, float *outputFrame);
|
||||
void _adaptiveHorizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, const unsigned int IDrowStart, const unsigned int IDrowEnd);
|
||||
void _adaptiveHorizontalAnticausalFilter(float *outputFrame, const unsigned int IDrowStart, const unsigned int IDrowEnd);
|
||||
void _adaptiveVerticalCausalFilter(float *outputFrame, const unsigned int IDcolumnStart, const unsigned int IDcolumnEnd);
|
||||
void _adaptiveVerticalAnticausalFilter_multGain(float *outputFrame, const unsigned int IDcolumnStart, const unsigned int IDcolumnEnd);
|
||||
void _computeGradient(const float *luminance);
|
||||
void _normalizeOutputs_0_maxOutputValue(void);
|
||||
// protected functions
|
||||
void _initColorSampling();
|
||||
void _interpolateImageDemultiplexedImage(float *inputOutputBuffer);
|
||||
void _interpolateSingleChannelImage111(float *inputOutputBuffer);
|
||||
void _interpolateBayerRGBchannels(float *inputOutputBuffer);
|
||||
void _applyRIFfilter(const float *sourceBuffer, float *destinationBuffer);
|
||||
void _getNormalizedContoursImage(const float *inputFrame, float *outputFrame);
|
||||
// -> special adaptive filters dedicated to low pass filtering on the chrominance (skeeps filtering on the edges)
|
||||
void _adaptiveSpatialLPfilter(const float *inputFrame, float *outputFrame);
|
||||
void _adaptiveHorizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, const unsigned int IDrowStart, const unsigned int IDrowEnd); // TBB parallelized
|
||||
void _adaptiveVerticalAnticausalFilter_multGain(float *outputFrame, const unsigned int IDcolumnStart, const unsigned int IDcolumnEnd);
|
||||
void _computeGradient(const float *luminance);
|
||||
void _normalizeOutputs_0_maxOutputValue(void);
|
||||
|
||||
// color space transform
|
||||
void _applyImageColorSpaceConversion(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const float *transformTable);
|
||||
// color space transform
|
||||
void _applyImageColorSpaceConversion(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const float *transformTable);
|
||||
|
||||
};
|
||||
#ifdef MAKE_PARALLEL
|
||||
/******************************************************
|
||||
** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors
|
||||
** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary
|
||||
** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised
|
||||
** ==> functors constructors can differ from the parameters used with their related serial functions
|
||||
*/
|
||||
|
||||
/* Template :
|
||||
class Parallel_ : public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
Parallel_()
|
||||
: {}
|
||||
|
||||
virtual void operator()( const cv::Range& r ) const {
|
||||
|
||||
}
|
||||
}:
|
||||
*/
|
||||
class Parallel_adaptiveHorizontalCausalFilter_addInput: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
const float *inputFrame, *imageGradient;
|
||||
unsigned int nbColumns;
|
||||
public:
|
||||
Parallel_adaptiveHorizontalCausalFilter_addInput(const float *inputImg, float *bufferToProcess, const float *imageGrad, const unsigned int nbCols)
|
||||
:outputFrame(bufferToProcess), inputFrame(inputImg), imageGradient(imageGrad), nbColumns(nbCols) {};
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
register float* outputPTR=outputFrame+r.start*nbColumns;
|
||||
register const float* inputPTR=inputFrame+r.start*nbColumns;
|
||||
register const float *imageGradientPTR= imageGradient+r.start*nbColumns;
|
||||
for (int IDrow=r.start; IDrow!=r.end; ++IDrow)
|
||||
{
|
||||
register float result=0;
|
||||
for (unsigned int index=0; index<nbColumns; ++index)
|
||||
{
|
||||
result = *(inputPTR++) + (*imageGradientPTR++)* result;
|
||||
*(outputPTR++) = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Parallel_adaptiveVerticalAnticausalFilter_multGain: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
float *outputFrame;
|
||||
const float *imageGradient;
|
||||
unsigned int nbRows, nbColumns;
|
||||
float filterParam_gain;
|
||||
public:
|
||||
Parallel_adaptiveVerticalAnticausalFilter_multGain(float *bufferToProcess, const float *imageGrad, const unsigned int nbRws, const unsigned int nbCols, const float gain)
|
||||
:outputFrame(bufferToProcess), imageGradient(imageGrad), nbRows(nbRws), nbColumns(nbCols), filterParam_gain(gain){}
|
||||
|
||||
virtual void operator()( const Range& r ) const {
|
||||
float* offset=outputFrame+nbColumns*nbRows-nbColumns;
|
||||
const float* gradOffset= imageGradient+nbColumns*nbRows-nbColumns;
|
||||
for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn)
|
||||
{
|
||||
register float result=0;
|
||||
register float *outputPTR=offset+IDcolumn;
|
||||
register const float *imageGradientPTR=gradOffset+IDcolumn;
|
||||
for (unsigned int index=0; index<nbRows; ++index)
|
||||
{
|
||||
result = *(outputPTR) + *(imageGradientPTR) * result;
|
||||
*(outputPTR) = filterParam_gain*result;
|
||||
outputPTR-=nbColumns;
|
||||
imageGradientPTR-=nbColumns;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif /*RETINACOLOR_HPP_*/
|
||||
|
||||
@@ -70,448 +70,483 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
//// If a parallelization method is available then, you should define MAKE_PARALLEL, in the other case, the classical serial code will be used
|
||||
#define MAKE_PARALLEL
|
||||
// ==> then include required includes
|
||||
#ifdef MAKE_PARALLEL
|
||||
|
||||
// ==> declare usefull generic tools
|
||||
template <class type>
|
||||
class Parallel_clipBufferValues: public cv::ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
type *bufferToClip;
|
||||
type minValue, maxValue;
|
||||
|
||||
public:
|
||||
Parallel_clipBufferValues(type* bufferToProcess, const type min, const type max)
|
||||
: bufferToClip(bufferToProcess), minValue(min), maxValue(max){}
|
||||
|
||||
virtual void operator()( const cv::Range &r ) const {
|
||||
register type *inputOutputBufferPTR=bufferToClip+r.start;
|
||||
for (register int jf = r.start; jf != r.end; ++jf, ++inputOutputBufferPTR)
|
||||
{
|
||||
if (*inputOutputBufferPTR>maxValue)
|
||||
*inputOutputBufferPTR=maxValue;
|
||||
else if (*inputOutputBufferPTR<minValue)
|
||||
*inputOutputBufferPTR=minValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
//#define __TEMPLATEBUFFERDEBUG //define TEMPLATEBUFFERDEBUG in order to display debug information
|
||||
|
||||
namespace cv
|
||||
{
|
||||
/**
|
||||
* @class TemplateBuffer
|
||||
* @brief this class is a simple template memory buffer which contains basic functions to get information on or normalize the buffer content
|
||||
* note that thanks to the parent STL template class "valarray", it is possible to perform easily operations on the full array such as addition, product etc.
|
||||
* @author Alexandre BENOIT (benoit.alexandre.vision@gmail.com), helped by Gelu IONESCU (gelu.ionescu@lis.inpg.fr)
|
||||
* creation date: september 2007
|
||||
*/
|
||||
template <class type> class TemplateBuffer : public std::valarray<type>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* constructor for monodimensional array
|
||||
* @param dim: the size of the vector
|
||||
* @class TemplateBuffer
|
||||
* @brief this class is a simple template memory buffer which contains basic functions to get information on or normalize the buffer content
|
||||
* note that thanks to the parent STL template class "valarray", it is possible to perform easily operations on the full array such as addition, product etc.
|
||||
* @author Alexandre BENOIT (benoit.alexandre.vision@gmail.com), helped by Gelu IONESCU (gelu.ionescu@lis.inpg.fr)
|
||||
* creation date: september 2007
|
||||
*/
|
||||
TemplateBuffer(const size_t dim=0)
|
||||
: std::valarray<type>((type)0, dim)
|
||||
{
|
||||
_NBrows=1;
|
||||
_NBcolumns=dim;
|
||||
_NBdepths=1;
|
||||
_NBpixels=dim;
|
||||
_doubleNBpixels=2*dim;
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor by copy for monodimensional array
|
||||
* @param pVal: the pointer to a buffer to copy
|
||||
* @param dim: the size of the vector
|
||||
*/
|
||||
TemplateBuffer(const type* pVal, const size_t dim)
|
||||
: std::valarray<type>(pVal, dim)
|
||||
{
|
||||
_NBrows=1;
|
||||
_NBcolumns=dim;
|
||||
_NBdepths=1;
|
||||
_NBpixels=dim;
|
||||
_doubleNBpixels=2*dim;
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor for bidimensional array
|
||||
* @param dimRows: the size of the vector
|
||||
* @param dimColumns: the size of the vector
|
||||
* @param depth: the number of layers of the buffer in its third dimension (3 of color images, 1 for gray images.
|
||||
*/
|
||||
TemplateBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
|
||||
: std::valarray<type>((type)0, dimRows*dimColumns*depth)
|
||||
{
|
||||
#ifdef TEMPLATEBUFFERDEBUG
|
||||
std::cout<<"TemplateBuffer::TemplateBuffer: new buffer, size="<<dimRows<<", "<<dimColumns<<", "<<depth<<"valarraySize="<<this->size()<<std::endl;
|
||||
#endif
|
||||
_NBrows=dimRows;
|
||||
_NBcolumns=dimColumns;
|
||||
_NBdepths=depth;
|
||||
_NBpixels=dimRows*dimColumns;
|
||||
_doubleNBpixels=2*dimRows*dimColumns;
|
||||
//_createTableIndex();
|
||||
#ifdef TEMPLATEBUFFERDEBUG
|
||||
std::cout<<"TemplateBuffer::TemplateBuffer: construction successful"<<std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* copy constructor
|
||||
* @param toCopy
|
||||
* @return thenconstructed instance
|
||||
*emplateBuffer(const TemplateBuffer &toCopy)
|
||||
:_NBrows(toCopy.getNBrows()),_NBcolumns(toCopy.getNBcolumns()),_NBdepths(toCopy.getNBdephs()), _NBpixels(toCopy.getNBpixels()), _doubleNBpixels(toCopy.getNBpixels()*2)
|
||||
//std::valarray<type>(toCopy)
|
||||
template <class type> class TemplateBuffer : public std::valarray<type>
|
||||
{
|
||||
memcpy(Buffer(), toCopy.Buffer(), this->size());
|
||||
}*/
|
||||
/**
|
||||
* destructor
|
||||
*/
|
||||
virtual ~TemplateBuffer()
|
||||
{
|
||||
#ifdef TEMPLATEBUFFERDEBUG
|
||||
std::cout<<"~TemplateBuffer"<<std::endl;
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
|
||||
/**
|
||||
* delete the buffer content (set zeros)
|
||||
*/
|
||||
inline void setZero(){std::valarray<type>::operator=(0);};//memset(Buffer(), 0, sizeof(type)*_NBpixels);};
|
||||
|
||||
/**
|
||||
* @return the numbers of rows (height) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getNBrows(){return (unsigned int)_NBrows;};
|
||||
|
||||
/**
|
||||
* @return the numbers of columns (width) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getNBcolumns(){return (unsigned int)_NBcolumns;};
|
||||
|
||||
/**
|
||||
* @return the numbers of pixels (width*height) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getNBpixels(){return (unsigned int)_NBpixels;};
|
||||
|
||||
/**
|
||||
* @return the numbers of pixels (width*height) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getDoubleNBpixels(){return (unsigned int)_doubleNBpixels;};
|
||||
|
||||
/**
|
||||
* @return the numbers of depths (3rd dimension: 1 for gray images, 3 for rgb images) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getDepthSize(){return (unsigned int)_NBdepths;};
|
||||
|
||||
/**
|
||||
* resize the buffer and recompute table index etc.
|
||||
*/
|
||||
void resizeBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
|
||||
{
|
||||
this->resize(dimRows*dimColumns*depth);
|
||||
_NBrows=dimRows;
|
||||
_NBcolumns=dimColumns;
|
||||
_NBdepths=depth;
|
||||
_NBpixels=dimRows*dimColumns;
|
||||
_doubleNBpixels=2*dimRows*dimColumns;
|
||||
}
|
||||
|
||||
inline TemplateBuffer<type> & operator=(const std::valarray<type> &b)
|
||||
{
|
||||
//std::cout<<"TemplateBuffer<type> & operator= affect vector: "<<std::endl;
|
||||
std::valarray<type>::operator=(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TemplateBuffer<type> & operator=(const type &b)
|
||||
{
|
||||
//std::cout<<"TemplateBuffer<type> & operator= affect value: "<<b<<std::endl;
|
||||
std::valarray<type>::operator=(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* inline const type &operator[](const unsigned int &b)
|
||||
{
|
||||
return (*this)[b];
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @return the buffer adress in non const mode
|
||||
*/
|
||||
inline type* Buffer() { return &(*this)[0]; }
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Standard Image manipulation functions
|
||||
|
||||
/**
|
||||
* standard 0 to 255 image normalization function
|
||||
* @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
static void normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t nbPixels, const type maxOutputValue=(type)255.0);
|
||||
|
||||
/**
|
||||
* standard 0 to 255 image normalization function
|
||||
* @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0){normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);};
|
||||
|
||||
/**
|
||||
* sigmoide image normalization function (saturates min and max values)
|
||||
* @param meanValue: specifies the mean value of th pixels to be processed
|
||||
* @param sensitivity: strenght of the sigmoide
|
||||
* @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
static void normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputPicture, type *outputBuffer, const unsigned int nbPixels);
|
||||
|
||||
/**
|
||||
* sigmoide image normalization function on the current buffer (saturates min and max values)
|
||||
* @param meanValue: specifies the mean value of th pixels to be processed
|
||||
* @param sensitivity: strenght of the sigmoide
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0){ (void)maxOutputValue; normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels());};
|
||||
|
||||
/**
|
||||
* sigmoide image normalization function (saturates min and max values), in this function, the sigmoide is centered on low values (high saturation of the medium and high values
|
||||
* @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param sensitivity: strenght of the sigmoide
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
void normalizeGrayOutputNearZeroCentreredSigmoide(type *inputPicture=(type*)NULL, type *outputBuffer=(type*)NULL, const type sensitivity=(type)40, const type maxOutputValue=(type)255.0);
|
||||
|
||||
/**
|
||||
* center and reduct the image (image-mean)/std
|
||||
* @param inputOutputBuffer: the image to be normalized if no parameter, the result is rewrited on it
|
||||
*/
|
||||
void centerReductImageLuminance(type *inputOutputBuffer=(type*)NULL);
|
||||
|
||||
/**
|
||||
* @return standard deviation of the buffer
|
||||
*/
|
||||
double getStandardDeviation()
|
||||
{
|
||||
double standardDeviation=0;
|
||||
double meanValue=getMean();
|
||||
|
||||
type *bufferPTR=Buffer();
|
||||
for (unsigned int i=0;i<this->size();++i)
|
||||
/**
|
||||
* constructor for monodimensional array
|
||||
* @param dim: the size of the vector
|
||||
*/
|
||||
TemplateBuffer(const size_t dim=0)
|
||||
: std::valarray<type>((type)0, dim)
|
||||
{
|
||||
double diff=(*(bufferPTR++)-meanValue);
|
||||
standardDeviation+=diff*diff;
|
||||
_NBrows=1;
|
||||
_NBcolumns=dim;
|
||||
_NBdepths=1;
|
||||
_NBpixels=dim;
|
||||
_doubleNBpixels=2*dim;
|
||||
}
|
||||
return sqrt(standardDeviation/this->size());
|
||||
|
||||
/**
|
||||
* constructor by copy for monodimensional array
|
||||
* @param pVal: the pointer to a buffer to copy
|
||||
* @param dim: the size of the vector
|
||||
*/
|
||||
TemplateBuffer(const type* pVal, const size_t dim)
|
||||
: std::valarray<type>(pVal, dim)
|
||||
{
|
||||
_NBrows=1;
|
||||
_NBcolumns=dim;
|
||||
_NBdepths=1;
|
||||
_NBpixels=dim;
|
||||
_doubleNBpixels=2*dim;
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor for bidimensional array
|
||||
* @param dimRows: the size of the vector
|
||||
* @param dimColumns: the size of the vector
|
||||
* @param depth: the number of layers of the buffer in its third dimension (3 of color images, 1 for gray images.
|
||||
*/
|
||||
TemplateBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
|
||||
: std::valarray<type>((type)0, dimRows*dimColumns*depth)
|
||||
{
|
||||
#ifdef TEMPLATEBUFFERDEBUG
|
||||
std::cout<<"TemplateBuffer::TemplateBuffer: new buffer, size="<<dimRows<<", "<<dimColumns<<", "<<depth<<"valarraySize="<<this->size()<<std::endl;
|
||||
#endif
|
||||
_NBrows=dimRows;
|
||||
_NBcolumns=dimColumns;
|
||||
_NBdepths=depth;
|
||||
_NBpixels=dimRows*dimColumns;
|
||||
_doubleNBpixels=2*dimRows*dimColumns;
|
||||
//_createTableIndex();
|
||||
#ifdef TEMPLATEBUFFERDEBUG
|
||||
std::cout<<"TemplateBuffer::TemplateBuffer: construction successful"<<std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* copy constructor
|
||||
* @param toCopy
|
||||
* @return thenconstructed instance
|
||||
*emplateBuffer(const TemplateBuffer &toCopy)
|
||||
:_NBrows(toCopy.getNBrows()),_NBcolumns(toCopy.getNBcolumns()),_NBdepths(toCopy.getNBdephs()), _NBpixels(toCopy.getNBpixels()), _doubleNBpixels(toCopy.getNBpixels()*2)
|
||||
//std::valarray<type>(toCopy)
|
||||
{
|
||||
memcpy(Buffer(), toCopy.Buffer(), this->size());
|
||||
}*/
|
||||
/**
|
||||
* destructor
|
||||
*/
|
||||
virtual ~TemplateBuffer()
|
||||
{
|
||||
#ifdef TEMPLATEBUFFERDEBUG
|
||||
std::cout<<"~TemplateBuffer"<<std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* delete the buffer content (set zeros)
|
||||
*/
|
||||
inline void setZero(){std::valarray<type>::operator=(0);};//memset(Buffer(), 0, sizeof(type)*_NBpixels);};
|
||||
|
||||
/**
|
||||
* @return the numbers of rows (height) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getNBrows(){return (unsigned int)_NBrows;};
|
||||
|
||||
/**
|
||||
* @return the numbers of columns (width) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getNBcolumns(){return (unsigned int)_NBcolumns;};
|
||||
|
||||
/**
|
||||
* @return the numbers of pixels (width*height) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getNBpixels(){return (unsigned int)_NBpixels;};
|
||||
|
||||
/**
|
||||
* @return the numbers of pixels (width*height) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getDoubleNBpixels(){return (unsigned int)_doubleNBpixels;};
|
||||
|
||||
/**
|
||||
* @return the numbers of depths (3rd dimension: 1 for gray images, 3 for rgb images) of the images used by the object
|
||||
*/
|
||||
inline unsigned int getDepthSize(){return (unsigned int)_NBdepths;};
|
||||
|
||||
/**
|
||||
* resize the buffer and recompute table index etc.
|
||||
*/
|
||||
void resizeBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
|
||||
{
|
||||
this->resize(dimRows*dimColumns*depth);
|
||||
_NBrows=dimRows;
|
||||
_NBcolumns=dimColumns;
|
||||
_NBdepths=depth;
|
||||
_NBpixels=dimRows*dimColumns;
|
||||
_doubleNBpixels=2*dimRows*dimColumns;
|
||||
}
|
||||
|
||||
inline TemplateBuffer<type> & operator=(const std::valarray<type> &b)
|
||||
{
|
||||
//std::cout<<"TemplateBuffer<type> & operator= affect vector: "<<std::endl;
|
||||
std::valarray<type>::operator=(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TemplateBuffer<type> & operator=(const type &b)
|
||||
{
|
||||
//std::cout<<"TemplateBuffer<type> & operator= affect value: "<<b<<std::endl;
|
||||
std::valarray<type>::operator=(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* inline const type &operator[](const unsigned int &b)
|
||||
{
|
||||
return (*this)[b];
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @return the buffer adress in non const mode
|
||||
*/
|
||||
inline type* Buffer() { return &(*this)[0]; }
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Standard Image manipulation functions
|
||||
|
||||
/**
|
||||
* standard 0 to 255 image normalization function
|
||||
* @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
static void normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t nbPixels, const type maxOutputValue=(type)255.0);
|
||||
|
||||
/**
|
||||
* standard 0 to 255 image normalization function
|
||||
* @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0){normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);};
|
||||
|
||||
/**
|
||||
* sigmoide image normalization function (saturates min and max values)
|
||||
* @param meanValue: specifies the mean value of th pixels to be processed
|
||||
* @param sensitivity: strenght of the sigmoide
|
||||
* @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
static void normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputPicture, type *outputBuffer, const unsigned int nbPixels);
|
||||
|
||||
/**
|
||||
* sigmoide image normalization function on the current buffer (saturates min and max values)
|
||||
* @param meanValue: specifies the mean value of th pixels to be processed
|
||||
* @param sensitivity: strenght of the sigmoide
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0){ (void)maxOutputValue; normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels());};
|
||||
|
||||
/**
|
||||
* sigmoide image normalization function (saturates min and max values), in this function, the sigmoide is centered on low values (high saturation of the medium and high values
|
||||
* @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized
|
||||
* @param sensitivity: strenght of the sigmoide
|
||||
* @param maxOutputValue: the maximum output value
|
||||
*/
|
||||
void normalizeGrayOutputNearZeroCentreredSigmoide(type *inputPicture=(type*)NULL, type *outputBuffer=(type*)NULL, const type sensitivity=(type)40, const type maxOutputValue=(type)255.0);
|
||||
|
||||
/**
|
||||
* center and reduct the image (image-mean)/std
|
||||
* @param inputOutputBuffer: the image to be normalized if no parameter, the result is rewrited on it
|
||||
*/
|
||||
void centerReductImageLuminance(type *inputOutputBuffer=(type*)NULL);
|
||||
|
||||
/**
|
||||
* @return standard deviation of the buffer
|
||||
*/
|
||||
double getStandardDeviation()
|
||||
{
|
||||
double standardDeviation=0;
|
||||
double meanValue=getMean();
|
||||
|
||||
type *bufferPTR=Buffer();
|
||||
for (unsigned int i=0;i<this->size();++i)
|
||||
{
|
||||
double diff=(*(bufferPTR++)-meanValue);
|
||||
standardDeviation+=diff*diff;
|
||||
}
|
||||
return sqrt(standardDeviation/this->size());
|
||||
};
|
||||
|
||||
/**
|
||||
* Clip buffer histogram
|
||||
* @param minRatio: the minimum ratio of the lower pixel values, range=[0,1] and lower than maxRatio
|
||||
* @param maxRatio: the aximum ratio of the higher pixel values, range=[0,1] and higher than minRatio
|
||||
*/
|
||||
void clipHistogram(double minRatio, double maxRatio, double maxOutputValue)
|
||||
{
|
||||
|
||||
if (minRatio>=maxRatio)
|
||||
{
|
||||
std::cerr<<"TemplateBuffer::clipHistogram: minRatio must be inferior to maxRatio, buffer unchanged"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* minRatio=min(max(minRatio, 1.0),0.0);
|
||||
maxRatio=max(max(maxRatio, 0.0),1.0);
|
||||
*/
|
||||
|
||||
// find the pixel value just above the threshold
|
||||
const double maxThreshold=this->max()*maxRatio;
|
||||
const double minThreshold=(this->max()-this->min())*minRatio+this->min();
|
||||
|
||||
type *bufferPTR=this->Buffer();
|
||||
|
||||
double deltaH=maxThreshold;
|
||||
double deltaL=maxThreshold;
|
||||
|
||||
double updatedHighValue=maxThreshold;
|
||||
double updatedLowValue=maxThreshold;
|
||||
|
||||
for (unsigned int i=0;i<this->size();++i)
|
||||
{
|
||||
double curentValue=(double)*(bufferPTR++);
|
||||
|
||||
// updating "closest to the high threshold" pixel value
|
||||
double highValueTest=maxThreshold-curentValue;
|
||||
if (highValueTest>0)
|
||||
{
|
||||
if (deltaH>highValueTest)
|
||||
{
|
||||
deltaH=highValueTest;
|
||||
updatedHighValue=curentValue;
|
||||
}
|
||||
}
|
||||
|
||||
// updating "closest to the low threshold" pixel value
|
||||
double lowValueTest=curentValue-minThreshold;
|
||||
if (lowValueTest>0)
|
||||
{
|
||||
if (deltaL>lowValueTest)
|
||||
{
|
||||
deltaL=lowValueTest;
|
||||
updatedLowValue=curentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout<<"Tdebug"<<std::endl;
|
||||
std::cout<<"deltaL="<<deltaL<<", deltaH="<<deltaH<<std::endl;
|
||||
std::cout<<"this->max()"<<this->max()<<"maxThreshold="<<maxThreshold<<"updatedHighValue="<<updatedHighValue<<std::endl;
|
||||
std::cout<<"this->min()"<<this->min()<<"minThreshold="<<minThreshold<<"updatedLowValue="<<updatedLowValue<<std::endl;
|
||||
// clipping values outside than the updated thresholds
|
||||
bufferPTR=this->Buffer();
|
||||
#ifdef MAKE_PARALLEL // call the TemplateBuffer multitreaded clipping method
|
||||
parallel_for_(cv::Range(0,this->size()), Parallel_clipBufferValues<type>(bufferPTR, updatedLowValue, updatedHighValue));
|
||||
#else
|
||||
|
||||
for (unsigned int i=0;i<this->size();++i, ++bufferPTR)
|
||||
{
|
||||
if (*bufferPTR<updatedLowValue)
|
||||
*bufferPTR=updatedLowValue;
|
||||
else if (*bufferPTR>updatedHighValue)
|
||||
*bufferPTR=updatedHighValue;
|
||||
}
|
||||
#endif
|
||||
normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mean value of the vector
|
||||
*/
|
||||
inline double getMean(){return this->sum()/this->size();};
|
||||
|
||||
protected:
|
||||
size_t _NBrows;
|
||||
size_t _NBcolumns;
|
||||
size_t _NBdepths;
|
||||
size_t _NBpixels;
|
||||
size_t _doubleNBpixels;
|
||||
// utilities
|
||||
static type _abs(const type x);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Clip buffer histogram
|
||||
* @param minRatio: the minimum ratio of the lower pixel values, range=[0,1] and lower than maxRatio
|
||||
* @param maxRatio: the aximum ratio of the higher pixel values, range=[0,1] and higher than minRatio
|
||||
*/
|
||||
void clipHistogram(double minRatio, double maxRatio, double maxOutputValue)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// normalize output between 0 and 255, can be applied on images of different size that the declared size if nbPixels parameters is setted up;
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t processedPixels, const type maxOutputValue)
|
||||
{
|
||||
type maxValue=inputOutputBuffer[0], minValue=inputOutputBuffer[0];
|
||||
|
||||
// get the min and max value
|
||||
register type *inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (register size_t j = 0; j<processedPixels; ++j)
|
||||
{
|
||||
type pixValue = *(inputOutputBufferPTR++);
|
||||
if (maxValue < pixValue)
|
||||
maxValue = pixValue;
|
||||
else if (minValue > pixValue)
|
||||
minValue = pixValue;
|
||||
}
|
||||
// change the range of the data to 0->255
|
||||
|
||||
type factor = maxOutputValue/(maxValue-minValue);
|
||||
type offset = (type)(-minValue*factor);
|
||||
|
||||
inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (register size_t j = 0; j < processedPixels; ++j, ++inputOutputBufferPTR)
|
||||
*inputOutputBufferPTR=*(inputOutputBufferPTR)*factor+offset;
|
||||
|
||||
}
|
||||
// normalize data with a sigmoide close to 0 (saturates values for those superior to 0)
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::normalizeGrayOutputNearZeroCentreredSigmoide(type *inputBuffer, type *outputBuffer, const type sensitivity, const type maxOutputValue)
|
||||
{
|
||||
if (inputBuffer==NULL)
|
||||
inputBuffer=Buffer();
|
||||
if (outputBuffer==NULL)
|
||||
outputBuffer=Buffer();
|
||||
|
||||
type X0cube=sensitivity*sensitivity*sensitivity;
|
||||
|
||||
register type *inputBufferPTR=inputBuffer;
|
||||
register type *outputBufferPTR=outputBuffer;
|
||||
|
||||
for (register size_t j = 0; j < _NBpixels; ++j, ++inputBufferPTR)
|
||||
{
|
||||
|
||||
type currentCubeLuminance=*inputBufferPTR**inputBufferPTR**inputBufferPTR;
|
||||
*(outputBufferPTR++)=maxOutputValue*currentCubeLuminance/(currentCubeLuminance+X0cube);
|
||||
}
|
||||
}
|
||||
|
||||
// normalize and adjust luminance with a centered to 128 sigmode
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputBuffer, type *outputBuffer, const unsigned int nbPixels)
|
||||
{
|
||||
|
||||
if (minRatio>=maxRatio)
|
||||
if (sensitivity==1.0)
|
||||
{
|
||||
std::cerr<<"TemplateBuffer::clipHistogram: minRatio must be inferior to maxRatio, buffer unchanged"<<std::endl;
|
||||
std::cerr<<"TemplateBuffer::TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..."<<std::endl;
|
||||
memcpy(outputBuffer, inputBuffer, sizeof(type)*nbPixels);
|
||||
return;
|
||||
}
|
||||
|
||||
/* minRatio=min(max(minRatio, 1.0),0.0);
|
||||
maxRatio=max(max(maxRatio, 0.0),1.0);
|
||||
*/
|
||||
type X0=maxOutputValue/(sensitivity-(type)1.0);
|
||||
|
||||
// find the pixel value just above the threshold
|
||||
const double maxThreshold=this->max()*maxRatio;
|
||||
const double minThreshold=(this->max()-this->min())*minRatio+this->min();
|
||||
register type *inputBufferPTR=inputBuffer;
|
||||
register type *outputBufferPTR=outputBuffer;
|
||||
|
||||
type *bufferPTR=this->Buffer();
|
||||
for (register size_t j = 0; j < nbPixels; ++j, ++inputBufferPTR)
|
||||
*(outputBufferPTR++)=(meanValue+(meanValue+X0)*(*(inputBufferPTR)-meanValue)/(_abs(*(inputBufferPTR)-meanValue)+X0));
|
||||
|
||||
double deltaH=maxThreshold;
|
||||
double deltaL=maxThreshold;
|
||||
}
|
||||
|
||||
double updatedHighValue=maxThreshold;
|
||||
double updatedLowValue=maxThreshold;
|
||||
// center and reduct the image (image-mean)/std
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::centerReductImageLuminance(type *inputOutputBuffer)
|
||||
{
|
||||
// if outputBuffer unsassigned, the rewrite the buffer
|
||||
if (inputOutputBuffer==NULL)
|
||||
inputOutputBuffer=Buffer();
|
||||
type meanValue=0, stdValue=0;
|
||||
|
||||
for (unsigned int i=0;i<this->size();++i)
|
||||
// compute mean value
|
||||
for (register size_t j = 0; j < _NBpixels; ++j)
|
||||
meanValue+=inputOutputBuffer[j];
|
||||
meanValue/=((type)_NBpixels);
|
||||
|
||||
// compute std value
|
||||
register type *inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (size_t index=0;index<_NBpixels;++index)
|
||||
{
|
||||
double curentValue=(double)*(bufferPTR++);
|
||||
|
||||
// updating "closest to the high threshold" pixel value
|
||||
double highValueTest=maxThreshold-curentValue;
|
||||
if (highValueTest>0)
|
||||
{
|
||||
if (deltaH>highValueTest)
|
||||
{
|
||||
deltaH=highValueTest;
|
||||
updatedHighValue=curentValue;
|
||||
}
|
||||
}
|
||||
|
||||
// updating "closest to the low threshold" pixel value
|
||||
double lowValueTest=curentValue-minThreshold;
|
||||
if (lowValueTest>0)
|
||||
{
|
||||
if (deltaL>lowValueTest)
|
||||
{
|
||||
deltaL=lowValueTest;
|
||||
updatedLowValue=curentValue;
|
||||
}
|
||||
}
|
||||
type inputMinusMean=*(inputOutputBufferPTR++)-meanValue;
|
||||
stdValue+=inputMinusMean*inputMinusMean;
|
||||
}
|
||||
|
||||
std::cout<<"Tdebug"<<std::endl;
|
||||
std::cout<<"deltaL="<<deltaL<<", deltaH="<<deltaH<<std::endl;
|
||||
std::cout<<"this->max()"<<this->max()<<"maxThreshold="<<maxThreshold<<"updatedHighValue="<<updatedHighValue<<std::endl;
|
||||
std::cout<<"this->min()"<<this->min()<<"minThreshold="<<minThreshold<<"updatedLowValue="<<updatedLowValue<<std::endl;
|
||||
// clipping values outside than the updated thresholds
|
||||
bufferPTR=this->Buffer();
|
||||
for (unsigned int i=0;i<this->size();++i, ++bufferPTR)
|
||||
{
|
||||
if (*bufferPTR<updatedLowValue)
|
||||
*bufferPTR=updatedLowValue;
|
||||
else if (*bufferPTR>updatedHighValue)
|
||||
*bufferPTR=updatedHighValue;
|
||||
}
|
||||
|
||||
normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);
|
||||
|
||||
stdValue=sqrt(stdValue/((type)_NBpixels));
|
||||
// adjust luminance in regard of mean and std value;
|
||||
inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (size_t index=0;index<_NBpixels;++index, ++inputOutputBufferPTR)
|
||||
*inputOutputBufferPTR=(*(inputOutputBufferPTR)-meanValue)/stdValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mean value of the vector
|
||||
*/
|
||||
inline double getMean(){return this->sum()/this->size();};
|
||||
|
||||
protected:
|
||||
size_t _NBrows;
|
||||
size_t _NBcolumns;
|
||||
size_t _NBdepths;
|
||||
size_t _NBpixels;
|
||||
size_t _doubleNBpixels;
|
||||
// utilities
|
||||
static type _abs(const type x);
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// normalize output between 0 and 255, can be applied on images of different size that the declared size if nbPixels parameters is setted up;
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t processedPixels, const type maxOutputValue)
|
||||
{
|
||||
type maxValue=inputOutputBuffer[0], minValue=inputOutputBuffer[0];
|
||||
|
||||
// get the min and max value
|
||||
register type *inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (register size_t j = 0; j<processedPixels; ++j)
|
||||
{
|
||||
type pixValue = *(inputOutputBufferPTR++);
|
||||
if (maxValue < pixValue)
|
||||
maxValue = pixValue;
|
||||
else if (minValue > pixValue)
|
||||
minValue = pixValue;
|
||||
}
|
||||
// change the range of the data to 0->255
|
||||
|
||||
type factor = maxOutputValue/(maxValue-minValue);
|
||||
type offset = (type)(-minValue*factor);
|
||||
|
||||
inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (register size_t j = 0; j < processedPixels; ++j, ++inputOutputBufferPTR)
|
||||
*inputOutputBufferPTR=*(inputOutputBufferPTR)*factor+offset;
|
||||
|
||||
}
|
||||
// normalize data with a sigmoide close to 0 (saturates values for those superior to 0)
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::normalizeGrayOutputNearZeroCentreredSigmoide(type *inputBuffer, type *outputBuffer, const type sensitivity, const type maxOutputValue)
|
||||
{
|
||||
if (inputBuffer==NULL)
|
||||
inputBuffer=Buffer();
|
||||
if (outputBuffer==NULL)
|
||||
outputBuffer=Buffer();
|
||||
|
||||
type X0cube=sensitivity*sensitivity*sensitivity;
|
||||
|
||||
register type *inputBufferPTR=inputBuffer;
|
||||
register type *outputBufferPTR=outputBuffer;
|
||||
|
||||
for (register size_t j = 0; j < _NBpixels; ++j, ++inputBufferPTR)
|
||||
template <class type>
|
||||
type TemplateBuffer<type>::_abs(const type x)
|
||||
{
|
||||
|
||||
type currentCubeLuminance=*inputBufferPTR**inputBufferPTR**inputBufferPTR;
|
||||
*(outputBufferPTR++)=maxOutputValue*currentCubeLuminance/(currentCubeLuminance+X0cube);
|
||||
if (x>0)
|
||||
return x;
|
||||
else
|
||||
return -x;
|
||||
}
|
||||
}
|
||||
|
||||
// normalize and adjust luminance with a centered to 128 sigmode
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputBuffer, type *outputBuffer, const unsigned int nbPixels)
|
||||
{
|
||||
|
||||
if (sensitivity==1.0)
|
||||
template < >
|
||||
inline int TemplateBuffer<int>::_abs(const int x)
|
||||
{
|
||||
std::cerr<<"TemplateBuffer::TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..."<<std::endl;
|
||||
memcpy(outputBuffer, inputBuffer, sizeof(type)*nbPixels);
|
||||
return;
|
||||
return std::abs(x);
|
||||
}
|
||||
|
||||
type X0=maxOutputValue/(sensitivity-(type)1.0);
|
||||
|
||||
register type *inputBufferPTR=inputBuffer;
|
||||
register type *outputBufferPTR=outputBuffer;
|
||||
|
||||
for (register size_t j = 0; j < nbPixels; ++j, ++inputBufferPTR)
|
||||
*(outputBufferPTR++)=(meanValue+(meanValue+X0)*(*(inputBufferPTR)-meanValue)/(_abs(*(inputBufferPTR)-meanValue)+X0));
|
||||
|
||||
}
|
||||
|
||||
// center and reduct the image (image-mean)/std
|
||||
template <class type>
|
||||
void TemplateBuffer<type>::centerReductImageLuminance(type *inputOutputBuffer)
|
||||
{
|
||||
// if outputBuffer unsassigned, the rewrite the buffer
|
||||
if (inputOutputBuffer==NULL)
|
||||
inputOutputBuffer=Buffer();
|
||||
type meanValue=0, stdValue=0;
|
||||
|
||||
// compute mean value
|
||||
for (register size_t j = 0; j < _NBpixels; ++j)
|
||||
meanValue+=inputOutputBuffer[j];
|
||||
meanValue/=((type)_NBpixels);
|
||||
|
||||
// compute std value
|
||||
register type *inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (size_t index=0;index<_NBpixels;++index)
|
||||
template < >
|
||||
inline double TemplateBuffer<double>::_abs(const double x)
|
||||
{
|
||||
type inputMinusMean=*(inputOutputBufferPTR++)-meanValue;
|
||||
stdValue+=inputMinusMean*inputMinusMean;
|
||||
return std::fabs(x);
|
||||
}
|
||||
|
||||
stdValue=sqrt(stdValue/((type)_NBpixels));
|
||||
// adjust luminance in regard of mean and std value;
|
||||
inputOutputBufferPTR=inputOutputBuffer;
|
||||
for (size_t index=0;index<_NBpixels;++index, ++inputOutputBufferPTR)
|
||||
*inputOutputBufferPTR=(*(inputOutputBufferPTR)-meanValue)/stdValue;
|
||||
}
|
||||
|
||||
|
||||
template <class type>
|
||||
type TemplateBuffer<type>::_abs(const type x)
|
||||
{
|
||||
|
||||
if (x>0)
|
||||
return x;
|
||||
else
|
||||
return -x;
|
||||
}
|
||||
|
||||
template < >
|
||||
inline int TemplateBuffer<int>::_abs(const int x)
|
||||
{
|
||||
return std::abs(x);
|
||||
}
|
||||
template < >
|
||||
inline double TemplateBuffer<double>::_abs(const double x)
|
||||
{
|
||||
return std::fabs(x);
|
||||
}
|
||||
|
||||
template < >
|
||||
inline float TemplateBuffer<float>::_abs(const float x)
|
||||
{
|
||||
return std::fabs(x);
|
||||
}
|
||||
template < >
|
||||
inline float TemplateBuffer<float>::_abs(const float x)
|
||||
{
|
||||
return std::fabs(x);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,19 +7,6 @@ The section describes the main data structures, used by the OpenCV 1.x API, and
|
||||
|
||||
CvPoint
|
||||
-------
|
||||
|
||||
.. ocv:struct:: CvPoint
|
||||
|
||||
2D point with integer coordinates (usually zero-based).
|
||||
|
||||
.. ocv:member:: int x
|
||||
|
||||
x-coordinate
|
||||
|
||||
.. ocv:member:: int y
|
||||
|
||||
y-coordinate
|
||||
|
||||
.. ocv:cfunction:: CvPoint cvPoint( int x, int y )
|
||||
|
||||
constructs ``CvPoint`` structure.
|
||||
@@ -28,23 +15,21 @@ CvPoint
|
||||
|
||||
converts ``CvPoint2D32f`` to ``CvPoint``.
|
||||
|
||||
.. ocv:struct:: CvPoint
|
||||
|
||||
2D point with integer coordinates (usually zero-based).
|
||||
|
||||
:param x: x-coordinate of the point.
|
||||
|
||||
:param y: y-coordinate of the point.
|
||||
|
||||
:param point: the point to convert.
|
||||
|
||||
.. seealso:: :ocv:class:`Point\_`
|
||||
|
||||
CvPoint2D32f
|
||||
------------
|
||||
|
||||
.. ocv:struct:: CvPoint2D32f
|
||||
|
||||
2D point with floating-point coordinates.
|
||||
|
||||
.. ocv:member:: float x
|
||||
|
||||
x-coordinate
|
||||
|
||||
.. ocv:member:: float y
|
||||
|
||||
y-coordinate
|
||||
|
||||
.. ocv:cfunction:: CvPoint2D32f cvPoint2D32f( double x, double y )
|
||||
|
||||
constructs ``CvPoint2D32f`` structure.
|
||||
@@ -53,6 +38,16 @@ CvPoint2D32f
|
||||
|
||||
converts ``CvPoint`` to ``CvPoint2D32f``.
|
||||
|
||||
.. ocv:struct:: CvPoint2D32f
|
||||
|
||||
2D point with floating-point coordinates.
|
||||
|
||||
:param x: floating-point x-coordinate of the point.
|
||||
|
||||
:param y: floating-point y-coordinate of the point.
|
||||
|
||||
:param point: the point to convert.
|
||||
|
||||
.. seealso:: :ocv:class:`Point\_`
|
||||
|
||||
CvPoint3D32f
|
||||
@@ -62,22 +57,16 @@ CvPoint3D32f
|
||||
|
||||
3D point with floating-point coordinates
|
||||
|
||||
.. ocv:member:: float x
|
||||
|
||||
x-coordinate
|
||||
|
||||
.. ocv:member:: float y
|
||||
|
||||
y-coordinate
|
||||
|
||||
.. ocv:member:: float z
|
||||
|
||||
z-coordinate
|
||||
|
||||
.. ocv:cfunction:: CvPoint3D32f cvPoint3D32f( double x, double y, double z )
|
||||
|
||||
constructs ``CvPoint3D32f`` structure.
|
||||
|
||||
:param x: floating-point x-coordinate of the point.
|
||||
|
||||
:param y: floating-point y-coordinate of the point.
|
||||
|
||||
:param z: floating-point z-coordinate of the point.
|
||||
|
||||
.. seealso:: :ocv:class:`Point3\_`
|
||||
|
||||
CvPoint2D64f
|
||||
@@ -87,18 +76,14 @@ CvPoint2D64f
|
||||
|
||||
2D point with double-precision floating-point coordinates.
|
||||
|
||||
.. ocv:member:: double x
|
||||
|
||||
x-coordinate
|
||||
|
||||
.. ocv:member:: double y
|
||||
|
||||
y-coordinate
|
||||
|
||||
.. ocv:cfunction:: CvPoint2D64f cvPoint2D64f( double x, double y )
|
||||
|
||||
constructs ``CvPoint2D64f`` structure.
|
||||
|
||||
:param x: double-precision floating-point x-coordinate of the point.
|
||||
|
||||
:param y: double-precision floating-point y-coordinate of the point.
|
||||
|
||||
.. seealso:: :ocv:class:`Point\_`
|
||||
|
||||
CvPoint3D64f
|
||||
@@ -108,20 +93,16 @@ CvPoint3D64f
|
||||
|
||||
3D point with double-precision floating-point coordinates.
|
||||
|
||||
.. ocv:member:: double x
|
||||
|
||||
x-coordinate
|
||||
|
||||
.. ocv:member:: double y
|
||||
|
||||
y-coordinate
|
||||
|
||||
.. ocv:member:: double z
|
||||
|
||||
.. ocv:cfunction:: CvPoint3D64f cvPoint3D64f( double x, double y, double z )
|
||||
|
||||
constructs ``CvPoint3D64f`` structure.
|
||||
|
||||
:param x: double-precision floating-point x-coordinate of the point.
|
||||
|
||||
:param y: double-precision floating-point y-coordinate of the point.
|
||||
|
||||
:param z: double-precision floating-point z-coordinate of the point.
|
||||
|
||||
.. seealso:: :ocv:class:`Point3\_`
|
||||
|
||||
CvSize
|
||||
@@ -131,18 +112,14 @@ CvSize
|
||||
|
||||
Size of a rectangle or an image.
|
||||
|
||||
.. ocv:member:: int width
|
||||
|
||||
Width of the rectangle
|
||||
|
||||
.. ocv:member:: int height
|
||||
|
||||
Height of the rectangle
|
||||
|
||||
.. ocv:cfunction:: CvSize cvSize( int width, int height )
|
||||
|
||||
constructs ``CvSize`` structure.
|
||||
|
||||
:param width: width of the rectangle.
|
||||
|
||||
:param height: height of the rectangle.
|
||||
|
||||
.. seealso:: :ocv:class:`Size\_`
|
||||
|
||||
CvSize2D32f
|
||||
@@ -152,18 +129,14 @@ CvSize2D32f
|
||||
|
||||
Sub-pixel accurate size of a rectangle.
|
||||
|
||||
.. ocv:member:: float width
|
||||
|
||||
Width of the rectangle
|
||||
|
||||
.. ocv:member:: float height
|
||||
|
||||
Height of the rectangle
|
||||
|
||||
.. ocv:cfunction:: CvSize2D32f cvSize2D32f( double width, double height )
|
||||
|
||||
constructs ``CvSize2D32f`` structure.
|
||||
|
||||
:param width: floating-point width of the rectangle.
|
||||
|
||||
:param height: floating-point height of the rectangle.
|
||||
|
||||
.. seealso:: :ocv:class:`Size\_`
|
||||
|
||||
CvRect
|
||||
@@ -173,26 +146,18 @@ CvRect
|
||||
|
||||
Stores coordinates of a rectangle.
|
||||
|
||||
.. ocv:member:: int x
|
||||
|
||||
x-coordinate of the top-left corner
|
||||
|
||||
.. ocv:member:: int y
|
||||
|
||||
y-coordinate of the top-left corner (sometimes bottom-left corner)
|
||||
|
||||
.. ocv:member:: int width
|
||||
|
||||
Width of the rectangle
|
||||
|
||||
.. ocv:member:: int height
|
||||
|
||||
Height of the rectangle
|
||||
|
||||
.. ocv:cfunction:: CvRect cvRect( int x, int y, int width, int height )
|
||||
|
||||
constructs ``CvRect`` structure.
|
||||
|
||||
:param x: x-coordinate of the top-left corner.
|
||||
|
||||
:param y: y-coordinate of the top-left corner (sometimes bottom-left corner).
|
||||
|
||||
:param width: width of the rectangle.
|
||||
|
||||
:param height: height of the rectangle.
|
||||
|
||||
.. seealso:: :ocv:class:`Rect\_`
|
||||
|
||||
|
||||
@@ -1666,7 +1631,17 @@ SetIPLAllocators
|
||||
----------------
|
||||
Makes OpenCV use IPL functions for allocating IplImage and IplROI structures.
|
||||
|
||||
.. ocv:cfunction:: void cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, Cv_iplAllocateImageData allocate_data, Cv_iplDeallocate deallocate, Cv_iplCreateROI create_roi, Cv_iplCloneImage clone_image )
|
||||
.. ocv:cfunction:: void cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, Cv_iplAllocateImageData allocate_data, Cv_iplDeallocate deallocate, Cv_iplCreateROI create_roi, Cv_iplCloneImage clone_image )
|
||||
|
||||
:param create_header: pointer to a function, creating IPL image header.
|
||||
|
||||
:param allocate_data: pointer to a function, allocating IPL image data.
|
||||
|
||||
:param deallocate: pointer to a function, deallocating IPL image.
|
||||
|
||||
:param create_roi: pointer to a function, creating IPL image ROI (i.e. Region of Interest).
|
||||
|
||||
:param clone_image: pointer to a function, cloning an IPL image.
|
||||
|
||||
Normally, the function is not called directly. Instead, a simple macro ``CV_TURN_ON_IPL_COMPATIBILITY()`` is used that calls ``cvSetIPLAllocators`` and passes there pointers to IPL allocation functions. ::
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ Calculates the per-element absolute difference between two arrays or between an
|
||||
|
||||
:param src2: second input array or a scalar.
|
||||
|
||||
:param src: single input array.
|
||||
|
||||
:param value: scalar value.
|
||||
|
||||
:param dst: output array that has the same size and type as input arrays.
|
||||
|
||||
The function ``absdiff`` calculates:
|
||||
@@ -93,6 +97,10 @@ Calculates the per-element sum of two arrays or an array and a scalar.
|
||||
|
||||
:param src2: second input array or a scalar.
|
||||
|
||||
:param src: single input array.
|
||||
|
||||
:param value: scalar value.
|
||||
|
||||
:param dst: output array that has the same size and number of channels as the input array(s); the depth is defined by ``dtype`` or ``src1``/``src2``.
|
||||
|
||||
:param mask: optional operation mask – 8-bit single channel array, that specifies elements of the output array to be changed.
|
||||
@@ -209,6 +217,10 @@ Calculates the per-element bit-wise conjunction of two arrays or an array and a
|
||||
|
||||
:param src2: second input array or a scalar.
|
||||
|
||||
:param src: single input array.
|
||||
|
||||
:param value: scalar value.
|
||||
|
||||
:param dst: output array that has the same size and type as the input arrays.
|
||||
|
||||
:param mask: optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.
|
||||
@@ -285,6 +297,10 @@ Calculates the per-element bit-wise disjunction of two arrays or an array and a
|
||||
|
||||
:param src2: second input array or a scalar.
|
||||
|
||||
:param src: single input array.
|
||||
|
||||
:param value: scalar value.
|
||||
|
||||
:param dst: output array that has the same size and type as the input arrays.
|
||||
|
||||
:param mask: optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.
|
||||
@@ -333,6 +349,10 @@ Calculates the per-element bit-wise "exclusive or" operation on two arrays or an
|
||||
|
||||
:param src2: second input array or a scalar.
|
||||
|
||||
:param src: single input array.
|
||||
|
||||
:param value: scalar value.
|
||||
|
||||
:param dst: output array that has the same size and type as the input arrays.
|
||||
|
||||
:param mask: optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.
|
||||
@@ -384,8 +404,14 @@ Calculates the covariance matrix of a set of vectors.
|
||||
|
||||
:param covar: output covariance matrix of the type ``ctype`` and square size.
|
||||
|
||||
:param ctype: type of the matrixl; it equals 'CV_64F' by default.
|
||||
|
||||
:param cov_mat: output covariance matrix (specific to C syntax).
|
||||
|
||||
:param mean: input or output (depending on the flags) array as the average value of the input vectors.
|
||||
|
||||
:param vects: a set of vectors.
|
||||
|
||||
:param flags: operation flags as a combination of the following values:
|
||||
|
||||
* **CV_COVAR_SCRAMBLED** The output covariance matrix is calculated as:
|
||||
@@ -444,6 +470,8 @@ Calculates the magnitude and angle of 2D vectors.
|
||||
|
||||
:param angleInDegrees: a flag, indicating whether the angles are measured in radians (which is by default), or in degrees.
|
||||
|
||||
:param angle_in_degrees: a flag, indicating whether the angles are measured in radians, or in degrees (specific to C syntax).
|
||||
|
||||
The function ``cartToPolar`` calculates either the magnitude, angle, or both for every 2D vector (x(I),y(I)):
|
||||
|
||||
.. math::
|
||||
@@ -502,6 +530,10 @@ Performs the per-element comparison of two arrays or an array and scalar value.
|
||||
|
||||
:param src2: second input array or a scalar (in the case of ``cvCmp`` and ``cv.Cmp`` it is always an array; in the case of ``cvCmpS``, ``cv.CmpS`` it is always a scalar); when it is an array, it must have a single channel.
|
||||
|
||||
:param src: single input array.
|
||||
|
||||
:param value: scalar value.
|
||||
|
||||
:param dst: output array that has the same size as the input arrays and type= ``CV_8UC1`` .
|
||||
|
||||
:param cmpop: a flag, that specifies correspondence between the arrays:
|
||||
@@ -513,6 +545,8 @@ Performs the per-element comparison of two arrays or an array and scalar value.
|
||||
* **CMP_LE** ``src1`` is less than or equal to ``src2``.
|
||||
* **CMP_NE** ``src1`` is unequal to ``src2``.
|
||||
|
||||
:param cmp_op: a flag, that specifies correspondence between the arrays (specific to C syntax; for possible values see 'cmpop above).
|
||||
|
||||
The function compares:
|
||||
|
||||
|
||||
@@ -2240,6 +2274,8 @@ PCA constructors
|
||||
|
||||
.. ocv:function:: PCA::PCA(InputArray data, InputArray mean, int flags, int maxComponents=0)
|
||||
|
||||
.. ocv:function:: PCA::PCA(InputArray data, InputArray mean, int flags, double retainedVariance)
|
||||
|
||||
:param data: input samples stored as matrix rows or matrix columns.
|
||||
|
||||
:param mean: optional mean value; if the matrix is empty (``noArray()``), the mean is computed from the data.
|
||||
@@ -2251,8 +2287,10 @@ PCA constructors
|
||||
* **CV_PCA_DATA_AS_COL** indicates that the input samples are stored as matrix columns.
|
||||
|
||||
:param maxComponents: maximum number of components that PCA should retain; by default, all the components are retained.
|
||||
|
||||
:param retainedVariance: Percentage of variance that PCA should retain. Using this parameter will let the PCA decided how many components to retain but it will always keep at least 2.
|
||||
|
||||
The default constructor initializes an empty PCA structure. The second constructor initializes the structure and calls
|
||||
The default constructor initializes an empty PCA structure. The other constructors initialize the structure and call
|
||||
:ocv:funcx:`PCA::operator()` .
|
||||
|
||||
|
||||
@@ -2263,6 +2301,8 @@ Performs Principal Component Analysis of the supplied dataset.
|
||||
|
||||
.. ocv:function:: PCA& PCA::operator()(InputArray data, InputArray mean, int flags, int maxComponents=0)
|
||||
|
||||
.. ocv:function:: PCA& PCA::operator()(InputArray data, InputArray mean, int flags, double retainedVariance)
|
||||
|
||||
.. ocv:pyfunction:: cv2.PCACompute(data[, mean[, eigenvectors[, maxComponents]]]) -> mean, eigenvectors
|
||||
|
||||
:param data: input samples stored as the matrix rows or as the matrix columns.
|
||||
@@ -2276,6 +2316,8 @@ Performs Principal Component Analysis of the supplied dataset.
|
||||
* **CV_PCA_DATA_AS_COL** indicates that the input samples are stored as matrix columns.
|
||||
|
||||
:param maxComponents: maximum number of components that PCA should retain; by default, all the components are retained.
|
||||
|
||||
:param retainedVariance: Percentage of variance that PCA should retain. Using this parameter will let the PCA decided how many components to retain but it will always keep at least 2.
|
||||
|
||||
The operator performs PCA of the supplied dataset. It is safe to reuse the same PCA structure for multiple datasets. That is, if the structure has been previously used with another dataset, the existing internal data is reclaimed and the new ``eigenvalues``, ``eigenvectors`` , and ``mean`` are allocated and computed.
|
||||
|
||||
|
||||
@@ -2359,8 +2359,10 @@ public:
|
||||
PCA();
|
||||
//! the constructor that performs PCA
|
||||
PCA(InputArray data, InputArray mean, int flags, int maxComponents=0);
|
||||
PCA(InputArray data, InputArray mean, int flags, double retainedVariance);
|
||||
//! operator that performs PCA. The previously stored data, if any, is released
|
||||
PCA& operator()(InputArray data, InputArray mean, int flags, int maxComponents=0);
|
||||
PCA& operator()(InputArray data, InputArray mean, int flags, double retainedVariance);
|
||||
//! projects vector from the original space to the principal components subspace
|
||||
Mat project(InputArray vec) const;
|
||||
//! projects vector from the original space to the principal components subspace
|
||||
@@ -2378,6 +2380,9 @@ public:
|
||||
CV_EXPORTS_W void PCACompute(InputArray data, CV_OUT InputOutputArray mean,
|
||||
OutputArray eigenvectors, int maxComponents=0);
|
||||
|
||||
CV_EXPORTS_W void PCACompute(InputArray data, CV_OUT InputOutputArray mean,
|
||||
OutputArray eigenvectors, double retainedVariance);
|
||||
|
||||
CV_EXPORTS_W void PCAProject(InputArray data, InputArray mean,
|
||||
InputArray eigenvectors, OutputArray result);
|
||||
|
||||
|
||||
@@ -74,6 +74,21 @@ void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCo
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
|
||||
void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src,
|
||||
Matx<_Tp, _rows, _cols>& dst )
|
||||
{
|
||||
if( !(src.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
dst = Matx<_Tp, _cols, _rows>(static_cast<const _Tp*>(src.data())).t();
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = Matx<_Tp, _rows, _cols>(static_cast<const _Tp*>(src.data()));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
|
||||
void cv2eigen( const Mat& src,
|
||||
Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
|
||||
@@ -103,6 +118,27 @@ void cv2eigen( const Mat& src,
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
|
||||
void cv2eigen( const Matx<_Tp, _rows, _cols>& src,
|
||||
Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
|
||||
{
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(_cols, _rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(_rows, _cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
Mat(src).copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
void cv2eigen( const Mat& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
|
||||
@@ -132,6 +168,27 @@ void cv2eigen( const Mat& src,
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows, int _cols>
|
||||
void cv2eigen( const Matx<_Tp, _rows, _cols>& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
|
||||
{
|
||||
dst.resize(_rows, _cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(_cols, _rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(_rows, _cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
Mat(src).copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
void cv2eigen( const Mat& src,
|
||||
@@ -159,6 +216,29 @@ void cv2eigen( const Mat& src,
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows>
|
||||
void cv2eigen( const Matx<_Tp, _rows, 1>& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst )
|
||||
{
|
||||
dst.resize(_rows);
|
||||
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(1, _rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(_rows, 1, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
src.copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename _Tp>
|
||||
void cv2eigen( const Mat& src,
|
||||
@@ -185,6 +265,29 @@ void cv2eigen( const Mat& src,
|
||||
}
|
||||
}
|
||||
|
||||
//Matx
|
||||
template<typename _Tp, int _cols>
|
||||
void cv2eigen( const Matx<_Tp, 1, _cols>& src,
|
||||
Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst )
|
||||
{
|
||||
dst.resize(_cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(_cols, 1, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(1, _cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
Mat(src).copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -404,7 +404,7 @@ inline bool Mat::empty() const { return data == 0 || total() == 0; }
|
||||
inline size_t Mat::total() const
|
||||
{
|
||||
if( dims <= 2 )
|
||||
return rows*cols;
|
||||
return (size_t)rows*cols;
|
||||
size_t p = 1;
|
||||
for( int i = 0; i < dims; i++ )
|
||||
p *= size[i];
|
||||
|
||||
@@ -866,7 +866,7 @@ template<typename _Tp, int m, int n> struct CV_EXPORTS Matx_FastSolveOp
|
||||
template<typename _Tp> struct CV_EXPORTS Matx_FastSolveOp<_Tp, 2, 1>
|
||||
{
|
||||
bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b,
|
||||
Matx<_Tp, 2, 1>& x, int method) const
|
||||
Matx<_Tp, 2, 1>& x, int) const
|
||||
{
|
||||
_Tp d = determinant(a);
|
||||
if( d == 0 )
|
||||
@@ -1244,7 +1244,7 @@ template<> inline Vec<double, 4> Vec<double, 4>::conj() const
|
||||
return conjugate(*this);
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> inline Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>& v) const
|
||||
template<typename _Tp, int cn> inline Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>&) const
|
||||
{
|
||||
CV_Error(CV_StsError, "for arbitrary-size vector there is no cross-product defined");
|
||||
return Vec<_Tp, cn>();
|
||||
@@ -2466,7 +2466,8 @@ dot(const Vector<_Tp>& v1, const Vector<_Tp>& v2)
|
||||
{
|
||||
const _Tp *ptr1 = &v1[0], *ptr2 = &v2[0];
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for(; i <= n - 4; i += 4 )
|
||||
const size_t n2 = (n > 4) ? n : 4;
|
||||
for(; i <= n2 - 4; i += 4 )
|
||||
s += (_Tw)ptr1[i]*ptr2[i] + (_Tw)ptr1[i+1]*ptr2[i+1] +
|
||||
(_Tw)ptr1[i+2]*ptr2[i+2] + (_Tw)ptr1[i+3]*ptr2[i+3];
|
||||
#endif
|
||||
@@ -2500,7 +2501,7 @@ inline RNG::operator double()
|
||||
unsigned t = next();
|
||||
return (((uint64)t << 32) | next())*5.4210108624275221700372640043497e-20;
|
||||
}
|
||||
inline int RNG::uniform(int a, int b) { return a == b ? a : next()%(b - a) + a; }
|
||||
inline int RNG::uniform(int a, int b) { return a == b ? a : (int)(next()%(b - a) + a); }
|
||||
inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; }
|
||||
inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; }
|
||||
|
||||
@@ -2937,8 +2938,8 @@ inline bool FileNode::isNamed() const { return !node ? false : (node->tag & NAME
|
||||
inline size_t FileNode::size() const
|
||||
{
|
||||
int t = type();
|
||||
return t == MAP ? ((CvSet*)node->data.map)->active_count :
|
||||
t == SEQ ? node->data.seq->total : (size_t)!isNone();
|
||||
return t == MAP ? (size_t)((CvSet*)node->data.map)->active_count :
|
||||
t == SEQ ? (size_t)node->data.seq->total : (size_t)!isNone();
|
||||
}
|
||||
|
||||
inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; }
|
||||
|
||||
@@ -861,7 +861,7 @@ cvCreateData( CvArr* arr )
|
||||
if( CV_IS_MAT_CONT( mat->type ))
|
||||
{
|
||||
total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?
|
||||
mat->dim[0].step : total_size);
|
||||
(size_t)mat->dim[0].step : total_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -7,7 +7,8 @@ using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
namespace {
|
||||
void helpParser()
|
||||
#if 0
|
||||
static void helpParser()
|
||||
{
|
||||
printf("\nThe CommandLineParser class is designed for command line arguments parsing\n"
|
||||
"Keys map: \n"
|
||||
@@ -50,6 +51,7 @@ void helpParser()
|
||||
" It also works with 'unsigned int', 'double', and 'float' types \n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
vector<string> split_string(const string& str, const string& delimiters)
|
||||
{
|
||||
|
||||
@@ -209,6 +209,7 @@ void Mat::copyTo( OutputArray _dst ) const
|
||||
int dtype = _dst.type();
|
||||
if( _dst.fixedType() && dtype != type() )
|
||||
{
|
||||
CV_Assert( channels() == CV_MAT_CN(dtype) );
|
||||
convertTo( _dst, dtype );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2811,6 +2811,11 @@ PCA::PCA(InputArray data, InputArray _mean, int flags, int maxComponents)
|
||||
operator()(data, _mean, flags, maxComponents);
|
||||
}
|
||||
|
||||
PCA::PCA(InputArray data, InputArray _mean, int flags, double retainedVariance)
|
||||
{
|
||||
operator()(data, _mean, flags, retainedVariance);
|
||||
}
|
||||
|
||||
PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComponents)
|
||||
{
|
||||
Mat data = _data.getMat(), _mean = __mean.getMat();
|
||||
@@ -2895,6 +2900,109 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp
|
||||
return *this;
|
||||
}
|
||||
|
||||
PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, double retainedVariance)
|
||||
{
|
||||
Mat data = _data.getMat(), _mean = __mean.getMat();
|
||||
int covar_flags = CV_COVAR_SCALE;
|
||||
int i, len, in_count;
|
||||
Size mean_sz;
|
||||
|
||||
CV_Assert( data.channels() == 1 );
|
||||
if( flags & CV_PCA_DATA_AS_COL )
|
||||
{
|
||||
len = data.rows;
|
||||
in_count = data.cols;
|
||||
covar_flags |= CV_COVAR_COLS;
|
||||
mean_sz = Size(1, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = data.cols;
|
||||
in_count = data.rows;
|
||||
covar_flags |= CV_COVAR_ROWS;
|
||||
mean_sz = Size(len, 1);
|
||||
}
|
||||
|
||||
CV_Assert( retainedVariance > 0 && retainedVariance <= 1 );
|
||||
|
||||
int count = std::min(len, in_count);
|
||||
|
||||
// "scrambled" way to compute PCA (when cols(A)>rows(A)):
|
||||
// B = A'A; B*x=b*x; C = AA'; C*y=c*y -> AA'*y=c*y -> A'A*(A'*y)=c*(A'*y) -> c = b, x=A'*y
|
||||
if( len <= in_count )
|
||||
covar_flags |= CV_COVAR_NORMAL;
|
||||
|
||||
int ctype = std::max(CV_32F, data.depth());
|
||||
mean.create( mean_sz, ctype );
|
||||
|
||||
Mat covar( count, count, ctype );
|
||||
|
||||
if( _mean.data )
|
||||
{
|
||||
CV_Assert( _mean.size() == mean_sz );
|
||||
_mean.convertTo(mean, ctype);
|
||||
}
|
||||
|
||||
calcCovarMatrix( data, covar, mean, covar_flags, ctype );
|
||||
eigen( covar, eigenvalues, eigenvectors );
|
||||
|
||||
if( !(covar_flags & CV_COVAR_NORMAL) )
|
||||
{
|
||||
// CV_PCA_DATA_AS_ROW: cols(A)>rows(A). x=A'*y -> x'=y'*A
|
||||
// CV_PCA_DATA_AS_COL: rows(A)>cols(A). x=A''*y -> x'=y'*A'
|
||||
Mat tmp_data, tmp_mean = repeat(mean, data.rows/mean.rows, data.cols/mean.cols);
|
||||
if( data.type() != ctype || tmp_mean.data == mean.data )
|
||||
{
|
||||
data.convertTo( tmp_data, ctype );
|
||||
subtract( tmp_data, tmp_mean, tmp_data );
|
||||
}
|
||||
else
|
||||
{
|
||||
subtract( data, tmp_mean, tmp_mean );
|
||||
tmp_data = tmp_mean;
|
||||
}
|
||||
|
||||
Mat evects1(count, len, ctype);
|
||||
gemm( eigenvectors, tmp_data, 1, Mat(), 0, evects1,
|
||||
(flags & CV_PCA_DATA_AS_COL) ? CV_GEMM_B_T : 0);
|
||||
eigenvectors = evects1;
|
||||
|
||||
// normalize all eigenvectors
|
||||
for( i = 0; i < eigenvectors.rows; i++ )
|
||||
{
|
||||
Mat vec = eigenvectors.row(i);
|
||||
normalize(vec, vec);
|
||||
}
|
||||
}
|
||||
|
||||
// compute the cumulative energy content for each eigenvector
|
||||
Mat g(eigenvalues.size(), ctype);
|
||||
|
||||
for(int ig = 0; ig < g.rows; ig++)
|
||||
{
|
||||
g.at<float>(ig,0) = 0;
|
||||
for(int im = 0; im <= ig; im++)
|
||||
{
|
||||
g.at<float>(ig,0) += eigenvalues.at<float>(im,0);
|
||||
}
|
||||
}
|
||||
|
||||
int L;
|
||||
for(L = 0; L < eigenvalues.rows; L++)
|
||||
{
|
||||
double energy = g.at<float>(L, 0) / g.at<float>(g.rows - 1, 0);
|
||||
if(energy > retainedVariance)
|
||||
break;
|
||||
}
|
||||
|
||||
L = std::max(2, L);
|
||||
|
||||
// use clone() to physically copy the data and thus deallocate the original matrices
|
||||
eigenvalues = eigenvalues.rowRange(0,L).clone();
|
||||
eigenvectors = eigenvectors.rowRange(0,L).clone();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void PCA::project(InputArray _data, OutputArray result) const
|
||||
{
|
||||
@@ -2965,6 +3073,15 @@ void cv::PCACompute(InputArray data, InputOutputArray mean,
|
||||
pca.eigenvectors.copyTo(eigenvectors);
|
||||
}
|
||||
|
||||
void cv::PCACompute(InputArray data, InputOutputArray mean,
|
||||
OutputArray eigenvectors, double retainedVariance)
|
||||
{
|
||||
PCA pca;
|
||||
pca(data, mean, 0, retainedVariance);
|
||||
pca.mean.copyTo(mean);
|
||||
pca.eigenvectors.copyTo(eigenvectors);
|
||||
}
|
||||
|
||||
void cv::PCAProject(InputArray data, InputArray mean,
|
||||
InputArray eigenvectors, OutputArray result)
|
||||
{
|
||||
|
||||
@@ -113,13 +113,13 @@ namespace
|
||||
|
||||
const CvOpenGlFuncTab* g_glFuncTab = 0;
|
||||
|
||||
//#ifdef HAVE_CUDA
|
||||
#if defined HAVE_CUDA || defined HAVE_OPENGL
|
||||
const CvOpenGlFuncTab* glFuncTab()
|
||||
{
|
||||
static EmptyGlFuncTab empty;
|
||||
return g_glFuncTab ? g_glFuncTab : ∅
|
||||
}
|
||||
//#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
CvOpenGlFuncTab::~CvOpenGlFuncTab()
|
||||
|
||||
@@ -2793,7 +2793,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
|
||||
fs->buffer_end = fs->buffer_start + buf_size;
|
||||
if( fs->fmt == CV_STORAGE_FORMAT_XML )
|
||||
{
|
||||
size_t file_size = fs->file ? ftell( fs->file ) : (size_t)0;
|
||||
size_t file_size = fs->file ? (size_t)ftell( fs->file ) : (size_t)0;
|
||||
fs->strstorage = cvCreateChildMemStorage( fs->memstorage );
|
||||
if( !append || file_size == 0 )
|
||||
{
|
||||
|
||||
@@ -178,7 +178,7 @@ struct HWFeatures
|
||||
f.have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
|
||||
f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
|
||||
f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
|
||||
f.have[CV_CPU_AVX] = (cpuid_data[2] & (1<<28)) != 0;
|
||||
f.have[CV_CPU_AVX] = (((cpuid_data[2] & (1<<28)) != 0)&&((cpuid_data[2] & (1<<27)) != 0));//OS uses XSAVE_XRSTORE and CPU support AVX
|
||||
}
|
||||
|
||||
return f;
|
||||
|
||||
@@ -845,7 +845,7 @@ int Core_SeqBaseTest::test_seq_ops( int iters )
|
||||
cvtest::randUni( rng, elem_mat, cvScalarAll(0), cvScalarAll(255) );
|
||||
|
||||
whence = op - 7;
|
||||
pos = whence < 0 ? 0 : whence > 0 ? sseq->count : cvtest::randInt(rng) % (sseq->count+1);
|
||||
pos = whence < 0 ? 0 : whence > 0 ? sseq->count : (int)(cvtest::randInt(rng) % (sseq->count+1));
|
||||
if( whence != 0 )
|
||||
{
|
||||
cvSeqPushMulti( seq, elem, count, whence < 0 );
|
||||
@@ -866,8 +866,8 @@ int Core_SeqBaseTest::test_seq_ops( int iters )
|
||||
if( sseq->count > 0 )
|
||||
{
|
||||
// choose the random element among the added
|
||||
pos = count > 0 ? cvtest::randInt(rng) % count + pos : MAX(pos-1,0);
|
||||
elem2 = cvGetSeqElem( seq, pos );
|
||||
pos = count > 0 ? (int)(cvtest::randInt(rng) % count + pos) : MAX(pos-1,0);
|
||||
elem2 = cvGetSeqElem( seq, pos );
|
||||
CV_TS_SEQ_CHECK_CONDITION( elem2 != 0, "multi push operation doesn't add elements" );
|
||||
CV_TS_SEQ_CHECK_CONDITION( seq->total == sseq->count &&
|
||||
memcmp( elem2, cvTsSimpleSeqElem(sseq,pos), elem_size) == 0,
|
||||
@@ -889,7 +889,7 @@ int Core_SeqBaseTest::test_seq_ops( int iters )
|
||||
count = cvtest::randInt(rng) % (sseq->count+1);
|
||||
whence = op - 10;
|
||||
pos = whence < 0 ? 0 : whence > 0 ? sseq->count - count :
|
||||
cvtest::randInt(rng) % (sseq->count - count + 1);
|
||||
(int)(cvtest::randInt(rng) % (sseq->count - count + 1));
|
||||
|
||||
if( whence != 0 )
|
||||
{
|
||||
|
||||
@@ -297,6 +297,7 @@ protected:
|
||||
prjEps, backPrjEps,
|
||||
evalEps, evecEps;
|
||||
int maxComponents = 100;
|
||||
double retainedVariance = 0.95;
|
||||
Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
|
||||
RNG& rng = ts->get_rng();
|
||||
|
||||
@@ -423,9 +424,33 @@ protected:
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 3. check C++ PCA w/retainedVariance
|
||||
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, retainedVariance );
|
||||
diffPrjEps = 1, diffBackPrjEps = 1;
|
||||
Mat rvPrjTestPoints = cPCA.project(rTestPoints.t());
|
||||
|
||||
if( cPCA.eigenvectors.rows > maxComponents)
|
||||
err = norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 );
|
||||
else
|
||||
err = norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), CV_RELATIVE_L2 );
|
||||
|
||||
if( err > diffPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f\n", err );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
err = norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), CV_RELATIVE_L2 );
|
||||
if( err > diffBackPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f\n", err );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CHECK_C
|
||||
// 3. check C PCA & ROW
|
||||
// 4. check C PCA & ROW
|
||||
_points = rPoints;
|
||||
_testPoints = rTestPoints;
|
||||
_avg = avg;
|
||||
@@ -455,7 +480,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. check C PCA & COL
|
||||
// 5. check C PCA & COL
|
||||
_points = cPoints;
|
||||
_testPoints = cTestPoints;
|
||||
avg = avg.t(); _avg = avg;
|
||||
@@ -871,4 +896,4 @@ TEST(Core_Mat, reshape_1942)
|
||||
cn = M.channels();
|
||||
);
|
||||
ASSERT_EQ(1, cn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,6 +766,19 @@ bool CV_OperationsTest::TestTemplateMat()
|
||||
Mat c = (a*b.t()).t();
|
||||
CV_Assert( norm(c, CV_L1) == 4. );
|
||||
}
|
||||
|
||||
bool badarg_catched = false;
|
||||
try
|
||||
{
|
||||
Mat m1 = Mat::zeros(1, 10, CV_8UC1);
|
||||
Mat m2 = Mat::zeros(10, 10, CV_8UC3);
|
||||
m1.copyTo(m2.row(1));
|
||||
}
|
||||
catch(const Exception& e)
|
||||
{
|
||||
badarg_catched = true;
|
||||
}
|
||||
CV_Assert( badarg_catched );
|
||||
}
|
||||
catch (const test_excep& e)
|
||||
{
|
||||
|
||||
@@ -168,7 +168,7 @@ void Core_RandTest::run( int )
|
||||
int sz = 0, dsz = 0, slice;
|
||||
for( slice = 0; slice < maxSlice; slice++, sz += dsz )
|
||||
{
|
||||
dsz = slice+1 < maxSlice ? cvtest::randInt(rng) % (SZ - sz + 1) : SZ - sz;
|
||||
dsz = slice+1 < maxSlice ? (int)(cvtest::randInt(rng) % (SZ - sz + 1)) : SZ - sz;
|
||||
Mat aslice = arr[k].colRange(sz, sz + dsz);
|
||||
tested_rng.fill(aslice, dist_type, A, B);
|
||||
}
|
||||
|
||||
@@ -267,6 +267,97 @@ public:
|
||||
static Ptr<Feature2D> create( const string& name );
|
||||
};
|
||||
|
||||
/*!
|
||||
BRISK implementation
|
||||
*/
|
||||
class CV_EXPORTS_W BRISK : public Feature2D
|
||||
{
|
||||
public:
|
||||
CV_WRAP explicit BRISK(int thresh=30, int octaves=3, float patternScale=1.0f);
|
||||
|
||||
virtual ~BRISK();
|
||||
|
||||
// returns the descriptor size in bytes
|
||||
int descriptorSize() const;
|
||||
// returns the descriptor type
|
||||
int descriptorType() const;
|
||||
|
||||
// Compute the BRISK features on an image
|
||||
void operator()(InputArray image, InputArray mask, vector<KeyPoint>& keypoints) const;
|
||||
|
||||
// Compute the BRISK features and descriptors on an image
|
||||
void operator()( InputArray image, InputArray mask, vector<KeyPoint>& keypoints,
|
||||
OutputArray descriptors, bool useProvidedKeypoints=false ) const;
|
||||
|
||||
AlgorithmInfo* info() const;
|
||||
|
||||
// custom setup
|
||||
CV_WRAP explicit BRISK(std::vector<float> &radiusList, std::vector<int> &numberList,
|
||||
float dMax=5.85f, float dMin=8.2f, std::vector<int> indexChange=std::vector<int>());
|
||||
|
||||
// call this to generate the kernel:
|
||||
// circle of radius r (pixels), with n points;
|
||||
// short pairings with dMax, long pairings with dMin
|
||||
CV_WRAP void generateKernel(std::vector<float> &radiusList,
|
||||
std::vector<int> &numberList, float dMax=5.85f, float dMin=8.2f,
|
||||
std::vector<int> indexChange=std::vector<int>());
|
||||
|
||||
protected:
|
||||
|
||||
void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
||||
void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
||||
|
||||
void computeKeypointsNoOrientation(InputArray image, InputArray mask, vector<KeyPoint>& keypoints) const;
|
||||
void computeDescriptorsAndOrOrientation(InputArray image, InputArray mask, vector<KeyPoint>& keypoints,
|
||||
OutputArray descriptors, bool doDescriptors, bool doOrientation,
|
||||
bool useProvidedKeypoints) const;
|
||||
|
||||
// Feature parameters
|
||||
CV_PROP_RW int threshold;
|
||||
CV_PROP_RW int octaves;
|
||||
|
||||
// some helper structures for the Brisk pattern representation
|
||||
struct BriskPatternPoint{
|
||||
float x; // x coordinate relative to center
|
||||
float y; // x coordinate relative to center
|
||||
float sigma; // Gaussian smoothing sigma
|
||||
};
|
||||
struct BriskShortPair{
|
||||
unsigned int i; // index of the first pattern point
|
||||
unsigned int j; // index of other pattern point
|
||||
};
|
||||
struct BriskLongPair{
|
||||
unsigned int i; // index of the first pattern point
|
||||
unsigned int j; // index of other pattern point
|
||||
int weighted_dx; // 1024.0/dx
|
||||
int weighted_dy; // 1024.0/dy
|
||||
};
|
||||
inline int smoothedIntensity(const cv::Mat& image,
|
||||
const cv::Mat& integral,const float key_x,
|
||||
const float key_y, const unsigned int scale,
|
||||
const unsigned int rot, const unsigned int point) const;
|
||||
// pattern properties
|
||||
BriskPatternPoint* patternPoints_; //[i][rotation][scale]
|
||||
unsigned int points_; // total number of collocation points
|
||||
float* scaleList_; // lists the scaling per scale index [scale]
|
||||
unsigned int* sizeList_; // lists the total pattern size per scale index [scale]
|
||||
static const unsigned int scales_; // scales discretization
|
||||
static const float scalerange_; // span of sizes 40->4 Octaves - else, this needs to be adjusted...
|
||||
static const unsigned int n_rot_; // discretization of the rotation look-up
|
||||
|
||||
// pairs
|
||||
int strings_; // number of uchars the descriptor consists of
|
||||
float dMax_; // short pair maximum distance
|
||||
float dMin_; // long pair maximum distance
|
||||
BriskShortPair* shortPairs_; // d<_dMax
|
||||
BriskLongPair* longPairs_; // d>_dMin
|
||||
unsigned int noShortPairs_; // number of shortParis
|
||||
unsigned int noLongPairs_; // number of longParis
|
||||
|
||||
// general
|
||||
static const float basicSize_;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
ORB implementation.
|
||||
@@ -473,7 +564,10 @@ protected:
|
||||
|
||||
//! detects corners using FAST algorithm by E. Rosten
|
||||
CV_EXPORTS void FAST( InputArray image, CV_OUT vector<KeyPoint>& keypoints,
|
||||
int threshold, bool nonmaxSupression=true, int type = 2 );
|
||||
int threshold, bool nonmaxSupression=true );
|
||||
|
||||
CV_EXPORTS void FAST( InputArray image, CV_OUT vector<KeyPoint>& keypoints,
|
||||
int threshold, bool nonmaxSupression, int type );
|
||||
|
||||
class CV_EXPORTS_W FastFeatureDetector : public FeatureDetector
|
||||
{
|
||||
|
||||
Executable
+2237
File diff suppressed because it is too large
Load Diff
@@ -42,335 +42,11 @@ The references are:
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "fast_score.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static void makeOffsets(int pixel[], int row_stride, int patternSize)
|
||||
{
|
||||
switch(patternSize) {
|
||||
case 16:
|
||||
pixel[0] = 0 + row_stride * 3;
|
||||
pixel[1] = 1 + row_stride * 3;
|
||||
pixel[2] = 2 + row_stride * 2;
|
||||
pixel[3] = 3 + row_stride * 1;
|
||||
pixel[4] = 3 + row_stride * 0;
|
||||
pixel[5] = 3 + row_stride * -1;
|
||||
pixel[6] = 2 + row_stride * -2;
|
||||
pixel[7] = 1 + row_stride * -3;
|
||||
pixel[8] = 0 + row_stride * -3;
|
||||
pixel[9] = -1 + row_stride * -3;
|
||||
pixel[10] = -2 + row_stride * -2;
|
||||
pixel[11] = -3 + row_stride * -1;
|
||||
pixel[12] = -3 + row_stride * 0;
|
||||
pixel[13] = -3 + row_stride * 1;
|
||||
pixel[14] = -2 + row_stride * 2;
|
||||
pixel[15] = -1 + row_stride * 3;
|
||||
break;
|
||||
case 12:
|
||||
pixel[0] = 0 + row_stride * 2;
|
||||
pixel[1] = 1 + row_stride * 2;
|
||||
pixel[2] = 2 + row_stride * 1;
|
||||
pixel[3] = 2 + row_stride * 0;
|
||||
pixel[4] = 2 + row_stride * -1;
|
||||
pixel[5] = 1 + row_stride * -2;
|
||||
pixel[6] = 0 + row_stride * -2;
|
||||
pixel[7] = -1 + row_stride * -2;
|
||||
pixel[8] = -2 + row_stride * -1;
|
||||
pixel[9] = -2 + row_stride * 0;
|
||||
pixel[10] = -2 + row_stride * 1;
|
||||
pixel[11] = -1 + row_stride * 2;
|
||||
break;
|
||||
case 8:
|
||||
pixel[0] = 0 + row_stride * 1;
|
||||
pixel[1] = 1 + row_stride * 1;
|
||||
pixel[2] = 1 + row_stride * 0;
|
||||
pixel[3] = 1 + row_stride * -1;
|
||||
pixel[4] = 0 + row_stride * -1;
|
||||
pixel[5] = -1 + row_stride * -1;
|
||||
pixel[6] = 0 + row_stride * 0;
|
||||
pixel[7] = 1 + row_stride * 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*static void testCorner(const uchar* ptr, const int pixel[], int K, int N, int threshold) {
|
||||
// check that with the computed "threshold" the pixel is still a corner
|
||||
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
|
||||
for( int delta = 0; delta <= 1; delta++ )
|
||||
{
|
||||
int v0 = std::min(ptr[0] + threshold + delta, 255);
|
||||
int v1 = std::max(ptr[0] - threshold - delta, 0);
|
||||
int c0 = 0, c1 = 0;
|
||||
|
||||
for( int k = 0; k < N; k++ )
|
||||
{
|
||||
int x = ptr[pixel[k]];
|
||||
if(x > v0)
|
||||
{
|
||||
if( ++c0 > K )
|
||||
break;
|
||||
c1 = 0;
|
||||
}
|
||||
else if( x < v1 )
|
||||
{
|
||||
if( ++c1 > K )
|
||||
break;
|
||||
c0 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c0 = c1 = 0;
|
||||
}
|
||||
}
|
||||
CV_Assert( (delta == 0 && std::max(c0, c1) > K) ||
|
||||
(delta == 1 && std::max(c0, c1) <= K) );
|
||||
}
|
||||
}*/
|
||||
|
||||
template<int patternSize>
|
||||
int cornerScore(const uchar* ptr, const int pixel[], int threshold);
|
||||
|
||||
template<>
|
||||
int cornerScore<16>(const uchar* ptr, const int pixel[], int threshold)
|
||||
{
|
||||
const int K = 8, N = 16 + K + 1;
|
||||
int k, v = ptr[0];
|
||||
short d[N];
|
||||
for( k = 0; k < N; k++ )
|
||||
d[k] = (short)(v - ptr[pixel[k]]);
|
||||
|
||||
#if CV_SSE2
|
||||
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||
for( k = 0; k < 16; k += 8 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||
__m128i a = _mm_min_epi16(v0, v1);
|
||||
__m128i b = _mm_max_epi16(v0, v1);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+6));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+7));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+8));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+9));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
}
|
||||
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||
#else
|
||||
int a0 = threshold;
|
||||
for( k = 0; k < 16; k += 2 )
|
||||
{
|
||||
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||
a = std::min(a, (int)d[k+3]);
|
||||
if( a <= a0 )
|
||||
continue;
|
||||
a = std::min(a, (int)d[k+4]);
|
||||
a = std::min(a, (int)d[k+5]);
|
||||
a = std::min(a, (int)d[k+6]);
|
||||
a = std::min(a, (int)d[k+7]);
|
||||
a = std::min(a, (int)d[k+8]);
|
||||
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||
a0 = std::max(a0, std::min(a, (int)d[k+9]));
|
||||
}
|
||||
|
||||
int b0 = -a0;
|
||||
for( k = 0; k < 16; k += 2 )
|
||||
{
|
||||
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||
b = std::max(b, (int)d[k+3]);
|
||||
b = std::max(b, (int)d[k+4]);
|
||||
b = std::max(b, (int)d[k+5]);
|
||||
if( b >= b0 )
|
||||
continue;
|
||||
b = std::max(b, (int)d[k+6]);
|
||||
b = std::max(b, (int)d[k+7]);
|
||||
b = std::max(b, (int)d[k+8]);
|
||||
|
||||
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||
b0 = std::min(b0, std::max(b, (int)d[k+9]));
|
||||
}
|
||||
|
||||
threshold = -b0-1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
testCorner(ptr, pixel, K, N, threshold);
|
||||
#endif
|
||||
return threshold;
|
||||
}
|
||||
|
||||
template<>
|
||||
int cornerScore<12>(const uchar* ptr, const int pixel[], int threshold)
|
||||
{
|
||||
const int K = 6, N = 12 + K + 1;
|
||||
int k, v = ptr[0];
|
||||
short d[N];
|
||||
for( k = 0; k < N; k++ )
|
||||
d[k] = (short)(v - ptr[pixel[k]]);
|
||||
|
||||
#if CV_SSE2
|
||||
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||
for( k = 0; k < 16; k += 8 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||
__m128i a = _mm_min_epi16(v0, v1);
|
||||
__m128i b = _mm_max_epi16(v0, v1);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+6));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+7));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
}
|
||||
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||
#else
|
||||
int a0 = threshold;
|
||||
for( k = 0; k < 12; k += 2 )
|
||||
{
|
||||
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||
if( a <= a0 )
|
||||
continue;
|
||||
a = std::min(a, (int)d[k+3]);
|
||||
a = std::min(a, (int)d[k+4]);
|
||||
a = std::min(a, (int)d[k+5]);
|
||||
a = std::min(a, (int)d[k+6]);
|
||||
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||
a0 = std::max(a0, std::min(a, (int)d[k+7]));
|
||||
}
|
||||
|
||||
int b0 = -a0;
|
||||
for( k = 0; k < 12; k += 2 )
|
||||
{
|
||||
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||
b = std::max(b, (int)d[k+3]);
|
||||
b = std::max(b, (int)d[k+4]);
|
||||
if( b >= b0 )
|
||||
continue;
|
||||
b = std::max(b, (int)d[k+5]);
|
||||
b = std::max(b, (int)d[k+6]);
|
||||
|
||||
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||
b0 = std::min(b0, std::max(b, (int)d[k+7]));
|
||||
}
|
||||
|
||||
threshold = -b0-1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
testCorner(ptr, pixel, K, N, threshold);
|
||||
#endif
|
||||
return threshold;
|
||||
}
|
||||
|
||||
template<>
|
||||
int cornerScore<8>(const uchar* ptr, const int pixel[], int threshold)
|
||||
{
|
||||
const int K = 4, N = 8 + K + 1;
|
||||
int k, v = ptr[0];
|
||||
short d[N];
|
||||
for( k = 0; k < N; k++ )
|
||||
d[k] = (short)(v - ptr[pixel[k]]);
|
||||
|
||||
#if CV_SSE2
|
||||
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||
for( k = 0; k < 16; k += 8 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||
__m128i a = _mm_min_epi16(v0, v1);
|
||||
__m128i b = _mm_max_epi16(v0, v1);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
}
|
||||
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||
#else
|
||||
int a0 = threshold;
|
||||
for( k = 0; k < 8; k += 2 )
|
||||
{
|
||||
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||
if( a <= a0 )
|
||||
continue;
|
||||
a = std::min(a, (int)d[k+3]);
|
||||
a = std::min(a, (int)d[k+4]);
|
||||
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||
a0 = std::max(a0, std::min(a, (int)d[k+5]));
|
||||
}
|
||||
|
||||
int b0 = -a0;
|
||||
for( k = 0; k < 8; k += 2 )
|
||||
{
|
||||
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||
b = std::max(b, (int)d[k+3]);
|
||||
if( b >= b0 )
|
||||
continue;
|
||||
b = std::max(b, (int)d[k+4]);
|
||||
|
||||
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||
b0 = std::min(b0, std::max(b, (int)d[k+5]));
|
||||
}
|
||||
|
||||
threshold = -b0-1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
testCorner(ptr, pixel, K, N, threshold);
|
||||
#endif
|
||||
return threshold;
|
||||
}
|
||||
|
||||
template<int patternSize>
|
||||
void FAST_t(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
|
||||
{
|
||||
@@ -381,8 +57,6 @@ void FAST_t(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bo
|
||||
#endif
|
||||
int i, j, k, pixel[25];
|
||||
makeOffsets(pixel, (int)img.step, patternSize);
|
||||
for(k = patternSize; k < 25; k++)
|
||||
pixel[k] = pixel[k - patternSize];
|
||||
|
||||
keypoints.clear();
|
||||
|
||||
@@ -578,6 +252,11 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
|
||||
{
|
||||
FAST(_img, keypoints, threshold, nonmax_suppression, FastFeatureDetector::TYPE_9_16);
|
||||
}
|
||||
/*
|
||||
* FastFeatureDetector
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
/* This is FAST corner detector, contributed to OpenCV by the author, Edward Rosten.
|
||||
Below is the original copyright and the references */
|
||||
|
||||
/*
|
||||
Copyright (c) 2006, 2008 Edward Rosten
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
*Redistributions 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.
|
||||
|
||||
*Neither the name of the University of Cambridge nor the names of
|
||||
its contributors may 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 COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
The references are:
|
||||
* Machine learning for high-speed corner detection,
|
||||
E. Rosten and T. Drummond, ECCV 2006
|
||||
* Faster and better: A machine learning approach to corner detection
|
||||
E. Rosten, R. Porter and T. Drummond, PAMI, 2009
|
||||
*/
|
||||
|
||||
#include "fast_score.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
void makeOffsets(int pixel[25], int row_stride, int patternSize)
|
||||
{
|
||||
CV_Assert(pixel != 0);
|
||||
switch(patternSize) {
|
||||
case 16:
|
||||
pixel[0] = 0 + row_stride * 3;
|
||||
pixel[1] = 1 + row_stride * 3;
|
||||
pixel[2] = 2 + row_stride * 2;
|
||||
pixel[3] = 3 + row_stride * 1;
|
||||
pixel[4] = 3 + row_stride * 0;
|
||||
pixel[5] = 3 + row_stride * -1;
|
||||
pixel[6] = 2 + row_stride * -2;
|
||||
pixel[7] = 1 + row_stride * -3;
|
||||
pixel[8] = 0 + row_stride * -3;
|
||||
pixel[9] = -1 + row_stride * -3;
|
||||
pixel[10] = -2 + row_stride * -2;
|
||||
pixel[11] = -3 + row_stride * -1;
|
||||
pixel[12] = -3 + row_stride * 0;
|
||||
pixel[13] = -3 + row_stride * 1;
|
||||
pixel[14] = -2 + row_stride * 2;
|
||||
pixel[15] = -1 + row_stride * 3;
|
||||
break;
|
||||
case 12:
|
||||
pixel[0] = 0 + row_stride * 2;
|
||||
pixel[1] = 1 + row_stride * 2;
|
||||
pixel[2] = 2 + row_stride * 1;
|
||||
pixel[3] = 2 + row_stride * 0;
|
||||
pixel[4] = 2 + row_stride * -1;
|
||||
pixel[5] = 1 + row_stride * -2;
|
||||
pixel[6] = 0 + row_stride * -2;
|
||||
pixel[7] = -1 + row_stride * -2;
|
||||
pixel[8] = -2 + row_stride * -1;
|
||||
pixel[9] = -2 + row_stride * 0;
|
||||
pixel[10] = -2 + row_stride * 1;
|
||||
pixel[11] = -1 + row_stride * 2;
|
||||
break;
|
||||
case 8:
|
||||
pixel[0] = 0 + row_stride * 1;
|
||||
pixel[1] = 1 + row_stride * 1;
|
||||
pixel[2] = 1 + row_stride * 0;
|
||||
pixel[3] = 1 + row_stride * -1;
|
||||
pixel[4] = 0 + row_stride * -1;
|
||||
pixel[5] = -1 + row_stride * -1;
|
||||
pixel[6] = 0 + row_stride * 0;
|
||||
pixel[7] = 1 + row_stride * 1;
|
||||
break;
|
||||
}
|
||||
for(int k = patternSize; k < 25; k++)
|
||||
pixel[k] = pixel[k - patternSize];
|
||||
}
|
||||
|
||||
/*static void testCorner(const uchar* ptr, const int pixel[], int K, int N, int threshold) {
|
||||
// check that with the computed "threshold" the pixel is still a corner
|
||||
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
|
||||
for( int delta = 0; delta <= 1; delta++ )
|
||||
{
|
||||
int v0 = std::min(ptr[0] + threshold + delta, 255);
|
||||
int v1 = std::max(ptr[0] - threshold - delta, 0);
|
||||
int c0 = 0, c1 = 0;
|
||||
|
||||
for( int k = 0; k < N; k++ )
|
||||
{
|
||||
int x = ptr[pixel[k]];
|
||||
if(x > v0)
|
||||
{
|
||||
if( ++c0 > K )
|
||||
break;
|
||||
c1 = 0;
|
||||
}
|
||||
else if( x < v1 )
|
||||
{
|
||||
if( ++c1 > K )
|
||||
break;
|
||||
c0 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c0 = c1 = 0;
|
||||
}
|
||||
}
|
||||
CV_Assert( (delta == 0 && std::max(c0, c1) > K) ||
|
||||
(delta == 1 && std::max(c0, c1) <= K) );
|
||||
}
|
||||
}*/
|
||||
|
||||
template<>
|
||||
int cornerScore<16>(const uchar* ptr, const int pixel[], int threshold)
|
||||
{
|
||||
const int K = 8, N = 16 + K + 1;
|
||||
int k, v = ptr[0];
|
||||
short d[N];
|
||||
for( k = 0; k < N; k++ )
|
||||
d[k] = (short)(v - ptr[pixel[k]]);
|
||||
|
||||
#if CV_SSE2
|
||||
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||
for( k = 0; k < 16; k += 8 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||
__m128i a = _mm_min_epi16(v0, v1);
|
||||
__m128i b = _mm_max_epi16(v0, v1);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+6));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+7));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+8));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+9));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
}
|
||||
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||
#else
|
||||
int a0 = threshold;
|
||||
for( k = 0; k < 16; k += 2 )
|
||||
{
|
||||
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||
a = std::min(a, (int)d[k+3]);
|
||||
if( a <= a0 )
|
||||
continue;
|
||||
a = std::min(a, (int)d[k+4]);
|
||||
a = std::min(a, (int)d[k+5]);
|
||||
a = std::min(a, (int)d[k+6]);
|
||||
a = std::min(a, (int)d[k+7]);
|
||||
a = std::min(a, (int)d[k+8]);
|
||||
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||
a0 = std::max(a0, std::min(a, (int)d[k+9]));
|
||||
}
|
||||
|
||||
int b0 = -a0;
|
||||
for( k = 0; k < 16; k += 2 )
|
||||
{
|
||||
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||
b = std::max(b, (int)d[k+3]);
|
||||
b = std::max(b, (int)d[k+4]);
|
||||
b = std::max(b, (int)d[k+5]);
|
||||
if( b >= b0 )
|
||||
continue;
|
||||
b = std::max(b, (int)d[k+6]);
|
||||
b = std::max(b, (int)d[k+7]);
|
||||
b = std::max(b, (int)d[k+8]);
|
||||
|
||||
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||
b0 = std::min(b0, std::max(b, (int)d[k+9]));
|
||||
}
|
||||
|
||||
threshold = -b0-1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
testCorner(ptr, pixel, K, N, threshold);
|
||||
#endif
|
||||
return threshold;
|
||||
}
|
||||
|
||||
template<>
|
||||
int cornerScore<12>(const uchar* ptr, const int pixel[], int threshold)
|
||||
{
|
||||
const int K = 6, N = 12 + K + 1;
|
||||
int k, v = ptr[0];
|
||||
short d[N];
|
||||
for( k = 0; k < N; k++ )
|
||||
d[k] = (short)(v - ptr[pixel[k]]);
|
||||
|
||||
#if CV_SSE2
|
||||
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||
for( k = 0; k < 16; k += 8 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||
__m128i a = _mm_min_epi16(v0, v1);
|
||||
__m128i b = _mm_max_epi16(v0, v1);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+6));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+7));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
}
|
||||
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||
#else
|
||||
int a0 = threshold;
|
||||
for( k = 0; k < 12; k += 2 )
|
||||
{
|
||||
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||
if( a <= a0 )
|
||||
continue;
|
||||
a = std::min(a, (int)d[k+3]);
|
||||
a = std::min(a, (int)d[k+4]);
|
||||
a = std::min(a, (int)d[k+5]);
|
||||
a = std::min(a, (int)d[k+6]);
|
||||
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||
a0 = std::max(a0, std::min(a, (int)d[k+7]));
|
||||
}
|
||||
|
||||
int b0 = -a0;
|
||||
for( k = 0; k < 12; k += 2 )
|
||||
{
|
||||
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||
b = std::max(b, (int)d[k+3]);
|
||||
b = std::max(b, (int)d[k+4]);
|
||||
if( b >= b0 )
|
||||
continue;
|
||||
b = std::max(b, (int)d[k+5]);
|
||||
b = std::max(b, (int)d[k+6]);
|
||||
|
||||
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||
b0 = std::min(b0, std::max(b, (int)d[k+7]));
|
||||
}
|
||||
|
||||
threshold = -b0-1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
testCorner(ptr, pixel, K, N, threshold);
|
||||
#endif
|
||||
return threshold;
|
||||
}
|
||||
|
||||
template<>
|
||||
int cornerScore<8>(const uchar* ptr, const int pixel[], int threshold)
|
||||
{
|
||||
const int K = 4, N = 8 + K + 1;
|
||||
int k, v = ptr[0];
|
||||
short d[N];
|
||||
for( k = 0; k < N; k++ )
|
||||
d[k] = (short)(v - ptr[pixel[k]]);
|
||||
|
||||
#if CV_SSE2
|
||||
__m128i q0 = _mm_set1_epi16(-1000), q1 = _mm_set1_epi16(1000);
|
||||
for( k = 0; k < 16; k += 8 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128((__m128i*)(d+k+1));
|
||||
__m128i v1 = _mm_loadu_si128((__m128i*)(d+k+2));
|
||||
__m128i a = _mm_min_epi16(v0, v1);
|
||||
__m128i b = _mm_max_epi16(v0, v1);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+3));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+4));
|
||||
a = _mm_min_epi16(a, v0);
|
||||
b = _mm_max_epi16(b, v0);
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
v0 = _mm_loadu_si128((__m128i*)(d+k+5));
|
||||
q0 = _mm_max_epi16(q0, _mm_min_epi16(a, v0));
|
||||
q1 = _mm_min_epi16(q1, _mm_max_epi16(b, v0));
|
||||
}
|
||||
q0 = _mm_max_epi16(q0, _mm_sub_epi16(_mm_setzero_si128(), q1));
|
||||
q0 = _mm_max_epi16(q0, _mm_unpackhi_epi64(q0, q0));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 4));
|
||||
q0 = _mm_max_epi16(q0, _mm_srli_si128(q0, 2));
|
||||
threshold = (short)_mm_cvtsi128_si32(q0) - 1;
|
||||
#else
|
||||
int a0 = threshold;
|
||||
for( k = 0; k < 8; k += 2 )
|
||||
{
|
||||
int a = std::min((int)d[k+1], (int)d[k+2]);
|
||||
if( a <= a0 )
|
||||
continue;
|
||||
a = std::min(a, (int)d[k+3]);
|
||||
a = std::min(a, (int)d[k+4]);
|
||||
a0 = std::max(a0, std::min(a, (int)d[k]));
|
||||
a0 = std::max(a0, std::min(a, (int)d[k+5]));
|
||||
}
|
||||
|
||||
int b0 = -a0;
|
||||
for( k = 0; k < 8; k += 2 )
|
||||
{
|
||||
int b = std::max((int)d[k+1], (int)d[k+2]);
|
||||
b = std::max(b, (int)d[k+3]);
|
||||
if( b >= b0 )
|
||||
continue;
|
||||
b = std::max(b, (int)d[k+4]);
|
||||
|
||||
b0 = std::min(b0, std::max(b, (int)d[k]));
|
||||
b0 = std::min(b0, std::max(b, (int)d[k+5]));
|
||||
}
|
||||
|
||||
threshold = -b0-1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
testCorner(ptr, pixel, K, N, threshold);
|
||||
#endif
|
||||
return threshold;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* This is FAST corner detector, contributed to OpenCV by the author, Edward Rosten.
|
||||
Below is the original copyright and the references */
|
||||
|
||||
/*
|
||||
Copyright (c) 2006, 2008 Edward Rosten
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
*Redistributions 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.
|
||||
|
||||
*Neither the name of the University of Cambridge nor the names of
|
||||
its contributors may 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 COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
The references are:
|
||||
* Machine learning for high-speed corner detection,
|
||||
E. Rosten and T. Drummond, ECCV 2006
|
||||
* Faster and better: A machine learning approach to corner detection
|
||||
E. Rosten, R. Porter and T. Drummond, PAMI, 2009
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_FEATURES_2D_FAST_HPP__
|
||||
#define __OPENCV_FEATURES_2D_FAST_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
void makeOffsets(int pixel[25], int row_stride, int patternSize);
|
||||
|
||||
//static void testCorner(const uchar* ptr, const int pixel[], int K, int N, int threshold);
|
||||
|
||||
template<int patternSize>
|
||||
int cornerScore(const uchar* ptr, const int pixel[], int threshold);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -51,6 +51,12 @@ using namespace cv;
|
||||
Otherwise, linker may throw away some seemingly unused stuff.
|
||||
*/
|
||||
|
||||
CV_INIT_ALGORITHM(BRISK, "Feature2D.BRISK",
|
||||
obj.info()->addParam(obj, "thres", obj.threshold);
|
||||
obj.info()->addParam(obj, "octaves", obj.octaves));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(BriefDescriptorExtractor, "Feature2D.BRIEF",
|
||||
obj.info()->addParam(obj, "bytes", obj.bytes_));
|
||||
|
||||
@@ -154,6 +160,7 @@ bool cv::initModule_features2d(void)
|
||||
{
|
||||
bool all = true;
|
||||
all &= !BriefDescriptorExtractor_info_auto.name().empty();
|
||||
all &= !BRISK_info_auto.name().empty();
|
||||
all &= !FastFeatureDetector_info_auto.name().empty();
|
||||
all &= !StarDetector_info_auto.name().empty();
|
||||
all &= !MSER_info_auto.name().empty();
|
||||
|
||||
@@ -455,7 +455,6 @@ uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
|
||||
const float radius = FreakPoint.sigma;
|
||||
|
||||
// calculate output:
|
||||
int ret_val;
|
||||
if( radius < 0.5 ) {
|
||||
// interpolation multipliers:
|
||||
const int r_x = static_cast<int>((xf-x)*1024);
|
||||
@@ -463,6 +462,7 @@ uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
|
||||
const int r_x_1 = (1024-r_x);
|
||||
const int r_y_1 = (1024-r_y);
|
||||
uchar* ptr = image.data+x+y*imagecols;
|
||||
unsigned int ret_val;
|
||||
// linear interpolation:
|
||||
ret_val = (r_x_1*r_y_1*int(*ptr));
|
||||
ptr++;
|
||||
@@ -471,7 +471,9 @@ uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
|
||||
ret_val += (r_x*r_y*int(*ptr));
|
||||
ptr--;
|
||||
ret_val += (r_x_1*r_y*int(*ptr));
|
||||
return static_cast<uchar>((ret_val+512)/1024);
|
||||
//return the rounded mean
|
||||
ret_val += 2 * 1024 * 1024;
|
||||
return static_cast<uchar>(ret_val / (4 * 1024 * 1024));
|
||||
}
|
||||
|
||||
// expected case:
|
||||
@@ -481,6 +483,7 @@ uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
|
||||
const int y_top = int(yf-radius+0.5);
|
||||
const int x_right = int(xf+radius+1.5);//integral image is 1px wider
|
||||
const int y_bottom = int(yf+radius+1.5);//integral image is 1px higher
|
||||
int ret_val;
|
||||
|
||||
ret_val = integral.at<int>(y_bottom,x_right);//bottom right corner
|
||||
ret_val -= integral.at<int>(y_bottom,x_left);
|
||||
|
||||
@@ -10,11 +10,10 @@
|
||||
// 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) 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:
|
||||
//
|
||||
@@ -23,7 +22,7 @@
|
||||
//
|
||||
// * 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 GpuMaterials provided with the distribution.
|
||||
// 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.
|
||||
@@ -41,52 +40,56 @@
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if defined WIN32 || defined _WIN32
|
||||
#include <Windows.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
class CriticalSection
|
||||
using namespace cv;
|
||||
|
||||
class CV_BRISKTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CriticalSection();
|
||||
~CriticalSection();
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
void Lock();
|
||||
void Unlock();
|
||||
CV_BRISKTest();
|
||||
~CV_BRISKTest();
|
||||
protected:
|
||||
#if defined WIN32 || defined _WIN32
|
||||
CRITICAL_SECTION m_CritSec;
|
||||
#else
|
||||
pthread_mutex_t m_CritSec;
|
||||
#endif
|
||||
void run(int);
|
||||
};
|
||||
|
||||
class myAutoLock
|
||||
CV_BRISKTest::CV_BRISKTest() {}
|
||||
CV_BRISKTest::~CV_BRISKTest() {}
|
||||
|
||||
void CV_BRISKTest::run( int )
|
||||
{
|
||||
public:
|
||||
explicit myAutoLock(CriticalSection *lock)
|
||||
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.jpg");
|
||||
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.jpg");
|
||||
|
||||
if (image1.empty() || image2.empty())
|
||||
{
|
||||
m_lock = lock;
|
||||
m_lock->Lock();
|
||||
};
|
||||
~myAutoLock()
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat gray1, gray2;
|
||||
cvtColor(image1, gray1, CV_BGR2GRAY);
|
||||
cvtColor(image2, gray2, CV_BGR2GRAY);
|
||||
|
||||
Ptr<FeatureDetector> detector = Algorithm::create<FeatureDetector>("Feature2D.BRISK");
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
vector<KeyPoint> keypoints2;
|
||||
detector->detect(image1, keypoints1);
|
||||
detector->detect(image2, keypoints2);
|
||||
|
||||
for(size_t i = 0; i < keypoints1.size(); ++i)
|
||||
{
|
||||
m_lock->Unlock();
|
||||
};
|
||||
protected:
|
||||
CriticalSection *m_lock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const KeyPoint& kp = keypoints1[i];
|
||||
ASSERT_NE(kp.angle, -1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < keypoints2.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints2[i];
|
||||
ASSERT_NE(kp.angle, -1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Features2d_BRISK, regression) { CV_BRISKTest test; test.safe_run(); }
|
||||
|
||||
@@ -301,6 +301,13 @@ private:
|
||||
* Tests registrations *
|
||||
\****************************************************************************************/
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_BRISK, regression )
|
||||
{
|
||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-brisk", (CV_DescriptorExtractorTest<Hamming>::DistanceType)2.f,
|
||||
DescriptorExtractor::create("BRISK") );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_ORB, regression )
|
||||
{
|
||||
// TODO adjust the parameters below
|
||||
|
||||
@@ -247,6 +247,12 @@ void CV_FeatureDetectorTest::run( int /*start_from*/ )
|
||||
* Tests registrations *
|
||||
\****************************************************************************************/
|
||||
|
||||
TEST( Features2d_Detector_BRISK, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-brisk", FeatureDetector::create("BRISK") );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_FAST, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-fast", FeatureDetector::create("FAST") );
|
||||
|
||||
@@ -119,6 +119,12 @@ protected:
|
||||
|
||||
// Registration of tests
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_BRISK, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"));
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_FAST, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.FAST"));
|
||||
|
||||
@@ -592,6 +592,15 @@ protected:
|
||||
/*
|
||||
* Detector's rotation invariance check
|
||||
*/
|
||||
|
||||
TEST(Features2d_RotationInvariance_Detector_BRISK, regression)
|
||||
{
|
||||
DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
||||
0.32f,
|
||||
0.81f);
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_RotationInvariance_Detector_ORB, regression)
|
||||
{
|
||||
DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
|
||||
@@ -603,6 +612,16 @@ TEST(Features2d_RotationInvariance_Detector_ORB, regression)
|
||||
/*
|
||||
* Descriptors's rotation invariance check
|
||||
*/
|
||||
|
||||
TEST(Features2d_RotationInvariance_Descriptor_BRISK, regression)
|
||||
{
|
||||
DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
||||
Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
|
||||
NORM_HAMMING,
|
||||
0.99f);
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
|
||||
{
|
||||
DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
|
||||
@@ -625,6 +644,14 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
|
||||
* Detector's scale invariance check
|
||||
*/
|
||||
|
||||
TEST(Features2d_ScaleInvariance_Detector_BRISK, regression)
|
||||
{
|
||||
DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
||||
0.08f,
|
||||
0.54f);
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
//TEST(Features2d_ScaleInvariance_Detector_ORB, regression)
|
||||
//{
|
||||
// DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
|
||||
@@ -637,6 +664,15 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
|
||||
* Descriptor's scale invariance check
|
||||
*/
|
||||
|
||||
//TEST(Features2d_ScaleInvariance_Descriptor_BRISK, regression)
|
||||
//{
|
||||
// DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
||||
// Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
|
||||
// NORM_HAMMING,
|
||||
// 0.99f);
|
||||
// test.safe_run();
|
||||
//}
|
||||
|
||||
//TEST(Features2d_ScaleInvariance_Descriptor_ORB, regression)
|
||||
//{
|
||||
// DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
|
||||
|
||||
@@ -260,8 +260,8 @@ private:
|
||||
* @param k_nn the number of nearest neighbors
|
||||
* @param checked_average used for debugging
|
||||
*/
|
||||
void getNeighbors(const ElementType* vec, bool do_radius, float radius, bool do_k, unsigned int k_nn,
|
||||
float& checked_average)
|
||||
void getNeighbors(const ElementType* vec, bool /*do_radius*/, float radius, bool do_k, unsigned int k_nn,
|
||||
float& /*checked_average*/)
|
||||
{
|
||||
static std::vector<ScoreIndexPair> score_index_heap;
|
||||
|
||||
|
||||
@@ -818,9 +818,57 @@ Performs linear blending of two images.
|
||||
:param result: Destination image.
|
||||
|
||||
:param stream: Stream for the asynchronous version.
|
||||
|
||||
|
||||
gpu::bilateralFilter
|
||||
-------------------
|
||||
Performs bilateral filtering of passed image
|
||||
|
||||
.. ocv:function:: void gpu::bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode, Stream& stream = Stream::Null());
|
||||
|
||||
:param src: Source image. Supports only (channles != 2 && depth() != CV_8S && depth() != CV_32S && depth() != CV_64F).
|
||||
|
||||
:param dst: Destination imagwe.
|
||||
|
||||
:param kernel_size: Kernel window size.
|
||||
|
||||
:param sigma_color: Filter sigma in the color space.
|
||||
|
||||
:param sigma_spatial: Filter sigma in the coordinate space.
|
||||
|
||||
:param borderMode: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now.
|
||||
|
||||
:param stream: Stream for the asynchronous version.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ocv:func:`bilateralFilter`,
|
||||
|
||||
|
||||
gpu::nonLocalMeans
|
||||
-------------------
|
||||
Performs pure non local means denoising without any simplification, and thus it is not fast.
|
||||
|
||||
.. ocv:function:: void nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_widow_size = 11, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null());
|
||||
|
||||
:param src: Source image. Supports only CV_8UC1, CV_8UC3.
|
||||
|
||||
:param dst: Destination imagwe.
|
||||
|
||||
:param h: Filter sigma regulating filter strength for color.
|
||||
|
||||
:param search_widow_size: Size of search window.
|
||||
|
||||
:param block_size: Size of block used for computing weights.
|
||||
|
||||
:param borderMode: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now.
|
||||
|
||||
:param stream: Stream for the asynchronous version.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ocv:func:`fastNlMeansDenoising`
|
||||
|
||||
gpu::alphaComp
|
||||
-------------------
|
||||
Composites two images using alpha opacity values contained in each image.
|
||||
|
||||
@@ -769,6 +769,14 @@ CV_EXPORTS void pyrUp(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::N
|
||||
CV_EXPORTS void blendLinear(const GpuMat& img1, const GpuMat& img2, const GpuMat& weights1, const GpuMat& weights2,
|
||||
GpuMat& result, Stream& stream = Stream::Null());
|
||||
|
||||
//! Performa bilateral filtering of passsed image
|
||||
CV_EXPORTS void bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial,
|
||||
int borderMode = BORDER_DEFAULT, Stream& stream = Stream::Null());
|
||||
|
||||
//! Brute force non-local means algorith (slow but universal)
|
||||
CV_EXPORTS void nonLocalMeans(const GpuMat& src, GpuMat& dst, float h,
|
||||
int search_widow_size = 11, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null());
|
||||
|
||||
|
||||
struct CV_EXPORTS CannyBuf;
|
||||
|
||||
|
||||
@@ -11,7 +11,16 @@ namespace {
|
||||
typedef pair<string, string> pair_string;
|
||||
DEF_PARAM_TEST_1(ImagePair, pair_string);
|
||||
|
||||
PERF_TEST_P(ImagePair, Calib3D_StereoBM, Values(make_pair<string, string>("gpu/perf/aloe.jpg", "gpu/perf/aloeR.jpg")))
|
||||
static pair_string make_string_pair(const string& a, const string& b)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return pair<string, string>(a, b);
|
||||
#else
|
||||
return make_pair<string, string>(a, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
PERF_TEST_P(ImagePair, Calib3D_StereoBM, Values(make_string_pair("gpu/perf/aloe.jpg", "gpu/perf/aloeR.jpg")))
|
||||
{
|
||||
declare.time(5.0);
|
||||
|
||||
@@ -57,7 +66,7 @@ PERF_TEST_P(ImagePair, Calib3D_StereoBM, Values(make_pair<string, string>("gpu/p
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// StereoBeliefPropagation
|
||||
|
||||
PERF_TEST_P(ImagePair, Calib3D_StereoBeliefPropagation, Values(make_pair<string, string>("gpu/stereobp/aloe-L.png", "gpu/stereobp/aloe-R.png")))
|
||||
PERF_TEST_P(ImagePair, Calib3D_StereoBeliefPropagation, Values(make_string_pair("gpu/stereobp/aloe-L.png", "gpu/stereobp/aloe-R.png")))
|
||||
{
|
||||
declare.time(10.0);
|
||||
|
||||
@@ -93,7 +102,7 @@ PERF_TEST_P(ImagePair, Calib3D_StereoBeliefPropagation, Values(make_pair<string,
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// StereoConstantSpaceBP
|
||||
|
||||
PERF_TEST_P(ImagePair, Calib3D_StereoConstantSpaceBP, Values(make_pair<string, string>("gpu/stereobm/aloe-L.png", "gpu/stereobm/aloe-R.png")))
|
||||
PERF_TEST_P(ImagePair, Calib3D_StereoConstantSpaceBP, Values(make_string_pair("gpu/stereobm/aloe-L.png", "gpu/stereobm/aloe-R.png")))
|
||||
{
|
||||
declare.time(10.0);
|
||||
|
||||
@@ -129,7 +138,7 @@ PERF_TEST_P(ImagePair, Calib3D_StereoConstantSpaceBP, Values(make_pair<string, s
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// DisparityBilateralFilter
|
||||
|
||||
PERF_TEST_P(ImagePair, Calib3D_DisparityBilateralFilter, Values(make_pair<string, string>("gpu/stereobm/aloe-L.png", "gpu/stereobm/aloe-disp.png")))
|
||||
PERF_TEST_P(ImagePair, Calib3D_DisparityBilateralFilter, Values(make_string_pair("gpu/stereobm/aloe-L.png", "gpu/stereobm/aloe-disp.png")))
|
||||
{
|
||||
const cv::Mat img = readImage(GetParam().first, cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(img.empty());
|
||||
|
||||
@@ -882,7 +882,7 @@ PERF_TEST_P(Sz_Depth, Core_BitwiseAndMat, Combine(GPU_TYPICAL_MAT_SIZES, Values(
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// BitwiseAndScalar
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseAndScalar, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseAndScalar, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
@@ -963,7 +963,7 @@ PERF_TEST_P(Sz_Depth, Core_BitwiseOrMat, Combine(GPU_TYPICAL_MAT_SIZES, Values(C
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// BitwiseOrScalar
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseOrScalar, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseOrScalar, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
@@ -1044,7 +1044,7 @@ PERF_TEST_P(Sz_Depth, Core_BitwiseXorMat, Combine(GPU_TYPICAL_MAT_SIZES, Values(
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// BitwiseXorScalar
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseXorScalar, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseXorScalar, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
@@ -1085,7 +1085,7 @@ PERF_TEST_P(Sz_Depth_Cn, Core_BitwiseXorScalar, Combine(GPU_TYPICAL_MAT_SIZES, V
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// RShift
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_RShift, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_RShift, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
@@ -1119,7 +1119,7 @@ PERF_TEST_P(Sz_Depth_Cn, Core_RShift, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// LShift
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_LShift, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_LShift, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32S), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
@@ -1461,7 +1461,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Code, cv::Size, MatDepth, int, FlipCode);
|
||||
PERF_TEST_P(Sz_Depth_Cn_Code, Core_Flip, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
ALL_FLIP_CODES))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
@@ -1973,7 +1973,7 @@ PERF_TEST_P(Sz_Norm, Core_NormDiff, Combine(
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_Sum, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4)))
|
||||
GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -2015,7 +2015,7 @@ PERF_TEST_P(Sz_Depth_Cn, Core_Sum, Combine(
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_SumAbs, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4)))
|
||||
GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -2052,7 +2052,7 @@ PERF_TEST_P(Sz_Depth_Cn, Core_SumAbs, Combine(
|
||||
PERF_TEST_P(Sz_Depth_Cn, Core_SumSqr, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values<MatDepth>(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4)))
|
||||
GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// BilateralFilter
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_KernelSz, cv::Size, MatDepth , int, int);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_KernelSz, Denoising_BilateralFilter,
|
||||
Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F), GPU_CHANNELS_1_3_4, Values(3, 5, 9)))
|
||||
{
|
||||
declare.time(30.0);
|
||||
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
int channels = GET_PARAM(2);
|
||||
int kernel_size = GET_PARAM(3);
|
||||
|
||||
float sigma_color = 7;
|
||||
float sigma_spatial = 5;
|
||||
int borderMode = cv::BORDER_REFLECT101;
|
||||
|
||||
int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
fillRandom(src);
|
||||
|
||||
if (runOnGpu)
|
||||
{
|
||||
cv::gpu::GpuMat d_src(src);
|
||||
cv::gpu::GpuMat d_dst;
|
||||
|
||||
cv::gpu::bilateralFilter(d_src, d_dst, kernel_size, sigma_color, sigma_spatial, borderMode);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cv::gpu::bilateralFilter(d_src, d_dst, kernel_size, sigma_color, sigma_spatial, borderMode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
cv::bilateralFilter(src, dst, kernel_size, sigma_color, sigma_spatial, borderMode);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cv::bilateralFilter(src, dst, kernel_size, sigma_color, sigma_spatial, borderMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// nonLocalMeans
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_WinSz_BlockSz, cv::Size, MatDepth , int, int, int);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_WinSz_BlockSz, Denoising_NonLocalMeans,
|
||||
Combine(GPU_TYPICAL_MAT_SIZES, Values<MatDepth>(CV_8U), Values(1), Values(21), Values(5, 7)))
|
||||
{
|
||||
declare.time(30.0);
|
||||
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
int channels = GET_PARAM(2);
|
||||
|
||||
int search_widow_size = GET_PARAM(3);
|
||||
int block_size = GET_PARAM(4);
|
||||
|
||||
float h = 10;
|
||||
int borderMode = cv::BORDER_REFLECT101;
|
||||
|
||||
int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
fillRandom(src);
|
||||
|
||||
if (runOnGpu)
|
||||
{
|
||||
cv::gpu::GpuMat d_src(src);
|
||||
cv::gpu::GpuMat d_dst;
|
||||
|
||||
cv::gpu::nonLocalMeans(d_src, d_dst, h, search_widow_size, block_size, borderMode);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cv::gpu::nonLocalMeans(d_src, d_dst, h, search_widow_size, block_size, borderMode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL();
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,13 @@ void generateMap(cv::Mat& map_x, cv::Mat& map_y, int remapMode)
|
||||
case HALF_SIZE:
|
||||
if (i > map_x.cols*0.25 && i < map_x.cols*0.75 && j > map_x.rows*0.25 && j < map_x.rows*0.75)
|
||||
{
|
||||
map_x.at<float>(j,i) = 2 * (i - map_x.cols * 0.25f) + 0.5f;
|
||||
map_y.at<float>(j,i) = 2 * (j - map_x.rows * 0.25f) + 0.5f;
|
||||
map_x.at<float>(j,i) = 2.f * (i - map_x.cols * 0.25f) + 0.5f;
|
||||
map_y.at<float>(j,i) = 2.f * (j - map_x.rows * 0.25f) + 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
map_x.at<float>(j,i) = 0;
|
||||
map_y.at<float>(j,i) = 0;
|
||||
map_x.at<float>(j,i) = 0.f;
|
||||
map_y.at<float>(j,i) = 0.f;
|
||||
}
|
||||
break;
|
||||
case UPSIDE_DOWN:
|
||||
@@ -54,7 +54,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Border_Mode, cv::Size, MatDepth, int, Interpola
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Border_Mode, ImgProc_Remap, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
ALL_BORDER_MODES,
|
||||
ALL_REMAP_MODES))
|
||||
@@ -113,7 +113,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Scale, cv::Size, MatDepth, int, Interpolation,
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Scale, ImgProc_Resize, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
ALL_INTERPOLATIONS,
|
||||
Values(0.5, 0.3, 2.0)))
|
||||
{
|
||||
@@ -163,7 +163,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Scale, cv::Size, MatDepth, int, double);
|
||||
PERF_TEST_P(Sz_Depth_Cn_Scale, ImgProc_ResizeArea, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
Values(0.2, 0.1, 0.05)))
|
||||
{
|
||||
declare.time(1.0);
|
||||
@@ -212,7 +212,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Border, cv::Size, MatDepth, int, Interpolation,
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Border, ImgProc_WarpAffine, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
ALL_BORDER_MODES))
|
||||
{
|
||||
@@ -265,7 +265,7 @@ PERF_TEST_P(Sz_Depth_Cn_Inter_Border, ImgProc_WarpAffine, Combine(
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Border, ImgProc_WarpPerspective, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
ALL_BORDER_MODES))
|
||||
{
|
||||
@@ -321,7 +321,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Border, cv::Size, MatDepth, int, BorderMode);
|
||||
PERF_TEST_P(Sz_Depth_Cn_Border, ImgProc_CopyMakeBorder, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
ALL_BORDER_MODES))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
@@ -789,7 +789,7 @@ PERF_TEST_P(Image, ImgProc_MeanShiftSegmentation, Values<string>("gpu/meanshift/
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// BlendLinear
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_BlendLinear, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_32F), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_BlendLinear, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_32F), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -887,7 +887,7 @@ DEF_PARAM_TEST(Sz_TemplateSz_Cn_Method, cv::Size, cv::Size, int, TemplateMethod)
|
||||
PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate8U, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(cv::Size(5, 5), cv::Size(16, 16), cv::Size(30, 30)),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
ALL_TEMPLATE_METHODS))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
@@ -933,7 +933,7 @@ PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate8U, Combine(
|
||||
PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate32F, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(cv::Size(5, 5), cv::Size(16, 16), cv::Size(30, 30)),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
Values(TemplateMethod(cv::TM_SQDIFF), TemplateMethod(cv::TM_CCORR))))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
@@ -1287,7 +1287,7 @@ DEF_PARAM_TEST(Sz_Depth_Cn_Inter, cv::Size, MatDepth, int, Interpolation);
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter, ImgProc_Rotate, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4),
|
||||
GPU_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC))))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
@@ -1324,7 +1324,7 @@ PERF_TEST_P(Sz_Depth_Cn_Inter, ImgProc_Rotate, Combine(
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_PyrDown, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4)))
|
||||
GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -1366,7 +1366,7 @@ PERF_TEST_P(Sz_Depth_Cn, ImgProc_PyrDown, Combine(
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_PyrUp, Combine(
|
||||
GPU_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
Values(1, 3, 4)))
|
||||
GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -1540,7 +1540,7 @@ PERF_TEST_P(Sz_Type_Op, ImgProc_AlphaComp, Combine(GPU_TYPICAL_MAT_SIZES, Values
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ImagePyramidBuild
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidBuild, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidBuild, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -1573,7 +1573,7 @@ PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidBuild, Combine(GPU_TYPICAL_MAT_SIZE
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ImagePyramidGetLayer
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidGetLayer, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, ImgProc_ImagePyramidGetLayer, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
|
||||
@@ -23,7 +23,7 @@ struct GreedyLabeling
|
||||
|
||||
struct InInterval
|
||||
{
|
||||
InInterval(const int& _lo, const int& _hi) : lo(-_lo), hi(_hi) {};
|
||||
InInterval(const int& _lo, const int& _hi) : lo(-_lo), hi(_hi) {}
|
||||
const int lo, hi;
|
||||
|
||||
bool operator() (const unsigned char a, const unsigned char b) const
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SetTo
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, MatOp_SetTo, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F, CV_64F), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, MatOp_SetTo, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F, CV_64F), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -45,7 +45,7 @@ PERF_TEST_P(Sz_Depth_Cn, MatOp_SetTo, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SetToMasked
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, MatOp_SetToMasked, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F, CV_64F), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, MatOp_SetToMasked, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F, CV_64F), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
@@ -87,7 +87,7 @@ PERF_TEST_P(Sz_Depth_Cn, MatOp_SetToMasked, Combine(GPU_TYPICAL_MAT_SIZES, Value
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CopyToMasked
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, MatOp_CopyToMasked, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F, CV_64F), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Sz_Depth_Cn, MatOp_CopyToMasked, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U, CV_16U, CV_32F, CV_64F), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
cv::Size size = GET_PARAM(0);
|
||||
int depth = GET_PARAM(1);
|
||||
|
||||
@@ -45,6 +45,47 @@ PERF_TEST_P(Image, ObjDetect_HOG, Values<string>("gpu/hog/road.png"))
|
||||
}
|
||||
}
|
||||
|
||||
//===========test for CalTech data =============//
|
||||
DEF_PARAM_TEST_1(HOG, string);
|
||||
|
||||
PERF_TEST_P(HOG, CalTech, Values<string>("gpu/caltech/image_00000009_0.png", "gpu/caltech/image_00000032_0.png",
|
||||
"gpu/caltech/image_00000165_0.png", "gpu/caltech/image_00000261_0.png", "gpu/caltech/image_00000469_0.png",
|
||||
"gpu/caltech/image_00000527_0.png", "gpu/caltech/image_00000574_0.png"))
|
||||
{
|
||||
cv::Mat img = readImage(GetParam(), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(img.empty());
|
||||
|
||||
std::vector<cv::Rect> found_locations;
|
||||
|
||||
if (runOnGpu)
|
||||
{
|
||||
cv::gpu::GpuMat d_img(img);
|
||||
|
||||
cv::gpu::HOGDescriptor d_hog;
|
||||
d_hog.setSVMDetector(cv::gpu::HOGDescriptor::getDefaultPeopleDetector());
|
||||
|
||||
d_hog.detectMultiScale(d_img, found_locations);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
d_hog.detectMultiScale(d_img, found_locations);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::HOGDescriptor hog;
|
||||
hog.setSVMDetector(cv::gpu::HOGDescriptor::getDefaultPeopleDetector());
|
||||
|
||||
hog.detectMultiScale(img, found_locations);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
hog.detectMultiScale(img, found_locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// HaarClassifier
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ PERF_TEST_P(ImagePair_Gray_NPts_WinSz_Levels_Iters, Video_PyrLKOpticalFlowSparse
|
||||
|
||||
if (runOnGpu)
|
||||
{
|
||||
cv::gpu::GpuMat d_pts(pts);
|
||||
cv::gpu::GpuMat d_pts(pts.reshape(2, 1));
|
||||
|
||||
cv::gpu::PyrLKOpticalFlow d_pyrLK;
|
||||
d_pyrLK.winSize = cv::Size(winSize, winSize);
|
||||
@@ -423,7 +423,7 @@ PERF_TEST_P(Video, Video_FGDStatModel, Values("gpu/video/768x576.avi", "gpu/vide
|
||||
|
||||
DEF_PARAM_TEST(Video_Cn_LearningRate, string, int, double);
|
||||
|
||||
PERF_TEST_P(Video_Cn_LearningRate, Video_MOG, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1, 3, 4), Values(0.0, 0.01)))
|
||||
PERF_TEST_P(Video_Cn_LearningRate, Video_MOG, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), GPU_CHANNELS_1_3_4, Values(0.0, 0.01)))
|
||||
{
|
||||
string inputFile = perf::TestBase::getDataPath(GET_PARAM(0));
|
||||
int cn = GET_PARAM(1);
|
||||
@@ -511,7 +511,7 @@ PERF_TEST_P(Video_Cn_LearningRate, Video_MOG, Combine(Values("gpu/video/768x576.
|
||||
|
||||
DEF_PARAM_TEST(Video_Cn, string, int);
|
||||
|
||||
PERF_TEST_P(Video_Cn, Video_MOG2, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Video_Cn, Video_MOG2, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
string inputFile = perf::TestBase::getDataPath(GET_PARAM(0));
|
||||
int cn = GET_PARAM(1);
|
||||
@@ -596,7 +596,7 @@ PERF_TEST_P(Video_Cn, Video_MOG2, Combine(Values("gpu/video/768x576.avi", "gpu/v
|
||||
//////////////////////////////////////////////////////
|
||||
// MOG2GetBackgroundImage
|
||||
|
||||
PERF_TEST_P(Video_Cn, Video_MOG2GetBackgroundImage, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Video_Cn, Video_MOG2GetBackgroundImage, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
string inputFile = perf::TestBase::getDataPath(GET_PARAM(0));
|
||||
int cn = GET_PARAM(1);
|
||||
@@ -676,7 +676,7 @@ PERF_TEST_P(Video_Cn, Video_MOG2GetBackgroundImage, Combine(Values("gpu/video/76
|
||||
//////////////////////////////////////////////////////
|
||||
// VIBE
|
||||
|
||||
PERF_TEST_P(Video_Cn, Video_VIBE, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1, 3, 4)))
|
||||
PERF_TEST_P(Video_Cn, Video_VIBE, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), GPU_CHANNELS_1_3_4))
|
||||
{
|
||||
string inputFile = perf::TestBase::getDataPath(GET_PARAM(0));
|
||||
int cn = GET_PARAM(1);
|
||||
@@ -739,7 +739,7 @@ PERF_TEST_P(Video_Cn, Video_VIBE, Combine(Values("gpu/video/768x576.avi", "gpu/v
|
||||
|
||||
DEF_PARAM_TEST(Video_Cn_MaxFeatures, string, int, int);
|
||||
|
||||
PERF_TEST_P(Video_Cn_MaxFeatures, Video_GMG, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1, 3, 4), Values(20, 40, 60)))
|
||||
PERF_TEST_P(Video_Cn_MaxFeatures, Video_GMG, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), GPU_CHANNELS_1_3_4, Values(20, 40, 60)))
|
||||
{
|
||||
std::string inputFile = perf::TestBase::getDataPath(GET_PARAM(0));
|
||||
int cn = GET_PARAM(1);
|
||||
|
||||
@@ -41,5 +41,6 @@ DEF_PARAM_TEST(Sz_Depth, cv::Size, MatDepth);
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn, cv::Size, MatDepth, int);
|
||||
|
||||
#define GPU_TYPICAL_MAT_SIZES testing::Values(perf::sz720p, perf::szSXGA, perf::sz1080p)
|
||||
#define GPU_CHANNELS_1_3_4 testing::Values(1, 3, 4)
|
||||
|
||||
#endif // __OPENCV_PERF_GPU_UTILITY_HPP__
|
||||
|
||||
@@ -57,16 +57,16 @@ void cv::gpu::DisparityBilateralFilter::operator()(const GpuMat&, const GpuMat&,
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace bilateral_filter
|
||||
namespace disp_bilateral_filter
|
||||
{
|
||||
void load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc);
|
||||
void disp_load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc);
|
||||
|
||||
void bilateral_filter_gpu(PtrStepSzb disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream);
|
||||
void bilateral_filter_gpu(PtrStepSz<short> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream);
|
||||
template<typename T>
|
||||
void disp_bilateral_filter(PtrStepSz<T> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream);
|
||||
}
|
||||
}}}
|
||||
|
||||
using namespace ::cv::gpu::device::bilateral_filter;
|
||||
using namespace ::cv::gpu::device::disp_bilateral_filter;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -103,14 +103,14 @@ namespace
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void bilateral_filter_operator(int ndisp, int radius, int iters, float edge_threshold,float max_disc_threshold,
|
||||
void disp_bilateral_filter_operator(int ndisp, int radius, int iters, float edge_threshold,float max_disc_threshold,
|
||||
GpuMat& table_color, GpuMat& table_space,
|
||||
const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream)
|
||||
{
|
||||
short edge_disc = max<short>(short(1), short(ndisp * edge_threshold + 0.5));
|
||||
short max_disc = short(ndisp * max_disc_threshold + 0.5);
|
||||
|
||||
load_constants(table_color.ptr<float>(), table_space, ndisp, radius, edge_disc, max_disc);
|
||||
disp_load_constants(table_color.ptr<float>(), table_space, ndisp, radius, edge_disc, max_disc);
|
||||
|
||||
if (&dst != &disp)
|
||||
{
|
||||
@@ -120,7 +120,7 @@ namespace
|
||||
disp.copyTo(dst);
|
||||
}
|
||||
|
||||
bilateral_filter_gpu((PtrStepSz<T>)dst, img, img.channels(), iters, StreamAccessor::getStream(stream));
|
||||
disp_bilateral_filter<T>(dst, img, img.channels(), iters, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
typedef void (*bilateral_filter_operator_t)(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold,
|
||||
@@ -128,7 +128,7 @@ namespace
|
||||
const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream);
|
||||
|
||||
const bilateral_filter_operator_t operators[] =
|
||||
{bilateral_filter_operator<unsigned char>, 0, 0, bilateral_filter_operator<short>, 0, 0, 0, 0};
|
||||
{disp_bilateral_filter_operator<unsigned char>, 0, 0, disp_bilateral_filter_operator<short>, 0, 0, 0, 0};
|
||||
}
|
||||
|
||||
cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp_, int radius_, int iters_)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 1993-2011, NVIDIA 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,
|
||||
@@ -28,7 +29,7 @@
|
||||
// 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
|
||||
// any express or bpied warranties, including, but not limited to, the bpied
|
||||
// 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
|
||||
@@ -41,186 +42,155 @@
|
||||
//M*/
|
||||
|
||||
#include "internal_shared.hpp"
|
||||
#include "opencv2/gpu/device/limits.hpp"
|
||||
|
||||
#include "opencv2/gpu/device/vec_traits.hpp"
|
||||
#include "opencv2/gpu/device/vec_math.hpp"
|
||||
#include "opencv2/gpu/device/border_interpolate.hpp"
|
||||
|
||||
using namespace cv::gpu;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
/// Bilateral filtering
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace bilateral_filter
|
||||
namespace imgproc
|
||||
{
|
||||
__constant__ float* ctable_color;
|
||||
__constant__ float* ctable_space;
|
||||
__constant__ size_t ctable_space_step;
|
||||
__device__ __forceinline__ float norm_l1(const float& a) { return ::fabs(a); }
|
||||
__device__ __forceinline__ float norm_l1(const float2& a) { return ::fabs(a.x) + ::fabs(a.y); }
|
||||
__device__ __forceinline__ float norm_l1(const float3& a) { return ::fabs(a.x) + ::fabs(a.y) + ::fabs(a.z); }
|
||||
__device__ __forceinline__ float norm_l1(const float4& a) { return ::fabs(a.x) + ::fabs(a.y) + ::fabs(a.z) + ::fabs(a.w); }
|
||||
|
||||
__constant__ int cndisp;
|
||||
__constant__ int cradius;
|
||||
__device__ __forceinline__ float sqr(const float& a) { return a * a; }
|
||||
|
||||
__constant__ short cedge_disc;
|
||||
__constant__ short cmax_disc;
|
||||
|
||||
void load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc)
|
||||
template<typename T, typename B>
|
||||
__global__ void bilateral_kernel(const PtrStepSz<T> src, PtrStep<T> dst, const B b, const int ksz, const float sigma_spatial2_inv_half, const float sigma_color2_inv_half)
|
||||
{
|
||||
cudaSafeCall( cudaMemcpyToSymbol(ctable_color, &table_color, sizeof(table_color)) );
|
||||
cudaSafeCall( cudaMemcpyToSymbol(ctable_space, &table_space.data, sizeof(table_space.data)) );
|
||||
size_t table_space_step = table_space.step / sizeof(float);
|
||||
cudaSafeCall( cudaMemcpyToSymbol(ctable_space_step, &table_space_step, sizeof(size_t)) );
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type value_type;
|
||||
|
||||
int x = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
int y = threadIdx.y + blockIdx.y * blockDim.y;
|
||||
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cndisp, &ndisp, sizeof(int)) );
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cradius, &radius, sizeof(int)) );
|
||||
if (x >= src.cols || y >= src.rows)
|
||||
return;
|
||||
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cedge_disc, &edge_disc, sizeof(short)) );
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cmax_disc, &max_disc, sizeof(short)) );
|
||||
value_type center = saturate_cast<value_type>(src(y, x));
|
||||
|
||||
value_type sum1 = VecTraits<value_type>::all(0);
|
||||
float sum2 = 0;
|
||||
|
||||
int r = ksz / 2;
|
||||
float r2 = (float)(r * r);
|
||||
|
||||
int tx = x - r + ksz;
|
||||
int ty = y - r + ksz;
|
||||
|
||||
if (x - ksz/2 >=0 && y - ksz/2 >=0 && tx < src.cols && ty < src.rows)
|
||||
{
|
||||
for (int cy = y - r; cy < ty; ++cy)
|
||||
for (int cx = x - r; cx < tx; ++cx)
|
||||
{
|
||||
float space2 = (x - cx) * (x - cx) + (y - cy) * (y - cy);
|
||||
if (space2 > r2)
|
||||
continue;
|
||||
|
||||
value_type value = saturate_cast<value_type>(src(cy, cx));
|
||||
|
||||
float weight = ::exp(space2 * sigma_spatial2_inv_half + sqr(norm_l1(value - center)) * sigma_color2_inv_half);
|
||||
sum1 = sum1 + weight * value;
|
||||
sum2 = sum2 + weight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int cy = y - r; cy < ty; ++cy)
|
||||
for (int cx = x - r; cx < tx; ++cx)
|
||||
{
|
||||
float space2 = (x - cx) * (x - cx) + (y - cy) * (y - cy);
|
||||
if (space2 > r2)
|
||||
continue;
|
||||
|
||||
value_type value = saturate_cast<value_type>(b.at(cy, cx, src.data, src.step));
|
||||
|
||||
float weight = ::exp(space2 * sigma_spatial2_inv_half + sqr(norm_l1(value - center)) * sigma_color2_inv_half);
|
||||
|
||||
sum1 = sum1 + weight * value;
|
||||
sum2 = sum2 + weight;
|
||||
}
|
||||
}
|
||||
dst(y, x) = saturate_cast<T>(sum1 / sum2);
|
||||
}
|
||||
|
||||
template <int channels>
|
||||
struct DistRgbMax
|
||||
template<typename T, template <typename> class B>
|
||||
void bilateral_caller(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, cudaStream_t stream)
|
||||
{
|
||||
static __device__ __forceinline__ uchar calc(const uchar* a, const uchar* b)
|
||||
{
|
||||
uchar x = ::abs(a[0] - b[0]);
|
||||
uchar y = ::abs(a[1] - b[1]);
|
||||
uchar z = ::abs(a[2] - b[2]);
|
||||
return (::max(::max(x, y), z));
|
||||
}
|
||||
};
|
||||
dim3 block (32, 8);
|
||||
dim3 grid (divUp (src.cols, block.x), divUp (src.rows, block.y));
|
||||
|
||||
template <>
|
||||
struct DistRgbMax<1>
|
||||
{
|
||||
static __device__ __forceinline__ uchar calc(const uchar* a, const uchar* b)
|
||||
{
|
||||
return ::abs(a[0] - b[0]);
|
||||
}
|
||||
};
|
||||
B<T> b(src.rows, src.cols);
|
||||
|
||||
template <int channels, typename T>
|
||||
__global__ void bilateral_filter(int t, T* disp, size_t disp_step, const uchar* img, size_t img_step, int h, int w)
|
||||
{
|
||||
const int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
const int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + t) & 1);
|
||||
float sigma_spatial2_inv_half = -0.5f/(sigma_spatial * sigma_spatial);
|
||||
float sigma_color2_inv_half = -0.5f/(sigma_color * sigma_color);
|
||||
|
||||
T dp[5];
|
||||
|
||||
if (y > 0 && y < h - 1 && x > 0 && x < w - 1)
|
||||
{
|
||||
dp[0] = *(disp + (y ) * disp_step + x + 0);
|
||||
dp[1] = *(disp + (y-1) * disp_step + x + 0);
|
||||
dp[2] = *(disp + (y ) * disp_step + x - 1);
|
||||
dp[3] = *(disp + (y+1) * disp_step + x + 0);
|
||||
dp[4] = *(disp + (y ) * disp_step + x + 1);
|
||||
|
||||
if(::abs(dp[1] - dp[0]) >= cedge_disc || ::abs(dp[2] - dp[0]) >= cedge_disc || ::abs(dp[3] - dp[0]) >= cedge_disc || ::abs(dp[4] - dp[0]) >= cedge_disc)
|
||||
{
|
||||
const int ymin = ::max(0, y - cradius);
|
||||
const int xmin = ::max(0, x - cradius);
|
||||
const int ymax = ::min(h - 1, y + cradius);
|
||||
const int xmax = ::min(w - 1, x + cradius);
|
||||
|
||||
float cost[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
const uchar* ic = img + y * img_step + channels * x;
|
||||
|
||||
for(int yi = ymin; yi <= ymax; yi++)
|
||||
{
|
||||
const T* disp_y = disp + yi * disp_step;
|
||||
|
||||
for(int xi = xmin; xi <= xmax; xi++)
|
||||
{
|
||||
const uchar* in = img + yi * img_step + channels * xi;
|
||||
|
||||
uchar dist_rgb = DistRgbMax<channels>::calc(in, ic);
|
||||
|
||||
const float weight = ctable_color[dist_rgb] * (ctable_space + ::abs(y-yi)* ctable_space_step)[::abs(x-xi)];
|
||||
|
||||
const T disp_reg = disp_y[xi];
|
||||
|
||||
cost[0] += ::min(cmax_disc, ::abs(disp_reg - dp[0])) * weight;
|
||||
cost[1] += ::min(cmax_disc, ::abs(disp_reg - dp[1])) * weight;
|
||||
cost[2] += ::min(cmax_disc, ::abs(disp_reg - dp[2])) * weight;
|
||||
cost[3] += ::min(cmax_disc, ::abs(disp_reg - dp[3])) * weight;
|
||||
cost[4] += ::min(cmax_disc, ::abs(disp_reg - dp[4])) * weight;
|
||||
}
|
||||
}
|
||||
|
||||
float minimum = numeric_limits<float>::max();
|
||||
int id = 0;
|
||||
|
||||
if (cost[0] < minimum)
|
||||
{
|
||||
minimum = cost[0];
|
||||
id = 0;
|
||||
}
|
||||
if (cost[1] < minimum)
|
||||
{
|
||||
minimum = cost[1];
|
||||
id = 1;
|
||||
}
|
||||
if (cost[2] < minimum)
|
||||
{
|
||||
minimum = cost[2];
|
||||
id = 2;
|
||||
}
|
||||
if (cost[3] < minimum)
|
||||
{
|
||||
minimum = cost[3];
|
||||
id = 3;
|
||||
}
|
||||
if (cost[4] < minimum)
|
||||
{
|
||||
minimum = cost[4];
|
||||
id = 4;
|
||||
}
|
||||
|
||||
*(disp + y * disp_step + x) = dp[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void bilateral_filter_caller(PtrStepSz<T> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream)
|
||||
{
|
||||
dim3 threads(32, 8, 1);
|
||||
dim3 grid(1, 1, 1);
|
||||
grid.x = divUp(disp.cols, threads.x << 1);
|
||||
grid.y = divUp(disp.rows, threads.y);
|
||||
|
||||
switch (channels)
|
||||
{
|
||||
case 1:
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
bilateral_filter<1><<<grid, threads, 0, stream>>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
bilateral_filter<1><<<grid, threads, 0, stream>>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
bilateral_filter<3><<<grid, threads, 0, stream>>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
bilateral_filter<3><<<grid, threads, 0, stream>>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cv::gpu::error("Unsupported channels count", __FILE__, __LINE__, "bilateral_filter_caller");
|
||||
}
|
||||
cudaSafeCall( cudaFuncSetCacheConfig (bilateral_kernel<T, B<T> >, cudaFuncCachePreferL1) );
|
||||
bilateral_kernel<<<grid, block>>>((PtrStepSz<T>)src, (PtrStepSz<T>)dst, b, kernel_size, sigma_spatial2_inv_half, sigma_color2_inv_half);
|
||||
cudaSafeCall ( cudaGetLastError () );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
void bilateral_filter_gpu(PtrStepSzb disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream)
|
||||
template<typename T>
|
||||
void bilateral_filter_gpu(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float gauss_spatial_coeff, float gauss_color_coeff, int borderMode, cudaStream_t stream)
|
||||
{
|
||||
bilateral_filter_caller(disp, img, channels, iters, stream);
|
||||
}
|
||||
typedef void (*caller_t)(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, cudaStream_t stream);
|
||||
|
||||
void bilateral_filter_gpu(PtrStepSz<short> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream)
|
||||
{
|
||||
bilateral_filter_caller(disp, img, channels, iters, stream);
|
||||
static caller_t funcs[] =
|
||||
{
|
||||
bilateral_caller<T, BrdReflect101>,
|
||||
bilateral_caller<T, BrdReplicate>,
|
||||
bilateral_caller<T, BrdConstant>,
|
||||
bilateral_caller<T, BrdReflect>,
|
||||
bilateral_caller<T, BrdWrap>,
|
||||
};
|
||||
funcs[borderMode](src, dst, kernel_size, gauss_spatial_coeff, gauss_color_coeff, stream);
|
||||
}
|
||||
} // namespace bilateral_filter
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
}
|
||||
}}}
|
||||
|
||||
|
||||
#define OCV_INSTANTIATE_BILATERAL_FILTER(T) \
|
||||
template void cv::gpu::device::imgproc::bilateral_filter_gpu<T>(const PtrStepSzb&, PtrStepSzb, int, float, float, int, cudaStream_t);
|
||||
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(uchar)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(uchar2)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(uchar3)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(uchar4)
|
||||
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(schar)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(schar2)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(schar3)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(schar4)
|
||||
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(short)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(short2)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(short3)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(short4)
|
||||
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(ushort)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(ushort2)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(ushort3)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(ushort4)
|
||||
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(int)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(int2)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(int3)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(int4)
|
||||
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(float)
|
||||
//OCV_INSTANTIATE_BILATERAL_FILTER(float2)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(float3)
|
||||
OCV_INSTANTIATE_BILATERAL_FILTER(float4)
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*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 "internal_shared.hpp"
|
||||
#include "opencv2/gpu/device/limits.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace disp_bilateral_filter
|
||||
{
|
||||
__constant__ float* ctable_color;
|
||||
__constant__ float* ctable_space;
|
||||
__constant__ size_t ctable_space_step;
|
||||
|
||||
__constant__ int cndisp;
|
||||
__constant__ int cradius;
|
||||
|
||||
__constant__ short cedge_disc;
|
||||
__constant__ short cmax_disc;
|
||||
|
||||
void disp_load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc)
|
||||
{
|
||||
cudaSafeCall( cudaMemcpyToSymbol(ctable_color, &table_color, sizeof(table_color)) );
|
||||
cudaSafeCall( cudaMemcpyToSymbol(ctable_space, &table_space.data, sizeof(table_space.data)) );
|
||||
size_t table_space_step = table_space.step / sizeof(float);
|
||||
cudaSafeCall( cudaMemcpyToSymbol(ctable_space_step, &table_space_step, sizeof(size_t)) );
|
||||
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cndisp, &ndisp, sizeof(int)) );
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cradius, &radius, sizeof(int)) );
|
||||
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cedge_disc, &edge_disc, sizeof(short)) );
|
||||
cudaSafeCall( cudaMemcpyToSymbol(cmax_disc, &max_disc, sizeof(short)) );
|
||||
}
|
||||
|
||||
template <int channels>
|
||||
struct DistRgbMax
|
||||
{
|
||||
static __device__ __forceinline__ uchar calc(const uchar* a, const uchar* b)
|
||||
{
|
||||
uchar x = ::abs(a[0] - b[0]);
|
||||
uchar y = ::abs(a[1] - b[1]);
|
||||
uchar z = ::abs(a[2] - b[2]);
|
||||
return (::max(::max(x, y), z));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DistRgbMax<1>
|
||||
{
|
||||
static __device__ __forceinline__ uchar calc(const uchar* a, const uchar* b)
|
||||
{
|
||||
return ::abs(a[0] - b[0]);
|
||||
}
|
||||
};
|
||||
|
||||
template <int channels, typename T>
|
||||
__global__ void disp_bilateral_filter(int t, T* disp, size_t disp_step, const uchar* img, size_t img_step, int h, int w)
|
||||
{
|
||||
const int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
const int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + t) & 1);
|
||||
|
||||
T dp[5];
|
||||
|
||||
if (y > 0 && y < h - 1 && x > 0 && x < w - 1)
|
||||
{
|
||||
dp[0] = *(disp + (y ) * disp_step + x + 0);
|
||||
dp[1] = *(disp + (y-1) * disp_step + x + 0);
|
||||
dp[2] = *(disp + (y ) * disp_step + x - 1);
|
||||
dp[3] = *(disp + (y+1) * disp_step + x + 0);
|
||||
dp[4] = *(disp + (y ) * disp_step + x + 1);
|
||||
|
||||
if(::abs(dp[1] - dp[0]) >= cedge_disc || ::abs(dp[2] - dp[0]) >= cedge_disc || ::abs(dp[3] - dp[0]) >= cedge_disc || ::abs(dp[4] - dp[0]) >= cedge_disc)
|
||||
{
|
||||
const int ymin = ::max(0, y - cradius);
|
||||
const int xmin = ::max(0, x - cradius);
|
||||
const int ymax = ::min(h - 1, y + cradius);
|
||||
const int xmax = ::min(w - 1, x + cradius);
|
||||
|
||||
float cost[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
const uchar* ic = img + y * img_step + channels * x;
|
||||
|
||||
for(int yi = ymin; yi <= ymax; yi++)
|
||||
{
|
||||
const T* disp_y = disp + yi * disp_step;
|
||||
|
||||
for(int xi = xmin; xi <= xmax; xi++)
|
||||
{
|
||||
const uchar* in = img + yi * img_step + channels * xi;
|
||||
|
||||
uchar dist_rgb = DistRgbMax<channels>::calc(in, ic);
|
||||
|
||||
const float weight = ctable_color[dist_rgb] * (ctable_space + ::abs(y-yi)* ctable_space_step)[::abs(x-xi)];
|
||||
|
||||
const T disp_reg = disp_y[xi];
|
||||
|
||||
cost[0] += ::min(cmax_disc, ::abs(disp_reg - dp[0])) * weight;
|
||||
cost[1] += ::min(cmax_disc, ::abs(disp_reg - dp[1])) * weight;
|
||||
cost[2] += ::min(cmax_disc, ::abs(disp_reg - dp[2])) * weight;
|
||||
cost[3] += ::min(cmax_disc, ::abs(disp_reg - dp[3])) * weight;
|
||||
cost[4] += ::min(cmax_disc, ::abs(disp_reg - dp[4])) * weight;
|
||||
}
|
||||
}
|
||||
|
||||
float minimum = numeric_limits<float>::max();
|
||||
int id = 0;
|
||||
|
||||
if (cost[0] < minimum)
|
||||
{
|
||||
minimum = cost[0];
|
||||
id = 0;
|
||||
}
|
||||
if (cost[1] < minimum)
|
||||
{
|
||||
minimum = cost[1];
|
||||
id = 1;
|
||||
}
|
||||
if (cost[2] < minimum)
|
||||
{
|
||||
minimum = cost[2];
|
||||
id = 2;
|
||||
}
|
||||
if (cost[3] < minimum)
|
||||
{
|
||||
minimum = cost[3];
|
||||
id = 3;
|
||||
}
|
||||
if (cost[4] < minimum)
|
||||
{
|
||||
minimum = cost[4];
|
||||
id = 4;
|
||||
}
|
||||
|
||||
*(disp + y * disp_step + x) = dp[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void disp_bilateral_filter(PtrStepSz<T> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream)
|
||||
{
|
||||
dim3 threads(32, 8, 1);
|
||||
dim3 grid(1, 1, 1);
|
||||
grid.x = divUp(disp.cols, threads.x << 1);
|
||||
grid.y = divUp(disp.rows, threads.y);
|
||||
|
||||
switch (channels)
|
||||
{
|
||||
case 1:
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
disp_bilateral_filter<1><<<grid, threads, 0, stream>>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
disp_bilateral_filter<1><<<grid, threads, 0, stream>>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (int i = 0; i < iters; ++i)
|
||||
{
|
||||
disp_bilateral_filter<3><<<grid, threads, 0, stream>>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
disp_bilateral_filter<3><<<grid, threads, 0, stream>>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cv::gpu::error("Unsupported channels count", __FILE__, __LINE__, "disp_bilateral_filter");
|
||||
}
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template void disp_bilateral_filter<uchar>(PtrStepSz<uchar> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream);
|
||||
template void disp_bilateral_filter<short>(PtrStepSz<short> disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream);
|
||||
} // namespace bilateral_filter
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
@@ -64,23 +64,22 @@ namespace cv { namespace gpu { namespace device
|
||||
const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x;
|
||||
const int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
if (y >= src.rows)
|
||||
return;
|
||||
|
||||
if (threadIdx.x == 0)
|
||||
s_qsize[threadIdx.y] = 0;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// fill the queue
|
||||
const uchar* srcRow = src.ptr(y);
|
||||
for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < src.cols; ++i, xx += blockDim.x)
|
||||
if (y < src.rows)
|
||||
{
|
||||
if (srcRow[xx])
|
||||
// fill the queue
|
||||
const uchar* srcRow = src.ptr(y);
|
||||
for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < src.cols; ++i, xx += blockDim.x)
|
||||
{
|
||||
const unsigned int val = (y << 16) | xx;
|
||||
const int qidx = Emulation::smem::atomicAdd(&s_qsize[threadIdx.y], 1);
|
||||
s_queues[threadIdx.y][qidx] = val;
|
||||
if (srcRow[xx])
|
||||
{
|
||||
const unsigned int val = (y << 16) | xx;
|
||||
const int qidx = Emulation::smem::atomicAdd(&s_qsize[threadIdx.y], 1);
|
||||
s_queues[threadIdx.y][qidx] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*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) 1993-2011, NVIDIA 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 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 bpied warranties, including, but not limited to, the bpied
|
||||
// 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 "internal_shared.hpp"
|
||||
|
||||
#include "opencv2/gpu/device/vec_traits.hpp"
|
||||
#include "opencv2/gpu/device/vec_math.hpp"
|
||||
#include "opencv2/gpu/device/border_interpolate.hpp"
|
||||
|
||||
using namespace cv::gpu;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
/// Non local means denosings
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
__device__ __forceinline__ float norm2(const float& v) { return v*v; }
|
||||
__device__ __forceinline__ float norm2(const float2& v) { return v.x*v.x + v.y*v.y; }
|
||||
__device__ __forceinline__ float norm2(const float3& v) { return v.x*v.x + v.y*v.y + v.z*v.z; }
|
||||
__device__ __forceinline__ float norm2(const float4& v) { return v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; }
|
||||
|
||||
template<typename T, typename B>
|
||||
__global__ void nlm_kernel(const PtrStepSz<T> src, PtrStep<T> dst, const B b, int search_radius, int block_radius, float h2_inv_half)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type value_type;
|
||||
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x >= src.cols || y >= src.rows)
|
||||
return;
|
||||
|
||||
float block_radius2_inv = -1.f/(block_radius * block_radius);
|
||||
|
||||
value_type sum1 = VecTraits<value_type>::all(0);
|
||||
float sum2 = 0.f;
|
||||
|
||||
for(float cy = -search_radius; cy <= search_radius; ++cy)
|
||||
for(float cx = -search_radius; cx <= search_radius; ++cx)
|
||||
{
|
||||
float color2 = 0;
|
||||
for(float by = -block_radius; by <= block_radius; ++by)
|
||||
for(float bx = -block_radius; bx <= block_radius; ++bx)
|
||||
{
|
||||
value_type v1 = saturate_cast<value_type>(src(y + by, x + bx));
|
||||
value_type v2 = saturate_cast<value_type>(src(y + cy + by, x + cx + bx));
|
||||
color2 += norm2(v1 - v2);
|
||||
}
|
||||
|
||||
float dist2 = cx * cx + cy * cy;
|
||||
float w = __expf(color2 * h2_inv_half + dist2 * block_radius2_inv);
|
||||
|
||||
sum1 = sum1 + saturate_cast<value_type>(src(y + cy, x + cy)) * w;
|
||||
sum2 += w;
|
||||
}
|
||||
|
||||
dst(y, x) = saturate_cast<T>(sum1 / sum2);
|
||||
|
||||
}
|
||||
|
||||
template<typename T, template <typename> class B>
|
||||
void nlm_caller(const PtrStepSzb src, PtrStepSzb dst, int search_radius, int block_radius, float h, cudaStream_t stream)
|
||||
{
|
||||
dim3 block (32, 8);
|
||||
dim3 grid (divUp (src.cols, block.x), divUp (src.rows, block.y));
|
||||
|
||||
B<T> b(src.rows, src.cols);
|
||||
|
||||
float h2_inv_half = -0.5f/(h * h * VecTraits<T>::cn);
|
||||
|
||||
cudaSafeCall( cudaFuncSetCacheConfig (nlm_kernel<T, B<T> >, cudaFuncCachePreferL1) );
|
||||
nlm_kernel<<<grid, block>>>((PtrStepSz<T>)src, (PtrStepSz<T>)dst, b, search_radius, block_radius, h2_inv_half);
|
||||
cudaSafeCall ( cudaGetLastError () );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void nlm_bruteforce_gpu(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream)
|
||||
{
|
||||
typedef void (*func_t)(const PtrStepSzb src, PtrStepSzb dst, int search_radius, int block_radius, float h, cudaStream_t stream);
|
||||
|
||||
static func_t funcs[] =
|
||||
{
|
||||
nlm_caller<T, BrdReflect101>,
|
||||
nlm_caller<T, BrdReplicate>,
|
||||
nlm_caller<T, BrdConstant>,
|
||||
nlm_caller<T, BrdReflect>,
|
||||
nlm_caller<T, BrdWrap>,
|
||||
};
|
||||
funcs[borderMode](src, dst, search_radius, block_radius, h, stream);
|
||||
}
|
||||
|
||||
template void nlm_bruteforce_gpu<uchar>(const PtrStepSzb&, PtrStepSzb, int, int, float, int, cudaStream_t);
|
||||
template void nlm_bruteforce_gpu<uchar3>(const PtrStepSzb&, PtrStepSzb, int, int, float, int, cudaStream_t);
|
||||
}
|
||||
}}}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*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 GpuMaterials 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 bpied warranties, including, but not limited to, the bpied
|
||||
// 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::gpu;
|
||||
|
||||
#if !defined (HAVE_CUDA)
|
||||
|
||||
void cv::gpu::bilateralFilter(const GpuMat&, GpuMat&, int, float, float, int, Stream&) { throw_nogpu(); }
|
||||
void cv::gpu::nonLocalMeans(const GpuMat&, GpuMat&, float, int, int, int, Stream&) { throw_nogpu(); }
|
||||
|
||||
#else
|
||||
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template<typename T>
|
||||
void bilateral_filter_gpu(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, int borderMode, cudaStream_t stream);
|
||||
|
||||
template<typename T>
|
||||
void nlm_bruteforce_gpu(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::gpu::bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode, Stream& s)
|
||||
{
|
||||
using cv::gpu::device::imgproc::bilateral_filter_gpu;
|
||||
|
||||
typedef void (*func_t)(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, int borderMode, cudaStream_t s);
|
||||
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{bilateral_filter_gpu<uchar> , 0 /*bilateral_filter_gpu<uchar2>*/ , bilateral_filter_gpu<uchar3> , bilateral_filter_gpu<uchar4> },
|
||||
{0 /*bilateral_filter_gpu<schar>*/, 0 /*bilateral_filter_gpu<schar2>*/ , 0 /*bilateral_filter_gpu<schar3>*/, 0 /*bilateral_filter_gpu<schar4>*/},
|
||||
{bilateral_filter_gpu<ushort> , 0 /*bilateral_filter_gpu<ushort2>*/, bilateral_filter_gpu<ushort3> , bilateral_filter_gpu<ushort4> },
|
||||
{bilateral_filter_gpu<short> , 0 /*bilateral_filter_gpu<short2>*/ , bilateral_filter_gpu<short3> , bilateral_filter_gpu<short4> },
|
||||
{0 /*bilateral_filter_gpu<int>*/ , 0 /*bilateral_filter_gpu<int2>*/ , 0 /*bilateral_filter_gpu<int3>*/ , 0 /*bilateral_filter_gpu<int4>*/ },
|
||||
{bilateral_filter_gpu<float> , 0 /*bilateral_filter_gpu<float2>*/ , bilateral_filter_gpu<float3> , bilateral_filter_gpu<float4> }
|
||||
};
|
||||
|
||||
sigma_color = (sigma_color <= 0 ) ? 1 : sigma_color;
|
||||
sigma_spatial = (sigma_spatial <= 0 ) ? 1 : sigma_spatial;
|
||||
|
||||
|
||||
int radius = (kernel_size <= 0) ? cvRound(sigma_spatial*1.5) : kernel_size/2;
|
||||
kernel_size = std::max(radius, 1)*2 + 1;
|
||||
|
||||
CV_Assert(src.depth() <= CV_32F && src.channels() <= 4);
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
CV_Assert(borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP);
|
||||
|
||||
int gpuBorderType;
|
||||
CV_Assert(tryConvertToGpuBorderType(borderMode, gpuBorderType));
|
||||
|
||||
dst.create(src.size(), src.type());
|
||||
func(src, dst, kernel_size, sigma_spatial, sigma_color, gpuBorderType, StreamAccessor::getStream(s));
|
||||
}
|
||||
|
||||
void cv::gpu::nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window_size, int block_size, int borderMode, Stream& s)
|
||||
{
|
||||
using cv::gpu::device::imgproc::nlm_bruteforce_gpu;
|
||||
typedef void (*func_t)(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream);
|
||||
|
||||
static const func_t funcs[4] = { nlm_bruteforce_gpu<uchar>, 0 /*nlm_bruteforce_gpu<uchar2>*/ , nlm_bruteforce_gpu<uchar3>, 0/*nlm_bruteforce_gpu<uchar4>,*/ };
|
||||
|
||||
CV_Assert(src.type() == CV_8U || src.type() == CV_8UC3);
|
||||
|
||||
const func_t func = funcs[src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
int b = borderMode;
|
||||
CV_Assert(b == BORDER_REFLECT101 || b == BORDER_REPLICATE || b == BORDER_CONSTANT || b == BORDER_REFLECT || b == BORDER_WRAP);
|
||||
|
||||
int gpuBorderType;
|
||||
CV_Assert(tryConvertToGpuBorderType(borderMode, gpuBorderType));
|
||||
|
||||
int search_radius = search_window_size/2;
|
||||
int block_radius = block_size/2;
|
||||
|
||||
dst.create(src.size(), src.type());
|
||||
func(src, dst, search_radius, block_radius, h, gpuBorderType, StreamAccessor::getStream(s));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -239,8 +239,8 @@ void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf&
|
||||
|
||||
for(size_t j = 0; j < m.size(); ++j)
|
||||
{
|
||||
float dx = p.x - m[j].x;
|
||||
float dy = p.y - m[j].y;
|
||||
float dx = (float)(p.x - m[j].x);
|
||||
float dy = (float)(p.y - m[j].y);
|
||||
|
||||
if (dx * dx + dy * dy < minDist)
|
||||
{
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "saturate_cast.hpp"
|
||||
#include "vec_traits.hpp"
|
||||
#include "type_traits.hpp"
|
||||
#include "device_functions.h"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
@@ -408,6 +409,7 @@ namespace cv { namespace gpu { namespace device
|
||||
OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR(pow, ::pow)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_UN_FUNCTOR
|
||||
#undef OPENCV_GPU_IMPLEMENT_UN_FUNCTOR_NO_DOUBLE
|
||||
#undef OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR
|
||||
|
||||
template<typename T> struct hypot_sqr_func : binary_function<T, T, float>
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*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"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// BilateralFilter
|
||||
|
||||
PARAM_TEST_CASE(BilateralFilter, cv::gpu::DeviceInfo, cv::Size, MatType)
|
||||
{
|
||||
cv::gpu::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
int type;
|
||||
int kernel_size;
|
||||
float sigma_color;
|
||||
float sigma_spatial;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
|
||||
kernel_size = 5;
|
||||
sigma_color = 10.f;
|
||||
sigma_spatial = 3.5f;
|
||||
|
||||
cv::gpu::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(BilateralFilter, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
//cv::Mat src = readImage("hog/road.png", cv::IMREAD_GRAYSCALE);
|
||||
//cv::Mat src = readImage("csstereobp/aloe-R.png", cv::IMREAD_GRAYSCALE);
|
||||
|
||||
src.convertTo(src, type);
|
||||
cv::gpu::GpuMat dst;
|
||||
|
||||
cv::gpu::bilateralFilter(loadMat(src), dst, kernel_size, sigma_color, sigma_spatial);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::bilateralFilter(src, dst_gold, kernel_size, sigma_color, sigma_spatial);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-3 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(GPU_Denoising, BilateralFilter, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
testing::Values(cv::Size(128, 128), cv::Size(113, 113), cv::Size(639, 481)),
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_32FC1), MatType(CV_32FC3))
|
||||
));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Brute Force Non local means
|
||||
|
||||
struct NonLocalMeans: testing::TestWithParam<cv::gpu::DeviceInfo>
|
||||
{
|
||||
cv::gpu::DeviceInfo devInfo;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GetParam();
|
||||
cv::gpu::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(NonLocalMeans, Regression)
|
||||
{
|
||||
using cv::gpu::GpuMat;
|
||||
|
||||
cv::Mat bgr = readImage("denoising/lena_noised_gaussian_sigma=20_multi_0.png", cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(bgr.empty());
|
||||
|
||||
cv::Mat gray;
|
||||
cv::cvtColor(bgr, gray, CV_BGR2GRAY);
|
||||
|
||||
GpuMat dbgr, dgray;
|
||||
cv::gpu::nonLocalMeans(GpuMat(bgr), dbgr, 10);
|
||||
cv::gpu::nonLocalMeans(GpuMat(gray), dgray, 10);
|
||||
|
||||
#if 0
|
||||
dumpImage("denoising/denoised_lena_bgr.png", cv::Mat(dbgr));
|
||||
dumpImage("denoising/denoised_lena_gray.png", cv::Mat(dgray));
|
||||
#endif
|
||||
|
||||
cv::Mat bgr_gold = readImage("denoising/denoised_lena_bgr.png", cv::IMREAD_COLOR);
|
||||
cv::Mat gray_gold = readImage("denoising/denoised_lena_gray.png", cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(bgr_gold.empty() || gray_gold.empty());
|
||||
|
||||
EXPECT_MAT_NEAR(bgr_gold, dbgr, 1e-4);
|
||||
EXPECT_MAT_NEAR(gray_gold, dgray, 1e-4);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(GPU_Denoising, NonLocalMeans, ALL_DEVICES);
|
||||
|
||||
|
||||
#endif // HAVE_CUDA
|
||||
@@ -175,7 +175,8 @@ struct HOG : testing::TestWithParam<cv::gpu::DeviceInfo>, cv::gpu::HOGDescriptor
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(HOG, Detect)
|
||||
// desabled while resize does not fixed
|
||||
TEST_P(HOG, DISABLED_Detect)
|
||||
{
|
||||
cv::Mat img_rgb = readImage("hog/road.png");
|
||||
ASSERT_FALSE(img_rgb.empty());
|
||||
@@ -286,6 +287,54 @@ TEST_P(HOG, GetDescriptors)
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(GPU_ObjDetect, HOG, ALL_DEVICES);
|
||||
|
||||
//============== caltech hog tests =====================//
|
||||
struct CalTech : public ::testing::TestWithParam<std::tr1::tuple<cv::gpu::DeviceInfo, std::string> >
|
||||
{
|
||||
cv::gpu::DeviceInfo devInfo;
|
||||
cv::Mat img;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
cv::gpu::setDevice(devInfo.deviceID());
|
||||
|
||||
img = readImage(GET_PARAM(1), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(img.empty());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(CalTech, HOG)
|
||||
{
|
||||
cv::gpu::GpuMat d_img(img);
|
||||
cv::Mat markedImage(img.clone());
|
||||
|
||||
cv::gpu::HOGDescriptor d_hog;
|
||||
d_hog.setSVMDetector(cv::gpu::HOGDescriptor::getDefaultPeopleDetector());
|
||||
d_hog.nlevels = d_hog.nlevels + 32;
|
||||
|
||||
std::vector<cv::Rect> found_locations;
|
||||
d_hog.detectMultiScale(d_img, found_locations);
|
||||
|
||||
#if defined (LOG_CASCADE_STATISTIC)
|
||||
for (int i = 0; i < (int)found_locations.size(); i++)
|
||||
{
|
||||
cv::Rect r = found_locations[i];
|
||||
|
||||
std::cout << r.x << " " << r.y << " " << r.width << " " << r.height << std::endl;
|
||||
cv::rectangle(markedImage, r , CV_RGB(255, 0, 0));
|
||||
}
|
||||
|
||||
cv::imshow("Res", markedImage); cv::waitKey();
|
||||
#endif
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(detect, CalTech, testing::Combine(ALL_DEVICES,
|
||||
::testing::Values<std::string>("caltech/image_00000009_0.png", "caltech/image_00000032_0.png",
|
||||
"caltech/image_00000165_0.png", "caltech/image_00000261_0.png", "caltech/image_00000469_0.png",
|
||||
"caltech/image_00000527_0.png", "caltech/image_00000574_0.png")));
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// LBP classifier
|
||||
|
||||
@@ -127,6 +127,14 @@ Mat readImageType(const std::string& fname, int type)
|
||||
return src;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Image dumping
|
||||
|
||||
void dumpImage(const std::string& fileName, const cv::Mat& image)
|
||||
{
|
||||
cv::imwrite(TS::ptr()->get_data_path() + fileName, image);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Gpu devices
|
||||
|
||||
|
||||
@@ -74,6 +74,11 @@ cv::Mat readImage(const std::string& fileName, int flags = cv::IMREAD_COLOR);
|
||||
//! read image from testdata folder and convert it to specified type
|
||||
cv::Mat readImageType(const std::string& fname, int type);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Image dumping
|
||||
|
||||
void dumpImage(const std::string& fileName, const cv::Mat& image);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Gpu devices
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ if(WITH_JASPER)
|
||||
list(APPEND GRFMT_LIBS ${JASPER_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_OPENEXR AND OPENEXR_FOUND)
|
||||
if(WITH_OPENEXR)
|
||||
add_definitions(-DHAVE_OPENEXR)
|
||||
ocv_include_directories(${OPENEXR_INCLUDE_PATHS})
|
||||
include_directories(SYSTEM ${OPENEXR_INCLUDE_PATHS})
|
||||
list(APPEND GRFMT_LIBS ${OPENEXR_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -48,15 +48,14 @@
|
||||
#include <android/log.h>
|
||||
#include <camera_activity.hpp>
|
||||
|
||||
//#if !defined(LOGD) && !defined(LOGI) && !defined(LOGE)
|
||||
#undef LOG_TAG
|
||||
#undef LOGD
|
||||
#undef LOGE
|
||||
#undef LOGI
|
||||
#define LOG_TAG "CV_CAP"
|
||||
#define LOG_TAG "OpenCV::camera"
|
||||
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
//#endif
|
||||
|
||||
class HighguiAndroidCameraActivity;
|
||||
|
||||
|
||||
@@ -2050,7 +2050,7 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret == (int64_t)AVERROR_EOF)
|
||||
if (ret == AVERROR_EOF)
|
||||
*endOfFile = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -956,6 +956,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
|
||||
if (capture->memoryMap == MAP_FAILED) {
|
||||
fprintf( stderr, "HIGHGUI ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
|
||||
icvCloseCAM_V4L(capture);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up video_mmap structure pointing to this memory mapped area so each image may be
|
||||
@@ -1709,6 +1710,7 @@ static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
|
||||
}
|
||||
#endif
|
||||
|
||||
free(capture->deviceName);
|
||||
//v4l2_free_ranges(capture);
|
||||
//cvFree((void **)capture);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
|
||||
#ifdef HAVE_OPENEXR
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER >= 1200
|
||||
# pragma warning( disable: 4100 4244 4267 )
|
||||
#endif
|
||||
|
||||
#include <ImfHeader.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
@@ -52,12 +56,7 @@
|
||||
#include <half.h>
|
||||
#include "grfmt_exr.hpp"
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER >= 1200
|
||||
#pragma comment(lib, "Half.lib")
|
||||
#pragma comment(lib, "Iex.lib")
|
||||
#pragma comment(lib, "IlmImf.lib")
|
||||
#pragma comment(lib, "IlmThread.lib")
|
||||
#pragma comment(lib, "Imath.lib")
|
||||
#if defined _WIN32
|
||||
|
||||
#undef UINT
|
||||
#define UINT ((Imf::PixelType)0)
|
||||
|
||||
@@ -1271,10 +1271,10 @@ struct ResizeAreaFast_2x2_8u
|
||||
for( ; dx < w; dx += 4 )
|
||||
{
|
||||
int index = dx*2;
|
||||
D[dx] = (S[index] + S[index+3] + nextS[index] + nextS[index+3] + 2) >> 2;
|
||||
D[dx+1] = (S[index+1] + S[index+4] + nextS[index+1] + nextS[index+4] + 2) >> 2;
|
||||
D[dx+2] = (S[index+2] + S[index+5] + nextS[index+2] + nextS[index+5] + 2) >> 2;
|
||||
D[dx+3] = (S[index+3] + S[index+6] + nextS[index+3] + nextS[index+6] + 2) >> 2;
|
||||
D[dx] = (S[index] + S[index+4] + nextS[index] + nextS[index+4] + 2) >> 2;
|
||||
D[dx+1] = (S[index+1] + S[index+5] + nextS[index+1] + nextS[index+5] + 2) >> 2;
|
||||
D[dx+2] = (S[index+2] + S[index+6] + nextS[index+2] + nextS[index+6] + 2) >> 2;
|
||||
D[dx+3] = (S[index+3] + S[index+7] + nextS[index+3] + nextS[index+7] + 2) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1314,7 +1314,7 @@ public:
|
||||
ssize.width *= cn;
|
||||
int dy, dx, k = 0;
|
||||
|
||||
VecOp vop(scale_x, scale_y, src.channels(), src.step/*, area_ofs*/);
|
||||
VecOp vop(scale_x, scale_y, src.channels(), (int)src.step/*, area_ofs*/);
|
||||
|
||||
for( dy = range.start; dy < range.end; dy++ )
|
||||
{
|
||||
|
||||
+556
-142
@@ -197,6 +197,420 @@ template<typename ST, typename T> struct ColumnSum : public BaseColumnFilter
|
||||
};
|
||||
|
||||
|
||||
template<> struct ColumnSum<int, uchar> : public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
scale = _scale;
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
int* SUM;
|
||||
bool haveScale = scale != 1;
|
||||
double _scale = scale;
|
||||
|
||||
#if CV_SSE2
|
||||
bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
|
||||
if( width != (int)sum.size() )
|
||||
{
|
||||
sum.resize(width);
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
SUM = &sum[0];
|
||||
if( sumCount == 0 )
|
||||
{
|
||||
memset((void*)SUM, 0, width*sizeof(int));
|
||||
for( ; sumCount < ksize - 1; sumCount++, src++ )
|
||||
{
|
||||
const int* Sp = (const int*)src[0];
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
for( ; i < width-4; i+=4 )
|
||||
{
|
||||
__m128i _sum = _mm_loadu_si128((const __m128i*)(SUM+i));
|
||||
__m128i _sp = _mm_loadu_si128((const __m128i*)(Sp+i));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i),_mm_add_epi32(_sum, _sp));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < width; i++ )
|
||||
SUM[i] += Sp[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( sumCount == ksize-1 );
|
||||
src += ksize-1;
|
||||
}
|
||||
|
||||
for( ; count--; src++ )
|
||||
{
|
||||
const int* Sp = (const int*)src[0];
|
||||
const int* Sm = (const int*)src[1-ksize];
|
||||
uchar* D = (uchar*)dst;
|
||||
if( haveScale )
|
||||
{
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
const __m128 scale4 = _mm_set1_ps((float)_scale);
|
||||
for( ; i < width-8; i+=8 )
|
||||
{
|
||||
__m128i _sm = _mm_loadu_si128((const __m128i*)(Sm+i));
|
||||
__m128i _sm1 = _mm_loadu_si128((const __m128i*)(Sm+i+4));
|
||||
|
||||
__m128i _s0 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i)));
|
||||
__m128i _s01 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i+4)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i+4)));
|
||||
|
||||
__m128i _s0T = _mm_cvtps_epi32(_mm_mul_ps(scale4, _mm_cvtepi32_ps(_s0)));
|
||||
__m128i _s0T1 = _mm_cvtps_epi32(_mm_mul_ps(scale4, _mm_cvtepi32_ps(_s01)));
|
||||
|
||||
_s0T = _mm_packs_epi32(_s0T, _s0T1);
|
||||
|
||||
_mm_storel_epi64((__m128i*)(D+i), _mm_packus_epi16(_s0T, _s0T));
|
||||
|
||||
_mm_storeu_si128((__m128i*)(SUM+i), _mm_sub_epi32(_s0,_sm));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i+4),_mm_sub_epi32(_s01,_sm1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < width; i++ )
|
||||
{
|
||||
int s0 = SUM[i] + Sp[i];
|
||||
D[i] = saturate_cast<uchar>(s0*_scale);
|
||||
SUM[i] = s0 - Sm[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
for( ; i < width-8; i+=8 )
|
||||
{
|
||||
__m128i _sm = _mm_loadu_si128((const __m128i*)(Sm+i));
|
||||
__m128i _sm1 = _mm_loadu_si128((const __m128i*)(Sm+i+4));
|
||||
|
||||
__m128i _s0 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i)));
|
||||
__m128i _s01 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i+4)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i+4)));
|
||||
|
||||
__m128i _s0T = _mm_packs_epi32(_s0, _s01);
|
||||
|
||||
_mm_storel_epi64((__m128i*)(D+i), _mm_packus_epi16(_s0T, _s0T));
|
||||
|
||||
_mm_storeu_si128((__m128i*)(SUM+i), _mm_sub_epi32(_s0,_sm));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i+4),_mm_sub_epi32(_s01,_sm1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; i < width; i++ )
|
||||
{
|
||||
int s0 = SUM[i] + Sp[i];
|
||||
D[i] = saturate_cast<uchar>(s0);
|
||||
SUM[i] = s0 - Sm[i];
|
||||
}
|
||||
}
|
||||
dst += dststep;
|
||||
}
|
||||
}
|
||||
|
||||
double scale;
|
||||
int sumCount;
|
||||
vector<int> sum;
|
||||
};
|
||||
|
||||
template<> struct ColumnSum<int, short> : public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
scale = _scale;
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
int* SUM;
|
||||
bool haveScale = scale != 1;
|
||||
double _scale = scale;
|
||||
|
||||
#if CV_SSE2
|
||||
bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
|
||||
if( width != (int)sum.size() )
|
||||
{
|
||||
sum.resize(width);
|
||||
sumCount = 0;
|
||||
}
|
||||
SUM = &sum[0];
|
||||
if( sumCount == 0 )
|
||||
{
|
||||
memset((void*)SUM, 0, width*sizeof(int));
|
||||
for( ; sumCount < ksize - 1; sumCount++, src++ )
|
||||
{
|
||||
const int* Sp = (const int*)src[0];
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
for( ; i < width-4; i+=4 )
|
||||
{
|
||||
__m128i _sum = _mm_loadu_si128((const __m128i*)(SUM+i));
|
||||
__m128i _sp = _mm_loadu_si128((const __m128i*)(Sp+i));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i),_mm_add_epi32(_sum, _sp));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < width; i++ )
|
||||
SUM[i] += Sp[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( sumCount == ksize-1 );
|
||||
src += ksize-1;
|
||||
}
|
||||
|
||||
for( ; count--; src++ )
|
||||
{
|
||||
const int* Sp = (const int*)src[0];
|
||||
const int* Sm = (const int*)src[1-ksize];
|
||||
short* D = (short*)dst;
|
||||
if( haveScale )
|
||||
{
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
const __m128 scale4 = _mm_set1_ps((float)_scale);
|
||||
for( ; i < width-8; i+=8 )
|
||||
{
|
||||
__m128i _sm = _mm_loadu_si128((const __m128i*)(Sm+i));
|
||||
__m128i _sm1 = _mm_loadu_si128((const __m128i*)(Sm+i+4));
|
||||
|
||||
__m128i _s0 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i)));
|
||||
__m128i _s01 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i+4)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i+4)));
|
||||
|
||||
__m128i _s0T = _mm_cvtps_epi32(_mm_mul_ps(scale4, _mm_cvtepi32_ps(_s0)));
|
||||
__m128i _s0T1 = _mm_cvtps_epi32(_mm_mul_ps(scale4, _mm_cvtepi32_ps(_s01)));
|
||||
|
||||
_mm_storeu_si128((__m128i*)(D+i), _mm_packs_epi32(_s0T, _s0T1));
|
||||
|
||||
_mm_storeu_si128((__m128i*)(SUM+i),_mm_sub_epi32(_s0,_sm));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i+4), _mm_sub_epi32(_s01,_sm1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < width; i++ )
|
||||
{
|
||||
int s0 = SUM[i] + Sp[i];
|
||||
D[i] = saturate_cast<short>(s0*_scale);
|
||||
SUM[i] = s0 - Sm[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
for( ; i < width-8; i+=8 )
|
||||
{
|
||||
|
||||
__m128i _sm = _mm_loadu_si128((const __m128i*)(Sm+i));
|
||||
__m128i _sm1 = _mm_loadu_si128((const __m128i*)(Sm+i+4));
|
||||
|
||||
__m128i _s0 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i)));
|
||||
__m128i _s01 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i+4)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i+4)));
|
||||
|
||||
_mm_storeu_si128((__m128i*)(D+i), _mm_packs_epi32(_s0, _s01));
|
||||
|
||||
_mm_storeu_si128((__m128i*)(SUM+i), _mm_sub_epi32(_s0,_sm));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i+4),_mm_sub_epi32(_s01,_sm1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; i < width; i++ )
|
||||
{
|
||||
int s0 = SUM[i] + Sp[i];
|
||||
D[i] = saturate_cast<short>(s0);
|
||||
SUM[i] = s0 - Sm[i];
|
||||
}
|
||||
}
|
||||
dst += dststep;
|
||||
}
|
||||
}
|
||||
|
||||
double scale;
|
||||
int sumCount;
|
||||
vector<int> sum;
|
||||
};
|
||||
|
||||
|
||||
template<> struct ColumnSum<int, ushort> : public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
scale = _scale;
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
int* SUM;
|
||||
bool haveScale = scale != 1;
|
||||
double _scale = scale;
|
||||
#if CV_SSE2
|
||||
bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
|
||||
if( width != (int)sum.size() )
|
||||
{
|
||||
sum.resize(width);
|
||||
sumCount = 0;
|
||||
}
|
||||
SUM = &sum[0];
|
||||
if( sumCount == 0 )
|
||||
{
|
||||
memset((void*)SUM, 0, width*sizeof(int));
|
||||
for( ; sumCount < ksize - 1; sumCount++, src++ )
|
||||
{
|
||||
const int* Sp = (const int*)src[0];
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
for( ; i < width-4; i+=4 )
|
||||
{
|
||||
__m128i _sum = _mm_loadu_si128((const __m128i*)(SUM+i));
|
||||
__m128i _sp = _mm_loadu_si128((const __m128i*)(Sp+i));
|
||||
_mm_storeu_si128((__m128i*)(SUM+i), _mm_add_epi32(_sum, _sp));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < width; i++ )
|
||||
SUM[i] += Sp[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( sumCount == ksize-1 );
|
||||
src += ksize-1;
|
||||
}
|
||||
|
||||
for( ; count--; src++ )
|
||||
{
|
||||
const int* Sp = (const int*)src[0];
|
||||
const int* Sm = (const int*)src[1-ksize];
|
||||
ushort* D = (ushort*)dst;
|
||||
if( haveScale )
|
||||
{
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
const __m128 scale4 = _mm_set1_ps((float)_scale);
|
||||
const __m128i delta0 = _mm_set1_epi32(0x8000);
|
||||
const __m128i delta1 = _mm_set1_epi32(0x80008000);
|
||||
|
||||
for( ; i < width-4; i+=4)
|
||||
{
|
||||
__m128i _sm = _mm_loadu_si128((const __m128i*)(Sm+i));
|
||||
__m128i _s0 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i)));
|
||||
|
||||
__m128i _res = _mm_cvtps_epi32(_mm_mul_ps(scale4, _mm_cvtepi32_ps(_s0)));
|
||||
|
||||
_res = _mm_sub_epi32(_res, delta0);
|
||||
_res = _mm_add_epi16(_mm_packs_epi16(_res, _res), delta1);
|
||||
|
||||
_mm_storel_epi64((__m128i*)(D+i), _res);
|
||||
_mm_storeu_si128((__m128i*)(SUM+i), _mm_sub_epi32(_s0,_sm));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; i < width; i++ )
|
||||
{
|
||||
int s0 = SUM[i] + Sp[i];
|
||||
D[i] = saturate_cast<ushort>(s0*_scale);
|
||||
SUM[i] = s0 - Sm[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
#if CV_SSE2
|
||||
if(haveSSE2)
|
||||
{
|
||||
const __m128i delta0 = _mm_set1_epi32(0x8000);
|
||||
const __m128i delta1 = _mm_set1_epi32(0x80008000);
|
||||
|
||||
for( ; i < width-4; i+=4 )
|
||||
{
|
||||
__m128i _sm = _mm_loadu_si128((const __m128i*)(Sm+i));
|
||||
__m128i _s0 = _mm_add_epi32(_mm_loadu_si128((const __m128i*)(SUM+i)),
|
||||
_mm_loadu_si128((const __m128i*)(Sp+i)));
|
||||
|
||||
__m128i _res = _mm_sub_epi32(_s0, delta0);
|
||||
_res = _mm_add_epi16(_mm_packs_epi16(_res, _res), delta1);
|
||||
|
||||
_mm_storel_epi64((__m128i*)(D+i), _res);
|
||||
_mm_storeu_si128((__m128i*)(SUM+i), _mm_sub_epi32(_s0,_sm));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; i < width; i++ )
|
||||
{
|
||||
int s0 = SUM[i] + Sp[i];
|
||||
D[i] = saturate_cast<ushort>(s0);
|
||||
SUM[i] = s0 - Sm[i];
|
||||
}
|
||||
}
|
||||
dst += dststep;
|
||||
}
|
||||
}
|
||||
|
||||
double scale;
|
||||
int sumCount;
|
||||
vector<int> sum;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
cv::Ptr<cv::BaseRowFilter> cv::getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
|
||||
@@ -1303,12 +1717,12 @@ public:
|
||||
{
|
||||
int i, j, cn = dest->channels(), k;
|
||||
Size size = dest->size();
|
||||
#if CV_SSE3
|
||||
#if CV_SSE3
|
||||
int CV_DECL_ALIGNED(16) buf[4];
|
||||
float CV_DECL_ALIGNED(16) bufSum[4];
|
||||
static const int CV_DECL_ALIGNED(16) bufSignMask[] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
||||
bool haveSSE3 = checkHardwareSupport(CV_CPU_SSE3);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for( i = range.start; i < range.end; i++ )
|
||||
{
|
||||
@@ -1321,36 +1735,36 @@ public:
|
||||
{
|
||||
float sum = 0, wsum = 0;
|
||||
int val0 = sptr[j];
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
__m128 _val0 = _mm_set1_ps(val0);
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
__m128 _val0 = _mm_set1_ps(static_cast<float>(val0));
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
|
||||
for( ; k <= maxk - 4; k += 4 )
|
||||
{
|
||||
__m128 _valF = _mm_set_ps(sptr[j + space_ofs[k+3]], sptr[j + space_ofs[k+2]],
|
||||
for( ; k <= maxk - 4; k += 4 )
|
||||
{
|
||||
__m128 _valF = _mm_set_ps(sptr[j + space_ofs[k+3]], sptr[j + space_ofs[k+2]],
|
||||
sptr[j + space_ofs[k+1]], sptr[j + space_ofs[k]]);
|
||||
|
||||
__m128 _val = _mm_andnot_ps(_signMask, _mm_sub_ps(_valF, _val0));
|
||||
_mm_store_si128((__m128i*)buf, _mm_cvtps_epi32(_val));
|
||||
|
||||
__m128 _val = _mm_andnot_ps(_signMask, _mm_sub_ps(_valF, _val0));
|
||||
_mm_store_si128((__m128i*)buf, _mm_cvtps_epi32(_val));
|
||||
|
||||
__m128 _cw = _mm_set_ps(color_weight[buf[3]],color_weight[buf[2]],
|
||||
__m128 _cw = _mm_set_ps(color_weight[buf[3]],color_weight[buf[2]],
|
||||
color_weight[buf[1]],color_weight[buf[0]]);
|
||||
__m128 _sw = _mm_loadu_ps(space_weight+k);
|
||||
__m128 _w = _mm_mul_ps(_cw, _sw);
|
||||
_cw = _mm_mul_ps(_w, _valF);
|
||||
__m128 _sw = _mm_loadu_ps(space_weight+k);
|
||||
__m128 _w = _mm_mul_ps(_cw, _sw);
|
||||
_cw = _mm_mul_ps(_w, _valF);
|
||||
|
||||
_sw = _mm_hadd_ps(_w, _cw);
|
||||
_sw = _mm_hadd_ps(_sw, _sw);
|
||||
_mm_storel_pi((__m64*)bufSum, _sw);
|
||||
_sw = _mm_hadd_ps(_w, _cw);
|
||||
_sw = _mm_hadd_ps(_sw, _sw);
|
||||
_mm_storel_pi((__m64*)bufSum, _sw);
|
||||
|
||||
sum += bufSum[1];
|
||||
wsum += bufSum[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sum += bufSum[1];
|
||||
wsum += bufSum[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; k < maxk; k++ )
|
||||
{
|
||||
int val = sptr[j + space_ofs[k]];
|
||||
@@ -1369,55 +1783,55 @@ public:
|
||||
{
|
||||
float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
|
||||
int b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
const __m128 _b0 = _mm_set1_ps(b0);
|
||||
const __m128 _g0 = _mm_set1_ps(g0);
|
||||
const __m128 _r0 = _mm_set1_ps(r0);
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
const __m128 _b0 = _mm_set1_ps(static_cast<float>(b0));
|
||||
const __m128 _g0 = _mm_set1_ps(static_cast<float>(g0));
|
||||
const __m128 _r0 = _mm_set1_ps(static_cast<float>(r0));
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
|
||||
for( ; k <= maxk - 4; k += 4 )
|
||||
{
|
||||
const uchar* sptr_k = sptr + j + space_ofs[k];
|
||||
const uchar* sptr_k1 = sptr + j + space_ofs[k+1];
|
||||
const uchar* sptr_k2 = sptr + j + space_ofs[k+2];
|
||||
const uchar* sptr_k3 = sptr + j + space_ofs[k+3];
|
||||
const uchar* sptr_k = sptr + j + space_ofs[k];
|
||||
const uchar* sptr_k1 = sptr + j + space_ofs[k+1];
|
||||
const uchar* sptr_k2 = sptr + j + space_ofs[k+2];
|
||||
const uchar* sptr_k3 = sptr + j + space_ofs[k+3];
|
||||
|
||||
__m128 _b = _mm_set_ps(sptr_k3[0],sptr_k2[0],sptr_k1[0],sptr_k[0]);
|
||||
__m128 _g = _mm_set_ps(sptr_k3[1],sptr_k2[1],sptr_k1[1],sptr_k[1]);
|
||||
__m128 _r = _mm_set_ps(sptr_k3[2],sptr_k2[2],sptr_k1[2],sptr_k[2]);
|
||||
__m128 _b = _mm_set_ps(sptr_k3[0],sptr_k2[0],sptr_k1[0],sptr_k[0]);
|
||||
__m128 _g = _mm_set_ps(sptr_k3[1],sptr_k2[1],sptr_k1[1],sptr_k[1]);
|
||||
__m128 _r = _mm_set_ps(sptr_k3[2],sptr_k2[2],sptr_k1[2],sptr_k[2]);
|
||||
|
||||
__m128 bt = _mm_andnot_ps(_signMask, _mm_sub_ps(_b,_b0));
|
||||
__m128 gt = _mm_andnot_ps(_signMask, _mm_sub_ps(_g,_g0));
|
||||
__m128 rt = _mm_andnot_ps(_signMask, _mm_sub_ps(_r,_r0));
|
||||
__m128 bt = _mm_andnot_ps(_signMask, _mm_sub_ps(_b,_b0));
|
||||
__m128 gt = _mm_andnot_ps(_signMask, _mm_sub_ps(_g,_g0));
|
||||
__m128 rt = _mm_andnot_ps(_signMask, _mm_sub_ps(_r,_r0));
|
||||
|
||||
bt =_mm_add_ps(rt, _mm_add_ps(bt, gt));
|
||||
_mm_store_si128((__m128i*)buf, _mm_cvtps_epi32(bt));
|
||||
bt =_mm_add_ps(rt, _mm_add_ps(bt, gt));
|
||||
_mm_store_si128((__m128i*)buf, _mm_cvtps_epi32(bt));
|
||||
|
||||
__m128 _w = _mm_set_ps(color_weight[buf[3]],color_weight[buf[2]],
|
||||
__m128 _w = _mm_set_ps(color_weight[buf[3]],color_weight[buf[2]],
|
||||
color_weight[buf[1]],color_weight[buf[0]]);
|
||||
__m128 _sw = _mm_loadu_ps(space_weight+k);
|
||||
__m128 _sw = _mm_loadu_ps(space_weight+k);
|
||||
|
||||
_w = _mm_mul_ps(_w,_sw);
|
||||
_b = _mm_mul_ps(_b, _w);
|
||||
_g = _mm_mul_ps(_g, _w);
|
||||
_r = _mm_mul_ps(_r, _w);
|
||||
_w = _mm_mul_ps(_w,_sw);
|
||||
_b = _mm_mul_ps(_b, _w);
|
||||
_g = _mm_mul_ps(_g, _w);
|
||||
_r = _mm_mul_ps(_r, _w);
|
||||
|
||||
_w = _mm_hadd_ps(_w, _b);
|
||||
_g = _mm_hadd_ps(_g, _r);
|
||||
_w = _mm_hadd_ps(_w, _b);
|
||||
_g = _mm_hadd_ps(_g, _r);
|
||||
|
||||
_w = _mm_hadd_ps(_w, _g);
|
||||
_mm_store_ps(bufSum, _w);
|
||||
_w = _mm_hadd_ps(_w, _g);
|
||||
_mm_store_ps(bufSum, _w);
|
||||
|
||||
wsum += bufSum[0];
|
||||
sum_b += bufSum[1];
|
||||
sum_g += bufSum[2];
|
||||
sum_r += bufSum[3];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
wsum += bufSum[0];
|
||||
sum_b += bufSum[1];
|
||||
sum_g += bufSum[2];
|
||||
sum_r += bufSum[3];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; k < maxk; k++ )
|
||||
{
|
||||
@@ -1491,8 +1905,8 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
|
||||
// initialize space-related bilateral filter coefficients
|
||||
for( i = -radius, maxk = 0; i <= radius; i++ )
|
||||
{
|
||||
j = -radius;
|
||||
{
|
||||
j = -radius;
|
||||
|
||||
for( ;j <= radius; j++ )
|
||||
{
|
||||
@@ -1502,7 +1916,7 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
|
||||
space_ofs[maxk++] = (int)(i*temp.step + j*cn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BilateralFilter_8u_Invoker body(dst, temp, radius, maxk, space_ofs, space_weight, color_weight);
|
||||
parallel_for_(Range(0, size.height), body);
|
||||
@@ -1525,12 +1939,12 @@ public:
|
||||
{
|
||||
int i, j, k;
|
||||
Size size = dest->size();
|
||||
#if CV_SSE3
|
||||
#if CV_SSE3
|
||||
int CV_DECL_ALIGNED(16) idxBuf[4];
|
||||
float CV_DECL_ALIGNED(16) bufSum32[4];
|
||||
static const int CV_DECL_ALIGNED(16) bufSignMask[] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
||||
bool haveSSE3 = checkHardwareSupport(CV_CPU_SSE3);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for( i = range.start; i < range.end; i++ )
|
||||
{
|
||||
@@ -1543,42 +1957,42 @@ public:
|
||||
{
|
||||
float sum = 0, wsum = 0;
|
||||
float val0 = sptr[j];
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
const __m128 _val0 = _mm_set1_ps(sptr[j]);
|
||||
const __m128 _scale_index = _mm_set1_ps(scale_index);
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
|
||||
for( ; k <= maxk - 4 ; k += 4 )
|
||||
{
|
||||
__m128 _sw = _mm_loadu_ps(space_weight + k);
|
||||
__m128 _val = _mm_set_ps(sptr[j + space_ofs[k+3]], sptr[j + space_ofs[k+2]],
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
const __m128 _val0 = _mm_set1_ps(sptr[j]);
|
||||
const __m128 _scale_index = _mm_set1_ps(scale_index);
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
|
||||
for( ; k <= maxk - 4 ; k += 4 )
|
||||
{
|
||||
__m128 _sw = _mm_loadu_ps(space_weight + k);
|
||||
__m128 _val = _mm_set_ps(sptr[j + space_ofs[k+3]], sptr[j + space_ofs[k+2]],
|
||||
sptr[j + space_ofs[k+1]], sptr[j + space_ofs[k]]);
|
||||
__m128 _alpha = _mm_mul_ps(_mm_andnot_ps( _signMask, _mm_sub_ps(_val,_val0)), _scale_index);
|
||||
__m128 _alpha = _mm_mul_ps(_mm_andnot_ps( _signMask, _mm_sub_ps(_val,_val0)), _scale_index);
|
||||
|
||||
__m128i _idx = _mm_cvtps_epi32(_alpha);
|
||||
_mm_store_si128((__m128i*)idxBuf, _idx);
|
||||
_alpha = _mm_sub_ps(_alpha, _mm_cvtepi32_ps(_idx));
|
||||
__m128i _idx = _mm_cvtps_epi32(_alpha);
|
||||
_mm_store_si128((__m128i*)idxBuf, _idx);
|
||||
_alpha = _mm_sub_ps(_alpha, _mm_cvtepi32_ps(_idx));
|
||||
|
||||
__m128 _explut = _mm_set_ps(expLUT[idxBuf[3]], expLUT[idxBuf[2]],
|
||||
__m128 _explut = _mm_set_ps(expLUT[idxBuf[3]], expLUT[idxBuf[2]],
|
||||
expLUT[idxBuf[1]], expLUT[idxBuf[0]]);
|
||||
__m128 _explut1 = _mm_set_ps(expLUT[idxBuf[3]+1], expLUT[idxBuf[2]+1],
|
||||
__m128 _explut1 = _mm_set_ps(expLUT[idxBuf[3]+1], expLUT[idxBuf[2]+1],
|
||||
expLUT[idxBuf[1]+1], expLUT[idxBuf[0]+1]);
|
||||
|
||||
__m128 _w = _mm_mul_ps(_sw, _mm_add_ps(_explut, _mm_mul_ps(_alpha, _mm_sub_ps(_explut1, _explut))));
|
||||
_val = _mm_mul_ps(_w, _val);
|
||||
|
||||
__m128 _w = _mm_mul_ps(_sw, _mm_add_ps(_explut, _mm_mul_ps(_alpha, _mm_sub_ps(_explut1, _explut))));
|
||||
_val = _mm_mul_ps(_w, _val);
|
||||
|
||||
_sw = _mm_hadd_ps(_w, _val);
|
||||
_sw = _mm_hadd_ps(_sw, _sw);
|
||||
_mm_storel_pi((__m64*)bufSum32, _sw);
|
||||
_sw = _mm_hadd_ps(_w, _val);
|
||||
_sw = _mm_hadd_ps(_sw, _sw);
|
||||
_mm_storel_pi((__m64*)bufSum32, _sw);
|
||||
|
||||
sum += bufSum32[1];
|
||||
wsum += bufSum32[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sum += bufSum32[1];
|
||||
wsum += bufSum32[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; k < maxk; k++ )
|
||||
{
|
||||
@@ -1600,63 +2014,63 @@ public:
|
||||
{
|
||||
float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
|
||||
float b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
const __m128 _b0 = _mm_set1_ps(b0);
|
||||
const __m128 _g0 = _mm_set1_ps(g0);
|
||||
const __m128 _r0 = _mm_set1_ps(r0);
|
||||
const __m128 _scale_index = _mm_set1_ps(scale_index);
|
||||
k = 0;
|
||||
#if CV_SSE3
|
||||
if( haveSSE3 )
|
||||
{
|
||||
const __m128 _b0 = _mm_set1_ps(b0);
|
||||
const __m128 _g0 = _mm_set1_ps(g0);
|
||||
const __m128 _r0 = _mm_set1_ps(r0);
|
||||
const __m128 _scale_index = _mm_set1_ps(scale_index);
|
||||
const __m128 _signMask = _mm_load_ps((const float*)bufSignMask);
|
||||
|
||||
for( ; k <= maxk-4; k += 4 )
|
||||
{
|
||||
__m128 _sw = _mm_loadu_ps(space_weight + k);
|
||||
|
||||
for( ; k <= maxk-4; k += 4 )
|
||||
{
|
||||
__m128 _sw = _mm_loadu_ps(space_weight + k);
|
||||
|
||||
const float* sptr_k = sptr + j + space_ofs[k];
|
||||
const float* sptr_k1 = sptr + j + space_ofs[k+1];
|
||||
const float* sptr_k2 = sptr + j + space_ofs[k+2];
|
||||
const float* sptr_k3 = sptr + j + space_ofs[k+3];
|
||||
const float* sptr_k = sptr + j + space_ofs[k];
|
||||
const float* sptr_k1 = sptr + j + space_ofs[k+1];
|
||||
const float* sptr_k2 = sptr + j + space_ofs[k+2];
|
||||
const float* sptr_k3 = sptr + j + space_ofs[k+3];
|
||||
|
||||
__m128 _b = _mm_set_ps(sptr_k3[0], sptr_k2[0], sptr_k1[0], sptr_k[0]);
|
||||
__m128 _g = _mm_set_ps(sptr_k3[1], sptr_k2[1], sptr_k1[1], sptr_k[1]);
|
||||
__m128 _r = _mm_set_ps(sptr_k3[2], sptr_k2[2], sptr_k1[2], sptr_k[2]);
|
||||
__m128 _b = _mm_set_ps(sptr_k3[0], sptr_k2[0], sptr_k1[0], sptr_k[0]);
|
||||
__m128 _g = _mm_set_ps(sptr_k3[1], sptr_k2[1], sptr_k1[1], sptr_k[1]);
|
||||
__m128 _r = _mm_set_ps(sptr_k3[2], sptr_k2[2], sptr_k1[2], sptr_k[2]);
|
||||
|
||||
__m128 _bt = _mm_andnot_ps(_signMask,_mm_sub_ps(_b,_b0));
|
||||
__m128 _gt = _mm_andnot_ps(_signMask,_mm_sub_ps(_g,_g0));
|
||||
__m128 _rt = _mm_andnot_ps(_signMask,_mm_sub_ps(_r,_r0));
|
||||
__m128 _bt = _mm_andnot_ps(_signMask,_mm_sub_ps(_b,_b0));
|
||||
__m128 _gt = _mm_andnot_ps(_signMask,_mm_sub_ps(_g,_g0));
|
||||
__m128 _rt = _mm_andnot_ps(_signMask,_mm_sub_ps(_r,_r0));
|
||||
|
||||
__m128 _alpha = _mm_mul_ps(_scale_index, _mm_add_ps(_rt,_mm_add_ps(_bt, _gt)));
|
||||
__m128 _alpha = _mm_mul_ps(_scale_index, _mm_add_ps(_rt,_mm_add_ps(_bt, _gt)));
|
||||
|
||||
__m128i _idx = _mm_cvtps_epi32(_alpha);
|
||||
_mm_store_si128((__m128i*)idxBuf, _idx);
|
||||
_alpha = _mm_sub_ps(_alpha, _mm_cvtepi32_ps(_idx));
|
||||
__m128i _idx = _mm_cvtps_epi32(_alpha);
|
||||
_mm_store_si128((__m128i*)idxBuf, _idx);
|
||||
_alpha = _mm_sub_ps(_alpha, _mm_cvtepi32_ps(_idx));
|
||||
|
||||
__m128 _explut = _mm_set_ps(expLUT[idxBuf[3]], expLUT[idxBuf[2]], expLUT[idxBuf[1]], expLUT[idxBuf[0]]);
|
||||
__m128 _explut1 = _mm_set_ps(expLUT[idxBuf[3]+1], expLUT[idxBuf[2]+1], expLUT[idxBuf[1]+1], expLUT[idxBuf[0]+1]);
|
||||
|
||||
__m128 _w = _mm_mul_ps(_sw, _mm_add_ps(_explut, _mm_mul_ps(_alpha, _mm_sub_ps(_explut1, _explut))));
|
||||
__m128 _explut = _mm_set_ps(expLUT[idxBuf[3]], expLUT[idxBuf[2]], expLUT[idxBuf[1]], expLUT[idxBuf[0]]);
|
||||
__m128 _explut1 = _mm_set_ps(expLUT[idxBuf[3]+1], expLUT[idxBuf[2]+1], expLUT[idxBuf[1]+1], expLUT[idxBuf[0]+1]);
|
||||
|
||||
__m128 _w = _mm_mul_ps(_sw, _mm_add_ps(_explut, _mm_mul_ps(_alpha, _mm_sub_ps(_explut1, _explut))));
|
||||
|
||||
_b = _mm_mul_ps(_b, _w);
|
||||
_g = _mm_mul_ps(_g, _w);
|
||||
_r = _mm_mul_ps(_r, _w);
|
||||
_b = _mm_mul_ps(_b, _w);
|
||||
_g = _mm_mul_ps(_g, _w);
|
||||
_r = _mm_mul_ps(_r, _w);
|
||||
|
||||
_w = _mm_hadd_ps(_w, _b);
|
||||
_g = _mm_hadd_ps(_g, _r);
|
||||
_w = _mm_hadd_ps(_w, _b);
|
||||
_g = _mm_hadd_ps(_g, _r);
|
||||
|
||||
_w = _mm_hadd_ps(_w, _g);
|
||||
_mm_store_ps(bufSum32, _w);
|
||||
_w = _mm_hadd_ps(_w, _g);
|
||||
_mm_store_ps(bufSum32, _w);
|
||||
|
||||
wsum += bufSum32[0];
|
||||
sum_b += bufSum32[1];
|
||||
sum_g += bufSum32[2];
|
||||
sum_r += bufSum32[3];
|
||||
}
|
||||
wsum += bufSum32[0];
|
||||
sum_b += bufSum32[1];
|
||||
sum_g += bufSum32[2];
|
||||
sum_r += bufSum32[3];
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
for(; k < maxk; k++ )
|
||||
{
|
||||
const float* sptr_k = sptr + j + space_ofs[k];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -182,7 +182,7 @@ if(ANDROID)
|
||||
# because samples and tests will make a copy of the library before install
|
||||
get_target_property(__opencv_java_location ${the_module} LOCATION)
|
||||
# Turn off stripping in debug build
|
||||
if ( NOT (CMAKE_BUILD_TYPE MATCHES "debug"))
|
||||
if ( NOT (CMAKE_BUILD_TYPE MATCHES "Debug"))
|
||||
add_custom_command(TARGET ${the_module} POST_BUILD COMMAND ${CMAKE_STRIP} --strip-unneeded "${__opencv_java_location}")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -48,11 +48,11 @@ add_custom_command(
|
||||
WORKING_DIRECTORY "${opencv_test_java_bin_dir}"
|
||||
MAIN_DEPENDENCY "${opencv_test_java_bin_dir}/${ANDROID_MANIFEST_FILE}"
|
||||
DEPENDS "${OpenCV_BINARY_DIR}/bin/.classes.jar.dephelper" opencv_java
|
||||
DEPENDS ${opencv_test_java_file_deps} ${__android_project_chain})
|
||||
set(__android_project_chain ${PROJECT_NAME} CACHE INTERNAL "auxiliary variable used for Android progects chaining")
|
||||
DEPENDS ${opencv_test_java_file_deps})
|
||||
|
||||
add_custom_target(${PROJECT_NAME} ALL SOURCES "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" )
|
||||
add_dependencies(${PROJECT_NAME} opencv_java)
|
||||
add_dependencies(${PROJECT_NAME} opencv_java ${__android_project_chain})
|
||||
set(__android_project_chain ${PROJECT_NAME} CACHE INTERNAL "auxiliary variable used for Android progects chaining" FORCE)
|
||||
|
||||
# put the final .apk to the OpenCV's bin folder
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" "${OpenCV_BINARY_DIR}/bin/${PROJECT_NAME}.apk")
|
||||
|
||||
@@ -105,7 +105,7 @@ class AsyncServiceHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* URI for OpenCV Manager on Google Play (Android Market)
|
||||
* URL of OpenCV Manager page on Google Play Market.
|
||||
*/
|
||||
protected static final String OPEN_CV_SERVICE_URL = "market://details?id=org.opencv.engine";
|
||||
|
||||
@@ -263,7 +263,7 @@ class AsyncServiceHelper
|
||||
}
|
||||
else
|
||||
{
|
||||
// If dependencies list is not defined or empty
|
||||
// If the dependencies list is not defined or empty.
|
||||
String AbsLibraryPath = Path + File.separator + "libopencv_java.so";
|
||||
result &= loadLibrary(AbsLibraryPath);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.content.DialogInterface.OnClickListener;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Basic implementation of LoaderCallbackInterface
|
||||
* Basic implementation of LoaderCallbackInterface.
|
||||
*/
|
||||
public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
|
||||
|
||||
@@ -22,9 +22,9 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
|
||||
/** OpenCV initialization was successful. **/
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
/** Application must override this method to handle successful library initialization **/
|
||||
/** Application must override this method to handle successful library initialization. **/
|
||||
} break;
|
||||
/** OpenCV Manager or library package installation is in progress. Restart of application is required **/
|
||||
/** OpenCV Manager or library package installation is in progress. Restart the application. **/
|
||||
case LoaderCallbackInterface.RESTART_REQUIRED:
|
||||
{
|
||||
Log.d(TAG, "OpenCV downloading. App restart is needed!");
|
||||
@@ -40,7 +40,7 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
|
||||
|
||||
RestartMessage.show();
|
||||
} break;
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
/** OpenCV loader can not start Google Play Market. **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not installed! You can get it here");
|
||||
@@ -55,13 +55,13 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
} break;
|
||||
/** Package installation was canceled **/
|
||||
/** Package installation has been canceled. **/
|
||||
case LoaderCallbackInterface.INSTALL_CANCELED:
|
||||
{
|
||||
Log.d(TAG, "OpenCV library instalation was canceled by user");
|
||||
mAppContext.finish();
|
||||
} break;
|
||||
/** Application is incompatible with this version of OpenCV Manager. Possible Service update is needed **/
|
||||
/** Application is incompatible with this version of OpenCV Manager. Possibly, a service update is required. **/
|
||||
case LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION:
|
||||
{
|
||||
Log.d(TAG, "OpenCV Manager Service is uncompatible with this app!");
|
||||
@@ -76,7 +76,7 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
|
||||
});
|
||||
IncomatibilityMessage.show();
|
||||
}
|
||||
/** Other status, i.e. INIT_FAILED **/
|
||||
/** Other status, i.e. INIT_FAILED. **/
|
||||
default:
|
||||
{
|
||||
Log.e(TAG, "OpenCV loading failed!");
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
package org.opencv.android;
|
||||
|
||||
/**
|
||||
* Installation callback interface
|
||||
* Installation callback interface.
|
||||
*/
|
||||
public interface InstallCallbackInterface
|
||||
{
|
||||
/**
|
||||
* Target package name
|
||||
* @return Return target package name
|
||||
* Target package name.
|
||||
* @return Return target package name.
|
||||
*/
|
||||
public String getPackageName();
|
||||
/**
|
||||
* Installation of package is approved
|
||||
* Installation is approved.
|
||||
*/
|
||||
public void install();
|
||||
/**
|
||||
* Installation canceled
|
||||
* Installation is canceled.
|
||||
*/
|
||||
public void cancel();
|
||||
};
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
package org.opencv.android;
|
||||
|
||||
/**
|
||||
* Interface for callback object in case of asynchronous initialization of OpenCV
|
||||
* Interface for callback object in case of asynchronous initialization of OpenCV.
|
||||
*/
|
||||
public interface LoaderCallbackInterface
|
||||
{
|
||||
/**
|
||||
* OpenCV initialization finished successfully
|
||||
* OpenCV initialization finished successfully.
|
||||
*/
|
||||
static final int SUCCESS = 0;
|
||||
/**
|
||||
* OpenCV library installation via Google Play service was initialized. Application restart is required
|
||||
* OpenCV library installation via Google Play service has been initialized. Restart the application.
|
||||
*/
|
||||
static final int RESTART_REQUIRED = 1;
|
||||
/**
|
||||
* Google Play (Android Market) cannot be invoked
|
||||
* Google Play Market cannot be invoked.
|
||||
*/
|
||||
static final int MARKET_ERROR = 2;
|
||||
/**
|
||||
* OpenCV library installation was canceled by user
|
||||
* OpenCV library installation has been canceled by the user.
|
||||
*/
|
||||
static final int INSTALL_CANCELED = 3;
|
||||
/**
|
||||
* Version of OpenCV Manager Service is incompatible with this app. Service update is needed
|
||||
* This version of OpenCV Manager Service is incompatible with the app. Possibly, a service update is required.
|
||||
*/
|
||||
static final int INCOMPATIBLE_MANAGER_VERSION = 4;
|
||||
/**
|
||||
* OpenCV library initialization failed
|
||||
* OpenCV library initialization has failed.
|
||||
*/
|
||||
static final int INIT_FAILED = 0xff;
|
||||
|
||||
/**
|
||||
* Callback method that is called after OpenCV library initialization
|
||||
* @param status Status of initialization. See Initialization status constants
|
||||
* Callback method, called after OpenCV library initialization.
|
||||
* @param status status of initialization (see initialization status constants).
|
||||
*/
|
||||
public void onManagerConnected(int status);
|
||||
|
||||
/**
|
||||
* Callback method that is called in case when package installation is needed
|
||||
* @param callback Answer object with approve and cancel methods and package description
|
||||
* Callback method, called in case the package installation is needed.
|
||||
* @param callback answer object with approve and cancel methods and the package description.
|
||||
*/
|
||||
public void onPackageInstall(InstallCallbackInterface callback);
|
||||
};
|
||||
|
||||
@@ -3,18 +3,18 @@ package org.opencv.android;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Helper class provides common initialization methods for OpenCV library
|
||||
* Helper class provides common initialization methods for OpenCV library.
|
||||
*/
|
||||
public class OpenCVLoader
|
||||
{
|
||||
/**
|
||||
* OpenCV Library version 2.4.2
|
||||
* OpenCV Library version 2.4.2.
|
||||
*/
|
||||
public static final String OPENCV_VERSION_2_4_2 = "2.4.2";
|
||||
|
||||
/**
|
||||
* Load and initialize OpenCV library from current application package. Roughly it is analog of system.loadLibrary("opencv_java")
|
||||
* @return Return true is initialization of OpenCV was successful
|
||||
* Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").
|
||||
* @return Returns true is initialization of OpenCV was successful.
|
||||
*/
|
||||
public static boolean initDebug()
|
||||
{
|
||||
@@ -22,11 +22,11 @@ public class OpenCVLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and initialize OpenCV library using OpenCV Engine service.
|
||||
* @param Version OpenCV Library version
|
||||
* @param AppContext Application context for connecting to service
|
||||
* @param Callback Object, that implements LoaderCallbackInterface for handling Connection status
|
||||
* @return Return true if initialization of OpenCV starts successfully
|
||||
* Loads and initializes OpenCV library using OpenCV Engine service.
|
||||
* @param Version OpenCV library version.
|
||||
* @param AppContext application context for connecting to the service.
|
||||
* @param Callback object, that implements LoaderCallbackInterface for handling the connection status.
|
||||
* @return Returns true if initialization of OpenCV is successful.
|
||||
*/
|
||||
public static boolean initAsync(String Version, Context AppContext,
|
||||
LoaderCallbackInterface Callback)
|
||||
|
||||
@@ -76,7 +76,7 @@ class StaticHelper {
|
||||
}
|
||||
else
|
||||
{
|
||||
// If dependencies list is not defined or empty
|
||||
// If dependencies list is not defined or empty.
|
||||
result &= loadLibrary("opencv_java");
|
||||
}
|
||||
|
||||
|
||||
@@ -76,14 +76,14 @@ public class Utils {
|
||||
/**
|
||||
* Converts Android Bitmap to OpenCV Mat.
|
||||
* <p>
|
||||
* The function converts an image in the Android Bitmap representation to the OpenCV Mat.
|
||||
* <br>The 'ARGB_8888' and 'RGB_565' input Bitmap formats are supported.
|
||||
* This function converts an Android Bitmap image to the OpenCV Mat.
|
||||
* <br>'ARGB_8888' and 'RGB_565' input Bitmap formats are supported.
|
||||
* <br>The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type,
|
||||
* it keeps the image in RGBA format.
|
||||
* <br>The function throws an exception if the conversion fails.
|
||||
* <br>This function throws an exception if the conversion fails.
|
||||
* @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
|
||||
* @param mat is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat.
|
||||
* @param unPremultiplyAlpha is a flag if the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one. The flag is ignored for 'RGB_565' bitmaps.
|
||||
* @param mat is a valid output Mat object, it will be reallocated if needed, so it may be empty.
|
||||
* @param unPremultiplyAlpha is a flag, that determines, whether the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one; this flag is ignored for 'RGB_565' bitmaps.
|
||||
*/
|
||||
public static void bitmapToMat(Bitmap bmp, Mat mat, boolean unPremultiplyAlpha) {
|
||||
if (bmp == null)
|
||||
@@ -94,9 +94,9 @@ public class Utils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortened form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false)
|
||||
* Short form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false).
|
||||
* @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
|
||||
* @param mat is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat.
|
||||
* @param mat is a valid output Mat object, it will be reallocated if needed, so Mat may be empty.
|
||||
*/
|
||||
public static void bitmapToMat(Bitmap bmp, Mat mat) {
|
||||
bitmapToMat(bmp, mat, false);
|
||||
@@ -106,14 +106,14 @@ public class Utils {
|
||||
/**
|
||||
* Converts OpenCV Mat to Android Bitmap.
|
||||
* <p>
|
||||
* <br>The function converts an image in the OpenCV Mat representation to the Android Bitmap.
|
||||
* <br>This function converts an image in the OpenCV Mat representation to the Android Bitmap.
|
||||
* <br>The input Mat object has to be of the types 'CV_8UC1' (gray-scale), 'CV_8UC3' (RGB) or 'CV_8UC4' (RGBA).
|
||||
* <br>The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'.
|
||||
* <br>The function throws an exception if the conversion fails.
|
||||
* <br>This function throws an exception if the conversion fails.
|
||||
*
|
||||
* @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
|
||||
* @param bmp is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'.
|
||||
* @param premultiplyAlpha is a flag if the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps). The flag is ignored for 'RGB_565' bitmaps.
|
||||
* @param mat is a valid input Mat object of types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
|
||||
* @param bmp is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'.
|
||||
* @param premultiplyAlpha is a flag, that determines, whether the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps); the flag is ignored for 'RGB_565' bitmaps.
|
||||
*/
|
||||
public static void matToBitmap(Mat mat, Bitmap bmp, boolean premultiplyAlpha) {
|
||||
if (mat == null)
|
||||
@@ -124,9 +124,9 @@ public class Utils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortened form of the <b>matToBitmap(mat, bmp, premultiplyAlpha=false)</b>
|
||||
* Short form of the <b>matToBitmap(mat, bmp, premultiplyAlpha=false)</b>
|
||||
* @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
|
||||
* @param bmp is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'.
|
||||
* @param bmp is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'.
|
||||
*/
|
||||
public static void matToBitmap(Mat mat, Bitmap bmp) {
|
||||
matToBitmap(mat, bmp, false);
|
||||
|
||||
@@ -4,15 +4,15 @@ package org.opencv.core;
|
||||
public class TermCriteria {
|
||||
|
||||
/**
|
||||
* the maximum number of iterations or elements to compute
|
||||
* The maximum number of iterations or elements to compute
|
||||
*/
|
||||
public static final int COUNT = 1;
|
||||
/**
|
||||
* the maximum number of iterations or elements to compute
|
||||
* The maximum number of iterations or elements to compute
|
||||
*/
|
||||
public static final int MAX_ITER = COUNT;
|
||||
/**
|
||||
* the desired accuracy or change in parameters at which the iterative algorithm stops
|
||||
* The desired accuracy threshold or change in parameters at which the iterative algorithm is terminated.
|
||||
*/
|
||||
public static final int EPS = 2;
|
||||
|
||||
@@ -21,14 +21,14 @@ public class TermCriteria {
|
||||
public double epsilon;
|
||||
|
||||
/**
|
||||
* Termination criteria in iterative algorithms
|
||||
* Termination criteria for iterative algorithms.
|
||||
*
|
||||
* @param type
|
||||
* the type of termination criteria: COUNT, EPS or COUNT + EPS
|
||||
* the type of termination criteria: COUNT, EPS or COUNT + EPS.
|
||||
* @param maxCount
|
||||
* the maximum number of iterations/elements
|
||||
* the maximum number of iterations/elements.
|
||||
* @param epsilon
|
||||
* the desired accuracy
|
||||
* the desired accuracy.
|
||||
*/
|
||||
public TermCriteria(int type, int maxCount, double epsilon) {
|
||||
this.type = type;
|
||||
@@ -37,7 +37,7 @@ public class TermCriteria {
|
||||
}
|
||||
|
||||
/**
|
||||
* Termination criteria in iterative algorithms
|
||||
* Termination criteria for iterative algorithms.
|
||||
*/
|
||||
public TermCriteria() {
|
||||
this(0, 0, 0.0);
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
package org.opencv.engine;
|
||||
|
||||
/**
|
||||
* Class provides Java interface to OpenCV Engine Service. Is synchronous with native OpenCVEngine class.
|
||||
* Class provides a Java interface for OpenCV Engine Service. It's synchronous with native OpenCVEngine class.
|
||||
*/
|
||||
interface OpenCVEngineInterface
|
||||
{
|
||||
/**
|
||||
* @return Return service version
|
||||
* @return Returns service version.
|
||||
*/
|
||||
int getEngineVersion();
|
||||
|
||||
/**
|
||||
* Find installed OpenCV library
|
||||
* @param OpenCV version
|
||||
* @return Return path to OpenCV native libs or empty string if OpenCV was not found
|
||||
* Finds an installed OpenCV library.
|
||||
* @param OpenCV version.
|
||||
* @return Returns path to OpenCV native libs or an empty string if OpenCV can not be found.
|
||||
*/
|
||||
String getLibPathByVersion(String version);
|
||||
|
||||
/**
|
||||
* Try to install defined version of OpenCV from Google Play (Android Market).
|
||||
* @param OpenCV version
|
||||
* @return Return true if installation was successful or OpenCV package has been already installed
|
||||
* Tries to install defined version of OpenCV from Google Play Market.
|
||||
* @param OpenCV version.
|
||||
* @return Returns true if installation was successful or OpenCV package has been already installed.
|
||||
*/
|
||||
boolean installVersion(String version);
|
||||
|
||||
/**
|
||||
* Return list of libraries in loading order separated by ";" symbol
|
||||
* @param OpenCV version
|
||||
* @return Return OpenCV libraries names separated by symbol ";" in loading order
|
||||
* Returns list of libraries in loading order, separated by semicolon.
|
||||
* @param OpenCV version.
|
||||
* @return Returns names of OpenCV libraries, separated by semicolon.
|
||||
*/
|
||||
String getLibraryList(String version);
|
||||
}
|
||||
@@ -3,21 +3,21 @@ package org.opencv.features2d;
|
||||
//C++: class DMatch
|
||||
|
||||
/**
|
||||
* Struct for matching: query descriptor index, train descriptor index, train
|
||||
* Structure for matching: query descriptor index, train descriptor index, train
|
||||
* image index and distance between descriptors.
|
||||
*/
|
||||
public class DMatch {
|
||||
|
||||
/**
|
||||
* query descriptor index
|
||||
* Query descriptor index.
|
||||
*/
|
||||
public int queryIdx;
|
||||
/**
|
||||
* train descriptor index
|
||||
* Train descriptor index.
|
||||
*/
|
||||
public int trainIdx;
|
||||
/**
|
||||
* train image index
|
||||
* Train image index.
|
||||
*/
|
||||
public int imgIdx;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class DMatch {
|
||||
}
|
||||
|
||||
/**
|
||||
* less is better
|
||||
* Less is better.
|
||||
*/
|
||||
public boolean lessThan(DMatch it) {
|
||||
return distance < it.distance;
|
||||
|
||||
@@ -6,29 +6,29 @@ import org.opencv.core.Point;
|
||||
public class KeyPoint {
|
||||
|
||||
/**
|
||||
* coordinates of the keypoint
|
||||
* Coordinates of the keypoint.
|
||||
*/
|
||||
public Point pt;
|
||||
/**
|
||||
* diameter of the meaningful keypoint neighborhood
|
||||
* Diameter of the useful keypoint adjacent area.
|
||||
*/
|
||||
public float size;
|
||||
/**
|
||||
* computed orientation of the keypoint (-1 if not applicable)
|
||||
* Computed orientation of the keypoint (-1 if not applicable).
|
||||
*/
|
||||
public float angle;
|
||||
/**
|
||||
* the response by which the most strong keypoints have been selected. Can
|
||||
* be used for further sorting or subsampling
|
||||
* The response, by which the strongest keypoints have been selected. Can
|
||||
* be used for further sorting or subsampling.
|
||||
*/
|
||||
public float response;
|
||||
/**
|
||||
* octave (pyramid layer) from which the keypoint has been extracted
|
||||
* Octave (pyramid layer), from which the keypoint has been extracted.
|
||||
*/
|
||||
public int octave;
|
||||
/**
|
||||
* object id that can be used to clustered keypoints by an object they
|
||||
* belong to
|
||||
* Object ID, that can be used to cluster keypoints by an object they
|
||||
* belong to.
|
||||
*/
|
||||
public int class_id;
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@ public class VideoCapture {
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns the specified "VideoCapture" property
|
||||
* Returns the specified "VideoCapture" property.
|
||||
*
|
||||
* Note: When querying a property that is not supported by the backend used by
|
||||
* the "VideoCapture" class, value 0 is returned.
|
||||
*
|
||||
* @param propId Property identifier. It can be one of the following:
|
||||
* * CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
|
||||
* * CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
|
||||
* @param propId property identifier; it can be one of the following:
|
||||
* * CV_CAP_PROP_FRAME_WIDTH width of the frames in the video stream.
|
||||
* * CV_CAP_PROP_FRAME_HEIGHT height of the frames in the video stream.
|
||||
*
|
||||
* @see <a href="http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-get">org.opencv.highgui.VideoCapture.get</a>
|
||||
*/
|
||||
@@ -173,10 +173,10 @@ public class VideoCapture {
|
||||
/**
|
||||
* Sets a property in the "VideoCapture".
|
||||
*
|
||||
* @param propId Property identifier. It can be one of the following:
|
||||
* * CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
|
||||
* * CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
|
||||
* @param value Value of the property.
|
||||
* @param propId property identifier; it can be one of the following:
|
||||
* * CV_CAP_PROP_FRAME_WIDTH width of the frames in the video stream.
|
||||
* * CV_CAP_PROP_FRAME_HEIGHT height of the frames in the video stream.
|
||||
* @param value value of the property.
|
||||
*
|
||||
* @see <a href="http://opencv.itseez.com/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-set">org.opencv.highgui.VideoCapture.set</a>
|
||||
*/
|
||||
|
||||
@@ -2069,7 +2069,7 @@ void CvDTree::cluster_categories( const int* vectors, int n, int m,
|
||||
{
|
||||
int sum = 0;
|
||||
const int* v = vectors + i*m;
|
||||
labels[i] = i < k ? i : (*r)(k);
|
||||
labels[i] = i < k ? i : r->uniform(0, k);
|
||||
|
||||
// compute weight of each vector
|
||||
for( j = 0; j < m; j++ )
|
||||
|
||||
@@ -128,20 +128,20 @@ inline HaarEvaluator::Feature :: Feature()
|
||||
p[2][0] = p[2][1] = p[2][2] = p[2][3] = 0;
|
||||
}
|
||||
|
||||
inline float HaarEvaluator::Feature :: calc( int offset ) const
|
||||
inline float HaarEvaluator::Feature :: calc( int _offset ) const
|
||||
{
|
||||
float ret = rect[0].weight * CALC_SUM(p[0], offset) + rect[1].weight * CALC_SUM(p[1], offset);
|
||||
float ret = rect[0].weight * CALC_SUM(p[0], _offset) + rect[1].weight * CALC_SUM(p[1], _offset);
|
||||
|
||||
if( rect[2].weight != 0.0f )
|
||||
ret += rect[2].weight * CALC_SUM(p[2], offset);
|
||||
ret += rect[2].weight * CALC_SUM(p[2], _offset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void HaarEvaluator::Feature :: updatePtrs( const Mat& sum )
|
||||
inline void HaarEvaluator::Feature :: updatePtrs( const Mat& _sum )
|
||||
{
|
||||
const int* ptr = (const int*)sum.data;
|
||||
size_t step = sum.step/sizeof(ptr[0]);
|
||||
const int* ptr = (const int*)_sum.data;
|
||||
size_t step = _sum.step/sizeof(ptr[0]);
|
||||
if (tilted)
|
||||
{
|
||||
CV_TILTED_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
|
||||
@@ -210,24 +210,24 @@ inline LBPEvaluator::Feature :: Feature()
|
||||
p[i] = 0;
|
||||
}
|
||||
|
||||
inline int LBPEvaluator::Feature :: calc( int offset ) const
|
||||
inline int LBPEvaluator::Feature :: calc( int _offset ) const
|
||||
{
|
||||
int cval = CALC_SUM_( p[5], p[6], p[9], p[10], offset );
|
||||
int cval = CALC_SUM_( p[5], p[6], p[9], p[10], _offset );
|
||||
|
||||
return (CALC_SUM_( p[0], p[1], p[4], p[5], offset ) >= cval ? 128 : 0) | // 0
|
||||
(CALC_SUM_( p[1], p[2], p[5], p[6], offset ) >= cval ? 64 : 0) | // 1
|
||||
(CALC_SUM_( p[2], p[3], p[6], p[7], offset ) >= cval ? 32 : 0) | // 2
|
||||
(CALC_SUM_( p[6], p[7], p[10], p[11], offset ) >= cval ? 16 : 0) | // 5
|
||||
(CALC_SUM_( p[10], p[11], p[14], p[15], offset ) >= cval ? 8 : 0)| // 8
|
||||
(CALC_SUM_( p[9], p[10], p[13], p[14], offset ) >= cval ? 4 : 0)| // 7
|
||||
(CALC_SUM_( p[8], p[9], p[12], p[13], offset ) >= cval ? 2 : 0)| // 6
|
||||
(CALC_SUM_( p[4], p[5], p[8], p[9], offset ) >= cval ? 1 : 0);
|
||||
return (CALC_SUM_( p[0], p[1], p[4], p[5], _offset ) >= cval ? 128 : 0) | // 0
|
||||
(CALC_SUM_( p[1], p[2], p[5], p[6], _offset ) >= cval ? 64 : 0) | // 1
|
||||
(CALC_SUM_( p[2], p[3], p[6], p[7], _offset ) >= cval ? 32 : 0) | // 2
|
||||
(CALC_SUM_( p[6], p[7], p[10], p[11], _offset ) >= cval ? 16 : 0) | // 5
|
||||
(CALC_SUM_( p[10], p[11], p[14], p[15], _offset ) >= cval ? 8 : 0)| // 8
|
||||
(CALC_SUM_( p[9], p[10], p[13], p[14], _offset ) >= cval ? 4 : 0)| // 7
|
||||
(CALC_SUM_( p[8], p[9], p[12], p[13], _offset ) >= cval ? 2 : 0)| // 6
|
||||
(CALC_SUM_( p[4], p[5], p[8], p[9], _offset ) >= cval ? 1 : 0);
|
||||
}
|
||||
|
||||
inline void LBPEvaluator::Feature :: updatePtrs( const Mat& sum )
|
||||
inline void LBPEvaluator::Feature :: updatePtrs( const Mat& _sum )
|
||||
{
|
||||
const int* ptr = (const int*)sum.data;
|
||||
size_t step = sum.step/sizeof(ptr[0]);
|
||||
const int* ptr = (const int*)_sum.data;
|
||||
size_t step = _sum.step/sizeof(ptr[0]);
|
||||
Rect tr = rect;
|
||||
CV_SUM_PTRS( p[0], p[1], p[4], p[5], ptr, tr, step );
|
||||
tr.x += 2*rect.width;
|
||||
@@ -292,10 +292,10 @@ inline HOGEvaluator::Feature :: Feature()
|
||||
featComponent = 0;
|
||||
}
|
||||
|
||||
inline float HOGEvaluator::Feature :: calc( int offset ) const
|
||||
inline float HOGEvaluator::Feature :: calc( int _offset ) const
|
||||
{
|
||||
float res = CALC_SUM(pF, offset);
|
||||
float normFactor = CALC_SUM(pN, offset);
|
||||
float res = CALC_SUM(pF, _offset);
|
||||
float normFactor = CALC_SUM(pN, _offset);
|
||||
res = (res > 0.001f) ? (res / ( normFactor + 0.001f) ) : 0.f;
|
||||
return res;
|
||||
}
|
||||
|
||||
+415
-91
@@ -43,26 +43,23 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <stdio.h>
|
||||
/*
|
||||
#if CV_SSE2
|
||||
|
||||
|
||||
#if CV_SSE2 || CV_SSE3
|
||||
# if !CV_SSE4_1 && !CV_SSE4_2
|
||||
# define _mm_blendv_pd(a, b, m) _mm_xor_pd(a, _mm_and_pd(_mm_xor_pd(b, a), m))
|
||||
# define _mm_blendv_ps(a, b, m) _mm_xor_ps(a, _mm_and_ps(_mm_xor_ps(b, a), m))
|
||||
# define _mm_blendv_pd(a, b, m) _mm_xor_pd(a, _mm_and_pd(_mm_xor_pd(b, a), m))
|
||||
# define _mm_blendv_ps(a, b, m) _mm_xor_ps(a, _mm_and_ps(_mm_xor_ps(b, a), m))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined CV_ICC
|
||||
# if defined CV_AVX
|
||||
# define CV_HAAR_USE_AVX 1
|
||||
# else
|
||||
# if defined CV_SSE2 || defined CV_SSE4_1 || defined CV_SSE4_2
|
||||
# define CV_HAAR_USE_SSE 1
|
||||
# else
|
||||
# define CV_HAAR_NO_SIMD 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
*/
|
||||
# if CV_AVX
|
||||
# define CV_HAAR_USE_AVX 1
|
||||
# else
|
||||
# if CV_SSE2 || CV_SSE3
|
||||
# define CV_HAAR_USE_SSE 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* these settings affect the quality of detection: change with care */
|
||||
#define CV_ADJUST_FEATURES 1
|
||||
#define CV_ADJUST_WEIGHTS 0
|
||||
@@ -636,34 +633,163 @@ cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* _cascade,
|
||||
}
|
||||
|
||||
|
||||
//AVX version icvEvalHidHaarClassifier. Process 8 CvHidHaarClassifiers per call. Check AVX support before invocation!!
|
||||
#ifdef CV_HAAR_USE_AVX
|
||||
CV_INLINE
|
||||
double icvEvalHidHaarClassifierAVX( CvHidHaarClassifier* classifier,
|
||||
double variance_norm_factor, size_t p_offset )
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idxV[8] = {0,0,0,0,0,0,0,0};
|
||||
char flags[8] = {0,0,0,0,0,0,0,0};
|
||||
CvHidHaarTreeNode* nodes[8];
|
||||
double res = 0;
|
||||
char exitConditionFlag = 0;
|
||||
for(;;)
|
||||
{
|
||||
float CV_DECL_ALIGNED(32) tmp[8] = {0,0,0,0,0,0,0,0};
|
||||
nodes[0] = classifier ->node + idxV[0];
|
||||
nodes[1] = (classifier+1)->node + idxV[1];
|
||||
nodes[2] = (classifier+2)->node + idxV[2];
|
||||
nodes[3] = (classifier+3)->node + idxV[3];
|
||||
nodes[4] = (classifier+4)->node + idxV[4];
|
||||
nodes[5] = (classifier+5)->node + idxV[5];
|
||||
nodes[6] = (classifier+6)->node + idxV[6];
|
||||
nodes[7] = (classifier+7)->node + idxV[7];
|
||||
|
||||
__m256 t = _mm256_set1_ps(variance_norm_factor);
|
||||
t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold,nodes[6]->threshold,nodes[5]->threshold,nodes[4]->threshold,nodes[3]->threshold,nodes[2]->threshold,nodes[1]->threshold,nodes[0]->threshold));
|
||||
|
||||
__m256 offset = _mm256_set_ps(calc_sum(nodes[7]->feature.rect[0],p_offset), calc_sum(nodes[6]->feature.rect[0],p_offset), calc_sum(nodes[5]->feature.rect[0],p_offset),
|
||||
calc_sum(nodes[4]->feature.rect[0],p_offset), calc_sum(nodes[3]->feature.rect[0],p_offset), calc_sum(nodes[2]->feature.rect[0],p_offset), calc_sum(nodes[1]->feature.rect[0],
|
||||
p_offset),calc_sum(nodes[0]->feature.rect[0],p_offset));
|
||||
__m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, nodes[6]->feature.rect[0].weight, nodes[5]->feature.rect[0].weight,
|
||||
nodes[4]->feature.rect[0].weight, nodes[3]->feature.rect[0].weight, nodes[2]->feature.rect[0].weight, nodes[1]->feature.rect[0].weight, nodes[0]->feature.rect[0].weight);
|
||||
__m256 sum = _mm256_mul_ps(offset, weight);
|
||||
|
||||
offset = _mm256_set_ps(calc_sum(nodes[7]->feature.rect[1],p_offset),calc_sum(nodes[6]->feature.rect[1],p_offset),calc_sum(nodes[5]->feature.rect[1],p_offset),
|
||||
calc_sum(nodes[4]->feature.rect[1],p_offset),calc_sum(nodes[3]->feature.rect[1],p_offset),calc_sum(nodes[2]->feature.rect[1],p_offset),calc_sum(nodes[1]->feature.rect[1],p_offset),
|
||||
calc_sum(nodes[0]->feature.rect[1],p_offset));
|
||||
weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, nodes[6]->feature.rect[1].weight, nodes[5]->feature.rect[1].weight, nodes[4]->feature.rect[1].weight,
|
||||
nodes[3]->feature.rect[1].weight, nodes[2]->feature.rect[1].weight, nodes[1]->feature.rect[1].weight, nodes[0]->feature.rect[1].weight);
|
||||
|
||||
sum = _mm256_add_ps(sum, _mm256_mul_ps(offset,weight));
|
||||
|
||||
if( nodes[0]->feature.rect[2].p0 )
|
||||
tmp[0] = calc_sum(nodes[0]->feature.rect[2],p_offset) * nodes[0]->feature.rect[2].weight;
|
||||
if( nodes[1]->feature.rect[2].p0 )
|
||||
tmp[1] = calc_sum(nodes[1]->feature.rect[2],p_offset) * nodes[1]->feature.rect[2].weight;
|
||||
if( nodes[2]->feature.rect[2].p0 )
|
||||
tmp[2] = calc_sum(nodes[2]->feature.rect[2],p_offset) * nodes[2]->feature.rect[2].weight;
|
||||
if( nodes[3]->feature.rect[2].p0 )
|
||||
tmp[3] = calc_sum(nodes[3]->feature.rect[2],p_offset) * nodes[3]->feature.rect[2].weight;
|
||||
if( nodes[4]->feature.rect[2].p0 )
|
||||
tmp[4] = calc_sum(nodes[4]->feature.rect[2],p_offset) * nodes[4]->feature.rect[2].weight;
|
||||
if( nodes[5]->feature.rect[2].p0 )
|
||||
tmp[5] = calc_sum(nodes[5]->feature.rect[2],p_offset) * nodes[5]->feature.rect[2].weight;
|
||||
if( nodes[6]->feature.rect[2].p0 )
|
||||
tmp[6] = calc_sum(nodes[6]->feature.rect[2],p_offset) * nodes[6]->feature.rect[2].weight;
|
||||
if( nodes[7]->feature.rect[2].p0 )
|
||||
tmp[7] = calc_sum(nodes[7]->feature.rect[2],p_offset) * nodes[7]->feature.rect[2].weight;
|
||||
|
||||
sum = _mm256_add_ps(sum,_mm256_load_ps(tmp));
|
||||
|
||||
__m256 left = _mm256_set_ps(nodes[7]->left,nodes[6]->left,nodes[5]->left,nodes[4]->left,nodes[3]->left,nodes[2]->left,nodes[1]->left,nodes[0]->left);
|
||||
__m256 right = _mm256_set_ps(nodes[7]->right,nodes[6]->right,nodes[5]->right,nodes[4]->right,nodes[3]->right,nodes[2]->right,nodes[1]->right,nodes[0]->right);
|
||||
|
||||
_mm256_store_si256((__m256i*)idxV,_mm256_cvttps_epi32(_mm256_blendv_ps(right, left,_mm256_cmp_ps(sum, t, _CMP_LT_OQ ))));
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if(idxV[i]<=0)
|
||||
{
|
||||
if(!flags[i])
|
||||
{
|
||||
exitConditionFlag++;
|
||||
flags[i]=1;
|
||||
res+=((classifier+i)->alpha[-idxV[i]]);
|
||||
}
|
||||
idxV[i]=0;
|
||||
}
|
||||
}
|
||||
if(exitConditionFlag==8)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CV_INLINE
|
||||
double icvEvalHidHaarClassifier( CvHidHaarClassifier* classifier,
|
||||
double variance_norm_factor,
|
||||
size_t p_offset )
|
||||
{
|
||||
int idx = 0;
|
||||
do
|
||||
/*#if CV_HAAR_USE_SSE && !CV_HAAR_USE_AVX
|
||||
if(cv::checkHardwareSupport(CV_CPU_SSE2))//based on old SSE variant. Works slow
|
||||
{
|
||||
double CV_DECL_ALIGNED(16) temp[2];
|
||||
__m128d zero = _mm_setzero_pd();
|
||||
do
|
||||
{
|
||||
CvHidHaarTreeNode* node = classifier->node + idx;
|
||||
__m128d t = _mm_set1_pd((node->threshold)*variance_norm_factor);
|
||||
__m128d left = _mm_set1_pd(node->left);
|
||||
__m128d right = _mm_set1_pd(node->right);
|
||||
|
||||
double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
_sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
_sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
|
||||
__m128d sum = _mm_set1_pd(_sum);
|
||||
t = _mm_cmplt_sd(sum, t);
|
||||
sum = _mm_blendv_pd(right, left, t);
|
||||
|
||||
_mm_store_pd(temp, sum);
|
||||
idx = (int)temp[0];
|
||||
}
|
||||
while(idx > 0 );
|
||||
|
||||
}
|
||||
else
|
||||
#endif*/
|
||||
{
|
||||
CvHidHaarTreeNode* node = classifier->node + idx;
|
||||
double t = node->threshold * variance_norm_factor;
|
||||
do
|
||||
{
|
||||
CvHidHaarTreeNode* node = classifier->node + idx;
|
||||
double t = node->threshold * variance_norm_factor;
|
||||
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
|
||||
if( node->feature.rect[2].p0 )
|
||||
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
|
||||
idx = sum < t ? node->left : node->right;
|
||||
idx = sum < t ? node->left : node->right;
|
||||
}
|
||||
while( idx > 0 );
|
||||
}
|
||||
while( idx > 0 );
|
||||
return classifier->alpha[-idx];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
cvRunHaarClassifierCascadeSum( const CvHaarClassifierCascade* _cascade,
|
||||
CvPoint pt, double& stage_sum, int start_stage )
|
||||
{
|
||||
#ifdef CV_HAAR_USE_AVX
|
||||
bool haveAVX = false;
|
||||
if(cv::checkHardwareSupport(CV_CPU_AVX))
|
||||
if(_xgetbv(_XCR_XFEATURE_ENABLED_MASK)&0x6)// Check if the OS will save the YMM registers
|
||||
{
|
||||
haveAVX = true;
|
||||
}
|
||||
#else
|
||||
#ifdef CV_HAAR_USE_SSE
|
||||
bool haveSSE2 = cv::checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int p_offset, pq_offset;
|
||||
int i, j;
|
||||
double mean, variance_norm_factor;
|
||||
@@ -702,10 +828,20 @@ cvRunHaarClassifierCascadeSum( const CvHaarClassifierCascade* _cascade,
|
||||
{
|
||||
stage_sum = 0.0;
|
||||
|
||||
#ifdef CV_HAAR_USE_AVX
|
||||
if(haveAVX)
|
||||
{
|
||||
for( ; j < cascade->stage_classifier[i].count-8; j+=8 )
|
||||
{
|
||||
stage_sum += icvEvalHidHaarClassifierAVX(
|
||||
cascade->stage_classifier[i].classifier+j,
|
||||
variance_norm_factor, p_offset );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( j = 0; j < ptr->count; j++ )
|
||||
{
|
||||
stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j,
|
||||
variance_norm_factor, p_offset );
|
||||
stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j, variance_norm_factor, p_offset );
|
||||
}
|
||||
|
||||
if( stage_sum >= ptr->threshold )
|
||||
@@ -723,99 +859,287 @@ cvRunHaarClassifierCascadeSum( const CvHaarClassifierCascade* _cascade,
|
||||
}
|
||||
else if( cascade->isStumpBased )
|
||||
{
|
||||
for( i = start_stage; i < cascade->count; i++ )
|
||||
{
|
||||
#ifndef CV_HAAR_USE_SSE
|
||||
stage_sum = 0.0;
|
||||
#else
|
||||
__m128d stage_sum = _mm_setzero_pd();
|
||||
#endif
|
||||
|
||||
if( cascade->stage_classifier[i].two_rects )
|
||||
#ifdef CV_HAAR_USE_AVX
|
||||
if(haveAVX)
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
CvHidHaarClassifier* classifiers[8];
|
||||
CvHidHaarTreeNode* nodes[8];
|
||||
for( i = start_stage; i < cascade->count; i++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
stage_sum = 0.0;
|
||||
int j = 0;
|
||||
float CV_DECL_ALIGNED(32) buf[8];
|
||||
if( cascade->stage_classifier[i].two_rects )
|
||||
{
|
||||
for( ; j <= cascade->stage_classifier[i].count-8; j+=8 )
|
||||
{
|
||||
//__m256 stage_sumPart = _mm256_setzero_ps();
|
||||
classifiers[0] = cascade->stage_classifier[i].classifier + j;
|
||||
nodes[0] = classifiers[0]->node;
|
||||
classifiers[1] = cascade->stage_classifier[i].classifier + j + 1;
|
||||
nodes[1] = classifiers[1]->node;
|
||||
classifiers[2] = cascade->stage_classifier[i].classifier + j + 2;
|
||||
nodes[2]= classifiers[2]->node;
|
||||
classifiers[3] = cascade->stage_classifier[i].classifier + j + 3;
|
||||
nodes[3] = classifiers[3]->node;
|
||||
classifiers[4] = cascade->stage_classifier[i].classifier + j + 4;
|
||||
nodes[4] = classifiers[4]->node;
|
||||
classifiers[5] = cascade->stage_classifier[i].classifier + j + 5;
|
||||
nodes[5] = classifiers[5]->node;
|
||||
classifiers[6] = cascade->stage_classifier[i].classifier + j + 6;
|
||||
nodes[6] = classifiers[6]->node;
|
||||
classifiers[7] = cascade->stage_classifier[i].classifier + j + 7;
|
||||
nodes[7] = classifiers[7]->node;
|
||||
|
||||
#ifndef CV_HAAR_USE_SSE
|
||||
double t = node->threshold*variance_norm_factor;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
stage_sum += classifier->alpha[sum >= t];
|
||||
#else
|
||||
// ayasin - NHM perf optim. Avoid use of costly flaky jcc
|
||||
__m128d t = _mm_set_sd(node->threshold*variance_norm_factor);
|
||||
__m128d a = _mm_set_sd(classifier->alpha[0]);
|
||||
__m128d b = _mm_set_sd(classifier->alpha[1]);
|
||||
__m128d sum = _mm_set_sd(calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight +
|
||||
calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight);
|
||||
t = _mm_cmpgt_sd(t, sum);
|
||||
stage_sum = _mm_add_sd(stage_sum, _mm_blendv_pd(b, a, t));
|
||||
#endif
|
||||
__m256 t = _mm256_set1_ps(variance_norm_factor);
|
||||
t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold,nodes[6]->threshold,nodes[5]->threshold,nodes[4]->threshold,nodes[3]->threshold,nodes[2]->threshold,nodes[1]->threshold,nodes[0]->threshold));
|
||||
|
||||
__m256 offset = _mm256_set_ps(calc_sum(nodes[7]->feature.rect[0],p_offset), calc_sum(nodes[6]->feature.rect[0],p_offset), calc_sum(nodes[5]->feature.rect[0],p_offset),
|
||||
calc_sum(nodes[4]->feature.rect[0],p_offset), calc_sum(nodes[3]->feature.rect[0],p_offset), calc_sum(nodes[2]->feature.rect[0],p_offset), calc_sum(nodes[1]->feature.rect[0],
|
||||
p_offset),calc_sum(nodes[0]->feature.rect[0],p_offset));
|
||||
__m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, nodes[6]->feature.rect[0].weight, nodes[5]->feature.rect[0].weight,
|
||||
nodes[4]->feature.rect[0].weight, nodes[3]->feature.rect[0].weight, nodes[2]->feature.rect[0].weight, nodes[1]->feature.rect[0].weight, nodes[0]->feature.rect[0].weight);
|
||||
__m256 sum = _mm256_mul_ps(offset, weight);
|
||||
|
||||
offset = _mm256_set_ps(calc_sum(nodes[7]->feature.rect[1],p_offset),calc_sum(nodes[6]->feature.rect[1],p_offset),calc_sum(nodes[5]->feature.rect[1],p_offset),
|
||||
calc_sum(nodes[4]->feature.rect[1],p_offset),calc_sum(nodes[3]->feature.rect[1],p_offset),calc_sum(nodes[2]->feature.rect[1],p_offset),calc_sum(nodes[1]->feature.rect[1],p_offset),
|
||||
calc_sum(nodes[0]->feature.rect[1],p_offset));
|
||||
weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, nodes[6]->feature.rect[1].weight, nodes[5]->feature.rect[1].weight, nodes[4]->feature.rect[1].weight,
|
||||
nodes[3]->feature.rect[1].weight, nodes[2]->feature.rect[1].weight, nodes[1]->feature.rect[1].weight, nodes[0]->feature.rect[1].weight);
|
||||
sum = _mm256_add_ps(sum, _mm256_mul_ps(offset,weight));
|
||||
|
||||
__m256 alpha0 = _mm256_set_ps(classifiers[7]->alpha[0],classifiers[6]->alpha[0],classifiers[5]->alpha[0],classifiers[4]->alpha[0],classifiers[3]->alpha[0],
|
||||
classifiers[2]->alpha[0],classifiers[1]->alpha[0],classifiers[0]->alpha[0]);
|
||||
__m256 alpha1 = _mm256_set_ps(classifiers[7]->alpha[1],classifiers[6]->alpha[1],classifiers[5]->alpha[1],classifiers[4]->alpha[1],classifiers[3]->alpha[1],
|
||||
classifiers[2]->alpha[1],classifiers[1]->alpha[1],classifiers[0]->alpha[1]);
|
||||
|
||||
_mm256_store_ps(buf, _mm256_blendv_ps(alpha0, alpha1, _mm256_cmp_ps(t, sum, _CMP_LE_OQ )));
|
||||
stage_sum+=(buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]);
|
||||
|
||||
}
|
||||
|
||||
for( ; j < cascade->stage_classifier[i].count; j++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
|
||||
double t = node->threshold*variance_norm_factor;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
stage_sum += classifier->alpha[sum >= t];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; j <= (cascade->stage_classifier[i].count)-8; j+=8 )
|
||||
{
|
||||
float CV_DECL_ALIGNED(32) tmp[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
classifiers[0] = cascade->stage_classifier[i].classifier + j;
|
||||
nodes[0] = classifiers[0]->node;
|
||||
classifiers[1] = cascade->stage_classifier[i].classifier + j + 1;
|
||||
nodes[1] = classifiers[1]->node;
|
||||
classifiers[2] = cascade->stage_classifier[i].classifier + j + 2;
|
||||
nodes[2]= classifiers[2]->node;
|
||||
classifiers[3] = cascade->stage_classifier[i].classifier + j + 3;
|
||||
nodes[3] = classifiers[3]->node;
|
||||
classifiers[4] = cascade->stage_classifier[i].classifier + j + 4;
|
||||
nodes[4] = classifiers[4]->node;
|
||||
classifiers[5] = cascade->stage_classifier[i].classifier + j + 5;
|
||||
nodes[5] = classifiers[5]->node;
|
||||
classifiers[6] = cascade->stage_classifier[i].classifier + j + 6;
|
||||
nodes[6] = classifiers[6]->node;
|
||||
classifiers[7] = cascade->stage_classifier[i].classifier + j + 7;
|
||||
nodes[7] = classifiers[7]->node;
|
||||
|
||||
__m256 t = _mm256_set1_ps(variance_norm_factor);
|
||||
t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold,nodes[6]->threshold,nodes[5]->threshold,nodes[4]->threshold,nodes[3]->threshold,nodes[2]->threshold,nodes[1]->threshold,nodes[0]->threshold));
|
||||
|
||||
__m256 offset = _mm256_set_ps(calc_sum(nodes[7]->feature.rect[0],p_offset), calc_sum(nodes[6]->feature.rect[0],p_offset), calc_sum(nodes[5]->feature.rect[0],p_offset),
|
||||
calc_sum(nodes[4]->feature.rect[0],p_offset), calc_sum(nodes[3]->feature.rect[0],p_offset), calc_sum(nodes[2]->feature.rect[0],p_offset), calc_sum(nodes[1]->feature.rect[0],
|
||||
p_offset),calc_sum(nodes[0]->feature.rect[0],p_offset));
|
||||
__m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, nodes[6]->feature.rect[0].weight, nodes[5]->feature.rect[0].weight,
|
||||
nodes[4]->feature.rect[0].weight, nodes[3]->feature.rect[0].weight, nodes[2]->feature.rect[0].weight, nodes[1]->feature.rect[0].weight, nodes[0]->feature.rect[0].weight);
|
||||
__m256 sum = _mm256_mul_ps(offset, weight);
|
||||
|
||||
offset = _mm256_set_ps(calc_sum(nodes[7]->feature.rect[1],p_offset),calc_sum(nodes[6]->feature.rect[1],p_offset),calc_sum(nodes[5]->feature.rect[1],p_offset),
|
||||
calc_sum(nodes[4]->feature.rect[1],p_offset),calc_sum(nodes[3]->feature.rect[1],p_offset),calc_sum(nodes[2]->feature.rect[1],p_offset),calc_sum(nodes[1]->feature.rect[1],p_offset),
|
||||
calc_sum(nodes[0]->feature.rect[1],p_offset));
|
||||
weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, nodes[6]->feature.rect[1].weight, nodes[5]->feature.rect[1].weight, nodes[4]->feature.rect[1].weight,
|
||||
nodes[3]->feature.rect[1].weight, nodes[2]->feature.rect[1].weight, nodes[1]->feature.rect[1].weight, nodes[0]->feature.rect[1].weight);
|
||||
|
||||
sum = _mm256_add_ps(sum, _mm256_mul_ps(offset,weight));
|
||||
|
||||
if( nodes[0]->feature.rect[2].p0 )
|
||||
tmp[0] = calc_sum(nodes[0]->feature.rect[2],p_offset) * nodes[0]->feature.rect[2].weight;
|
||||
if( nodes[1]->feature.rect[2].p0 )
|
||||
tmp[1] = calc_sum(nodes[1]->feature.rect[2],p_offset) * nodes[1]->feature.rect[2].weight;
|
||||
if( nodes[2]->feature.rect[2].p0 )
|
||||
tmp[2] = calc_sum(nodes[2]->feature.rect[2],p_offset) * nodes[2]->feature.rect[2].weight;
|
||||
if( nodes[3]->feature.rect[2].p0 )
|
||||
tmp[3] = calc_sum(nodes[3]->feature.rect[2],p_offset) * nodes[3]->feature.rect[2].weight;
|
||||
if( nodes[4]->feature.rect[2].p0 )
|
||||
tmp[4] = calc_sum(nodes[4]->feature.rect[2],p_offset) * nodes[4]->feature.rect[2].weight;
|
||||
if( nodes[5]->feature.rect[2].p0 )
|
||||
tmp[5] = calc_sum(nodes[5]->feature.rect[2],p_offset) * nodes[5]->feature.rect[2].weight;
|
||||
if( nodes[6]->feature.rect[2].p0 )
|
||||
tmp[6] = calc_sum(nodes[6]->feature.rect[2],p_offset) * nodes[6]->feature.rect[2].weight;
|
||||
if( nodes[7]->feature.rect[2].p0 )
|
||||
tmp[7] = calc_sum(nodes[7]->feature.rect[2],p_offset) * nodes[7]->feature.rect[2].weight;
|
||||
|
||||
sum = _mm256_add_ps(sum, _mm256_load_ps(tmp));
|
||||
|
||||
__m256 alpha0 = _mm256_set_ps(classifiers[7]->alpha[0],classifiers[6]->alpha[0],classifiers[5]->alpha[0],classifiers[4]->alpha[0],classifiers[3]->alpha[0],
|
||||
classifiers[2]->alpha[0],classifiers[1]->alpha[0],classifiers[0]->alpha[0]);
|
||||
__m256 alpha1 = _mm256_set_ps(classifiers[7]->alpha[1],classifiers[6]->alpha[1],classifiers[5]->alpha[1],classifiers[4]->alpha[1],classifiers[3]->alpha[1],
|
||||
classifiers[2]->alpha[1],classifiers[1]->alpha[1],classifiers[0]->alpha[1]);
|
||||
|
||||
__m256 outBuf = _mm256_blendv_ps(alpha0, alpha1, _mm256_cmp_ps(t, sum, _CMP_LE_OQ ));
|
||||
outBuf = _mm256_hadd_ps(outBuf, outBuf);
|
||||
outBuf = _mm256_hadd_ps(outBuf, outBuf);
|
||||
_mm256_store_ps(buf, outBuf);
|
||||
stage_sum+=(buf[0]+buf[4]);//(buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]);
|
||||
}
|
||||
|
||||
for( ; j < cascade->stage_classifier[i].count; j++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
|
||||
double t = node->threshold*variance_norm_factor;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
stage_sum += classifier->alpha[sum >= t];
|
||||
}
|
||||
}
|
||||
if( stage_sum < cascade->stage_classifier[i].threshold )
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined CV_HAAR_USE_SSE && CV_HAAR_USE_SSE && !CV_HAAR_USE_AVX //old SSE optimization
|
||||
if(haveSSE2)
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
for( i = start_stage; i < cascade->count; i++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
#ifndef CV_HAAR_USE_SSE
|
||||
double t = node->threshold*variance_norm_factor;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
__m128d stage_sum = _mm_setzero_pd();
|
||||
if( cascade->stage_classifier[i].two_rects )
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
|
||||
stage_sum += classifier->alpha[sum >= t];
|
||||
#else
|
||||
// ayasin - NHM perf optim. Avoid use of costly flaky jcc
|
||||
__m128d t = _mm_set_sd(node->threshold*variance_norm_factor);
|
||||
__m128d a = _mm_set_sd(classifier->alpha[0]);
|
||||
__m128d b = _mm_set_sd(classifier->alpha[1]);
|
||||
double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
_sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
_sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
__m128d sum = _mm_set_sd(_sum);
|
||||
// ayasin - NHM perf optim. Avoid use of costly flaky jcc
|
||||
__m128d t = _mm_set_sd(node->threshold*variance_norm_factor);
|
||||
__m128d a = _mm_set_sd(classifier->alpha[0]);
|
||||
__m128d b = _mm_set_sd(classifier->alpha[1]);
|
||||
__m128d sum = _mm_set_sd(calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight +
|
||||
calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight);
|
||||
t = _mm_cmpgt_sd(t, sum);
|
||||
stage_sum = _mm_add_sd(stage_sum, _mm_blendv_pd(b, a, t));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
// ayasin - NHM perf optim. Avoid use of costly flaky jcc
|
||||
__m128d t = _mm_set_sd(node->threshold*variance_norm_factor);
|
||||
__m128d a = _mm_set_sd(classifier->alpha[0]);
|
||||
__m128d b = _mm_set_sd(classifier->alpha[1]);
|
||||
double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
_sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
_sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
__m128d sum = _mm_set_sd(_sum);
|
||||
|
||||
t = _mm_cmpgt_sd(t, sum);
|
||||
stage_sum = _mm_add_sd(stage_sum, _mm_blendv_pd(b, a, t));
|
||||
#endif
|
||||
t = _mm_cmpgt_sd(t, sum);
|
||||
stage_sum = _mm_add_sd(stage_sum, _mm_blendv_pd(b, a, t));
|
||||
}
|
||||
}
|
||||
__m128d i_threshold = _mm_set1_pd(cascade->stage_classifier[i].threshold);
|
||||
if( _mm_comilt_sd(stage_sum, i_threshold) )
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for( i = start_stage; i < cascade->count; i++ )
|
||||
{
|
||||
stage_sum = 0.0;
|
||||
if( cascade->stage_classifier[i].two_rects )
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
double t = node->threshold*variance_norm_factor;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
stage_sum += classifier->alpha[sum >= t];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
{
|
||||
CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
|
||||
CvHidHaarTreeNode* node = classifier->node;
|
||||
double t = node->threshold*variance_norm_factor;
|
||||
double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
|
||||
sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;
|
||||
if( node->feature.rect[2].p0 )
|
||||
sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;
|
||||
stage_sum += classifier->alpha[sum >= t];
|
||||
}
|
||||
}
|
||||
if( stage_sum < cascade->stage_classifier[i].threshold )
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CV_HAAR_USE_SSE
|
||||
if( stage_sum < cascade->stage_classifier[i].threshold )
|
||||
#else
|
||||
__m128d i_threshold = _mm_set_sd(cascade->stage_classifier[i].threshold);
|
||||
if( _mm_comilt_sd(stage_sum, i_threshold) )
|
||||
#endif
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
for( i = start_stage; i < cascade->count; i++ )
|
||||
{
|
||||
stage_sum = 0.0;
|
||||
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
int k = 0;
|
||||
#ifdef CV_HAAR_USE_AVX
|
||||
if(haveAVX)
|
||||
{
|
||||
stage_sum += icvEvalHidHaarClassifier(
|
||||
cascade->stage_classifier[i].classifier + j,
|
||||
variance_norm_factor, p_offset );
|
||||
for( ; k < cascade->stage_classifier[i].count-8; k+=8 )
|
||||
{
|
||||
stage_sum += icvEvalHidHaarClassifierAVX(
|
||||
cascade->stage_classifier[i].classifier+k,
|
||||
variance_norm_factor, p_offset );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for(; k < cascade->stage_classifier[i].count; k++ )
|
||||
{
|
||||
|
||||
stage_sum += icvEvalHidHaarClassifier(
|
||||
cascade->stage_classifier[i].classifier + k,
|
||||
variance_norm_factor, p_offset );
|
||||
}
|
||||
|
||||
if( stage_sum < cascade->stage_classifier[i].threshold )
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
//_mm256_zeroupper();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL int
|
||||
cvRunHaarClassifierCascade( const CvHaarClassifierCascade* _cascade,
|
||||
CvPoint pt, int start_stage )
|
||||
|
||||
@@ -856,8 +856,8 @@ bool DepthNormalPyramid::extractTemplate(Template& templ) const
|
||||
std::stable_sort(candidates.begin(), candidates.end());
|
||||
|
||||
// Use heuristic based on object area for initial distance threshold
|
||||
int area = static_cast<int>(no_mask ? normal.total() : countNonZero(local_mask));
|
||||
float distance = sqrtf(static_cast<float>(area)) / sqrtf(static_cast<float>(num_features)) + 1.5f;
|
||||
float area = no_mask ? (float)normal.total() : (float)countNonZero(local_mask);
|
||||
float distance = sqrtf(area) / sqrtf((float)num_features) + 1.5f;
|
||||
selectScatteredFeatures(candidates, templ.features, num_features, distance);
|
||||
|
||||
// Size determined externally, needs to match templates for other modalities
|
||||
|
||||
@@ -88,7 +88,10 @@ namespace cv
|
||||
//CV_EXPORTS void getComputeCapability(cl_device_id device, int &major, int &minor);
|
||||
//optional function, if you want save opencl binary kernel to the file, set its path
|
||||
CV_EXPORTS void setBinpath(const char *path);
|
||||
|
||||
//The two functions below are used to get opencl runtime so that opencv can interactive with
|
||||
//other opencl program
|
||||
CV_EXPORTS void* getoclContext();
|
||||
CV_EXPORTS void* getoclCommandQueue();
|
||||
//////////////////////////////// Error handling ////////////////////////
|
||||
CV_EXPORTS void error(const char *error_string, const char *file, const int line, const char *func);
|
||||
|
||||
@@ -144,32 +147,15 @@ namespace cv
|
||||
//! assignment operator. Perfom blocking upload to device.
|
||||
oclMat &operator = (const Mat &m);
|
||||
|
||||
/* Fixme! To be supported in OpenCL later. */
|
||||
#if 0
|
||||
//! returns lightweight DevMem2D_ structure for passing to nvcc-compiled code.
|
||||
// Contains just image size, data ptr and step.
|
||||
template <class T> operator DevMem2D_<T>() const;
|
||||
template <class T> operator PtrStep_<T>() const;
|
||||
#endif
|
||||
|
||||
//! pefroms blocking upload data to oclMat.
|
||||
void upload(const cv::Mat &m);
|
||||
|
||||
/* Fixme! To be supported in OpenCL later. */
|
||||
#if 0
|
||||
//! upload async
|
||||
void upload(const CudaMem &m, Stream &stream);
|
||||
#endif
|
||||
|
||||
//! downloads data from device to host memory. Blocking calls.
|
||||
operator Mat() const;
|
||||
void download(cv::Mat &m) const;
|
||||
|
||||
/* Fixme! To be supported in OpenCL later. */
|
||||
#if 0
|
||||
//! download async
|
||||
void download(CudaMem &m, Stream &stream) const;
|
||||
#endif
|
||||
|
||||
//! returns a new oclMatrix header for the specified row
|
||||
oclMat row(int y) const;
|
||||
@@ -855,10 +841,6 @@ namespace cv
|
||||
int minNeighbors, int flags, CvSize minSize = cvSize(0, 0), CvSize maxSize = cvSize(0, 0));
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////jhp_benchmark////////////////////////////////////////////////////
|
||||
void benchmark_copy_vectorize(const oclMat &src, oclMat &dst);
|
||||
void benchmark_copy_offset_stride(const oclMat &src, oclMat &dst);
|
||||
void benchmark_ILP();
|
||||
|
||||
//! computes vertical sum, supports only CV_32FC1 images
|
||||
CV_EXPORTS void columnSum(const oclMat& src, oclMat& sum);
|
||||
@@ -895,32 +877,32 @@ namespace cv
|
||||
// Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4
|
||||
CV_EXPORTS void matchTemplate(const oclMat& image, const oclMat& templ, oclMat& result, int method, MatchTemplateBuf& buf);
|
||||
|
||||
///////////////////////////////////////////// Canny /////////////////////////////////////////////
|
||||
struct CV_EXPORTS CannyBuf;
|
||||
|
||||
//! compute edges of the input image using Canny operator
|
||||
// Support CV_8UC1 only
|
||||
CV_EXPORTS void Canny(const oclMat& image, oclMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
||||
CV_EXPORTS void Canny(const oclMat& image, CannyBuf& buf, oclMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
||||
CV_EXPORTS void Canny(const oclMat& dx, const oclMat& dy, oclMat& edges, double low_thresh, double high_thresh, bool L2gradient = false);
|
||||
CV_EXPORTS void Canny(const oclMat& dx, const oclMat& dy, CannyBuf& buf, oclMat& edges, double low_thresh, double high_thresh, bool L2gradient = false);
|
||||
|
||||
struct CV_EXPORTS CannyBuf
|
||||
{
|
||||
CannyBuf() {}
|
||||
explicit CannyBuf(const Size& image_size, int apperture_size = 3) {create(image_size, apperture_size);}
|
||||
CannyBuf(const oclMat& dx_, const oclMat& dy_);
|
||||
|
||||
void create(const Size& image_size, int apperture_size = 3);
|
||||
|
||||
void release();
|
||||
|
||||
oclMat dx, dy;
|
||||
oclMat dx_buf, dy_buf;
|
||||
oclMat edgeBuf;
|
||||
oclMat trackBuf1, trackBuf2;
|
||||
oclMat counter;
|
||||
Ptr<FilterEngine_GPU> filterDX, filterDY;
|
||||
///////////////////////////////////////////// Canny /////////////////////////////////////////////
|
||||
struct CV_EXPORTS CannyBuf;
|
||||
|
||||
//! compute edges of the input image using Canny operator
|
||||
// Support CV_8UC1 only
|
||||
CV_EXPORTS void Canny(const oclMat& image, oclMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
||||
CV_EXPORTS void Canny(const oclMat& image, CannyBuf& buf, oclMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
||||
CV_EXPORTS void Canny(const oclMat& dx, const oclMat& dy, oclMat& edges, double low_thresh, double high_thresh, bool L2gradient = false);
|
||||
CV_EXPORTS void Canny(const oclMat& dx, const oclMat& dy, CannyBuf& buf, oclMat& edges, double low_thresh, double high_thresh, bool L2gradient = false);
|
||||
|
||||
struct CV_EXPORTS CannyBuf
|
||||
{
|
||||
CannyBuf() {}
|
||||
explicit CannyBuf(const Size& image_size, int apperture_size = 3) {create(image_size, apperture_size);}
|
||||
CannyBuf(const oclMat& dx_, const oclMat& dy_);
|
||||
|
||||
void create(const Size& image_size, int apperture_size = 3);
|
||||
|
||||
void release();
|
||||
|
||||
oclMat dx, dy;
|
||||
oclMat dx_buf, dy_buf;
|
||||
oclMat edgeBuf;
|
||||
oclMat trackBuf1, trackBuf2;
|
||||
void * counter;
|
||||
Ptr<FilterEngine_GPU> filterDX, filterDY;
|
||||
};
|
||||
|
||||
#ifdef HAVE_CLAMDFFT
|
||||
@@ -953,154 +935,161 @@ namespace cv
|
||||
const oclMat& src3, double beta, oclMat& dst, int flags = 0);
|
||||
#endif
|
||||
|
||||
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
|
||||
struct CV_EXPORTS HOGDescriptor
|
||||
{
|
||||
enum { DEFAULT_WIN_SIGMA = -1 };
|
||||
enum { DEFAULT_NLEVELS = 64 };
|
||||
enum { DESCR_FORMAT_ROW_BY_ROW, DESCR_FORMAT_COL_BY_COL };
|
||||
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
|
||||
struct CV_EXPORTS HOGDescriptor
|
||||
{
|
||||
enum { DEFAULT_WIN_SIGMA = -1 };
|
||||
enum { DEFAULT_NLEVELS = 64 };
|
||||
enum { DESCR_FORMAT_ROW_BY_ROW, DESCR_FORMAT_COL_BY_COL };
|
||||
|
||||
HOGDescriptor(Size win_size=Size(64, 128), Size block_size=Size(16, 16),
|
||||
Size block_stride=Size(8, 8), Size cell_size=Size(8, 8),
|
||||
int nbins=9, double win_sigma=DEFAULT_WIN_SIGMA,
|
||||
double threshold_L2hys=0.2, bool gamma_correction=true,
|
||||
int nlevels=DEFAULT_NLEVELS);
|
||||
|
||||
size_t getDescriptorSize() const;
|
||||
size_t getBlockHistogramSize() const;
|
||||
|
||||
void setSVMDetector(const vector<float>& detector);
|
||||
|
||||
static vector<float> getDefaultPeopleDetector();
|
||||
static vector<float> getPeopleDetector48x96();
|
||||
static vector<float> getPeopleDetector64x128();
|
||||
|
||||
void detect(const oclMat& img, vector<Point>& found_locations,
|
||||
double hit_threshold=0, Size win_stride=Size(),
|
||||
Size padding=Size());
|
||||
|
||||
void detectMultiScale(const oclMat& img, vector<Rect>& found_locations,
|
||||
double hit_threshold=0, Size win_stride=Size(),
|
||||
Size padding=Size(), double scale0=1.05,
|
||||
int group_threshold=2);
|
||||
|
||||
void getDescriptors(const oclMat& img, Size win_stride,
|
||||
oclMat& descriptors,
|
||||
int descr_format=DESCR_FORMAT_COL_BY_COL);
|
||||
|
||||
Size win_size;
|
||||
Size block_size;
|
||||
Size block_stride;
|
||||
Size cell_size;
|
||||
int nbins;
|
||||
double win_sigma;
|
||||
double threshold_L2hys;
|
||||
bool gamma_correction;
|
||||
int nlevels;
|
||||
|
||||
protected:
|
||||
// initialize buffers; only need to do once in case of multiscale detection
|
||||
void init_buffer(const oclMat& img, Size win_stride);
|
||||
|
||||
void computeBlockHistograms(const oclMat& img);
|
||||
void computeGradient(const oclMat& img, oclMat& grad, oclMat& qangle);
|
||||
|
||||
double getWinSigma() const;
|
||||
bool checkDetectorSize() const;
|
||||
|
||||
static int numPartsWithin(int size, int part_size, int stride);
|
||||
static Size numPartsWithin(Size size, Size part_size, Size stride);
|
||||
|
||||
// Coefficients of the separating plane
|
||||
float free_coef;
|
||||
oclMat detector;
|
||||
|
||||
// Results of the last classification step
|
||||
oclMat labels;
|
||||
Mat labels_host;
|
||||
|
||||
// Results of the last histogram evaluation step
|
||||
oclMat block_hists;
|
||||
|
||||
// Gradients conputation results
|
||||
oclMat grad, qangle;
|
||||
|
||||
// scaled image
|
||||
oclMat image_scale;
|
||||
|
||||
// effect size of input image (might be different from original size after scaling)
|
||||
Size effect_size;
|
||||
};
|
||||
|
||||
HOGDescriptor(Size win_size=Size(64, 128), Size block_size=Size(16, 16),
|
||||
Size block_stride=Size(8, 8), Size cell_size=Size(8, 8),
|
||||
int nbins=9, double win_sigma=DEFAULT_WIN_SIGMA,
|
||||
double threshold_L2hys=0.2, bool gamma_correction=true,
|
||||
int nlevels=DEFAULT_NLEVELS);
|
||||
|
||||
size_t getDescriptorSize() const;
|
||||
size_t getBlockHistogramSize() const;
|
||||
|
||||
void setSVMDetector(const vector<float>& detector);
|
||||
|
||||
static vector<float> getDefaultPeopleDetector();
|
||||
static vector<float> getPeopleDetector48x96();
|
||||
static vector<float> getPeopleDetector64x128();
|
||||
|
||||
void detect(const oclMat& img, vector<Point>& found_locations,
|
||||
double hit_threshold=0, Size win_stride=Size(),
|
||||
Size padding=Size());
|
||||
|
||||
void detectMultiScale(const oclMat& img, vector<Rect>& found_locations,
|
||||
double hit_threshold=0, Size win_stride=Size(),
|
||||
Size padding=Size(), double scale0=1.05,
|
||||
int group_threshold=2);
|
||||
|
||||
void getDescriptors(const oclMat& img, Size win_stride,
|
||||
oclMat& descriptors,
|
||||
int descr_format=DESCR_FORMAT_COL_BY_COL);
|
||||
|
||||
Size win_size;
|
||||
Size block_size;
|
||||
Size block_stride;
|
||||
Size cell_size;
|
||||
int nbins;
|
||||
double win_sigma;
|
||||
double threshold_L2hys;
|
||||
bool gamma_correction;
|
||||
int nlevels;
|
||||
|
||||
protected:
|
||||
void computeBlockHistograms(const oclMat& img);
|
||||
void computeGradient(const oclMat& img, oclMat& grad, oclMat& qangle);
|
||||
|
||||
double getWinSigma() const;
|
||||
bool checkDetectorSize() const;
|
||||
|
||||
static int numPartsWithin(int size, int part_size, int stride);
|
||||
static Size numPartsWithin(Size size, Size part_size, Size stride);
|
||||
|
||||
// Coefficients of the separating plane
|
||||
float free_coef;
|
||||
oclMat detector;
|
||||
|
||||
// Results of the last classification step
|
||||
oclMat labels;
|
||||
Mat labels_host;
|
||||
|
||||
// Results of the last histogram evaluation step
|
||||
oclMat block_hists;
|
||||
|
||||
// Gradients conputation results
|
||||
oclMat grad, qangle;
|
||||
|
||||
std::vector<oclMat> image_scales;
|
||||
};
|
||||
|
||||
//! Speeded up robust features, port from GPU module.
|
||||
////////////////////////////////// SURF //////////////////////////////////////////
|
||||
class CV_EXPORTS SURF_OCL
|
||||
{
|
||||
public:
|
||||
enum KeypointLayout
|
||||
{
|
||||
X_ROW = 0,
|
||||
Y_ROW,
|
||||
LAPLACIAN_ROW,
|
||||
OCTAVE_ROW,
|
||||
SIZE_ROW,
|
||||
ANGLE_ROW,
|
||||
HESSIAN_ROW,
|
||||
ROWS_COUNT
|
||||
};
|
||||
|
||||
//! the default constructor
|
||||
SURF_OCL();
|
||||
//! the full constructor taking all the necessary parameters
|
||||
explicit SURF_OCL(double _hessianThreshold, int _nOctaves=4,
|
||||
int _nOctaveLayers=2, bool _extended=false, float _keypointsRatio=0.01f, bool _upright = false);
|
||||
|
||||
//! returns the descriptor size in float's (64 or 128)
|
||||
int descriptorSize() const;
|
||||
|
||||
//! upload host keypoints to device memory
|
||||
void uploadKeypoints(const vector<cv::KeyPoint>& keypoints, oclMat& keypointsocl);
|
||||
//! download keypoints from device to host memory
|
||||
void downloadKeypoints(const oclMat& keypointsocl, vector<KeyPoint>& keypoints);
|
||||
|
||||
//! download descriptors from device to host memory
|
||||
void downloadDescriptors(const oclMat& descriptorsocl, vector<float>& descriptors);
|
||||
|
||||
//! finds the keypoints using fast hessian detector used in SURF
|
||||
//! supports CV_8UC1 images
|
||||
//! keypoints will have nFeature cols and 6 rows
|
||||
//! keypoints.ptr<float>(X_ROW)[i] will contain x coordinate of i'th feature
|
||||
//! keypoints.ptr<float>(Y_ROW)[i] will contain y coordinate of i'th feature
|
||||
//! keypoints.ptr<float>(LAPLACIAN_ROW)[i] will contain laplacian sign of i'th feature
|
||||
//! keypoints.ptr<float>(OCTAVE_ROW)[i] will contain octave of i'th feature
|
||||
//! keypoints.ptr<float>(SIZE_ROW)[i] will contain size of i'th feature
|
||||
//! keypoints.ptr<float>(ANGLE_ROW)[i] will contain orientation of i'th feature
|
||||
//! keypoints.ptr<float>(HESSIAN_ROW)[i] will contain response of i'th feature
|
||||
void operator()(const oclMat& img, const oclMat& mask, oclMat& keypoints);
|
||||
//! finds the keypoints and computes their descriptors.
|
||||
//! Optionally it can compute descriptors for the user-provided keypoints and recompute keypoints direction
|
||||
void operator()(const oclMat& img, const oclMat& mask, oclMat& keypoints, oclMat& descriptors,
|
||||
bool useProvidedKeypoints = false);
|
||||
|
||||
void operator()(const oclMat& img, const oclMat& mask, std::vector<KeyPoint>& keypoints);
|
||||
void operator()(const oclMat& img, const oclMat& mask, std::vector<KeyPoint>& keypoints, oclMat& descriptors,
|
||||
bool useProvidedKeypoints = false);
|
||||
|
||||
void operator()(const oclMat& img, const oclMat& mask, std::vector<KeyPoint>& keypoints, std::vector<float>& descriptors,
|
||||
bool useProvidedKeypoints = false);
|
||||
|
||||
void releaseMemory();
|
||||
|
||||
// SURF parameters
|
||||
float hessianThreshold;
|
||||
int nOctaves;
|
||||
int nOctaveLayers;
|
||||
bool extended;
|
||||
bool upright;
|
||||
|
||||
//! max keypoints = min(keypointsRatio * img.size().area(), 65535)
|
||||
float keypointsRatio;
|
||||
|
||||
oclMat sum, mask1, maskSum, intBuffer;
|
||||
|
||||
oclMat det, trace;
|
||||
|
||||
oclMat maxPosBuffer;
|
||||
|
||||
};
|
||||
//! Speeded up robust features, port from GPU module.
|
||||
////////////////////////////////// SURF //////////////////////////////////////////
|
||||
class CV_EXPORTS SURF_OCL
|
||||
{
|
||||
public:
|
||||
enum KeypointLayout
|
||||
{
|
||||
X_ROW = 0,
|
||||
Y_ROW,
|
||||
LAPLACIAN_ROW,
|
||||
OCTAVE_ROW,
|
||||
SIZE_ROW,
|
||||
ANGLE_ROW,
|
||||
HESSIAN_ROW,
|
||||
ROWS_COUNT
|
||||
};
|
||||
|
||||
//! the default constructor
|
||||
SURF_OCL();
|
||||
//! the full constructor taking all the necessary parameters
|
||||
explicit SURF_OCL(double _hessianThreshold, int _nOctaves=4,
|
||||
int _nOctaveLayers=2, bool _extended=false, float _keypointsRatio=0.01f, bool _upright = false);
|
||||
|
||||
//! returns the descriptor size in float's (64 or 128)
|
||||
int descriptorSize() const;
|
||||
|
||||
//! upload host keypoints to device memory
|
||||
void uploadKeypoints(const vector<cv::KeyPoint>& keypoints, oclMat& keypointsocl);
|
||||
//! download keypoints from device to host memory
|
||||
void downloadKeypoints(const oclMat& keypointsocl, vector<KeyPoint>& keypoints);
|
||||
|
||||
//! download descriptors from device to host memory
|
||||
void downloadDescriptors(const oclMat& descriptorsocl, vector<float>& descriptors);
|
||||
|
||||
//! finds the keypoints using fast hessian detector used in SURF
|
||||
//! supports CV_8UC1 images
|
||||
//! keypoints will have nFeature cols and 6 rows
|
||||
//! keypoints.ptr<float>(X_ROW)[i] will contain x coordinate of i'th feature
|
||||
//! keypoints.ptr<float>(Y_ROW)[i] will contain y coordinate of i'th feature
|
||||
//! keypoints.ptr<float>(LAPLACIAN_ROW)[i] will contain laplacian sign of i'th feature
|
||||
//! keypoints.ptr<float>(OCTAVE_ROW)[i] will contain octave of i'th feature
|
||||
//! keypoints.ptr<float>(SIZE_ROW)[i] will contain size of i'th feature
|
||||
//! keypoints.ptr<float>(ANGLE_ROW)[i] will contain orientation of i'th feature
|
||||
//! keypoints.ptr<float>(HESSIAN_ROW)[i] will contain response of i'th feature
|
||||
void operator()(const oclMat& img, const oclMat& mask, oclMat& keypoints);
|
||||
//! finds the keypoints and computes their descriptors.
|
||||
//! Optionally it can compute descriptors for the user-provided keypoints and recompute keypoints direction
|
||||
void operator()(const oclMat& img, const oclMat& mask, oclMat& keypoints, oclMat& descriptors,
|
||||
bool useProvidedKeypoints = false);
|
||||
|
||||
void operator()(const oclMat& img, const oclMat& mask, std::vector<KeyPoint>& keypoints);
|
||||
void operator()(const oclMat& img, const oclMat& mask, std::vector<KeyPoint>& keypoints, oclMat& descriptors,
|
||||
bool useProvidedKeypoints = false);
|
||||
|
||||
void operator()(const oclMat& img, const oclMat& mask, std::vector<KeyPoint>& keypoints, std::vector<float>& descriptors,
|
||||
bool useProvidedKeypoints = false);
|
||||
|
||||
void releaseMemory();
|
||||
|
||||
// SURF parameters
|
||||
float hessianThreshold;
|
||||
int nOctaves;
|
||||
int nOctaveLayers;
|
||||
bool extended;
|
||||
bool upright;
|
||||
|
||||
//! max keypoints = min(keypointsRatio * img.size().area(), 65535)
|
||||
float keypointsRatio;
|
||||
|
||||
oclMat sum, mask1, maskSum, intBuffer;
|
||||
|
||||
oclMat det, trace;
|
||||
|
||||
oclMat maxPosBuffer;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#include "opencv2/ocl/matrix_operations.hpp"
|
||||
|
||||
+11
-14
@@ -74,29 +74,26 @@ void print_info()
|
||||
|
||||
}
|
||||
|
||||
#if PERF_TEST_OCL
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
static std::vector<Info> ocl_info;
|
||||
ocl::getDevice(ocl_info);
|
||||
|
||||
run_perf_test();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<cv::ocl::Info> oclinfo;
|
||||
TS::ptr()->init("ocl");
|
||||
InitGoogleTest(&argc, argv);
|
||||
|
||||
print_info();
|
||||
|
||||
int devnums = getDevice(oclinfo);
|
||||
if(devnums<1)
|
||||
{
|
||||
std::cout << "no device found\n";
|
||||
return -1;
|
||||
}
|
||||
//if you want to use undefault device, set it here
|
||||
//setDevice(oclinfo[0]);
|
||||
setBinpath(CLBINPATH);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif // PERF_TEST_OCL
|
||||
|
||||
#else // HAVE_OPENC
|
||||
#else // DON'T HAVE_OPENCL
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user