|
|
|
|
|
/*!
|
|
|
|
|
|
* \file lightCompensate.h
|
|
|
|
|
|
* \date 2019/08/13
|
|
|
|
|
|
*
|
|
|
|
|
|
* \author Lou.Lixuan
|
|
|
|
|
|
* Contact: Lou.Lixuan@hzleaper.com
|
|
|
|
|
|
*
|
|
|
|
|
|
*
|
|
|
|
|
|
* \note
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef FlatFieldCalibrator_h_
|
|
|
|
|
|
#define FlatFieldCalibrator_h_
|
|
|
|
|
|
|
|
|
|
|
|
#include "StdUtils.h"
|
|
|
|
|
|
#include "CVUtils.h"
|
|
|
|
|
|
#include "CyclopsModules.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief calibrate non-uniformity between same background pixles.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Note: Both gray and color source is supported.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Example:
|
|
|
|
|
|
* \code{.cpp}
|
|
|
|
|
|
* Mat src = imread("yourfilePath/picName.png", 1);
|
|
|
|
|
|
* FlatFieldCalibrator calib;
|
|
|
|
|
|
* calib.setInitBGR(Scalar(70,87,60));
|
|
|
|
|
|
* calib.setExpectedBGR(Scalar(105, 120, 112));
|
|
|
|
|
|
* calib.setBGRWidth(10, 10, 10);
|
|
|
|
|
|
* calib.setKernelSize(81, 81);
|
|
|
|
|
|
* calib.setRefreshSpeed(0.5);
|
|
|
|
|
|
* calib.init(src, FlatFieldCalibrator::COLOR);
|
|
|
|
|
|
*
|
|
|
|
|
|
* string filePath = "yourfilePath";
|
|
|
|
|
|
* float changeRate = 0.0;
|
|
|
|
|
|
* for (int i = 0; i < 100; ++i) {
|
|
|
|
|
|
* string fileName = to_string(i) + ".png";
|
|
|
|
|
|
* Mat trainMat = imread(path + fileName, 0);
|
|
|
|
|
|
* calib.train(trainMat, changeRate, FlatFieldCalibrator::COLOR);
|
|
|
|
|
|
* }
|
|
|
|
|
|
* Mat intensity
|
|
|
|
|
|
* calib.foregroundToIntensity(intensity, FlatFieldCalibrator::COLOR);
|
|
|
|
|
|
* Mat testMat = imread("yourfilePath/testPicName.png", 1), dst;
|
|
|
|
|
|
* calib.apply(testMat, dst, FlatFieldCalibrator::COLOR);
|
|
|
|
|
|
* \endcode
|
|
|
|
|
|
*
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
class FlatFieldCalibrator : public ICyclopsModuleInstance
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
enum ColorType {
|
|
|
|
|
|
GRAY, COLOR
|
|
|
|
|
|
};
|
|
|
|
|
|
enum FieldCalcType
|
|
|
|
|
|
{
|
|
|
|
|
|
/*! get light intensity directly in every iteration */
|
|
|
|
|
|
DIRECT = 0,
|
|
|
|
|
|
/*! extract foreground in every iteration, get light intensity finally*/
|
|
|
|
|
|
INDIRECT = 1,
|
|
|
|
|
|
// add more type before this line...
|
|
|
|
|
|
};
|
|
|
|
|
|
/*! \fn setFieldCalcType
|
|
|
|
|
|
* Define which algorithm we should use in light field construction, default to INDIRECT
|
|
|
|
|
|
* \fn getInitRange
|
|
|
|
|
|
* Get which algorithm we are using in light field construction
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER_GET(FieldCalcType, FieldCalcType)
|
|
|
|
|
|
/*! \fn setInitBGR
|
|
|
|
|
|
* Define initial value of pixels belong to background, 3 to 255, default to (70, 70, 70)
|
|
|
|
|
|
* \fn getInitBGR
|
|
|
|
|
|
* Get initial value of pixels belong to foreground
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER_GET(Scalar, InitBGR)
|
|
|
|
|
|
/*! \fn setExpectedBGR
|
|
|
|
|
|
* Define expected BGR value of pixels belong to background, 3 to 255, default to <120, 120, 120>
|
|
|
|
|
|
* \fn getExpectedBGR
|
|
|
|
|
|
* Get expected BGR value of pixels belong to foreground
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER_GET(Scalar, ExpectedBGR)
|
|
|
|
|
|
/*! \fn setBGRWidth
|
|
|
|
|
|
* Define distribution width of BGR value belong to background, 3 to 25, default to <10, 10, 10>
|
|
|
|
|
|
* \fn getBGRWidth
|
|
|
|
|
|
* Get distribution width of BGR value belong to foreground
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER_GET(Scalar, BGRWidth)
|
|
|
|
|
|
// define kernel size, odd numbers(1, 3, 5, ...), 1 to INT_MAX, default to (121, 121)
|
|
|
|
|
|
DECLARE_PARAMETER_GET(Size, KSize)
|
|
|
|
|
|
/*! \fn setRefreshSpeed
|
|
|
|
|
|
* Define refresh speed of light field, 0 to 1.0, default to 0.5
|
|
|
|
|
|
* \fn getBGRWidth
|
|
|
|
|
|
* Get refresh speed of light field
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER2(float, RefreshSpeed, 0, 1.0)
|
|
|
|
|
|
/*! \fn setGroundDensity
|
|
|
|
|
|
* Define minimum density of foregroundMask which is used to dilate foreground, 0 to 1.0, default to 0.2
|
|
|
|
|
|
* \fn getGroundDensity
|
|
|
|
|
|
* Get minimum density of foregroundMask which is used to dilate foreground
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER2(float, GroundDensity, 0, 1.0)
|
|
|
|
|
|
/*! \fn setIterationNum
|
|
|
|
|
|
* Define maximum number of iterations, 50 to 200, default to 50
|
|
|
|
|
|
* \fn getIterationNum
|
|
|
|
|
|
* Get maximum number of iterations
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER2(int, IterationNum, 10, 200)
|
|
|
|
|
|
/*! \fn setPrecision
|
|
|
|
|
|
* Define precision during training, default to 0.01
|
|
|
|
|
|
* \fn getPrecision
|
|
|
|
|
|
* Get value of precision
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECLARE_PARAMETER(float, Precision)
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
FlatFieldCalibrator();
|
|
|
|
|
|
virtual ~FlatFieldCalibrator() {}
|
|
|
|
|
|
|
|
|
|
|
|
typedef std::shared_ptr<FlatFieldCalibrator> Ptr;
|
|
|
|
|
|
DECL_GET_INSTANCE(FlatFieldCalibrator::Ptr)
|
|
|
|
|
|
|
|
|
|
|
|
/*! \fn serializeToMemory
|
|
|
|
|
|
* Serialize FlatFieldCalibrator (including its calibration matrix) into a in-memory string, see also deserializeFromMemory()
|
|
|
|
|
|
* @param str used to take the output serialization result
|
|
|
|
|
|
* @return true for succeed, false for fail
|
|
|
|
|
|
* \fn serializeToFile
|
|
|
|
|
|
* Serialize FlatFieldCalibrator (including its calibration matrix) into a text file, see also deserializeFromFile()
|
|
|
|
|
|
* @param filename file name (full path) where we will write the data
|
|
|
|
|
|
* @return true for succeed, false for fail
|
|
|
|
|
|
* \fn deserializeFromMemory
|
|
|
|
|
|
* Deserialize FlatFieldCalibrator from in-memory string, see also serializeToMemory()
|
|
|
|
|
|
* @param str in-memory string
|
|
|
|
|
|
* @return true for succeed, false for fail
|
|
|
|
|
|
* \fn deserializeFromFile
|
|
|
|
|
|
* Deserialize FlatFieldCalibrator from a text file, see also serializeToFile()
|
|
|
|
|
|
* @param filename file name (full path) where we will read the data
|
|
|
|
|
|
* @return true for succeed, false for fail
|
|
|
|
|
|
*/
|
|
|
|
|
|
DECL_SERIALIZE_FUNCS
|
|
|
|
|
|
|
|
|
|
|
|
virtual bool setInitBGR(Scalar color);
|
|
|
|
|
|
virtual bool setExpectedBGR(Scalar color);
|
|
|
|
|
|
virtual bool setBGRWidth(Scalar colorWidth);
|
|
|
|
|
|
virtual bool setKernelSize(int w, int h);
|
|
|
|
|
|
Mat getGrayIntensity() { return mGrayIntensity.clone(); }
|
|
|
|
|
|
Mat getColorIntensity() { return mColorIntensity.clone(); }
|
|
|
|
|
|
|
|
|
|
|
|
/*! initialize intensity mat
|
|
|
|
|
|
* @param src input the source image, whose light intensity will be extracted
|
|
|
|
|
|
* @param type input type of calibrate, ColorType::<GRAY, COLOR>
|
|
|
|
|
|
*/
|
|
|
|
|
|
virtual bool init(const Mat&src, int colorType);
|
|
|
|
|
|
/*! extracted information from image, refresh intensity mat
|
|
|
|
|
|
* @param src input the source image, whose light intensity will be extracted
|
|
|
|
|
|
* @param maskChangedRate output the change rate of intensity
|
|
|
|
|
|
* @param type input type of calibrate, ColorType::<GRAY, COLOR>
|
|
|
|
|
|
*/
|
|
|
|
|
|
virtual bool train(const Mat&src, float& changeRate, int type);
|
|
|
|
|
|
/*! apply light compensation to the image
|
|
|
|
|
|
* @param src input the source image
|
|
|
|
|
|
* @param dst output light compensated image
|
|
|
|
|
|
* @param type input type of calibrate, ColorType::<GRAY, COLOR>
|
|
|
|
|
|
*/
|
|
|
|
|
|
virtual bool apply(const Mat& src, Mat& dst, int type);
|
|
|
|
|
|
/*! transform foreground to intensity field
|
|
|
|
|
|
* @param intensity output the intensity mat
|
|
|
|
|
|
* @param type input type of calibrate, ColorType::<GRAY, COLOR>
|
|
|
|
|
|
*/
|
|
|
|
|
|
virtual bool foregroundToIntensity(Mat& intensity, int colorType);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
void initLightField(const Mat& src, int colorType);
|
|
|
|
|
|
/*! refresh intensity according to src image and background mask
|
|
|
|
|
|
* @param src input the source image
|
|
|
|
|
|
* @param curIntensity input the current intensity
|
|
|
|
|
|
* @param nextIntensity input the nextIntensity, avoid space allocation
|
|
|
|
|
|
* @param tempI input temp space, avoid space allocation
|
|
|
|
|
|
* @param backgroundMask input mask of background
|
|
|
|
|
|
* @param type input type of calibrate
|
|
|
|
|
|
* @return change rate of intensity
|
|
|
|
|
|
*/
|
|
|
|
|
|
float refreshIntensity(const Mat& src, Mat& curIntensity, Mat&nextIntensity, Mat& tempI, const Mat& backgroundMask, int type);
|
|
|
|
|
|
float _train(const Mat& src, int type);
|
|
|
|
|
|
float _trainColor(const Mat& src);
|
|
|
|
|
|
void extractForeground(const Mat& src, int colorType);
|
|
|
|
|
|
void dilateCurForeground(const Mat& src, Mat& curForeground, Mat& foregroundMask, int colorType);
|
|
|
|
|
|
/*! there is only one connected domain
|
|
|
|
|
|
* @param srcMask input the source mask
|
|
|
|
|
|
* @param domainMask output main domain mask
|
|
|
|
|
|
*/
|
|
|
|
|
|
void getMainDomainMask(const Mat& srcMask, Mat& domainMask);
|
|
|
|
|
|
bool patchUp(const Mat&src, const Rect& rect, int type);
|
|
|
|
|
|
|
|
|
|
|
|
virtual bool serialize(FileStorage& fs);
|
|
|
|
|
|
virtual bool deserialize(const FileNode& fs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
Mat mGrayIntensity;
|
|
|
|
|
|
Mat mColorIntensity;
|
|
|
|
|
|
Mat mMaskLUT;
|
|
|
|
|
|
Mat mMask;
|
|
|
|
|
|
Mat mForeground;
|
|
|
|
|
|
bool mNewForeground;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|