/*! * \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 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:: */ 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:: */ 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:: */ 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:: */ 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