Commit 1bd91cd5 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #39 from fpuja/saliencyModuleDevelop

Saliency module develop
parents b4edf34f e2fde8a6
set(the_description "Saliency API")
ocv_define_module(saliency opencv_imgproc opencv_highgui opencv_features2d)
# Saliency Module
The purpose of this module is to create, group and make available to the users, different saliency algorithms, belonging to different categories.
Common Interfaces of Saliency
=============================
.. highlight:: cpp
Saliency : Algorithm
--------------------
.. ocv:class:: Saliency
Base abstract class for Saliency algorithms::
class CV_EXPORTS Saliency : public virtual Algorithm
{
public:
virtual ~Saliency();
static Ptr<Saliency> create( const String& saliencyType );
bool computeSaliency( const InputArray image, OutputArray saliencyMap );
String getClassName() const;
};
Saliency::create
----------------
Creates a specialized saliency algorithm by its name.
.. ocv:function:: static Ptr<Saliency> Saliency::create( const String& saliencyType )
:param saliencyType: saliency Type
The following saliency types are now supported:
* ``"SPECTRAL_RESIDUAL"`` -- :ocv:class:`StaticSaliencySpectralResidual`
* ``"BING"`` -- :ocv:class:`ObjectnessBING`
Saliency::computeSaliency
-------------------------
Performs all the operations, according to the specific algorithm created, to obtain the saliency map.
.. ocv:function:: bool Saliency::computeSaliency( const InputArray image, OutputArray saliencyMap )
:param image: image or set of input images. According to InputArray proxy and to the needs of different algorithms (currently plugged), the param image may be *Mat* or *vector<Mat>*
:param saliencyMap: saliency map. According to OutputArray proxy and to the results given by different algorithms (currently plugged), the saliency map may be a *Mat* or *vector<Vec4i>* (BING results).
Saliency::getClassName
----------------------
Get the name of the specific Saliency Algorithm.
.. ocv:function:: String Saliency::getClassName() const
misc @ 16789e8d
Subproject commit 16789e8dcad170f502c81ea2b9714a4dd6bff0c1
Motion Saliency Algorithms
============================
.. highlight:: cpp
Algorithms belonging to this category, are particularly focused to detect salient objects over time (hence also over frame), then there is a temporal component sealing cosider that allows to detect "moving" objects as salient, meaning therefore also the more general sense of detection the changes in the scene.
Presently, the Fast Self-tuning Background Subtraction Algorithm [BinWangApr2014]_ has been implemented.
.. [BinWangApr2014] B. Wang and P. Dudek "A Fast Self-tuning Background Subtraction Algorithm", in proc of IEEE Workshop on Change Detection, 2014
MotionSaliencyBinWangApr2014
----------------------------
.. ocv:class:: MotionSaliencyBinWangApr2014
Implementation of MotionSaliencyBinWangApr2014 from :ocv:class:`MotionSaliency`::
class CV_EXPORTS MotionSaliencyBinWangApr2014 : public MotionSaliency
{
public:
MotionSaliencyBinWangApr2014();
~MotionSaliencyBinWangApr2014();
void setImagesize( int W, int H );
bool init();
protected:
bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap );
};
MotionSaliencyBinWangApr2014::MotionSaliencyBinWangApr2014
----------------------------------------------------------
Constructor
.. ocv:function:: MotionSaliencyBinWangApr2014::MotionSaliencyBinWangApr2014()
MotionSaliencyBinWangApr2014::setImagesize
------------------------------------------
This is a utility function that allows to set the correct size (taken from the input image) in the corresponding variables that will be used to size the data structures of the algorithm.
.. ocv:function:: void MotionSaliencyBinWangApr2014::setImagesize( int W, int H )
:param W: width of input image
:param H: height of input image
MotionSaliencyBinWangApr2014::init
-----------------------------------
This function allows the correct initialization of all data structures that will be used by the algorithm.
.. ocv:function:: bool MotionSaliencyBinWangApr2014::init()
MotionSaliencyBinWangApr2014::computeSaliencyImpl
-------------------------------------------------
Performs all the operations and calls all internal functions necessary for the accomplishment of the Fast Self-tuning Background Subtraction Algorithm algorithm.
.. ocv:function:: bool MotionSaliencyBinWangApr2014::computeSaliencyImpl( const InputArray image, OutputArray saliencyMap )
:param image: input image. According to the needs of this specialized algorithm, the param image is a single *Mat*.
:param saliencyMap: Saliency Map. Is a binarized map that, in accordance with the nature of the algorithm, highlights the moving objects or areas of change in the scene.
The saliency map is given by a single *Mat* (one for each frame of an hypothetical video stream).
Objectness Algorithms
============================
.. highlight:: cpp
Objectness is usually represented as a value which reflects how likely an image window covers an object of any category. Algorithms belonging to this category, avoid making decisions early on, by proposing a small number of category-independent proposals, that are expected to cover all objects in an image. Being able to perceive objects before identifying them is closely related to bottom up visual attention (saliency)
Presently, the Binarized normed gradients algorithm [BING]_ has been implemented.
.. [BING] Cheng, Ming-Ming, et al. "BING: Binarized normed gradients for objectness estimation at 300fps." IEEE CVPR. 2014.
ObjectnessBING
--------------
.. ocv:class:: ObjectnessBING
Implementation of BING from :ocv:class:`Objectness`::
class CV_EXPORTS ObjectnessBING : public Objectness
{
public:
ObjectnessBING();
~ObjectnessBING();
void read();
void write() const;
vector<float> getobjectnessValues();
void setTrainingPath( string trainingPath );
void setBBResDir( string resultsDir );
protected:
bool computeSaliencyImpl( const InputArray src, OutputArray dst );
};
ObjectnessBING::ObjectnessBING
------------------------------
Constructor
.. ocv:function:: ObjectnessBING::ObjectnessBING()
ObjectnessBING::getobjectnessValues
-----------------------------------
Return the list of the rectangles' objectness value, in the same order as the *vector<Vec4i> objectnessBoundingBox* returned by the algorithm (in computeSaliencyImpl function).
The bigger value these scores are, it is more likely to be an object window.
.. ocv:function:: vector<float> ObjectnessBING::getobjectnessValues()
ObjectnessBING::setTrainingPath
--------------------------------
This is a utility function that allows to set the correct path from which the algorithm will load the trained model.
.. ocv:function:: void ObjectnessBING::setTrainingPath( string trainingPath )
:param trainingPath: trained model path
ObjectnessBING::setBBResDir
---------------------------
This is a utility function that allows to set an arbitrary path in which the algorithm will save the optional results
(ie writing on file the total number and the list of rectangles returned by objectess, one for each row).
.. ocv:function:: void ObjectnessBING::setBBResDir( string resultsDir )
:param setBBResDir: results' folder path
ObjectnessBING::computeSaliencyImpl
-----------------------------------
Performs all the operations and calls all internal functions necessary for the accomplishment of the Binarized normed gradients algorithm.
.. ocv:function:: bool ObjectnessBING::computeSaliencyImpl( const InputArray image, OutputArray objectnessBoundingBox )
:param image: input image. According to the needs of this specialized algorithm, the param image is a single *Mat*
:param saliencyMap: objectness Bounding Box vector. According to the result given by this specialized algorithm, the objectnessBoundingBox is a *vector<Vec4i>*.
Each bounding box is represented by a *Vec4i* for (minX, minY, maxX, maxY).
Saliency API
============
.. highlight:: cpp
Many computer vision applications may benefit from understanding where humans focus given a scene. Other than cognitively understanding the way human perceive images and scenes, finding salient regions and objects in the images helps various tasks such as speeding up object detection, object recognition, object tracking and content-aware image editing.
About the saliency, there is a rich literature but the development is very fragmented. The principal purpose of this API is to give a
unique interface, a unique framework for use and plug sever saliency algorithms, also with very different nature and methodology, but they share the same purpose, organizing algorithms into three main categories:
**Static Saliency**: algorithms belonging to this category, exploit different image features that allow to detect salient objects in a non dynamic scenarios.
**Motion Saliency**: algorithms belonging to this category, are particularly focused to detect salient objects over time (hence also over frame), then there is a temporal component sealing cosider that allows to detect "moving" objects as salient, meaning therefore also the more general sense of detection the changes in the scene.
**Objectness**: Objectness is usually represented as a value which reflects how likely an image window covers an object of any category. Algorithms belonging to this category, avoid making decisions early on, by proposing a small number of category-independent proposals, that are expected to cover all objects in an image. Being able to perceive objects before identifying them is closely related to bottom up visual attention (saliency).
UML design:
-----------
**Saliency diagram**
.. image:: pics/saliency.png
:width: 80%
:alt: Saliency diagram
:align: center
To see how API works, try tracker demo: https://github.com/fpuja/opencv_contrib/blob/saliencyModuleDevelop/modules/saliency/samples/computeSaliency.cpp
.. note:: This Tracking API has been designed with PlantUML. If you modify this API please change UML files under modules/tracking/misc/
Saliency classes:
-----------------
.. toctree::
:maxdepth: 2
common_interfaces_saliency
saliency_categories
static_saliency_algorithms
motion_saliency_algorithms
objectness_algorithms
Saliency categories
============================
.. highlight:: cpp
Base classes which give a general interface for each specialized type of saliency algorithm and provide utility methods for each algorithm in its class.
StaticSaliency
--------------
.. ocv:class:: StaticSaliency
StaticSaliency class::
class CV_EXPORTS StaticSaliency : public virtual Saliency
{
public:
bool computeBinaryMap( const Mat& saliencyMap, Mat& binaryMap );
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap ) = 0;
};
StaticSaliency::computeBinaryMap
--------------------------------
This function perform a binary map of given saliency map. This is obtained in this way:
In a first step, to improve the definition of interest areas and facilitate identification of targets, a segmentation
by clustering is performed, using *K-means algorithm*. Then, to gain a binary representation of clustered saliency map, since values of the map can vary according to the characteristics of frame under analysis, it is not convenient to use a fixed threshold.
So, *Otsu’s algorithm* is used, which assumes that the image to be thresholded contains two classes of pixels or bi-modal histograms (e.g. foreground and back-ground pixels); later on, the algorithm calculates the optimal threshold separating those two classes, so that their
intra-class variance is minimal.
.. ocv:function:: bool computeBinaryMap( const Mat& saliencyMap, Mat& binaryMap )
:param saliencyMap: the saliency map obtained through one of the specialized algorithms
:param binaryMap: the binary map
MotionSaliency
--------------
.. ocv:class:: MotionSaliency
MotionSaliency class::
class CV_EXPORTS MotionSaliency : public virtual Saliency
{
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap ) = 0;
};
Objectness
----------
.. ocv:class:: Objectness
Objectness class::
class CV_EXPORTS Objectness : public virtual Saliency
{
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap ) = 0;
};
Static Saliency algorithms
============================
.. highlight:: cpp
Algorithms belonging to this category, exploit different image features that allow to detect salient objects in a non dynamic scenarios.
Presently, the Spectral Residual approach [SR]_ has been implemented.
.. [SR] Hou, Xiaodi, and Liqing Zhang. "Saliency detection: A spectral residual approach." Computer Vision and Pattern Recognition, 2007. CVPR'07. IEEE Conference on. IEEE, 2007.
SpectralResidual
----------------
Starting from the principle of natural image statistics, this method simulate the behavior of pre-attentive visual search. The algorithm analyze the log spectrum of each image and obtain the spectral residual. Then transform the spectral residual to spatial domain to obtain the saliency map, which suggests the positions of proto-objects.
.. ocv:class:: StaticSaliencySpectralResidual
Implementation of SpectralResidual from :ocv:class:`StaticSaliency`::
class CV_EXPORTS StaticSaliencySpectralResidual : public StaticSaliency
{
public:
StaticSaliencySpectralResidual();
~StaticSaliencySpectralResidual();
typedef Ptr<Size> (Algorithm::*SizeGetter)();
typedef void (Algorithm::*SizeSetter)( const Ptr<Size> & );
Ptr<Size> getWsize();
void setWsize( const Ptr<Size> &newSize );
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
protected:
bool computeSaliencyImpl( const InputArray src, OutputArray dst );
};
StaticSaliencySpectralResidual::StaticSaliencySpectralResidual
--------------------------------------------------------------
Constructor
.. ocv:function:: StaticSaliencySpectralResidual::StaticSaliencySpectralResidual()
StaticSaliencySpectralResidual::getWsize
----------------------------------------
Return the resized image size.
.. ocv:function:: Ptr<Size> StaticSaliencySpectralResidual::getWsize()
StaticSaliencySpectralResidual::setWsize
----------------------------------------
Set the dimension to which the image should be resized.
.. ocv:function:: StaticSaliencySpectralResidual::void setWsize( const Ptr<Size> &newSize )
:param newSize: dimension to which the image should be resized
StaticSaliencySpectralResidual::computeSaliency
-----------------------------------------------
Performs all the operations and calls all internal functions necessary for the accomplishment of spectral residual saliency map.
.. ocv:function:: bool StaticSaliencySpectralResidual::computeSaliency( const InputArray image, OutputArray saliencyMap )
:param image: input image. According to the needs of this specialized saliency algorithm, the param image is a single *Mat*
:param saliencyMap: saliency map. According to the result given by this specialized saliency algorithm, the saliency map is a single *Mat*
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_SALIENCY_HPP__
#define __OPENCV_SALIENCY_HPP__
#include "opencv2/saliency/saliencyBaseClasses.hpp"
#include "opencv2/saliency/saliencySpecializedClasses.hpp"
namespace cv
{
namespace saliency
{
CV_EXPORTS bool initModule_saliency( void );
}
}
#endif //__OPENCV_SALIENCY_HPP__
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_SALIENCY_BASE_CLASSES_HPP__
#define __OPENCV_SALIENCY_BASE_CLASSES_HPP__
#include "opencv2/core.hpp"
#include <opencv2/core/persistence.hpp>
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <sstream>
#include <complex>
namespace cv
{
namespace saliency
{
/************************************ Saliency Base Class ************************************/
class CV_EXPORTS Saliency : public virtual Algorithm
{
public:
/**
* \brief Destructor
*/
virtual ~Saliency();
/**
* \brief Create Saliency by saliency type.
*/
static Ptr<Saliency> create( const String& saliencyType );
/**
* \brief Compute the saliency
* \param image The image.
* \param saliencyMap The computed saliency map.
* \return true if the saliency map is computed, false otherwise
*/
bool computeSaliency( const InputArray image, OutputArray saliencyMap );
/**
* \brief Get the name of the specific saliency type
* \return The name of the tracker initializer
*/
String getClassName() const;
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap ) = 0;
String className;
};
/************************************ Static Saliency Base Class ************************************/
class CV_EXPORTS StaticSaliency : public virtual Saliency
{
public:
bool computeBinaryMap( const Mat& saliencyMap, Mat& binaryMap );
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap )=0;
};
/************************************ Motion Saliency Base Class ************************************/
class CV_EXPORTS MotionSaliency : public virtual Saliency
{
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap )=0;
};
/************************************ Objectness Base Class ************************************/
class CV_EXPORTS Objectness : public virtual Saliency
{
protected:
virtual bool computeSaliencyImpl( const InputArray image, OutputArray saliencyMap )=0;
};
} /* namespace saliency */
} /* namespace cv */
#endif
/*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) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <opencv2/core/utility.hpp>
#include <opencv2/saliency.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
using namespace saliency;
static const char* keys =
{ "{@saliency_algorithm | | Saliency algorithm <saliencyAlgorithmType.[saliencyAlgorithmTypeSubType]> }"
"{@video_name | | video name }"
"{@start_frame |1| Start frame }"
"{@training_path |1| Path of the folder containing the trained files}" };
static void help()
{
cout << "\nThis example shows the functionality of \"Saliency \""
"Call:\n"
"./example_saliency_computeSaliency <saliencyAlgorithmSubType> <video_name> <start_frame> \n"
<< endl;
}
int main( int argc, char** argv )
{
CommandLineParser parser( argc, argv, keys );
String saliency_algorithm = parser.get<String>( 0 );
String video_name = parser.get<String>( 1 );
int start_frame = parser.get<int>( 2 );
String training_path = parser.get<String>( 3 );
if( saliency_algorithm.empty() || video_name.empty() )
{
help();
return -1;
}
//open the capture
VideoCapture cap;
cap.open( video_name );
cap.set( CAP_PROP_POS_FRAMES, start_frame );
if( !cap.isOpened() )
{
help();
cout << "***Could not initialize capturing...***\n";
cout << "Current parameter's value: \n";
parser.printMessage();
return -1;
}
Mat frame;
//instantiates the specific Saliency
Ptr<Saliency> saliencyAlgorithm = Saliency::create( saliency_algorithm );
if( saliencyAlgorithm == NULL )
{
cout << "***Error in the instantiation of the saliency algorithm...***\n";
return -1;
}
Mat binaryMap;
Mat image;
cap >> frame;
if( frame.empty() )
{
return 0;
}
frame.copyTo( image );
if( saliency_algorithm.find( "SPECTRAL_RESIDUAL" ) == 0 )
{
Mat saliencyMap;
if( saliencyAlgorithm->computeSaliency( image, saliencyMap ) )
{
StaticSaliencySpectralResidual spec;
spec.computeBinaryMap( saliencyMap, binaryMap );
imshow( "Saliency Map", saliencyMap );
imshow( "Original Image", image );
imshow( "Binary Map", binaryMap );
waitKey( 0 );
}
}
else if( saliency_algorithm.find( "BING" ) == 0 )
{
if( training_path.empty() )
{
cout << "Path of trained files missing! " << endl;
return -1;
}
else
{
vector<Vec4i> saliencyMap;
saliencyAlgorithm.dynamicCast<ObjectnessBING>()->setTrainingPath( training_path );
saliencyAlgorithm.dynamicCast<ObjectnessBING>()->setBBResDir( training_path + "/Results" );
if( saliencyAlgorithm->computeSaliency( image, saliencyMap ) )
{
std::cout << "Objectness done" << std::endl;
}
}
}
else if( saliency_algorithm.find( "BinWangApr2014" ) == 0 )
{
//Ptr<Size> size = Ptr<Size>( new Size( image.cols, image.rows ) );
saliencyAlgorithm.dynamicCast<MotionSaliencyBinWangApr2014>()->setImagesize( image.cols, image.rows );
saliencyAlgorithm.dynamicCast<MotionSaliencyBinWangApr2014>()->init();
bool paused = false;
for ( ;; )
{
if( !paused )
{
cap >> frame;
cvtColor( frame, frame, COLOR_BGR2GRAY );
Mat saliencyMap;
if( saliencyAlgorithm->computeSaliency( frame, saliencyMap ) )
{
std::cout << "current frame motion saliency done" << std::endl;
}
imshow( "image", frame );
imshow( "saliencyMap", saliencyMap * 255 );
}
char c = (char) waitKey( 2 );
if( c == 'q' )
break;
if( c == 'p' )
paused = !paused;
}
}
return 0;
}
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "CmFile.hpp"
namespace cv
{
namespace saliency
{
bool CmFile::MkDir( std::string &_path )
{
if( _path.size() == 0 )
return false;
static char buffer[1024];
strcpy( buffer, _S( _path ) );
#ifdef _WIN32
for (int i = 0; buffer[i] != 0; i ++)
{
if (buffer[i] == '\\' || buffer[i] == '/')
{
buffer[i] = '\0';
CreateDirectoryA(buffer, 0);
buffer[i] = '/';
}
}
CreateDirectoryA(_S(_path), 0);
return true;
#else
for ( int i = 0; buffer[i] != 0; i++ )
{
if( buffer[i] == '\\' || buffer[i] == '/' )
{
buffer[i] = '\0';
mkdir( buffer, 0 );
buffer[i] = '/';
}
}
mkdir( _S( _path ), 0 );
return true;
#endif
}
} // namespace saliency
} // namespace cv
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_CM_FILE_HPP__
#define __OPENCV_CM_FILE_HPP__
#ifdef _WIN32
#include <windows.h>
#else
#include <iostream>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#endif
#include "kyheader.hpp"
namespace cv
{
namespace saliency
{
struct CmFile
{
static bool MkDir(std::string& path);
};
}
}
#endif
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "CmShow.hpp"
#include "opencv2/core.hpp"
#include <opencv2/highgui.hpp>
typedef std::pair<int, int> CostiIdx;
namespace cv
{
namespace saliency
{
Mat CmShow::HistBins( CMat& color3f, CMat& val, CStr& title, bool descendShow, CMat &with )
{
// Prepare data
int H = 300, spaceH = 6, barH = 10, n = color3f.cols;
CV_Assert( color3f.size() == val.size() && color3f.rows == 1 );
Mat binVal1i, binColor3b, width1i;
if( with.size() == val.size() )
with.convertTo( width1i, CV_32S, 400 / sum( with ).val[0] ); // Default shown width
else
width1i = Mat( 1, n, CV_32S, Scalar( 10 ) ); // Default bin width = 10
int W = cvRound( sum( width1i ).val[0] );
color3f.convertTo( binColor3b, CV_8UC3, 255 );
double maxVal, minVal;
minMaxLoc( val, &minVal, &maxVal );
printf( "%g\n", H / max( maxVal, -minVal ) );
val.convertTo( binVal1i, CV_32S, 20000 );
Size szShow( W, H + spaceH + barH );
szShow.height += minVal < 0 && !descendShow ? H + spaceH : 0;
Mat showImg3b( szShow, CV_8UC3, Scalar( 255, 255, 255 ) );
int* binH = (int*) ( binVal1i.data );
Vec3b* binColor = (Vec3b*) ( binColor3b.data );
int* binW = (int*) ( width1i.data );
std::vector<CostiIdx> costIdx( n );
if( descendShow )
{
for ( int i = 0; i < n; i++ )
costIdx[i] = std::make_pair( binH[i], i );
sort( costIdx.begin(), costIdx.end(), std::greater<CostiIdx>() );
}
// Show image
for ( int i = 0, x = 0; i < n; i++ )
{
int idx = descendShow ? costIdx[i].second : i;
int h = descendShow ? abs( binH[idx] ) : binH[idx];
Scalar color( binColor[idx] );
Rect reg( x, H + spaceH, binW[idx], barH );
showImg3b( reg ) = color; // Draw bar
rectangle( showImg3b, reg, Scalar( 0 ) );
reg.height = abs( h );
reg.y = h >= 0 ? H - h : H + 2 * spaceH + barH;
showImg3b( reg ) = color;
rectangle( showImg3b, reg, Scalar( 0 ) );
x += binW[idx];
}
imshow( String( title.c_str() ), showImg3b );
return showImg3b;
}
} // namespace saliency
} // namespace cv
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_CM_SHOW_HPP__
#define __OPENCV_CM_SHOW_HPP__
#include "BING/kyheader.hpp"
namespace cv
{
namespace saliency
{
class CmShow
{
public:
static cv::Mat HistBins( CMat& color3f, CMat& val, CStr& title, bool descendShow = false, CMat &with = cv::Mat() );
static void showTinyMat( CStr &title, CMat &m );
static inline void SaveShow( CMat& img, CStr& title );
};
}
}
#endif //__OPENCV_CM_SHOW_HPP__
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_CM_TIMER_HPP__
#define __OPENCV_CM_TIMER_HPP__
#include "BING/kyheader.hpp"
namespace cv
{
namespace saliency
{
class CmTimer
{
public:
CmTimer( CStr t ) :
title( t )
{
is_started = false;
start_clock = 0;
cumulative_clock = 0;
n_starts = 0;
}
~CmTimer()
{
if( is_started )
printf( "CmTimer '%s' is started and is being destroyed.\n", title.c_str() );
}
inline void Start();
inline void Stop();
inline void Reset();
inline bool Report();
inline bool StopAndReport()
{
Stop();
return Report();
}
inline float TimeInSeconds();
private:
CStr title;
CmTimer& operator=( const CmTimer& );
bool is_started;
clock_t start_clock;
clock_t cumulative_clock;
unsigned int n_starts;
};
/************************************************************************/
/* Implementations */
/************************************************************************/
void CmTimer::Start()
{
if( is_started )
{
printf( "CmTimer '%s' is already started. Nothing done.\n", title.c_str() );
return;
}
is_started = true;
n_starts++;
start_clock = clock();
}
void CmTimer::Stop()
{
if( !is_started )
{
printf( "CmTimer '%s' is started. Nothing done\n", title.c_str() );
return;
}
cumulative_clock += clock() - start_clock;
is_started = false;
}
void CmTimer::Reset()
{
if( is_started )
{
printf( "CmTimer '%s'is started during reset request.\n Only reset cumulative time.\n", title.c_str() );
return;
}
cumulative_clock = 0;
}
bool CmTimer::Report()
{
if( is_started )
{
printf( "CmTimer '%s' is started.\n Cannot provide a time report.", title.c_str() );
return false;
}
float timeUsed = TimeInSeconds();
printf( "[%s] CumuTime: %gs, #run: %d, AvgTime: %gs\n", title.c_str(), timeUsed, n_starts, timeUsed / n_starts );
return true;
}
float CmTimer::TimeInSeconds()
{
if( is_started )
{
printf( "CmTimer '%s' is started. Nothing done\n", title.c_str() );
return 0;
}
return float( cumulative_clock ) / CLOCKS_PER_SEC;
}
} // namespace saliency
} // namespace cv
#endif // __OPENCV_CM_TIMER_HPP__
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "CmShow.hpp"
namespace cv
{
namespace saliency
{
float ObjectnessBING::FilterTIG::dot( const int64_t tig1, const int64_t tig2, const int64_t tig4, const int64_t tig8 )
{
int64_t bcT1 = (int64_t) POPCNT64( tig1 );
int64_t bcT2 = (int64_t) POPCNT64( tig2 );
int64_t bcT4 = (int64_t) POPCNT64( tig4 );
int64_t bcT8 = (int64_t) POPCNT64( tig8 );
int64_t bc01 = (int64_t) ( POPCNT64(_bTIGs[0] & tig1) << 1 ) - bcT1;
int64_t bc02 = (int64_t) ( ( POPCNT64(_bTIGs[0] & tig2) << 1 ) - bcT2 ) << 1;
int64_t bc04 = (int64_t) ( ( POPCNT64(_bTIGs[0] & tig4) << 1 ) - bcT4 ) << 2;
int64_t bc08 = (int64_t) ( ( POPCNT64(_bTIGs[0] & tig8) << 1 ) - bcT8 ) << 3;
int64_t bc11 = (int64_t) ( POPCNT64(_bTIGs[1] & tig1) << 1 ) - bcT1;
int64_t bc12 = (int64_t) ( ( POPCNT64(_bTIGs[1] & tig2) << 1 ) - bcT2 ) << 1;
int64_t bc14 = (int64_t) ( ( POPCNT64(_bTIGs[1] & tig4) << 1 ) - bcT4 ) << 2;
int64_t bc18 = (int64_t) ( ( POPCNT64(_bTIGs[1] & tig8) << 1 ) - bcT8 ) << 3;
return _coeffs1[0] * ( bc01 + bc02 + bc04 + bc08 ) + _coeffs1[1] * ( bc11 + bc12 + bc14 + bc18 );
}
void ObjectnessBING::FilterTIG::update( Mat &w1f )
{
CV_Assert( w1f.cols * w1f.rows == D && w1f.type() == CV_32F && w1f.isContinuous() );
float b[D], residuals[D];
memcpy( residuals, w1f.data, sizeof(float) * D );
for ( int i = 0; i < NUM_COMP; i++ )
{
float avg = 0;
for ( int j = 0; j < D; j++ )
{
b[j] = residuals[j] >= 0.0f ? 1.0f : -1.0f;
avg += residuals[j] * b[j];
}
avg /= D;
_coeffs1[i] = avg, _coeffs2[i] = avg * 2, _coeffs4[i] = avg * 4, _coeffs8[i] = avg * 8;
for ( int j = 0; j < D; j++ )
residuals[j] -= avg * b[j];
uint64_t tig = 0;
for ( int j = 0; j < D; j++ )
tig = ( tig << 1 ) | ( b[j] > 0 ? 1 : 0 );
_bTIGs[i] = tig;
}
}
void ObjectnessBING::FilterTIG::reconstruct( Mat &w1f )
{
w1f = Mat::zeros( 8, 8, CV_32F );
float *weight = (float*) w1f.data;
for ( int i = 0; i < NUM_COMP; i++ )
{
uint64_t tig = _bTIGs[i];
for ( int j = 0; j < D; j++ )
weight[j] += _coeffs1[i] * ( ( ( tig >> ( 63 - j ) ) & 1 ) ? 1 : -1 );
}
}
// For a W by H gradient magnitude map, find a W-7 by H-7 CV_32F matching score map
// Please refer to my paper for definition of the variables used in this function
Mat ObjectnessBING::FilterTIG::matchTemplate( const Mat &mag1u )
{
const int H = mag1u.rows, W = mag1u.cols;
const Size sz( W + 1, H + 1 ); // Expand original size to avoid dealing with boundary conditions
Mat_<int64_t> Tig1 = Mat_<int64_t>::zeros( sz ), Tig2 = Mat_<int64_t>::zeros( sz );
Mat_<int64_t> Tig4 = Mat_<int64_t>::zeros( sz ), Tig8 = Mat_<int64_t>::zeros( sz );
Mat_<BYTE> Row1 = Mat_<BYTE>::zeros( sz ), Row2 = Mat_<BYTE>::zeros( sz );
Mat_<BYTE> Row4 = Mat_<BYTE>::zeros( sz ), Row8 = Mat_<BYTE>::zeros( sz );
Mat_<float> scores( sz );
for ( int y = 1; y <= H; y++ )
{
const BYTE* G = mag1u.ptr<BYTE>( y - 1 );
int64_t* T1 = Tig1.ptr<int64_t>( y ); // Binary TIG of current row
int64_t* T2 = Tig2.ptr<int64_t>( y );
int64_t* T4 = Tig4.ptr<int64_t>( y );
int64_t* T8 = Tig8.ptr<int64_t>( y );
int64_t* Tu1 = Tig1.ptr<int64_t>( y - 1 ); // Binary TIG of upper row
int64_t* Tu2 = Tig2.ptr<int64_t>( y - 1 );
int64_t* Tu4 = Tig4.ptr<int64_t>( y - 1 );
int64_t* Tu8 = Tig8.ptr<int64_t>( y - 1 );
BYTE* R1 = Row1.ptr<BYTE>( y );
BYTE* R2 = Row2.ptr<BYTE>( y );
BYTE* R4 = Row4.ptr<BYTE>( y );
BYTE* R8 = Row8.ptr<BYTE>( y );
float *s = scores.ptr<float>( y );
for ( int x = 1; x <= W; x++ )
{
BYTE g = G[x - 1];
R1[x] = ( R1[x - 1] << 1 ) | ( ( g >> 4 ) & 1 );
R2[x] = ( R2[x - 1] << 1 ) | ( ( g >> 5 ) & 1 );
R4[x] = ( R4[x - 1] << 1 ) | ( ( g >> 6 ) & 1 );
R8[x] = ( R8[x - 1] << 1 ) | ( ( g >> 7 ) & 1 );
T1[x] = ( Tu1[x] << 8 ) | R1[x];
T2[x] = ( Tu2[x] << 8 ) | R2[x];
T4[x] = ( Tu4[x] << 8 ) | R4[x];
T8[x] = ( Tu8[x] << 8 ) | R8[x];
s[x] = dot( T1[x], T2[x], T4[x], T8[x] );
}
}
Mat matchCost1f;
scores( Rect( 8, 8, W - 7, H - 7 ) ).copyTo( matchCost1f );
return matchCost1f;
}
} // namespace saliency
} // namespace cv
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace saliency
{
}
}
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef KYHEADER_H
#define KYHEADER_H
#include <assert.h>
#include <string>
#include <vector>
#include <functional>
#include <list>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <time.h>
#include <fstream>
#include <stdint.h>
// TODO: reference additional headers your program requires here
#include "opencv2/core.hpp"
#define CV_VERSION_ID CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
#ifdef _DEBUG
#define cvLIB(name) "opencv_" name CV_VERSION_ID "d"
#else
#define cvLIB(name) "opencv_" name CV_VERSION_ID
#endif
#ifdef WIN32
/* windows stuff */
#else
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
typedef bool BOOL;
typedef void *HANDLE;
#endif
#ifndef _MSC_VER
typedef unsigned char BYTE;
#else
#include <windows.h>
#endif
typedef std::vector<int> vecI;
typedef const std::string CStr;
typedef const cv::Mat CMat;
typedef std::vector<std::string> vecS;
typedef std::vector<cv::Mat> vecM;
typedef std::vector<float> vecF;
typedef std::vector<double> vecD;
namespace cv
{
namespace saliency
{
enum
{
CV_FLIP_BOTH = -1,
CV_FLIP_VERTICAL = 0,
CV_FLIP_HORIZONTAL = 1
};
#define _S(str) ((str).c_str())
#define CHK_IND(p) ((p).x >= 0 && (p).x < _w && (p).y >= 0 && (p).y < _h)
#define CV_Assert_(expr, args) \
{\
if(!(expr)) {\
String msg = cv::format args; \
printf("%s in %s:%d\n", msg.c_str(), __FILE__, __LINE__); \
cv::error(cv::Exception(CV_StsAssert, msg, __FUNCTION__, __FILE__, __LINE__) ); }\
}
// Return -1 if not in the list
template<typename T>
static inline int findFromList( const T &word, const std::vector<T> &strList )
{
std::vector<cv::String>::iterator it = std::find( strList.begin(), strList.end(), word );
if( it == strList.end() )
{
return -1;
}
else
{
int index = it - strList.begin();
return index;
}
}
template<typename T> inline T sqr( T x )
{
return x * x;
} // out of range risk for T = byte, ...
template<class T, int D> inline T vecSqrDist( const cv::Vec<T, D> &v1, const cv::Vec<T, D> &v2 )
{
T s = 0;
for ( int i = 0; i < D; i++ )
s += sqr( v1[i] - v2[i] );
return s;
} // out of range risk for T = byte, ...
template<class T, int D> inline T vecDist( const cv::Vec<T, D> &v1, const cv::Vec<T, D> &v2 )
{
return sqrt( vecSqrDist( v1, v2 ) );
} // out of range risk for T = byte, ...
inline cv::Rect Vec4i2Rect( cv::Vec4i &v )
{
return cv::Rect( cv::Point( v[0] - 1, v[1] - 1 ), cv::Point( v[2], v[3] ) );
}
#if defined(_MSC_VER)
# include <intrin.h>
# define POPCNT(x) __popcnt(x)
# define POPCNT64(x) __popcnt64(x)
#endif
#if defined(__GNUC__)
# define POPCNT(x) __builtin_popcount(x)
# define POPCNT64(x) __builtin_popcountll(x)
#endif
inline int popcnt64( register uint64_t u )
{
u = ( u & 0x5555555555555555 ) + ( ( u >> 1 ) & 0x5555555555555555 );
u = ( u & 0x3333333333333333 ) + ( ( u >> 2 ) & 0x3333333333333333 );
u = ( u & 0x0f0f0f0f0f0f0f0f ) + ( ( u >> 4 ) & 0x0f0f0f0f0f0f0f0f );
u = ( u & 0x00ff00ff00ff00ff ) + ( ( u >> 8 ) & 0x00ff00ff00ff00ff );
u = ( u & 0x0000ffff0000ffff ) + ( ( u >> 16 ) & 0x0000ffff0000ffff );
u = ( u & 0x00000000ffffffff ) + ( ( u >> 32 ) & 0x00000000ffffffff );
return (int)u;
}
inline int popcnt( register uint32_t u )
{
u = ( u & 0x55555555 ) + ( ( u >> 1 ) & 0x55555555 );
u = ( u & 0x33333333 ) + ( ( u >> 2 ) & 0x33333333 );
u = ( u & 0x0f0f0f0f ) + ( ( u >> 4 ) & 0x0f0f0f0f );
u = ( u & 0x00ff00ff ) + ( ( u >> 8 ) & 0x00ff00ff );
u = ( u & 0x0000ffff ) + ( ( u >> 16 ) & 0x0000ffff );
return (int)u;
}
inline int popcnt64_nibble( register uint64_t u )
{
static const uint8_t Table[] =
{ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
int c = 0;
while ( u )
{
c += Table[u & 0xf];
u >>= 4;
}
return (int)c;
}
inline int popcnt_nibble( register uint32_t u )
{
static const uint8_t Table[] =
{ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
int c = 0;
while ( u )
{
c += Table[u & 0xf];
u >>= 4;
}
return (int)c;
}
inline int popcnt64_byte( register uint64_t u )
{
#define B2(k) k, k+1, k+1, k+2
#define B4(k) B2(k), B2(k+1), B2(k+1), B2(k+2)
#define B6(k) B4(k), B4(k+1), B4(k+1), B4(k+2)
static const uint8_t Table[] =
{ B6( 0 ), B6( 1 ), B6( 1 ), B6( 2 ) };
#undef B6
#undef B4
#undef B2
int c = 0;
while ( u )
{
c += Table[u & 0xff];
u >>= 8;
}
return (int)c;
}
inline int popcnt_byte( register uint32_t u )
{
#define B2(k) k, k+1, k+1, k+2
#define B4(k) B2(k), B2(k+1), B2(k+1), B2(k+2)
#define B6(k) B4(k), B4(k+1), B4(k+1), B4(k+2)
static const uint8_t Table[] =
{ B6( 0 ), B6( 1 ), B6( 1 ), B6( 2 ) };
#undef B6
#undef B4
#undef B2
int c = 0;
while ( u )
{
c += Table[u & 0xff];
u >>= 8;
}
return (int)c;
}
}
}
#endif // KYHEADER_H
This diff is collapsed.
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace saliency
{
/**
* Motion Saliency
*/
} /* namespace saliency */
}/* namespace cv */
This diff is collapsed.
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace saliency
{
/**
* Objectness
*/
} /* namespace saliency*/
}/* namespace cv */
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__
#include "opencv2/saliency.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#endif
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace saliency
{
Saliency::~Saliency()
{
}
Ptr<Saliency> Saliency::create( const String& saliencyType )
{
return Algorithm::create<Saliency>( "SALIENCY." + saliencyType );
}
bool Saliency::computeSaliency( const InputArray image, OutputArray saliencyMap )
{
if( image.empty() )
return false;
return computeSaliencyImpl( image, saliencyMap );
}
String Saliency::getClassName() const
{
return className;
}
} /* namespace saliency */
} /* namespace cv */
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "opencv2/saliency.hpp"
namespace cv
{
namespace saliency
{
CV_INIT_ALGORITHM( StaticSaliencySpectralResidual, "SALIENCY.SPECTRAL_RESIDUAL",
obj.info()->addParam( obj, "resImWidth", obj.resImWidth); obj.info()->addParam( obj, "resImHeight", obj.resImHeight) );
CV_INIT_ALGORITHM(
ObjectnessBING, "SALIENCY.BING",
obj.info()->addParam(obj, "_base", obj._base); obj.info()->addParam(obj, "_NSS", obj._NSS); obj.info()->addParam(obj, "_W", obj._W) );
CV_INIT_ALGORITHM( MotionSaliencyBinWangApr2014, "SALIENCY.BinWangApr2014",
obj.info()->addParam( obj, "imageWidth", obj.imageWidth); obj.info()->addParam( obj, "imageHeight", obj.imageHeight) );
bool initModule_saliency( void )
{
bool all = true;
all &= !StaticSaliencySpectralResidual_info_auto.name().empty();
//all &= !MotionSaliencySuBSENSE_info_auto.name().empty();
all &= !MotionSaliencyBinWangApr2014_info_auto.name().empty();
all &= !ObjectnessBING_info_auto.name().empty();
return all;
}
} // namespace saliency
} // namespace cv
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace saliency
{
/**
* StaticSaliency
*/
bool StaticSaliency::computeBinaryMap( const Mat& saliencyMap, Mat& BinaryMap )
{
Mat labels = Mat::zeros( saliencyMap.rows * saliencyMap.cols, 1, 1 );
Mat samples = Mat_<float>( saliencyMap.rows * saliencyMap.cols, 1 );
Mat centers;
TermCriteria terminationCriteria;
terminationCriteria.epsilon = 0.2;
terminationCriteria.maxCount = 1000;
terminationCriteria.type = TermCriteria::COUNT + TermCriteria::EPS;
int elemCounter = 0;
for ( int i = 0; i < saliencyMap.rows; i++ )
{
for ( int j = 0; j < saliencyMap.cols; j++ )
{
samples.at<float>( elemCounter, 0 ) = saliencyMap.at<float>( i, j );
elemCounter++;
}
}
kmeans( samples, 5, labels, terminationCriteria, 5, KMEANS_RANDOM_CENTERS, centers );
Mat outputMat = Mat_<float>( saliencyMap.size() );
int intCounter = 0;
for ( int x = 0; x < saliencyMap.rows; x++ )
{
for ( int y = 0; y < saliencyMap.cols; y++ )
{
outputMat.at<float>( x, y ) = centers.at<float>( labels.at<int>( intCounter, 0 ), 0 );
intCounter++;
}
}
//Convert
outputMat = outputMat * 255;
outputMat.convertTo( outputMat, CV_8U );
// adaptative thresholding using Otsu's method, to make saliency map binary
threshold( outputMat, BinaryMap, 0, 255, THRESH_BINARY | THRESH_OTSU );
return true;
}
}/* namespace saliency */
}/* namespace cv */
/*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) 2014, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace saliency
{
/**
* SaliencySpectralResidual
*/
StaticSaliencySpectralResidual::StaticSaliencySpectralResidual()
{
className = "SPECTRAL_RESIDUAL";
resImWidth = 64;
resImHeight = 64;
}
StaticSaliencySpectralResidual::~StaticSaliencySpectralResidual()
{
}
void StaticSaliencySpectralResidual::read( const cv::FileNode& /*fn*/)
{
//params.read( fn );
}
void StaticSaliencySpectralResidual::write( cv::FileStorage& /*fs*/) const
{
//params.write( fs );
}
bool StaticSaliencySpectralResidual::computeSaliencyImpl( const InputArray image, OutputArray saliencyMap )
{
Mat grayTemp, grayDown;
std::vector<Mat> mv;
Size resizedImageSize( resImWidth, resImHeight );
Mat realImage( resizedImageSize, CV_64F );
Mat imaginaryImage( resizedImageSize, CV_64F );
imaginaryImage.setTo( 0 );
Mat combinedImage( resizedImageSize, CV_64FC2 );
Mat imageDFT;
Mat logAmplitude;
Mat angle( resizedImageSize, CV_64F );
Mat magnitude( resizedImageSize, CV_64F );
Mat logAmplitude_blur, imageGR;
if( image.channels() == 3 )
{
cvtColor( image, imageGR, COLOR_BGR2GRAY );
resize( imageGR, grayDown, resizedImageSize, 0, 0, INTER_LINEAR );
}
else
{
resize( image, grayDown, resizedImageSize, 0, 0, INTER_LINEAR );
}
grayDown.convertTo( realImage, CV_64F );
mv.push_back( realImage );
mv.push_back( imaginaryImage );
merge( mv, combinedImage );
dft( combinedImage, imageDFT );
split( imageDFT, mv );
//-- Get magnitude and phase of frequency spectrum --//
cartToPolar( mv.at( 0 ), mv.at( 1 ), magnitude, angle, false );
log( magnitude, logAmplitude );
//-- Blur log amplitude with averaging filter --//
blur( logAmplitude, logAmplitude_blur, Size( 3, 3 ), Point( -1, -1 ), BORDER_DEFAULT );
exp( logAmplitude - logAmplitude_blur, magnitude );
//-- Back to cartesian frequency domain --//
polarToCart( magnitude, angle, mv.at( 0 ), mv.at( 1 ), false );
merge( mv, imageDFT );
dft( imageDFT, combinedImage, DFT_INVERSE );
split( combinedImage, mv );
cartToPolar( mv.at( 0 ), mv.at( 1 ), magnitude, angle, false );
GaussianBlur( magnitude, magnitude, Size( 5, 5 ), 8, 0, BORDER_DEFAULT );
magnitude = magnitude.mul( magnitude );
double minVal, maxVal;
minMaxLoc( magnitude, &minVal, &maxVal );
magnitude = magnitude / maxVal;
magnitude.convertTo( magnitude, CV_32F );
resize( magnitude, saliencyMap, image.size(), 0, 0, INTER_LINEAR );
#ifdef SALIENCY_DEBUG
// visualize saliency map
imshow( "Saliency Map Interna", saliencyMap );
#endif
return true;
}
} /* namespace saliency */
}/* namespace cv */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment