/*! * \file CyclopsParam.h * \date 2019/11/12 * * \author Lin, Chi * Contact: lin.chi@hzleaper.com * * * \note */ #ifndef __CyclopsParam_h_ #define __CyclopsParam_h_ #include #include #include "CVUtils.h" struct CyclopsParam { virtual void serialize(FileStorage& fs) const = 0; virtual void deserialize(const FileNode& node) = 0; virtual void resetValue() = 0; virtual size_t getType() const = 0; virtual CyclopsParam* copy() const = 0; virtual void backup() = 0; virtual void restore() = 0; virtual void print(std::stringstream& ss) const = 0; virtual void fromString(std::stringstream& ss) = 0; }; template struct CyclopsParamX : public CyclopsParam { T val; const T minVal; const T maxVal; const T defaultVal; T backupVal; CyclopsParamX(const T& defaultV, const T& minV, const T& maxV) : defaultVal(defaultV), val(defaultV), minVal(minV), maxVal(maxV) {} virtual ~CyclopsParamX() {} virtual void serialize(FileStorage& fs) const { fs << "val" << val; fs << "backup" << backupVal; } virtual void deserialize(const FileNode& node) { node["val"] >> val; node["backup"] >> backupVal; } void setValue(const T& v) { if (v >= minVal && v <= maxVal) { val = v; } } virtual void resetValue() { val = defaultVal; } virtual size_t getType() const { return typeid(T).hash_code(); } virtual CyclopsParam* copy() const { CyclopsParamX* p = new CyclopsParamX(defaultVal, minVal, maxVal); p->val = val; return p; } virtual void backup() { backupVal = val; } virtual void restore() { val = backupVal; } virtual void print(std::stringstream& ss) const { ss << val; } virtual void fromString(std::stringstream& ss) { ss >> val; } }; typedef CyclopsParamX CyclopsParamInt; typedef CyclopsParamX CyclopsParamDouble; typedef CyclopsParamX CyclopsParamBool; typedef CyclopsParamX CyclopsParamSize; // special instantiation for size param void CyclopsParamSize::print(std::stringstream& ss) const { ss << val.width << " x " << val.height; } void CyclopsParamSize::fromString(std::stringstream& ss) { ss >> val.width; std::string temp; ss >> temp; ss >> val.height; } // add more CyclopsParamX for other data types struct CyclopsParams { public: CyclopsParams() {} ~CyclopsParams() { for (CyclopsParam* p : params) delete p; params.clear(); } CyclopsParams(const CyclopsParams& other) { setDirtyBit(true); validateFunc = other.validateFunc; for (const CyclopsParam* p : other.params) { params.push_back(p->copy()); } } void operator= (const CyclopsParams& other) = delete; template void addParam(const T& defaultV, const T& minV, const T& maxV) { params.push_back(new CyclopsParamX(defaultV, minV, maxV)); } template void addParam(const T& defaultV) { params.push_back(new CyclopsParamX(defaultV, std::numeric_limits::lowest(), std::numeric_limits::max())); } template void addParam(const T& defaultV, const T& oneLimit) { params.push_back(new CyclopsParamX(defaultV, oneLimit <= defaultV ? oneLimit : std::numeric_limits::lowest(), oneLimit > defaultV ? oneLimit : std::numeric_limits::max())); } template<> void addParam(const Size& defaultV) { params.push_back(new CyclopsParamSize(defaultV, Size(0, 0), Size(INT_MAX, INT_MAX))); } template<> void addParam(const Size& defaultV, const Size& minV, const Size& maxV) { params.push_back(new CyclopsParamSize(defaultV, minV, maxV)); } template<> void addParam(const Size& defaultV, const Size& oneLimit) = delete; int count() const { return params.size(); } void serialize(FileStorage& fs) const { fs << "params" << "["; for (const CyclopsParam* p : params) { fs << "{:"; fs << "type" << std::to_string(p->getType()); p->serialize(fs); fs << "}"; } fs << "]"; fs << "dirty" << dirtyBit; } void deserialize(const FileNode& node) { FileNode pNode = node["params"]; if (pNode.isNone()) return; if (params.size() != pNode.size()) return; int i = 0; for (auto it = pNode.begin(); it != pNode.end(); ++it, i++) { std::string typecode; (*it)["type"] >> typecode; if (typecode != std::to_string(params[i]->getType())) continue; params[i]->deserialize(*it); } node["dirty"] >> dirtyBit; } template void setValue(int idx, const T& val) { if (idx < 0 || idx > params.size()) return; CyclopsParamX* p = dynamic_cast*>(params[idx]); if (p && p->val != val) { p->setValue(val); setDirtyBit(true); } } void setValueFromString(int idx, const std::string& str) { if (idx < 0 || idx > params.size()) return; CyclopsParam* p = params[idx]; std::stringstream ss(str); p->fromString(ss); } template T getValue(int idx) const { if (idx < 0 || idx > params.size()) return T(); const CyclopsParamX* p = dynamic_cast*>(params[idx]); if (p) { return p->val; } return T(); } void reset() { for (CyclopsParam* p : params) { p->resetValue(); } setDirtyBit(true); } template void getSetting(int idx, T* pMinVal = nullptr, T* pMaxVal = nullptr, T* pDefaultVal = nullptr) const { if (idx < 0 || idx > params.size()) return; const CyclopsParamX* p = dynamic_cast*>(params[idx]); if (p) { if (pMinVal) *pMinVal = p->minVal; if (pMaxVal) *pMaxVal = p->maxVal; if (pDefaultVal) *pDefaultVal = p->defaultVal; } } template bool checkParamType(int idx) const { if (idx < 0 || idx > params.size()) return false; return params[idx]->getType() == typeid(T).hash_code(); } void setDirtyBit(bool dirty) { dirtyBit = dirty; } bool isDirty() const { return dirtyBit; } typedef std::function(CyclopsParams*, const Size&, bool)> ValidateFunc; void setValidateFunc(ValidateFunc func) { validateFunc = func; } std::list isValid(const Size& sampleSize, bool fix) { return validateFunc ? validateFunc(this, sampleSize, fix) : std::list(); } bool isValidSimple(const Size& sampleSize) { return isValid(sampleSize, false).empty(); } void backupAll() { for (CyclopsParam* p : params) { p->backup(); } } void restoreAll() { for (CyclopsParam* p : params) { p->restore(); } setDirtyBit(true); } std::string print() const { std::stringstream ss; for (int i = 0; i < params.size(); ++i) { const CyclopsParam* p = params[i]; p->print(ss); ss << ","; } return ss.str(); } protected: friend class CyclopsGrids; CyclopsParam* get(int idx) { if (idx < 0 || idx > params.size()) return nullptr; return params[idx]; } const CyclopsParam* get(int idx) const { if (idx < 0 || idx > params.size()) return nullptr; return params[idx]; } private: std::vector params; bool dirtyBit = true; ValidateFunc validateFunc = nullptr; }; #endif // CyclopsParam_h_