diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..2b27bb2f4aa05f653de31138a2ac2b24a850aa84 --- /dev/null +++ b/.clang-format @@ -0,0 +1,104 @@ +--- +Language: Cpp +Standard: Cpp11 +UseTab: Never +TabWidth: 4 +IndentWidth: 4 +AccessModifierOffset: -4 +ContinuationIndentWidth: 4 +ColumnLimit: 79 +ConstructorInitializerIndentWidth: 0 +BinPackArguments: false +BinPackParameters: false +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignOperands: true +AlignEscapedNewlines: Right +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +CompactNamespaces: false +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +IndentCaseLabels: false +IndentPPDirectives: BeforeHash +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +PenaltyBreakAssignment: 100 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +CommentPragmas: '' +MacroBlockBegin: '' +MacroBlockEnd: '' +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +... diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..7b80d1c534ecc2c161a0b02606664db720304395 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{c,h,cc,hh,cpp,hpp,cxx,hxx}] +indent_style = space +indent_size = 4 + +[*.py] +indent_style = space +indent_size = 4 + +[*.yml] +indent_style = space +indent_size = 2 diff --git a/Src/BioTrackerPlugin.cpp b/Src/BioTrackerPlugin.cpp index a10baf4d78527e5909fabd22d5551d7d406a4194..d683f9467c2435c5e9db23ac87db51cb4a6db636 100644 --- a/Src/BioTrackerPlugin.cpp +++ b/Src/BioTrackerPlugin.cpp @@ -9,111 +9,213 @@ #include "View/TrackedElementView.h" #include "Utility/TrackedComponents/TrackedComponentFactory.h" -BioTrackerPlugin::BioTrackerPlugin() { +BioTrackerPlugin::BioTrackerPlugin() +{ } -BioTrackerPlugin::~BioTrackerPlugin() { +BioTrackerPlugin::~BioTrackerPlugin() +{ _cfg->save(Config::configLocation, "BackgroundSubtractionConfig.ini"); - delete _cfg; + delete _cfg; } -IView* BioTrackerPlugin::getTrackerParameterWidget() { - return qobject_cast<ControllerTrackingAlgorithm*> (m_TrackerController)->getTrackingParameterWidget(); +IView* BioTrackerPlugin::getTrackerParameterWidget() +{ + return qobject_cast<ControllerTrackingAlgorithm*>(m_TrackerController) + ->getTrackingParameterWidget(); } -IView *BioTrackerPlugin::getTrackerElementsWidget() +IView* BioTrackerPlugin::getTrackerElementsWidget() { - return qobject_cast<ControllerTrackedComponent *> (m_ComponentController)->getTrackingElementsWidget(); + return qobject_cast<ControllerTrackedComponent*>(m_ComponentController) + ->getTrackingElementsWidget(); } // forwards tracked component model to coreApp -IModel* BioTrackerPlugin::getTrackerComponentModel() { - return qobject_cast<ControllerTrackedComponent *> (m_ComponentController)->getModel(); +IModel* BioTrackerPlugin::getTrackerComponentModel() +{ + return qobject_cast<ControllerTrackedComponent*>(m_ComponentController) + ->getModel(); } -IModelTrackedComponentFactory *BioTrackerPlugin::getComponentFactory() { - return new TrackedComponentFactory(); +IModelTrackedComponentFactory* BioTrackerPlugin::getComponentFactory() +{ + return new TrackedComponentFactory(); } -void BioTrackerPlugin::createPlugin() { - _cfg = new Config(); +void BioTrackerPlugin::createPlugin() +{ + _cfg = new Config(); _cfg->load(Config::configLocation, "BackgroundSubtractionConfig.ini"); - m_PluginContext = new PluginContext(this, _cfg); - m_PluginContext->createApplication(); + m_PluginContext = new PluginContext(this, _cfg); + m_PluginContext->createApplication(); - IController * ctr = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - m_ComponentController = qobject_cast<ControllerTrackedComponent *>(ctr); + IController* ctr = m_PluginContext->requestController( + ENUMS::CONTROLLERTYPE::COMPONENT); + m_ComponentController = qobject_cast<ControllerTrackedComponent*>(ctr); - IController * ctr2 = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::TRACKING); - m_TrackerController = qobject_cast<ControllerTrackingAlgorithm *>(ctr2); + IController* ctr2 = m_PluginContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKING); + m_TrackerController = qobject_cast<ControllerTrackingAlgorithm*>(ctr2); - connectInterfaces(); + connectInterfaces(); - qDebug() << "BST-Tracker loaded!"; + qDebug() << "BST-Tracker loaded!"; } -void BioTrackerPlugin::connectInterfaces() { - ControllerTrackingAlgorithm* ctrAlg = qobject_cast<ControllerTrackingAlgorithm*> (m_TrackerController); - ControllerTrackedComponent* ctrTrC = qobject_cast<ControllerTrackedComponent*> (m_ComponentController); - - //controllertrackingalgorithm - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitCvMat, this, &BioTrackerPlugin::emitCvMat); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitTrackingDone, this, &BioTrackerPlugin::emitTrackingDone); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitChangeDisplayImage, this, &BioTrackerPlugin::emitChangeDisplayImage); - QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrAlg, &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); - //tracking algorithm - QObject::connect(static_cast<BioTrackerTrackingAlgorithm*>(ctrAlg->getModel()), SIGNAL(emitDimensionUpdate(int, int)), this, SIGNAL(emitDimensionUpdate(int, int))); - //controllertrackedcomponents - QObject::connect(this, &BioTrackerPlugin::emitAddTrajectory, ctrTrC, &ControllerTrackedComponent::receiveAddTrajectory, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitRemoveTrajectory, ctrTrC, &ControllerTrackedComponent::receiveRemoveTrajectory, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitRemoveTrajectoryId, ctrTrC, &ControllerTrackedComponent::receiveRemoveTrajectoryId, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitRemoveTrackEntity, ctrTrC, &ControllerTrackedComponent::receiveRemoveTrackEntity, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitValidateTrajectory, ctrTrC, &ControllerTrackedComponent::receiveValidateTrajectory, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitValidateEntity, ctrTrC, &ControllerTrackedComponent::receiveValidateEntity, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitEntityRotation, ctrTrC, &ControllerTrackedComponent::receiveEntityRotation, Qt::DirectConnection); - //connect this to enable moving of elements -> we need pxtocm() to create new poses - QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrTrC, &ControllerTrackedComponent::receiveAreaDescriptorUpdate, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitMoveElement, ctrTrC, &ControllerTrackedComponent::receiveMoveElement, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitSwapIds, ctrTrC, &ControllerTrackedComponent::receiveSwapIds, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitToggleFixTrack, ctrTrC, &ControllerTrackedComponent::receiveToggleFixTrack, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitCurrentFrameNumber, ctrTrC, &ControllerTrackedComponent::receiveCurrentFrameNumber, Qt::DirectConnection); +void BioTrackerPlugin::connectInterfaces() +{ + ControllerTrackingAlgorithm* ctrAlg = + qobject_cast<ControllerTrackingAlgorithm*>(m_TrackerController); + ControllerTrackedComponent* ctrTrC = + qobject_cast<ControllerTrackedComponent*>(m_ComponentController); + + // controllertrackingalgorithm + QObject::connect(ctrAlg, + &ControllerTrackingAlgorithm::emitCvMat, + this, + &BioTrackerPlugin::emitCvMat); + QObject::connect(ctrAlg, + &ControllerTrackingAlgorithm::emitTrackingDone, + this, + &BioTrackerPlugin::emitTrackingDone); + QObject::connect(ctrAlg, + &ControllerTrackingAlgorithm::emitChangeDisplayImage, + this, + &BioTrackerPlugin::emitChangeDisplayImage); + QObject::connect( + this, + &BioTrackerPlugin::emitAreaDescriptorUpdate, + ctrAlg, + &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); + // tracking algorithm + QObject::connect( + static_cast<BioTrackerTrackingAlgorithm*>(ctrAlg->getModel()), + SIGNAL(emitDimensionUpdate(int, int)), + this, + SIGNAL(emitDimensionUpdate(int, int))); + // controllertrackedcomponents + QObject::connect(this, + &BioTrackerPlugin::emitAddTrajectory, + ctrTrC, + &ControllerTrackedComponent::receiveAddTrajectory, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitRemoveTrajectory, + ctrTrC, + &ControllerTrackedComponent::receiveRemoveTrajectory, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitRemoveTrajectoryId, + ctrTrC, + &ControllerTrackedComponent::receiveRemoveTrajectoryId, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitRemoveTrackEntity, + ctrTrC, + &ControllerTrackedComponent::receiveRemoveTrackEntity, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitValidateTrajectory, + ctrTrC, + &ControllerTrackedComponent::receiveValidateTrajectory, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitValidateEntity, + ctrTrC, + &ControllerTrackedComponent::receiveValidateEntity, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitEntityRotation, + ctrTrC, + &ControllerTrackedComponent::receiveEntityRotation, + Qt::DirectConnection); + // connect this to enable moving of elements -> we need pxtocm() to create + // new poses + QObject::connect(this, + &BioTrackerPlugin::emitAreaDescriptorUpdate, + ctrTrC, + &ControllerTrackedComponent::receiveAreaDescriptorUpdate, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitMoveElement, + ctrTrC, + &ControllerTrackedComponent::receiveMoveElement, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitSwapIds, + ctrTrC, + &ControllerTrackedComponent::receiveSwapIds, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitToggleFixTrack, + ctrTrC, + &ControllerTrackedComponent::receiveToggleFixTrack, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitCurrentFrameNumber, + ctrTrC, + &ControllerTrackedComponent::receiveCurrentFrameNumber, + Qt::DirectConnection); } - -void BioTrackerPlugin::receiveAreaDescriptor(IModelAreaDescriptor *areaDescr) { - Q_EMIT emitAreaDescriptorUpdate(areaDescr); +void BioTrackerPlugin::receiveAreaDescriptor(IModelAreaDescriptor* areaDescr) +{ + Q_EMIT emitAreaDescriptorUpdate(areaDescr); } -void BioTrackerPlugin::receiveCurrentFrameFromMainApp(std::shared_ptr<cv::Mat> mat, uint frameNumber) { - qobject_cast<ControllerTrackingAlgorithm*> (m_TrackerController)->doTracking(mat, frameNumber); +void BioTrackerPlugin::receiveCurrentFrameFromMainApp( + std::shared_ptr<cv::Mat> mat, + uint frameNumber) +{ + qobject_cast<ControllerTrackingAlgorithm*>(m_TrackerController) + ->doTracking(mat, frameNumber); - Q_EMIT emitCurrentFrameNumber(frameNumber); + Q_EMIT emitCurrentFrameNumber(frameNumber); } -void BioTrackerPlugin::receiveCurrentFrameNumberFromMainApp(uint frameNumber) { - Q_EMIT emitCurrentFrameNumber(frameNumber); +void BioTrackerPlugin::receiveCurrentFrameNumberFromMainApp(uint frameNumber) +{ + Q_EMIT emitCurrentFrameNumber(frameNumber); } -void BioTrackerPlugin::receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory) { - Q_EMIT emitRemoveTrajectory(trajectory); +void BioTrackerPlugin::receiveRemoveTrajectory( + IModelTrackedTrajectory* trajectory) +{ + Q_EMIT emitRemoveTrajectory(trajectory); } -void BioTrackerPlugin::receiveAddTrajectory(QPoint pos) { - Q_EMIT emitAddTrajectory(pos); +void BioTrackerPlugin::receiveAddTrajectory(QPoint pos) +{ + Q_EMIT emitAddTrajectory(pos); } -void BioTrackerPlugin::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) { - Q_EMIT emitSwapIds(trajectory0, trajectory1); +void BioTrackerPlugin::receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1) +{ + Q_EMIT emitSwapIds(trajectory0, trajectory1); } -void BioTrackerPlugin::sendCorePermissions() { - // get plugin settings - - // signal permissions - Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>(ENUMS::COREPERMISSIONS::COMPONENTVIEW, _cfg->EnableView)); - Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>(ENUMS::COREPERMISSIONS::COMPONENTMOVE, _cfg->EnableMove)); - Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>(ENUMS::COREPERMISSIONS::COMPONENTREMOVE, _cfg->EnableRemove)); - Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>(ENUMS::COREPERMISSIONS::COMPONENTSWAP, _cfg->EnableSwap)); - Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>(ENUMS::COREPERMISSIONS::COMPONENTADD, _cfg->EnableAdd)); - Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>(ENUMS::COREPERMISSIONS::COMPONENTROTATE, _cfg->EnableRotate)); +void BioTrackerPlugin::sendCorePermissions() +{ + // get plugin settings + + // signal permissions + Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>( + ENUMS::COREPERMISSIONS::COMPONENTVIEW, + _cfg->EnableView)); + Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>( + ENUMS::COREPERMISSIONS::COMPONENTMOVE, + _cfg->EnableMove)); + Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>( + ENUMS::COREPERMISSIONS::COMPONENTREMOVE, + _cfg->EnableRemove)); + Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>( + ENUMS::COREPERMISSIONS::COMPONENTSWAP, + _cfg->EnableSwap)); + Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>( + ENUMS::COREPERMISSIONS::COMPONENTADD, + _cfg->EnableAdd)); + Q_EMIT emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool>( + ENUMS::COREPERMISSIONS::COMPONENTROTATE, + _cfg->EnableRotate)); } - diff --git a/Src/BioTrackerPlugin.h b/Src/BioTrackerPlugin.h index 10679bd4f17ea33489561986d72210e80909acf9..cbf2cf2d68fd60456f6f7c9005b1146b0f2f7b47 100644 --- a/Src/BioTrackerPlugin.h +++ b/Src/BioTrackerPlugin.h @@ -11,69 +11,78 @@ #include "QPoint" #include "Config.h" -class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin { - Q_OBJECT - Q_INTERFACES(IBioTrackerPlugin) - Q_PLUGIN_METADATA(IID IBioTrackerPlugin_iid FILE "plugin.json") +class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin +{ + Q_OBJECT + Q_INTERFACES(IBioTrackerPlugin) + Q_PLUGIN_METADATA(IID IBioTrackerPlugin_iid FILE "plugin.json") - public: - BioTrackerPlugin(); - ~BioTrackerPlugin(); +public: + BioTrackerPlugin(); + ~BioTrackerPlugin(); - // IBioTrackerPlugin interface - IView* getTrackerParameterWidget(); - IView *getTrackerElementsWidget(); - IModel* getTrackerComponentModel(); - IModelTrackedComponentFactory *getComponentFactory(); + // IBioTrackerPlugin interface + IView* getTrackerParameterWidget(); + IView* getTrackerElementsWidget(); + IModel* getTrackerComponentModel(); + IModelTrackedComponentFactory* getComponentFactory(); - public: - void createPlugin(); - void receiveCurrentFrameFromMainApp(std::shared_ptr<cv::Mat> mat, uint frameNumber); - void sendCorePermissions(); +public: + void createPlugin(); + void receiveCurrentFrameFromMainApp(std::shared_ptr<cv::Mat> mat, + uint frameNumber); + void sendCorePermissions(); - private: - void connectInterfaces(); +private: + void connectInterfaces(); signals: - void emitCvMat(std::shared_ptr<cv::Mat> mat, QString name); - void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - void emitCorePermission(std::pair<ENUMS::COREPERMISSIONS, bool> permission); - void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); - void emitAddTrajectory(QPoint pos); - void emitRemoveTrajectoryId(int id); - void emitValidateTrajectory(int id); - void emitValidateEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void emitMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint pos); - void emitSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - void emitCurrentFrameNumber(uint frameNumber); - void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - void emitEntityRotation(IModelTrackedTrajectory* trajectory, double angle, uint frameNumber); - - void emitDimensionUpdate(int x, int y); + void emitCvMat(std::shared_ptr<cv::Mat> mat, QString name); + void emitTrackingDone(uint framenumber); + void emitChangeDisplayImage(QString str); + void emitAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); + void emitCorePermission( + std::pair<ENUMS::COREPERMISSIONS, bool> permission); + void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void emitAddTrajectory(QPoint pos); + void emitRemoveTrajectoryId(int id); + void emitValidateTrajectory(int id); + void emitValidateEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void emitMoveElement(IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint pos); + void emitSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + void emitCurrentFrameNumber(uint frameNumber); + void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); + void emitEntityRotation(IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber); + + void emitDimensionUpdate(int x, int y); public slots: - void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); - void receiveAddTrajectory(QPoint pos); - void receiveSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - void receiveCurrentFrameNumberFromMainApp(uint frameNumber); + void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void receiveAddTrajectory(QPoint pos); + void receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + void receiveCurrentFrameNumberFromMainApp(uint frameNumber); private slots: - void receiveAreaDescriptor(IModelAreaDescriptor *areaDescr); + void receiveAreaDescriptor(IModelAreaDescriptor* areaDescr); private: - IController *m_TrackerController; - IController *m_ComponentController; - IController *m_AreaDescrController; + IController* m_TrackerController; + IController* m_ComponentController; + IController* m_AreaDescrController; - IBioTrackerContext *m_PluginContext; - Config* _cfg; + IBioTrackerContext* m_PluginContext; + Config* _cfg; public: - QList<ENUMS::COREPERMISSIONS> m_CorePermissions; - - + QList<ENUMS::COREPERMISSIONS> m_CorePermissions; }; #endif // BIOTRACKERPLUGIN_H diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt index 9b2e99aef13fef3747ac3b399c93683e4d675b90..337279ff0f56b7cd06012c275e0ccc2df7e24f00 100644 --- a/Src/CMakeLists.txt +++ b/Src/CMakeLists.txt @@ -41,7 +41,6 @@ add_behavior_plugin(${target} "helper/StringHelper.cpp" "Controller/ControllerTrackedComponent.cpp" "Controller/ControllerTrackingAlgorithm.cpp" - "Controller/null_Controller.cpp" ) install(TARGETS ${target} OPTIONAL DESTINATION .) diff --git a/Src/Config.cpp b/Src/Config.cpp index 72e8d3c099fdf09e1657620749cb344e9db745d9..1f06a680f6a128f1f27692261074e1955e28b77e 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -11,18 +11,18 @@ #include <QStandardPaths> template<typename Stream> -Stream &operator>>(Stream& s, QString& q) +Stream& operator>>(Stream& s, QString& q) { std::string tmp; s >> tmp; q = tmp.data(); - return s; + return s; } template<typename Stream> -Stream &operator<<(Stream& s, QString const& q) +Stream& operator<<(Stream& s, QString const& q) { - return s << q.toStdString(); + return s << q.toStdString(); } void Config::load(QString dir, QString file) @@ -34,61 +34,81 @@ void Config::load(QString dir, QString file) d.mkpath(dir); QFile fin(dir + "/" + file); - if(!fin.exists()) - { + if (!fin.exists()) { fin.open(QIODevice::ReadWrite); fin.close(); } - + read_ini((dir + "/" + file).toStdString(), tree); Config* config = this; std::string globalPrefix = "General."; - config->EnableView = tree.get<int>(globalPrefix+"EnableView",config->EnableView); - config->EnableMove = tree.get<int>(globalPrefix+"EnableMove",config->EnableMove); - config->EnableRemove = tree.get<int>(globalPrefix+"EnableRemove",config->EnableRemove); - config->EnableSwap = tree.get<int>(globalPrefix+"EnableSwap",config->EnableSwap); - config->EnableAdd = tree.get<int>(globalPrefix+"EnableAdd",config->EnableAdd); - config->EnableRotate = tree.get<int>(globalPrefix+"EnableRotate",config->EnableRotate); - config->UseAbsoluteDifference = tree.get<bool>(globalPrefix+"UseAbsoluteDifference",config->UseAbsoluteDifference); - config->BinarizationThreshold = tree.get<int>(globalPrefix+"BinarizationThreshold",config->BinarizationThreshold); - config->SizeErode = tree.get<int>(globalPrefix+"SizeErode",config->SizeErode); - config->SizeDilate = tree.get<int>(globalPrefix+"SizeDilate",config->SizeDilate); - config->MinBlobSize = tree.get<int>(globalPrefix+"MinBlobSize",config->MinBlobSize); - config->MaxBlobSize = tree.get<int>(globalPrefix+"MaxBlobSize",config->MaxBlobSize); - config->LearningRate = tree.get<double>(globalPrefix+"LearningRate",config->LearningRate); - config->DoNetwork = tree.get<int>(globalPrefix+"DoNetwork",config->DoNetwork); - config->NetworkPort = tree.get<int>(globalPrefix+"NetworkPort",config->NetworkPort); - config->DoBackground = tree.get<int>(globalPrefix+"DoBackground",config->DoBackground); - config->ResetBackground = tree.get<int>(globalPrefix+"ResetBackground",config->ResetBackground); + config->EnableView = tree.get<int>(globalPrefix + "EnableView", + config->EnableView); + config->EnableMove = tree.get<int>(globalPrefix + "EnableMove", + config->EnableMove); + config->EnableRemove = tree.get<int>(globalPrefix + "EnableRemove", + config->EnableRemove); + config->EnableSwap = tree.get<int>(globalPrefix + "EnableSwap", + config->EnableSwap); + config->EnableAdd = tree.get<int>(globalPrefix + "EnableAdd", + config->EnableAdd); + config->EnableRotate = tree.get<int>(globalPrefix + "EnableRotate", + config->EnableRotate); + config->UseAbsoluteDifference = tree.get<bool>( + globalPrefix + "UseAbsoluteDifference", + config->UseAbsoluteDifference); + config->BinarizationThreshold = tree.get<int>( + globalPrefix + "BinarizationThreshold", + config->BinarizationThreshold); + config->SizeErode = tree.get<int>(globalPrefix + "SizeErode", + config->SizeErode); + config->SizeDilate = tree.get<int>(globalPrefix + "SizeDilate", + config->SizeDilate); + config->MinBlobSize = tree.get<int>(globalPrefix + "MinBlobSize", + config->MinBlobSize); + config->MaxBlobSize = tree.get<int>(globalPrefix + "MaxBlobSize", + config->MaxBlobSize); + config->LearningRate = tree.get<double>(globalPrefix + "LearningRate", + config->LearningRate); + config->DoNetwork = tree.get<int>(globalPrefix + "DoNetwork", + config->DoNetwork); + config->NetworkPort = tree.get<int>(globalPrefix + "NetworkPort", + config->NetworkPort); + config->DoBackground = tree.get<int>(globalPrefix + "DoBackground", + config->DoBackground); + config->ResetBackground = tree.get<int>(globalPrefix + "ResetBackground", + config->ResetBackground); } void Config::save(QString dir, QString file) { using namespace boost::property_tree; - auto tree = ptree{}; - Config *config = this; + auto tree = ptree{}; + Config* config = this; std::string globalPrefix = "General."; - tree.put(globalPrefix+"EnableView", config->EnableView); - tree.put(globalPrefix+"EnableMove", config->EnableMove); - tree.put(globalPrefix+"EnableRemove", config->EnableRemove); - tree.put(globalPrefix+"EnableSwap", config->EnableSwap); - tree.put(globalPrefix+"EnableAdd", config->EnableAdd); - tree.put(globalPrefix+"EnableRotate", config->EnableRotate); - tree.put(globalPrefix+"UseAbsoluteDifference", config->UseAbsoluteDifference); - tree.put(globalPrefix+"BinarizationThreshold", config->BinarizationThreshold); - tree.put(globalPrefix+"SizeErode", config->SizeErode); - tree.put(globalPrefix+"SizeDilate", config->SizeDilate); - tree.put(globalPrefix+"MinBlobSize", config->MinBlobSize); - tree.put(globalPrefix+"MaxBlobSize", config->MaxBlobSize); - tree.put(globalPrefix+"LearningRate", config->LearningRate); - tree.put(globalPrefix+"DoNetwork", config->DoNetwork); - tree.put(globalPrefix+"NetworkPort", config->NetworkPort); - tree.put(globalPrefix+"DoBackground", config->DoBackground); - tree.put(globalPrefix+"ResetBackground", config->ResetBackground); + tree.put(globalPrefix + "EnableView", config->EnableView); + tree.put(globalPrefix + "EnableMove", config->EnableMove); + tree.put(globalPrefix + "EnableRemove", config->EnableRemove); + tree.put(globalPrefix + "EnableSwap", config->EnableSwap); + tree.put(globalPrefix + "EnableAdd", config->EnableAdd); + tree.put(globalPrefix + "EnableRotate", config->EnableRotate); + tree.put(globalPrefix + "UseAbsoluteDifference", + config->UseAbsoluteDifference); + tree.put(globalPrefix + "BinarizationThreshold", + config->BinarizationThreshold); + tree.put(globalPrefix + "SizeErode", config->SizeErode); + tree.put(globalPrefix + "SizeDilate", config->SizeDilate); + tree.put(globalPrefix + "MinBlobSize", config->MinBlobSize); + tree.put(globalPrefix + "MaxBlobSize", config->MaxBlobSize); + tree.put(globalPrefix + "LearningRate", config->LearningRate); + tree.put(globalPrefix + "DoNetwork", config->DoNetwork); + tree.put(globalPrefix + "NetworkPort", config->NetworkPort); + tree.put(globalPrefix + "DoBackground", config->DoBackground); + tree.put(globalPrefix + "ResetBackground", config->ResetBackground); write_ini((dir + "/" + file).toStdString(), tree); } diff --git a/Src/Config.h b/Src/Config.h index f2680603b8bb3c603d69d83d6c720fc620836c6d..01bb358fd80beb403fb8f3066b14878192282742 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -7,33 +7,33 @@ class Config : public IConfig { public: - bool UseAbsoluteDifference = true; - int BinarizationThreshold = 40; + bool UseAbsoluteDifference = true; + int BinarizationThreshold = 40; - int SizeErode = 8; - int SizeDilate = 8; - int MinBlobSize = 40; - int MaxBlobSize = 999999; + int SizeErode = 8; + int SizeDilate = 8; + int MinBlobSize = 40; + int MaxBlobSize = 999999; - double LearningRate = 0.05; + double LearningRate = 0.05; - int DoNetwork = false; - int NetworkPort = 54444; + int DoNetwork = false; + int NetworkPort = 54444; - int DoBackground = true; - int ResetBackground = false; + int DoBackground = true; + int ResetBackground = false; - int EnableView = 1; - int EnableMove = 1; + int EnableView = 1; + int EnableMove = 1; int EnableRemove = 1; - int EnableSwap = 1; - int EnableAdd = 1; + int EnableSwap = 1; + int EnableAdd = 1; int EnableRotate = 1; int NoFish = 0; void load(QString dir, QString file = "config.ini") override; void save(QString dir, QString file) override; - + static const QString DefaultArena; }; diff --git a/Src/Controller/ControllerTrackedComponent.cpp b/Src/Controller/ControllerTrackedComponent.cpp index e71f1b2c6b48b1970cd756efce5c30109bf29e85..6cc4554a8ed1a543f5b78ef4fe2465b2421d1f68 100644 --- a/Src/Controller/ControllerTrackedComponent.cpp +++ b/Src/Controller/ControllerTrackedComponent.cpp @@ -5,168 +5,201 @@ #include "qdebug.h" #include "qmath.h" -ControllerTrackedComponent::ControllerTrackedComponent(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) +ControllerTrackedComponent::ControllerTrackedComponent( + QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IController(parent, context, ctr) { - m_currentFrameNumber = 0; + m_currentFrameNumber = 0; } void ControllerTrackedComponent::createView() { - m_View = new TrackedElementView(0, this, m_Model); + m_View = new TrackedElementView(0, this, m_Model); } void ControllerTrackedComponent::connectModelToController() { - } void ControllerTrackedComponent::connectControllerToController() { } -void createTrajectories(int count, TrackedTrajectory* all) { +void createTrajectories(int count, TrackedTrajectory* all) +{ } void ControllerTrackedComponent::createModel() { - TrackedTrajectory *t = new TrackedTrajectory(this, "All"); - m_Model = t; + TrackedTrajectory* t = new TrackedTrajectory(this, "All"); + m_Model = t; } - -IView *ControllerTrackedComponent::getTrackingElementsWidget() +IView* ControllerTrackedComponent::getTrackingElementsWidget() { - return m_View; + return m_View; } -void ControllerTrackedComponent::receiveRemoveTrajectory(IModelTrackedTrajectory * trajectory) +void ControllerTrackedComponent::receiveRemoveTrajectory( + IModelTrackedTrajectory* trajectory) { - trajectory->setValid(false); - qDebug() << "TRACKER: Track" << trajectory->getId() << "set invalid"; + trajectory->setValid(false); + qDebug() << "TRACKER: Track" << trajectory->getId() << "set invalid"; } void ControllerTrackedComponent::receiveRemoveTrajectoryId(int id) { - TrackedTrajectory* allTraj = qobject_cast<TrackedTrajectory*>(m_Model); - if (allTraj) { - IModelTrackedComponent* traj = allTraj->getChild(id - 1); - traj->setValid(false); - qDebug() << "TRACKER: Track" << id << "set invalid"; - } + TrackedTrajectory* allTraj = qobject_cast<TrackedTrajectory*>(m_Model); + if (allTraj) { + IModelTrackedComponent* traj = allTraj->getChild(id - 1); + traj->setValid(false); + qDebug() << "TRACKER: Track" << id << "set invalid"; + } } void ControllerTrackedComponent::receiveValidateTrajectory(int id) { - TrackedTrajectory* allTraj = qobject_cast<TrackedTrajectory*>(m_Model); - if (allTraj) { - IModelTrackedComponent* traj = allTraj->getChild(id - 1); - traj->setValid(true); - qDebug() << "TRACKER: Track" << id << "validated"; - } + TrackedTrajectory* allTraj = qobject_cast<TrackedTrajectory*>(m_Model); + if (allTraj) { + IModelTrackedComponent* traj = allTraj->getChild(id - 1); + traj->setValid(true); + qDebug() << "TRACKER: Track" << id << "validated"; + } } -void ControllerTrackedComponent::receiveValidateEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) +void ControllerTrackedComponent::receiveValidateEntity( + IModelTrackedTrajectory* trajectory, + uint frameNumber) { - trajectory->getChild(frameNumber)->setValid(true); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "set valid"; + trajectory->getChild(frameNumber)->setValid(true); + qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" + << frameNumber << "set valid"; } -void ControllerTrackedComponent::receiveRemoveTrackEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) +void ControllerTrackedComponent::receiveRemoveTrackEntity( + IModelTrackedTrajectory* trajectory, + uint frameNumber) { - trajectory->getChild(frameNumber)->setValid(false); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "deleted (set invalid)"; + trajectory->getChild(frameNumber)->setValid(false); + qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" + << frameNumber << "deleted (set invalid)"; } void ControllerTrackedComponent::receiveAddTrajectory(QPoint position) { - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - - cv::Point newPosPx = cv::Point(position.x(), position.y()); - cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); + std::chrono::system_clock::time_point start = + std::chrono::system_clock::now(); - BST::TrackedTrajectory* newTraj = new BST::TrackedTrajectory(); - BST::TrackedElement* firstElem = new BST::TrackedElement(newTraj, "n.a.", newTraj->getId()); + cv::Point newPosPx = cv::Point(position.x(), position.y()); + cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); - FishPose newPose = FishPose(newPosCm, newPosPx, 0, 0, 20, 20, 0.0); + BST::TrackedTrajectory* newTraj = new BST::TrackedTrajectory(); + BST::TrackedElement* firstElem = new BST::TrackedElement(newTraj, + "n.a.", + newTraj->getId()); - firstElem->setFishPose(newPose); + FishPose newPose = FishPose(newPosCm, newPosPx, 0, 0, 20, 20, 0.0); + firstElem->setFishPose(newPose); - firstElem->setTime(start); - newTraj->add(firstElem, m_currentFrameNumber); - TrackedTrajectory* allTraj = qobject_cast<TrackedTrajectory*>(m_Model); - if (allTraj) { - allTraj->add(newTraj); - qDebug() << "TRACKER: Trajectory added at" << firstElem->getXpx() << "," << firstElem->getYpx(); - } + firstElem->setTime(start); + newTraj->add(firstElem, m_currentFrameNumber); + TrackedTrajectory* allTraj = qobject_cast<TrackedTrajectory*>(m_Model); + if (allTraj) { + allTraj->add(newTraj); + qDebug() << "TRACKER: Trajectory added at" << firstElem->getXpx() + << "," << firstElem->getYpx(); + } } -void ControllerTrackedComponent::receiveMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint position) +void ControllerTrackedComponent::receiveMoveElement( + IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint position) { - BST::TrackedTrajectory* traj = dynamic_cast<BST::TrackedTrajectory*>(trajectory); - // don't move when frame number under 0 and main trajectory (id's: 0)!! - if (!(traj->getId() == 0) && frameNumber >= 0) { - BST::TrackedElement* element = dynamic_cast<BST::TrackedElement*>(traj->getChild(frameNumber)); + BST::TrackedTrajectory* traj = dynamic_cast<BST::TrackedTrajectory*>( + trajectory); + // don't move when frame number under 0 and main trajectory (id's: 0)!! + if (!(traj->getId() == 0) && frameNumber >= 0) { + BST::TrackedElement* element = dynamic_cast<BST::TrackedElement*>( + traj->getChild(frameNumber)); - //TODO rewrite this when default ipose is implemented... - FishPose oldPose = element->getFishPose(); + // TODO rewrite this when default ipose is implemented... + FishPose oldPose = element->getFishPose(); - cv::Point newPosPx = cv::Point(position.x(), position.y()); - cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); - // ignore blobs outside the tracking area - if (!m_areaDescr->inTrackingArea(newPosPx)) { - qDebug() << "Attention! You moved the entity outside of the tracking area!"; - } + cv::Point newPosPx = cv::Point(position.x(), position.y()); + cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); + // ignore blobs outside the tracking area + if (!m_areaDescr->inTrackingArea(newPosPx)) { + qDebug() << "Attention! You moved the entity outside of the " + "tracking area!"; + } - FishPose newPose = FishPose(newPosCm, newPosPx, oldPose.orientation_rad(), oldPose.orientation_deg(), oldPose.width(), oldPose.height(), oldPose.getScore()); + FishPose newPose = FishPose(newPosCm, + newPosPx, + oldPose.orientation_rad(), + oldPose.orientation_deg(), + oldPose.width(), + oldPose.height(), + oldPose.getScore()); - element->setFishPose(newPose); - } + element->setFishPose(newPose); + } } -void ControllerTrackedComponent::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) +void ControllerTrackedComponent::receiveSwapIds( + IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1) { - TrackedTrajectory* traj0 = dynamic_cast<TrackedTrajectory*>(trajectory0); - TrackedTrajectory* traj1 = dynamic_cast<TrackedTrajectory*>(trajectory1); + TrackedTrajectory* traj0 = dynamic_cast<TrackedTrajectory*>(trajectory0); + TrackedTrajectory* traj1 = dynamic_cast<TrackedTrajectory*>(trajectory1); - if (traj0 && traj1) { - if (traj0->getId() !=0 && traj1->getId() !=0) { - int traj0Id = traj0->getId(); - int traj1Id = traj1->getId(); + if (traj0 && traj1) { + if (traj0->getId() != 0 && traj1->getId() != 0) { + int traj0Id = traj0->getId(); + int traj1Id = traj1->getId(); - traj0->setId(traj1Id); - traj1->setId(traj0Id); + traj0->setId(traj1Id); + traj1->setId(traj0Id); - qDebug() << "TRACKER: Swap IDs " << traj0Id << "and " << traj1Id; - } - } + qDebug() << "TRACKER: Swap IDs " << traj0Id << "and " << traj1Id; + } + } } -void ControllerTrackedComponent::receiveToggleFixTrack(IModelTrackedTrajectory * trajectory, bool toggle) +void ControllerTrackedComponent::receiveToggleFixTrack( + IModelTrackedTrajectory* trajectory, + bool toggle) { - qDebug() << "TRACKER: Fix trajectory " << trajectory->getId(); - trajectory->setFixed(toggle); + qDebug() << "TRACKER: Fix trajectory " << trajectory->getId(); + trajectory->setFixed(toggle); } -void ControllerTrackedComponent::receiveEntityRotation(IModelTrackedTrajectory * trajectory, double angle, uint frameNumber) +void ControllerTrackedComponent::receiveEntityRotation( + IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber) { - TrackedTrajectory* traj = dynamic_cast<TrackedTrajectory*>(trajectory); - if (traj) { - IModelTrackedPoint* pointLike = dynamic_cast<IModelTrackedPoint*>(traj->getChild(frameNumber)); - if (pointLike) { - pointLike->setDeg(float(angle)); - pointLike->setRad(float(qDegreesToRadians(angle))); - } - } + TrackedTrajectory* traj = dynamic_cast<TrackedTrajectory*>(trajectory); + if (traj) { + IModelTrackedPoint* pointLike = dynamic_cast<IModelTrackedPoint*>( + traj->getChild(frameNumber)); + if (pointLike) { + pointLike->setDeg(float(angle)); + pointLike->setRad(float(qDegreesToRadians(angle))); + } + } } void ControllerTrackedComponent::receiveCurrentFrameNumber(uint framenumber) { - m_currentFrameNumber = (int)framenumber; + m_currentFrameNumber = (int) framenumber; } -void ControllerTrackedComponent::receiveAreaDescriptorUpdate(IModelAreaDescriptor * areaDescr) +void ControllerTrackedComponent::receiveAreaDescriptorUpdate( + IModelAreaDescriptor* areaDescr) { - m_areaDescr = areaDescr; + m_areaDescr = areaDescr; } diff --git a/Src/Controller/ControllerTrackedComponent.h b/Src/Controller/ControllerTrackedComponent.h index 6c1e82e0a7a8e6630ddb603001fe597aa3de9c8a..8ccdbb6082f3d2fc6e01c792ba1a94339df60d1d 100644 --- a/Src/Controller/ControllerTrackedComponent.h +++ b/Src/Controller/ControllerTrackedComponent.h @@ -9,41 +9,59 @@ class ControllerTrackedComponent : public IController { - Q_OBJECT + Q_OBJECT public: - ControllerTrackedComponent(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COMPONENT); + ControllerTrackedComponent( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COMPONENT); - Config *getConfig() { return _cfg;}; - void setConfig(Config *cfg) { _cfg = cfg;}; - IView *getTrackingElementsWidget(); + Config* getConfig() + { + return _cfg; + }; + void setConfig(Config* cfg) + { + _cfg = cfg; + }; + IView* getTrackingElementsWidget(); public Q_SLOTS: - void receiveAddTrajectory(QPoint position); - void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); - void receiveRemoveTrajectoryId(int id); - void receiveRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void receiveValidateTrajectory(int id); - void receiveValidateEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void receiveMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint position); - /* TODO Swaps ID's of last elements (-> swap elements) or swap ID's of trajectories and all of its elements? - */ - void receiveSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - void receiveToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - void receiveEntityRotation(IModelTrackedTrajectory* trajectory, double angle, uint frameNumber); - void receiveCurrentFrameNumber(uint framenumber); + void receiveAddTrajectory(QPoint position); + void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void receiveRemoveTrajectoryId(int id); + void receiveRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void receiveValidateTrajectory(int id); + void receiveValidateEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void receiveMoveElement(IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint position); + /* TODO Swaps ID's of last elements (-> swap elements) or swap ID's of + * trajectories and all of its elements? + */ + void receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + void receiveToggleFixTrack(IModelTrackedTrajectory* trajectory, + bool toggle); + void receiveEntityRotation(IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber); + void receiveCurrentFrameNumber(uint framenumber); - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); - // IController interface + // IController interface protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - Config *_cfg; + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + Config* _cfg; - //members - int m_currentFrameNumber; - IModelAreaDescriptor* m_areaDescr; + // members + int m_currentFrameNumber; + IModelAreaDescriptor* m_areaDescr; }; #endif // CONTROLLERTRACKEDCOMPONENT_H diff --git a/Src/Controller/ControllerTrackingAlgorithm.cpp b/Src/Controller/ControllerTrackingAlgorithm.cpp index 8544888d21359e88058c0bc08f01c7b5f39ef61d..555a7f64b65b82bca023294b034bc2461d8be3e8 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.cpp +++ b/Src/Controller/ControllerTrackingAlgorithm.cpp @@ -5,37 +5,46 @@ #include "../View/TrackerParameterView.h" #include "../View/TrackedElementView.h" -ControllerTrackingAlgorithm::ControllerTrackingAlgorithm(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) +ControllerTrackingAlgorithm::ControllerTrackingAlgorithm( + QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IController(parent, context, ctr) { - m_BioTrackerContext = context; + m_BioTrackerContext = context; } void ControllerTrackingAlgorithm::connectControllerToController() { - IController * ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - QPointer< ControllerTrackedComponent > ctrComponent = qobject_cast<ControllerTrackedComponent *>(ctr); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMPONENT); + QPointer<ControllerTrackedComponent> ctrComponent = + qobject_cast<ControllerTrackedComponent*>(ctr); - m_TrackedTrajectoryMajor = ctrComponent->getModel(); + m_TrackedTrajectoryMajor = ctrComponent->getModel(); } -void ControllerTrackingAlgorithm::doTracking(std::shared_ptr<cv::Mat> mat, uint number) +void ControllerTrackingAlgorithm::doTracking(std::shared_ptr<cv::Mat> mat, + uint number) { - qobject_cast<BioTrackerTrackingAlgorithm *>(m_Model)->doTracking(mat, number); + qobject_cast<BioTrackerTrackingAlgorithm*>(m_Model)->doTracking(mat, + number); } -IView *ControllerTrackingAlgorithm::getTrackingParameterWidget() +IView* ControllerTrackingAlgorithm::getTrackingParameterWidget() { return m_View; } void ControllerTrackingAlgorithm::createModel() { - connectControllerToController(); + connectControllerToController(); - m_TrackingParameter = new TrackerParameter(this); + m_TrackingParameter = new TrackerParameter(this); - m_Model = new BioTrackerTrackingAlgorithm(this, m_TrackingParameter, m_TrackedTrajectoryMajor); + m_Model = new BioTrackerTrackingAlgorithm(this, + m_TrackingParameter, + m_TrackedTrajectoryMajor); } void ControllerTrackingAlgorithm::createView() @@ -45,22 +54,45 @@ void ControllerTrackingAlgorithm::createView() void ControllerTrackingAlgorithm::connectModelToController() { - BioTrackerTrackingAlgorithm *trackingAlg = qobject_cast<BioTrackerTrackingAlgorithm *>(m_Model); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitCvMatA, this, &ControllerTrackingAlgorithm::emitCvMat); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitTrackingDone, this, &ControllerTrackingAlgorithm::emitTrackingDone); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, this, &ControllerTrackingAlgorithm::emitChangeDisplayImage); - QObject::connect(this, &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, trackingAlg, &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); + BioTrackerTrackingAlgorithm* trackingAlg = + qobject_cast<BioTrackerTrackingAlgorithm*>(m_Model); + QObject::connect(trackingAlg, + &BioTrackerTrackingAlgorithm::emitCvMatA, + this, + &ControllerTrackingAlgorithm::emitCvMat); + QObject::connect(trackingAlg, + &BioTrackerTrackingAlgorithm::emitTrackingDone, + this, + &ControllerTrackingAlgorithm::emitTrackingDone); + QObject::connect(trackingAlg, + &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, + this, + &ControllerTrackingAlgorithm::emitChangeDisplayImage); + QObject::connect( + this, + &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, + trackingAlg, + &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); - QObject::connect(static_cast<TrackerParameterView*>(m_View), &TrackerParameterView::parametersChanged, - trackingAlg, &BioTrackerTrackingAlgorithm::receiveParametersChanged); + QObject::connect(static_cast<TrackerParameterView*>(m_View), + &TrackerParameterView::parametersChanged, + trackingAlg, + &BioTrackerTrackingAlgorithm::receiveParametersChanged); - //enable the tracker to send video dimension updates to the views via signal - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - IView *v = qobject_cast<ControllerTrackedComponent*>(ctr)->getView(); - TrackedElementView *v2 = dynamic_cast<TrackedElementView *>(v); - QObject::connect(trackingAlg, SIGNAL(emitDimensionUpdate(int, int)), v2, SLOT(rcvDimensionUpdate(int, int))); + // enable the tracker to send video dimension updates to the views via + // signal + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMPONENT); + IView* v = qobject_cast<ControllerTrackedComponent*>(ctr)->getView(); + TrackedElementView* v2 = dynamic_cast<TrackedElementView*>(v); + QObject::connect(trackingAlg, + SIGNAL(emitDimensionUpdate(int, int)), + v2, + SLOT(rcvDimensionUpdate(int, int))); } -void ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - Q_EMIT emitAreaDescriptorUpdate(areaDescr); +void ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate( + IModelAreaDescriptor* areaDescr) +{ + Q_EMIT emitAreaDescriptorUpdate(areaDescr); } diff --git a/Src/Controller/ControllerTrackingAlgorithm.h b/Src/Controller/ControllerTrackingAlgorithm.h index 785493440cc5c88aad5ddb2a13395be69c17f0ee..9f8af37d6595ed20035629b59183e3ff207fd49d 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.h +++ b/Src/Controller/ControllerTrackingAlgorithm.h @@ -7,15 +7,23 @@ #include "Interfaces/IModel/IModelDataExporter.h" #include "../Config.h" - class ControllerTrackingAlgorithm : public IController { Q_OBJECT public: - ControllerTrackingAlgorithm(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - Config* getConfig() { return _cfg;}; - void setConfig(Config *cfg) { _cfg = cfg;}; + ControllerTrackingAlgorithm( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + + Config* getConfig() + { + return _cfg; + }; + void setConfig(Config* cfg) + { + _cfg = cfg; + }; // IController interface public: void connectControllerToController() override; @@ -25,7 +33,7 @@ public: IView* getTrackingParameterWidget(); public Q_SLOTS: - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); protected: void createModel() override; @@ -35,12 +43,12 @@ protected: Q_SIGNALS: void emitCvMat(std::shared_ptr<cv::Mat> mat, QString name); void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void emitChangeDisplayImage(QString str); + void emitAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); private: IModel* m_TrackingParameter; - IModel* m_TrackedTrajectoryMajor; + IModel* m_TrackedTrajectoryMajor; Config* _cfg; }; diff --git a/Src/Controller/null_Controller.cpp b/Src/Controller/null_Controller.cpp deleted file mode 100644 index 612c02f3a220bdb5dac5ee38c26e2a7f9d7e4d61..0000000000000000000000000000000000000000 --- a/Src/Controller/null_Controller.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "null_Controller.h" - -null_Controller::null_Controller() -{ - -} - -void null_Controller::createModel() -{ - -} - -void null_Controller::createView() -{ - -} - -void null_Controller::connectModelToController() -{ - -} - -void null_Controller::connectControllerToController() -{ - -} diff --git a/Src/Controller/null_Controller.h b/Src/Controller/null_Controller.h deleted file mode 100644 index a0fcc211f6da112ab9ff01c8c535c9c29ebf1762..0000000000000000000000000000000000000000 --- a/Src/Controller/null_Controller.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NULL_CONTROLLER_H -#define NULL_CONTROLLER_H - -#include "Interfaces/IController/IController.h" -class null_Controller : public IController -{ -public: - null_Controller(); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; -}; - -#endif // NULL_CONTROLLER_H diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 52a3788c41d2afe10bc040a68a79f3a17bed358d..e0efb8652d2f714fb9222cdcb934dda4cd5221a3 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -3,72 +3,85 @@ #include "TrackedComponents/TrackedComponentFactory.h" #include <chrono> -BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController *parent, IModel* parameter, IModel* trajectory) +BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController* parent, + IModel* parameter, + IModel* trajectory) : IModelTrackingAlgorithm(parent) , _ipp((TrackerParameter*) parameter) { - _cfg = static_cast<ControllerTrackingAlgorithm*>(parent)->getConfig(); - _TrackingParameter = (TrackerParameter*)parameter; - _TrackedTrajectoryMajor = (BST::TrackedTrajectory*)trajectory; - _nn2d = std::make_shared<NN2dMapper>(_TrackedTrajectoryMajor); - - _bd = BlobsDetector(); - - _noFish = -1; - - if (_cfg->DoNetwork) { - _listener = new TcpListener(this); - _listener->listen(QHostAddress::Any, _cfg->NetworkPort); - QObject::connect(_listener, SIGNAL(newConnection()), _listener, SLOT(acceptConnection())); - } - + _cfg = static_cast<ControllerTrackingAlgorithm*>(parent)->getConfig(); + _TrackingParameter = (TrackerParameter*) parameter; + _TrackedTrajectoryMajor = (BST::TrackedTrajectory*) trajectory; + _nn2d = std::make_shared<NN2dMapper>(_TrackedTrajectoryMajor); + + _bd = BlobsDetector(); + + _noFish = -1; + + if (_cfg->DoNetwork) { + _listener = new TcpListener(this); + _listener->listen(QHostAddress::Any, _cfg->NetworkPort); + QObject::connect(_listener, + SIGNAL(newConnection()), + _listener, + SLOT(acceptConnection())); + } - _lastImage = nullptr; + _lastImage = nullptr; _lastFramenumber = -1; } - -void BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - _AreaInfo = areaDescr; - _bd.setAreaInfo(_AreaInfo); +void BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate( + IModelAreaDescriptor* areaDescr) +{ + _AreaInfo = areaDescr; + _bd.setAreaInfo(_AreaInfo); } BioTrackerTrackingAlgorithm::~BioTrackerTrackingAlgorithm() { } -std::vector<FishPose> BioTrackerTrackingAlgorithm::getLastPositionsAsPose() { - //TODO: This seems kinda fragile: I just assume that the tree has this very certain structure: - // Trajectory -> M Trajectories -> N TrackedElements - // For every of M Trajectories grab the last (highest index) of TrackedElements. - //TODO: If we are tracking somewhere in the middle, this is bad. Do it by id! - std::vector<FishPose> last; - for (int i = 0; i < _TrackedTrajectoryMajor->size(); i++) { - BST::TrackedTrajectory *t = dynamic_cast<BST::TrackedTrajectory *>(_TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - BST::TrackedElement *e = (BST::TrackedElement *)t->getLastChild(); - last.push_back(e->getFishPose()); - } - } - return last; +std::vector<FishPose> BioTrackerTrackingAlgorithm::getLastPositionsAsPose() +{ + // TODO: This seems kinda fragile: I just assume that the tree has this + // very certain structure: + // Trajectory -> M Trajectories -> N TrackedElements + // For every of M Trajectories grab the last (highest index) of + // TrackedElements. + // TODO: If we are tracking somewhere in the middle, this is bad. Do it by + // id! + std::vector<FishPose> last; + for (int i = 0; i < _TrackedTrajectoryMajor->size(); i++) { + BST::TrackedTrajectory* t = dynamic_cast<BST::TrackedTrajectory*>( + _TrackedTrajectoryMajor->getChild(i)); + if (t && t->getValid() && !t->getFixed()) { + BST::TrackedElement* e = (BST::TrackedElement*) t->getLastChild(); + last.push_back(e->getFishPose()); + } + } + return last; } -void BioTrackerTrackingAlgorithm::refreshPolygon() { - +void BioTrackerTrackingAlgorithm::refreshPolygon() +{ } -void BioTrackerTrackingAlgorithm::receiveParametersChanged() { +void BioTrackerTrackingAlgorithm::receiveParametersChanged() +{ if (_lastFramenumber >= 0 && _lastImage && !_lastImage->empty()) { doTracking(_lastImage, _lastFramenumber); } } -void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map<std::string, std::shared_ptr<cv::Mat>> *images) { +void BioTrackerTrackingAlgorithm::sendSelectedImage( + std::map<std::string, std::shared_ptr<cv::Mat>>* images) +{ std::shared_ptr<cv::Mat> sendImage; - //Send forth whatever the user selected + // Send forth whatever the user selected switch (_TrackingParameter->getSendImage()) { - case 0: //Send none + case 0: // Send none Q_EMIT emitChangeDisplayImage("Original"); break; case 1: @@ -94,123 +107,148 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map<std::string, std::s } } -std::vector<BlobPose> BioTrackerTrackingAlgorithm::getContourCentroids(cv::Mat& image, int minSize){ - - std::vector<std::vector<cv::Point> > contours; - std::vector<cv::Vec4i> hierarchy; - std::vector<BlobPose> centroids; - - findContours( image, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0) ); - for(auto x: contours){ - cv::Point2f c(0,0); - float i=0; - for(auto y: x){ +std::vector<BlobPose> BioTrackerTrackingAlgorithm::getContourCentroids( + cv::Mat& image, + int minSize) +{ + + std::vector<std::vector<cv::Point>> contours; + std::vector<cv::Vec4i> hierarchy; + std::vector<BlobPose> centroids; + + findContours(image, + contours, + hierarchy, + cv::RETR_TREE, + cv::CHAIN_APPROX_SIMPLE, + cv::Point(0, 0)); + for (auto x : contours) { + cv::Point2f c(0, 0); + float i = 0; + for (auto y : x) { c += cv::Point2f(y); i++; } c.x = c.x / i; c.y = c.y / i; - - //cv::RotatedRect minEllipse; - cv::RotatedRect bb = minAreaRect( x ); - //check if blob is in tracking area --> this can be optimized by checking earlier (only search blobs in tracking area) - if(!_AreaInfo->inTrackingArea(c)){ - continue; - } + // cv::RotatedRect minEllipse; + cv::RotatedRect bb = minAreaRect(x); - BlobPose bc(_AreaInfo->pxToCm(c), c, bb.angle, bb.size.width, bb.size.height); + // check if blob is in tracking area --> this can be optimized by + // checking earlier (only search blobs in tracking area) + if (!_AreaInfo->inTrackingArea(c)) { + continue; + } + + BlobPose bc(_AreaInfo->pxToCm(c), + c, + bb.angle, + bb.size.width, + bb.size.height); centroids.push_back(bc); } - + return centroids; } -void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr<cv::Mat> p_image, uint framenumber) +void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr<cv::Mat> p_image, + uint framenumber) { - _ipp.m_TrackingParameter = _TrackingParameter; - _lastImage = p_image; - _lastFramenumber = framenumber; - - //dont do nothing if we ain't got an image - if (p_image->empty()) { - return; - } + _ipp.m_TrackingParameter = _TrackingParameter; + _lastImage = p_image; + _lastFramenumber = framenumber; - if (_imageX != p_image->size().width || _imageY != p_image->size().height) { - _imageX = p_image->size().width; - _imageY = p_image->size().height; - Q_EMIT emitDimensionUpdate(_imageX, _imageY); - } + // dont do nothing if we ain't got an image + if (p_image->empty()) { + return; + } - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + if (_imageX != p_image->size().width || + _imageY != p_image->size().height) { + _imageX = p_image->size().width; + _imageY = p_image->size().height; + Q_EMIT emitDimensionUpdate(_imageX, _imageY); + } - //Refuse to run tracking if we have no area info... - if (_AreaInfo == nullptr) { - Q_EMIT emitTrackingDone(framenumber); - return; - } + std::chrono::system_clock::time_point start = + std::chrono::system_clock::now(); + // Refuse to run tracking if we have no area info... + if (_AreaInfo == nullptr) { + Q_EMIT emitTrackingDone(framenumber); + return; + } - //The user changed the # of fish. Reset the history and start over! - if (_noFish != _TrackedTrajectoryMajor->validCount()) { - _noFish = _TrackedTrajectoryMajor->validCount(); - _nn2d = std::make_shared<NN2dMapper>(_TrackedTrajectoryMajor); - } + // The user changed the # of fish. Reset the history and start over! + if (_noFish != _TrackedTrajectoryMajor->validCount()) { + _noFish = _TrackedTrajectoryMajor->validCount(); + _nn2d = std::make_shared<NN2dMapper>(_TrackedTrajectoryMajor); + } if (_TrackingParameter->getResetBackground()) { _TrackingParameter->setResetBackground(false); _ipp.resetBackgroundImage(); } - //Do the preprocessing - std::map<std::string, std::shared_ptr<cv::Mat>> images = _ipp.preProcess(p_image); - std::shared_ptr<cv::Mat> dilated = images.find(std::string("Dilated"))->second; - std::shared_ptr<cv::Mat> greyMat = images.find(std::string("Greyscale"))->second; - - //Find blobs via ellipsefitting - _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); - _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); - //std::vector<BlobPose> blobs = _bd.getPoses(*dilated, *greyMat); + // Do the preprocessing + std::map<std::string, std::shared_ptr<cv::Mat>> images = _ipp.preProcess( + p_image); + std::shared_ptr<cv::Mat> dilated = + images.find(std::string("Dilated"))->second; + std::shared_ptr<cv::Mat> greyMat = + images.find(std::string("Greyscale"))->second; + + // Find blobs via ellipsefitting + _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); + _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); + // std::vector<BlobPose> blobs = _bd.getPoses(*dilated, *greyMat); std::vector<BlobPose> blobs = getContourCentroids(*dilated, 111); - // Never switch the position of the trajectories. The NN2d mapper relies on this! - // If you mess up the order, add or remove some t, then create a new mapper. - std::vector<FishPose> fish = getLastPositionsAsPose(); - - //Find new positions using 2D nearest neighbor - std::tuple<std::vector<FishPose>, std::vector<float>> poses = _nn2d->getNewPoses(_TrackedTrajectoryMajor, framenumber, blobs); - - //Insert new poses into data structure - int trajNumber = 0; - for (int i = 0; i < _TrackedTrajectoryMajor->size(); i++) { - BST::TrackedTrajectory *t = dynamic_cast<BST::TrackedTrajectory *>(_TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - BST::TrackedElement *e = new BST::TrackedElement(t, "n.a.", t->getId()); - - e->setFishPose(std::get<0>(poses)[trajNumber]); - e->setTime(start); - t->add(e, framenumber); - trajNumber++; - } - } - - //Send forth new positions to the robotracker, if networking is enabled - if (_TrackingParameter->getDoNetwork()){ - std::vector<FishPose> ps = std::get<0>(poses); - _listener->sendPositions(framenumber, ps, std::vector<cv::Point2f>(), start); - } + // Never switch the position of the trajectories. The NN2d mapper relies on + // this! If you mess up the order, add or remove some t, then create a new + // mapper. + std::vector<FishPose> fish = getLastPositionsAsPose(); + + // Find new positions using 2D nearest neighbor + std::tuple<std::vector<FishPose>, std::vector<float>> poses = + _nn2d->getNewPoses(_TrackedTrajectoryMajor, framenumber, blobs); + + // Insert new poses into data structure + int trajNumber = 0; + for (int i = 0; i < _TrackedTrajectoryMajor->size(); i++) { + BST::TrackedTrajectory* t = dynamic_cast<BST::TrackedTrajectory*>( + _TrackedTrajectoryMajor->getChild(i)); + if (t && t->getValid() && !t->getFixed()) { + BST::TrackedElement* e = new BST::TrackedElement(t, + "n.a.", + t->getId()); + + e->setFishPose(std::get<0>(poses)[trajNumber]); + e->setTime(start); + t->add(e, framenumber); + trajNumber++; + } + } + + // Send forth new positions to the robotracker, if networking is enabled + if (_TrackingParameter->getDoNetwork()) { + std::vector<FishPose> ps = std::get<0>(poses); + _listener->sendPositions(framenumber, + ps, + std::vector<cv::Point2f>(), + start); + } sendSelectedImage(&images); - - //First the user still wants to see the original image, right? - if (framenumber==1) { - Q_EMIT emitChangeDisplayImage("Original"); - } + // First the user still wants to see the original image, right? + if (framenumber == 1) { + Q_EMIT emitChangeDisplayImage("Original"); + } - std::string newSel = _TrackingParameter->getNewSelection(); + std::string newSel = _TrackingParameter->getNewSelection(); - Q_EMIT emitTrackingDone(framenumber); + Q_EMIT emitTrackingDone(framenumber); } diff --git a/Src/Model/BioTrackerTrackingAlgorithm.h b/Src/Model/BioTrackerTrackingAlgorithm.h index 8518aa0117221f3b5623ece8e51e9553f424b4ef..ca456feebbdf2c9185c46061c76891cd4eac5d8b 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.h +++ b/Src/Model/BioTrackerTrackingAlgorithm.h @@ -1,7 +1,6 @@ #ifndef BIOTRACKERTRACKINGALGORITHM_H #define BIOTRACKERTRACKINGALGORITHM_H - #include "Interfaces/IModel/IModel.h" #include "TrackerParameter.h" @@ -25,47 +24,50 @@ class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm { Q_OBJECT public: - BioTrackerTrackingAlgorithm(IController *parent, IModel* parameter, IModel* trajectory); - ~BioTrackerTrackingAlgorithm(); + BioTrackerTrackingAlgorithm(IController* parent, + IModel* parameter, + IModel* trajectory); + ~BioTrackerTrackingAlgorithm(); Q_SIGNALS: void emitCvMatA(std::shared_ptr<cv::Mat> image, QString name); - void emitDimensionUpdate(int x, int y); - void emitTrackingDone(uint framenumber); + void emitDimensionUpdate(int x, int y); + void emitTrackingDone(uint framenumber); // ITrackingAlgorithm interface public Q_SLOTS: - void doTracking(std::shared_ptr<cv::Mat> image, uint framenumber) override; - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void doTracking(std::shared_ptr<cv::Mat> image, uint framenumber) override; + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); void receiveParametersChanged(); private: -std::vector<BlobPose> getContourCentroids(cv::Mat& image, int minSize); - void refreshPolygon(); - void sendSelectedImage(std::map<std::string, std::shared_ptr<cv::Mat>>* images); + std::vector<BlobPose> getContourCentroids(cv::Mat& image, int minSize); + void refreshPolygon(); + void sendSelectedImage( + std::map<std::string, std::shared_ptr<cv::Mat>>* images); - std::vector<FishPose> getLastPositionsAsPose(); + std::vector<FishPose> getLastPositionsAsPose(); BST::TrackedTrajectory* _TrackedTrajectoryMajor; - TrackerParameter* _TrackingParameter; - IModelAreaDescriptor* _AreaInfo; + TrackerParameter* _TrackingParameter; + IModelAreaDescriptor* _AreaInfo; - TcpListener* _listener; + TcpListener* _listener; - ImagePreProcessor _ipp; - BlobsDetector _bd; - std::shared_ptr<NN2dMapper> _nn2d; + ImagePreProcessor _ipp; + BlobsDetector _bd; + std::shared_ptr<NN2dMapper> _nn2d; - int _noFish; + int _noFish; - //std::ofstream _ofs; + // std::ofstream _ofs; - int _imageX; - int _imageY; + int _imageX; + int _imageY; std::shared_ptr<cv::Mat> _lastImage; - uint _lastFramenumber; - Config *_cfg; + uint _lastFramenumber; + Config* _cfg; }; #endif // BIOTRACKERTRACKINGALGORITHM_H diff --git a/Src/Model/Network/TcpListener.cpp b/Src/Model/Network/TcpListener.cpp index 4f7613600de6782dce2f6ea26c8de30bb655cacd..6a6f5fb3b72d6d627dc5f4a8436dd0719825938a 100644 --- a/Src/Model/Network/TcpListener.cpp +++ b/Src/Model/Network/TcpListener.cpp @@ -2,68 +2,74 @@ #include <sstream> -TcpListener::TcpListener(QObject *parent) : QTcpServer(parent) +TcpListener::TcpListener(QObject* parent) +: QTcpServer(parent) { } void TcpListener::acceptConnection() { - while (this->hasPendingConnections()) - { - QTcpSocket *socket = this->nextPendingConnection(); - _sockets.insert(socket); - QObject::connect(socket, &QTcpSocket::disconnected, [this, socket](){ - _sockets.erase(socket); - }); - } + while (this->hasPendingConnections()) { + QTcpSocket* socket = this->nextPendingConnection(); + _sockets.insert(socket); + QObject::connect(socket, &QTcpSocket::disconnected, [this, socket]() { + _sockets.erase(socket); + }); + } } void TcpListener::sendPositionsToSocket(std::string packet) { - for (auto const& socket : _sockets) { - socket->write(packet.c_str()); - } + for (auto const& socket : _sockets) { + socket->write(packet.c_str()); + } } std::string TcpListener::sendPositions( - int frameNo, - const std::vector<FishPose>& poses, - const std::vector<cv::Point2f>& polygon, - std::chrono::system_clock::time_point ts) + int frameNo, + const std::vector<FishPose>& poses, + const std::vector<cv::Point2f>& polygon, + std::chrono::system_clock::time_point ts) { - std::stringstream str; - str << "frame:" << frameNo << ";"; + std::stringstream str; + str << "frame:" << frameNo << ";"; - str << "polygon:" << polygon.size() << ";"; - for (auto vertex = polygon.cbegin(); vertex != polygon.cend(); ++vertex) - { - str << vertex->x << "x" << vertex->y << ";"; - } + str << "polygon:" << polygon.size() << ";"; + for (auto vertex = polygon.cbegin(); vertex != polygon.cend(); ++vertex) { + str << vertex->x << "x" << vertex->y << ";"; + } - int fishCount = poses.size(); - int fi = 0; - str << "fishcount:" << fishCount << ";"; + int fishCount = poses.size(); + int fi = 0; + str << "fishcount:" << fishCount << ";"; - for (int i=0; i < poses.size(); i++) - { + for (int i = 0; i < poses.size(); i++) { - str << i+1 << "," // the id of the fish - << poses[i].position_cm().x << "," // real position in cm - x-coordinate - << poses[i].position_cm().y << "," // real position in cm - y-coordinate - << poses[i].orientation_rad() << "," // orientation in radian - << poses[i].orientation_deg() << "," // orientation in degree - << poses[i].width() << "," // size of the fish blob: width - << poses[i].height() << "," // size of the fish blob: height - << long(std::chrono::duration_cast<std::chrono::milliseconds>(ts.time_since_epoch()).count()) << "," // the time stamp - << "F" << (((i + 1) == poses.size()) ? ";" : "&"); // F: obsolete "isRobofish" flag (F: not a robofish) - } - str << "end\n"; + str << i + 1 << "," // the id of the fish + << poses[i].position_cm().x + << "," // real position in cm - x-coordinate + << poses[i].position_cm().y + << "," // real position in cm - y-coordinate + << poses[i].orientation_rad() << "," // orientation in radian + << poses[i].orientation_deg() << "," // orientation in degree + << poses[i].width() << "," // size of the fish blob: width + << poses[i].height() << "," // size of the fish blob: height + << long(std::chrono::duration_cast<std::chrono::milliseconds>( + ts.time_since_epoch()) + .count()) + << "," // the time stamp + << "F" + << (((i + 1) == poses.size()) ? ";" + : "&"); // F: obsolete "isRobofish" + // flag (F: not a robofish) + } + str << "end\n"; - std::cout << str.str() << std::endl; + std::cout << str.str() << std::endl; #ifdef SAVETRACKINGPACKAGES - _trackingInfoOutputFile4Simulation << str.str(); + _trackingInfoOutputFile4Simulation << str.str(); #endif - sendPositionsToSocket(str.str()); - return str.str(); + sendPositionsToSocket(str.str()); + return str.str(); } diff --git a/Src/Model/Network/TcpListener.h b/Src/Model/Network/TcpListener.h index d53d30f561f8f78426d4cf9fef530681f4d9d21a..e3fbfd500597ac886ca3250e3177ea8a195f245c 100644 --- a/Src/Model/Network/TcpListener.h +++ b/Src/Model/Network/TcpListener.h @@ -13,19 +13,19 @@ class TcpListener : public QTcpServer { - Q_OBJECT + Q_OBJECT public: - TcpListener(QObject *parent = 0); + TcpListener(QObject* parent = 0); public slots: - void acceptConnection(); - void sendPositionsToSocket(std::string packet); - std::string sendPositions(int frameNo, - const std::vector<FishPose>& poses, - const std::vector<cv::Point2f>& polygon, - std::chrono::system_clock::time_point ts); + void acceptConnection(); + void sendPositionsToSocket(std::string packet); + std::string sendPositions(int frameNo, + const std::vector<FishPose>& poses, + const std::vector<cv::Point2f>& polygon, + std::chrono::system_clock::time_point ts); private: - std::unordered_set<QTcpSocket *> _sockets; + std::unordered_set<QTcpSocket*> _sockets; }; diff --git a/Src/Model/TrackedComponents/TrackedComponentFactory.cpp b/Src/Model/TrackedComponents/TrackedComponentFactory.cpp index d2e92cd9d8e695ce94eeab2fadd579055b65e379..b83c7ed62592ecee8f387e9cc1968c33ed1c16d8 100644 --- a/Src/Model/TrackedComponents/TrackedComponentFactory.cpp +++ b/Src/Model/TrackedComponents/TrackedComponentFactory.cpp @@ -3,37 +3,40 @@ #include "TrackedTrajectory.h" #include "TrackedElement.h" -namespace BST{ - - TrackedComponentFactory::TrackedComponentFactory() - { - - } - - TrackedComponentFactory::~TrackedComponentFactory() - { - - } - - QList<QString> TrackedComponentFactory::getElementTypes() { - return QList<QString>{ "TrackedElement" }; - } - - IModelTrackedComponent *TrackedComponentFactory::createTrackedElement(QString name) - { - return new BST::TrackedElement(this, "n.a."); - } - - IModelTrackedComponent *TrackedComponentFactory::createTrackedObject(QString name) - { - BST::TrackedTrajectory *t = new BST::TrackedTrajectory(); - BST::TrackedElement *e = new BST::TrackedElement(this, "n.a.", 0); - t->add(e, 0); - return t; - } - - IModelTrackedComponent *TrackedComponentFactory::createTrackedTrajectory(QString name) - { - return new BST::TrackedTrajectory(); - } +namespace BST +{ + + TrackedComponentFactory::TrackedComponentFactory() + { + } + + TrackedComponentFactory::~TrackedComponentFactory() + { + } + + QList<QString> TrackedComponentFactory::getElementTypes() + { + return QList<QString>{"TrackedElement"}; + } + + IModelTrackedComponent* TrackedComponentFactory::createTrackedElement( + QString name) + { + return new BST::TrackedElement(this, "n.a."); + } + + IModelTrackedComponent* TrackedComponentFactory::createTrackedObject( + QString name) + { + BST::TrackedTrajectory* t = new BST::TrackedTrajectory(); + BST::TrackedElement* e = new BST::TrackedElement(this, "n.a.", 0); + t->add(e, 0); + return t; + } + + IModelTrackedComponent* TrackedComponentFactory::createTrackedTrajectory( + QString name) + { + return new BST::TrackedTrajectory(); + } } diff --git a/Src/Model/TrackedComponents/TrackedComponentFactory.h b/Src/Model/TrackedComponents/TrackedComponentFactory.h index 26455a20f40a6ce802344d966ff538caf136a149..3d009ab1322b2da4761c2ebbcbf87e2b2866100a 100644 --- a/Src/Model/TrackedComponents/TrackedComponentFactory.h +++ b/Src/Model/TrackedComponents/TrackedComponentFactory.h @@ -2,22 +2,22 @@ #include "Interfaces/IModel/IModelTrackedComponentFactory.h" -namespace BST{ - -class TrackedComponentFactory : public IModelTrackedComponentFactory +namespace BST { - Q_OBJECT -public: - TrackedComponentFactory(); - ~TrackedComponentFactory(); - QList<QString> getElementTypes() override; + class TrackedComponentFactory : public IModelTrackedComponentFactory + { + Q_OBJECT + public: + TrackedComponentFactory(); + ~TrackedComponentFactory(); - // ITrackedComponentFactory interface -protected: - IModelTrackedComponent *createTrackedElement(QString name) override; - IModelTrackedComponent *createTrackedObject(QString name) override; - IModelTrackedComponent *createTrackedTrajectory(QString name) override; -}; -} + QList<QString> getElementTypes() override; + // ITrackedComponentFactory interface + protected: + IModelTrackedComponent* createTrackedElement(QString name) override; + IModelTrackedComponent* createTrackedObject(QString name) override; + IModelTrackedComponent* createTrackedTrajectory(QString name) override; + }; +} diff --git a/Src/Model/TrackedComponents/TrackedElement.cpp b/Src/Model/TrackedComponents/TrackedElement.cpp index ae313ac856744592216283bc8aa9c9e9345ad918..7f9904da5114d37c1efa069413c53c0f26cf2fe7 100644 --- a/Src/Model/TrackedComponents/TrackedElement.cpp +++ b/Src/Model/TrackedComponents/TrackedElement.cpp @@ -6,182 +6,233 @@ #include "QPainter" #include "QtMath" - namespace BST { - TrackedElement::TrackedElement(QObject *parent, QString name, int id) : - IModelTrackedPoint(parent) - { - _x = 0; - _y = 0; - _id = id; - _deg = 0; - _rad = 0; - _valid = false; - _fixed = false; - } - - void TrackedElement::setValid(bool v) - { - _valid = v; - if (_parentNode) { - TrackedTrajectory* n = dynamic_cast<TrackedTrajectory*>(_parentNode); - if (n) - n->triggerRecalcValid(); - } - } - - - QString TrackedElement::getName() - { - return ""; - } - - void TrackedElement::setFishPose(FishPose p) - { - _pose = p; - _x = p.position_cm().x; - _y = p.position_cm().y; - _deg = p.orientation_deg(); - _rad = p.orientation_rad(); - _ypx = p.position_px().y; - _xpx = p.position_px().x; - _valid = true; - Q_EMIT notifyView(); - } - - void TrackedElement::setTime(std::chrono::system_clock::time_point t) { - _timeSysclck = t; - }; - - void TrackedElement::setTime(qint64 t) { - std::string::size_type sz = 0; - long long ll = t / 1000; - long long remainder = t % 1000; - std::time_t tm(ll); - - _timeSysclck = std::chrono::system_clock::from_time_t(tm); - std::chrono::duration<long long, std::milli> dur(remainder); - _timeSysclck += dur; - }; - - qint64 TrackedElement::getTime() { - qint64 q(std::chrono::duration_cast<std::chrono::milliseconds>(_timeSysclck.time_since_epoch()).count()); - return q; - }; - - QString TrackedElement::getTimeString() { - std::time_t t = std::chrono::system_clock::to_time_t(_timeSysclck); - QDateTime dt; - dt.setTime_t(t); - _timeString = dt.toString(); - return _timeString; - }; - - FishPose TrackedElement::getFishPose() - { - return _pose; - } - - void TrackedElement::setX(float val) { - _x = val; - FishPose pnew(cv::Point2f(_x, _pose.position_cm().y), cv::Point2f(-1, -1), _rad, _deg, _pose.width(), _pose.height(), _pose.getScore()); - _ypx = _pose.position_px().y; - _xpx = _pose.position_px().x; - _pose = pnew; - }; - - void TrackedElement::setY(float val) { - _y = val; - FishPose pnew(cv::Point2f(_pose.position_cm().x, _y), cv::Point2f(-1, -1), _rad, _deg, _pose.width(), _pose.height(), _pose.getScore()); - _ypx = _pose.position_px().y; - _xpx = _pose.position_px().x; - _pose = pnew; - }; - - void TrackedElement::setRad(float r) { - _rad = r; - FishPose pnew(_pose.position_cm(), _pose.position_px(), _rad, _deg, _pose.width(), _pose.height(), _pose.getScore()); - _pose = pnew; - }; - - void TrackedElement::setDeg(float d) { - _deg = d; - FishPose pnew(_pose.position_cm(), _pose.position_px(), _rad, _deg, _pose.width(), _pose.height(), _pose.getScore()); - _pose = pnew; - - }; - - void TrackedElement::setW(float w) { - _w = w; - FishPose pnew(_pose.position_cm(), _pose.position_px(), _rad, _deg, _w, _pose.height(), _pose.getScore()); - _pose = pnew; - } - - void TrackedElement::setH(float h) { - _h = h; - FishPose pnew(_pose.position_cm(), _pose.position_px(), _rad, _deg, _pose.width(), _h, _pose.getScore()); - _pose = pnew; - } - - - void TrackedElement::setXpx(float val) { - _xpx = val; - } - - void TrackedElement::setYpx(float val) { - _ypx = val; - } - - void TrackedElement::setWpx(float w) { - std::cout << "Stub..." << std::endl; - } - - void TrackedElement::setHpx(float h) { - std::cout << "Stub..." << std::endl; - } - - float TrackedElement::getX() { - return _pose.position_cm().x; - } - - float TrackedElement::getY() { - return _pose.position_cm().y; - } - - float TrackedElement::getXpx() { - return _xpx;// _pose.position_px().x; - } - - float TrackedElement::getYpx() { - return _ypx;// _pose.position_px().y; - } - - float TrackedElement::getDeg() { - return _pose.orientation_deg(); - } - - void TrackedElement::operate() - { - qDebug() << "I am TrackedElement "; - } - - void TrackedElement::pressed() - { - Q_EMIT notifyView(); - - } - - void TrackedElement::notPressed() - { - Q_EMIT notifyView(); - } - - bool TrackedElement::getPressedStatus() - { - return false; - } + TrackedElement::TrackedElement(QObject* parent, QString name, int id) + : IModelTrackedPoint(parent) + { + _x = 0; + _y = 0; + _id = id; + _deg = 0; + _rad = 0; + _valid = false; + _fixed = false; + } + + void TrackedElement::setValid(bool v) + { + _valid = v; + if (_parentNode) { + TrackedTrajectory* n = dynamic_cast<TrackedTrajectory*>( + _parentNode); + if (n) + n->triggerRecalcValid(); + } + } + + QString TrackedElement::getName() + { + return ""; + } + + void TrackedElement::setFishPose(FishPose p) + { + _pose = p; + _x = p.position_cm().x; + _y = p.position_cm().y; + _deg = p.orientation_deg(); + _rad = p.orientation_rad(); + _ypx = p.position_px().y; + _xpx = p.position_px().x; + _valid = true; + Q_EMIT notifyView(); + } + + void TrackedElement::setTime(std::chrono::system_clock::time_point t) + { + _timeSysclck = t; + }; + + void TrackedElement::setTime(qint64 t) + { + std::string::size_type sz = 0; + long long ll = t / 1000; + long long remainder = t % 1000; + std::time_t tm(ll); + + _timeSysclck = std::chrono::system_clock::from_time_t(tm); + std::chrono::duration<long long, std::milli> dur(remainder); + _timeSysclck += dur; + }; + + qint64 TrackedElement::getTime() + { + qint64 q(std::chrono::duration_cast<std::chrono::milliseconds>( + _timeSysclck.time_since_epoch()) + .count()); + return q; + }; + + QString TrackedElement::getTimeString() + { + std::time_t t = std::chrono::system_clock::to_time_t(_timeSysclck); + QDateTime dt; + dt.setTime_t(t); + _timeString = dt.toString(); + return _timeString; + }; + + FishPose TrackedElement::getFishPose() + { + return _pose; + } + + void TrackedElement::setX(float val) + { + _x = val; + FishPose pnew(cv::Point2f(_x, _pose.position_cm().y), + cv::Point2f(-1, -1), + _rad, + _deg, + _pose.width(), + _pose.height(), + _pose.getScore()); + _ypx = _pose.position_px().y; + _xpx = _pose.position_px().x; + _pose = pnew; + }; + + void TrackedElement::setY(float val) + { + _y = val; + FishPose pnew(cv::Point2f(_pose.position_cm().x, _y), + cv::Point2f(-1, -1), + _rad, + _deg, + _pose.width(), + _pose.height(), + _pose.getScore()); + _ypx = _pose.position_px().y; + _xpx = _pose.position_px().x; + _pose = pnew; + }; + + void TrackedElement::setRad(float r) + { + _rad = r; + FishPose pnew(_pose.position_cm(), + _pose.position_px(), + _rad, + _deg, + _pose.width(), + _pose.height(), + _pose.getScore()); + _pose = pnew; + }; + + void TrackedElement::setDeg(float d) + { + _deg = d; + FishPose pnew(_pose.position_cm(), + _pose.position_px(), + _rad, + _deg, + _pose.width(), + _pose.height(), + _pose.getScore()); + _pose = pnew; + }; + + void TrackedElement::setW(float w) + { + _w = w; + FishPose pnew(_pose.position_cm(), + _pose.position_px(), + _rad, + _deg, + _w, + _pose.height(), + _pose.getScore()); + _pose = pnew; + } + + void TrackedElement::setH(float h) + { + _h = h; + FishPose pnew(_pose.position_cm(), + _pose.position_px(), + _rad, + _deg, + _pose.width(), + _h, + _pose.getScore()); + _pose = pnew; + } + + void TrackedElement::setXpx(float val) + { + _xpx = val; + } + + void TrackedElement::setYpx(float val) + { + _ypx = val; + } + + void TrackedElement::setWpx(float w) + { + std::cout << "Stub..." << std::endl; + } + + void TrackedElement::setHpx(float h) + { + std::cout << "Stub..." << std::endl; + } + + float TrackedElement::getX() + { + return _pose.position_cm().x; + } + + float TrackedElement::getY() + { + return _pose.position_cm().y; + } + + float TrackedElement::getXpx() + { + return _xpx; // _pose.position_px().x; + } + + float TrackedElement::getYpx() + { + return _ypx; // _pose.position_px().y; + } + + float TrackedElement::getDeg() + { + return _pose.orientation_deg(); + } + + void TrackedElement::operate() + { + qDebug() << "I am TrackedElement "; + } + + void TrackedElement::pressed() + { + Q_EMIT notifyView(); + } + + void TrackedElement::notPressed() + { + Q_EMIT notifyView(); + } + + bool TrackedElement::getPressedStatus() + { + return false; + } } - - diff --git a/Src/Model/TrackedComponents/TrackedElement.h b/Src/Model/TrackedComponents/TrackedElement.h index 1dfaa6938d6924dd52429443dc74a0be66b508d3..d7990596652f7f7d40a4238e5e5e61d48cd6d645 100644 --- a/Src/Model/TrackedComponents/TrackedElement.h +++ b/Src/Model/TrackedComponents/TrackedElement.h @@ -9,86 +9,160 @@ namespace BST { - /** - * This class is an example of how a TrackedComponent could be defined. - * This class inherits from the IModelTrackedComponent class and is therefor part of the Composite Pattern. - * This class represents the Leaf class in the Composite Pattern. - * Objects of this class have a QObject as parent. - */ - class TrackedElement : public IModelTrackedPoint - { - Q_OBJECT + /** + * This class is an example of how a TrackedComponent could be defined. + * This class inherits from the IModelTrackedComponent class and is + * therefor part of the Composite Pattern. This class represents the Leaf + * class in the Composite Pattern. Objects of this class have a QObject as + * parent. + */ + class TrackedElement : public IModelTrackedPoint + { + Q_OBJECT - public: - TrackedElement(QObject *parent = 0, QString name = "n.a.", int id = 0); + public: + TrackedElement(QObject* parent = 0, QString name = "n.a.", int id = 0); - QString getName(); - QString getCoordinateUnit() override { return _unit; }; - void setCoordinateUnit(QString str) override { _unit = str; }; + QString getName(); + QString getCoordinateUnit() override + { + return _unit; + }; + void setCoordinateUnit(QString str) override + { + _unit = str; + }; - void setX(float val); - void setY(float val); - void setW(float w); - void setH(float h); - void setXpx(float val); - void setYpx(float val); - void setWpx(float w); - void setHpx(float h); - void setRad(float r); - void setDeg(float d); - void setId(int val) { _id = val; }; - void setTime(std::chrono::system_clock::time_point t); - void setTime(qint64 t); - void setTimeString(QString t) { _timeString = t; }; - void setValid(bool v); - void setFixed(bool f) { _fixed = f; }; + void setX(float val); + void setY(float val); + void setW(float w); + void setH(float h); + void setXpx(float val); + void setYpx(float val); + void setWpx(float w); + void setHpx(float h); + void setRad(float r); + void setDeg(float d); + void setId(int val) + { + _id = val; + }; + void setTime(std::chrono::system_clock::time_point t); + void setTime(qint64 t); + void setTimeString(QString t) + { + _timeString = t; + }; + void setValid(bool v); + void setFixed(bool f) + { + _fixed = f; + }; + float getX(); + float getY(); + float getXpx(); + float getYpx(); + float getW() + { + return _w; + }; + float getH() + { + return _h; + }; + float getWpx() + { + return _w; + }; + float getHpx() + { + return _h; + }; + float getRad() + { + return _rad; + }; + float getDeg(); + int getId() + { + return _id; + }; + qint64 getTime(); + QString getTimeString(); + bool getValid() + { + return _valid; + }; + bool getFixed() + { + return _fixed; + }; - float getX(); - float getY(); - float getXpx(); - float getYpx(); - float getW() { return _w; }; - float getH() { return _h; }; - float getWpx() { return _w; }; - float getHpx() { return _h; }; - float getRad() { return _rad; }; - float getDeg(); - int getId() { return _id; }; - qint64 getTime(); - QString getTimeString(); - bool getValid() { return _valid; }; - bool getFixed() { return _fixed; }; + bool hasX() + { + return true; + }; + bool hasY() + { + return true; + }; + bool hasW() + { + return false; + }; + bool hasH() + { + return false; + }; + bool hasXpx() + { + return true; + }; + bool hasYpx() + { + return true; + }; + bool hasWpx() + { + return false; + }; + bool hasHpx() + { + return false; + }; + bool hasRad() + { + return true; + }; + bool hasDeg() + { + return true; + }; + bool hasTime() + { + return true; + }; + bool hasTimeString() + { + return true; + }; - bool hasX() { return true; }; - bool hasY() { return true; }; - bool hasW() { return false; }; - bool hasH() { return false; }; - bool hasXpx() { return true; }; - bool hasYpx() { return true; }; - bool hasWpx() { return false; }; - bool hasHpx() { return false; }; - bool hasRad() { return true; }; - bool hasDeg() { return true; }; - bool hasTime() { return true; }; - bool hasTimeString() { return true; }; + void pressed(); + void notPressed(); + bool getPressedStatus(); - void pressed(); - void notPressed(); - bool getPressedStatus(); + void setFishPose(FishPose p); + FishPose getFishPose(); - void setFishPose(FishPose p); - FishPose getFishPose(); + // ITrackedPoint interface + public: + void operate(); - // ITrackedPoint interface - public: - void operate(); - - private: - std::chrono::system_clock::time_point _timeSysclck; - QString _unit = "cm"; - FishPose _pose; - QString _timeString; - }; + private: + std::chrono::system_clock::time_point _timeSysclck; + QString _unit = "cm"; + FishPose _pose; + QString _timeString; + }; } - diff --git a/Src/Model/TrackedComponents/TrackedTrajectory.cpp b/Src/Model/TrackedComponents/TrackedTrajectory.cpp index e4dd321d6c2eb6f2ef3fcfa17c896846e9637801..9fd38d6ce681a440b55e9e29e6c9541de6c042c7 100644 --- a/Src/Model/TrackedComponents/TrackedTrajectory.cpp +++ b/Src/Model/TrackedComponents/TrackedTrajectory.cpp @@ -2,43 +2,49 @@ #include "QDebug" #include "TrackedElement.h" -namespace BST{ - - void TrackedTrajectory::triggerRecalcValid() { +namespace BST +{ + + void TrackedTrajectory::triggerRecalcValid() + { g_calcValid = 1; } - void TrackedTrajectory::setValid(bool v) { + void TrackedTrajectory::setValid(bool v) + { _valid = v; if (_parentNode) { - TrackedTrajectory* n = dynamic_cast<TrackedTrajectory*>(_parentNode); + TrackedTrajectory* n = dynamic_cast<TrackedTrajectory*>( + _parentNode); if (n) n->triggerRecalcValid(); } } - TrackedTrajectory::TrackedTrajectory(QObject *parent, QString name) : - ::TrackedTrajectory(parent), - name(name) + TrackedTrajectory::TrackedTrajectory(QObject* parent, QString name) + : ::TrackedTrajectory(parent) + , name(name) { setFixed(false); - g_calcValid = 1; + g_calcValid = 1; g_validCount = 0; - _size = 0; - _valid = true; + _size = 0; + _valid = true; } void TrackedTrajectory::operate() { - qDebug() << "Printing all TrackedElements in TrackedObject " << name; - qDebug() << "========================= Begin =========================="; + qDebug() << "Printing all TrackedElements in TrackedObject " << name; + qDebug() + << "========================= Begin =========================="; for (int i = 0; i < _TrackedComponents.size(); ++i) { - dynamic_cast<TrackedElement *>(_TrackedComponents.at(i))->operate(); + dynamic_cast<TrackedElement*>(_TrackedComponents.at(i))->operate(); } - qDebug() << "======================== End ========================="; + qDebug() + << "======================== End ========================="; } - void TrackedTrajectory::add(IModelTrackedComponent *comp, int pos) + void TrackedTrajectory::add(IModelTrackedComponent* comp, int pos) { comp->setParent(this); @@ -47,10 +53,8 @@ namespace BST{ _TrackedComponents.append(comp); _size++; g_validCount++; - } - else if (_size <= pos) { - while (_size < pos) - { + } else if (_size <= pos) { + while (_size < pos) { _TrackedComponents.append(nullptr); _size++; } @@ -58,13 +62,12 @@ namespace BST{ _TrackedComponents.append(comp); _size++; g_validCount++; - } - else { + } else { _TrackedComponents[pos] = comp; } } - bool TrackedTrajectory::remove(IModelTrackedComponent *comp) + bool TrackedTrajectory::remove(IModelTrackedComponent* comp) { g_calcValid = 1; comp->setValid(false); @@ -74,7 +77,7 @@ namespace BST{ void TrackedTrajectory::clear() { g_calcValid = 1; - foreach(IModelTrackedComponent* el, _TrackedComponents) { + foreach (IModelTrackedComponent* el, _TrackedComponents) { if (dynamic_cast<IModelTrackedTrajectory*>(el)) dynamic_cast<IModelTrackedTrajectory*>(el)->clear(); } @@ -97,8 +100,8 @@ namespace BST{ IModelTrackedComponent* TrackedTrajectory::getValidChild(int index) { int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (el){ + foreach (IModelTrackedComponent* el, _TrackedComponents) { + if (el) { if (c == index && el->getValid()) return el; c += el->getValid() ? 1 : 0; @@ -124,16 +127,15 @@ namespace BST{ { if (g_calcValid == 1) { int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { + foreach (IModelTrackedComponent* el, _TrackedComponents) { if (el) c += el->getValid() ? 1 : 0; } g_validCount = c; - g_calcValid = 0; + g_calcValid = 0; return c; - } - else { + } else { return g_validCount; } } diff --git a/Src/Model/TrackedComponents/TrackedTrajectory.h b/Src/Model/TrackedComponents/TrackedTrajectory.h index 867e476079b9f52b1708bc1586b5d5b48253d038..7459e9e810fae8b21985db3dd82fd5f68b8293a8 100644 --- a/Src/Model/TrackedComponents/TrackedTrajectory.h +++ b/Src/Model/TrackedComponents/TrackedTrajectory.h @@ -6,44 +6,44 @@ namespace BST { - /** - * This class inherits from the IModelTrackedTrajectory class and is therefor part of the Composite Pattern. - * This class represents the Composite class. - * This class is responsibility for the handling of Leaf objects. - * Internaly this class uses a QList for storing Leaf object. - * - * Objects of this class have a QObject as parent. - */ - class TrackedTrajectory : public ::TrackedTrajectory { - Q_OBJECT - - public: - TrackedTrajectory(QObject *parent = 0, QString name = "n.a."); - ~TrackedTrajectory()override{}; - - // ITrackedComponent interface - public: - void operate(); - - // ITrackedObject interface - public: - void add(IModelTrackedComponent *comp, int pos = -1) override; - bool remove(IModelTrackedComponent *comp) override; - void clear() override; - IModelTrackedComponent *getChild(int index) override; - IModelTrackedComponent* getValidChild(int index) override; - IModelTrackedComponent *getLastChild() override; - int size() override; - int validCount() override; - void setValid(bool v) override; - void triggerRecalcValid(); - - private: - int g_calcValid = 1; - int g_validCount = 0; - int _size = 0; - QString name; - }; - + /** + * This class inherits from the IModelTrackedTrajectory class and is + * therefor part of the Composite Pattern. This class represents the + * Composite class. This class is responsibility for the handling of Leaf + * objects. Internaly this class uses a QList for storing Leaf object. + * + * Objects of this class have a QObject as parent. + */ + class TrackedTrajectory : public ::TrackedTrajectory + { + Q_OBJECT + + public: + TrackedTrajectory(QObject* parent = 0, QString name = "n.a."); + ~TrackedTrajectory() override{}; + + // ITrackedComponent interface + public: + void operate(); + + // ITrackedObject interface + public: + void add(IModelTrackedComponent* comp, int pos = -1) override; + bool remove(IModelTrackedComponent* comp) override; + void clear() override; + IModelTrackedComponent* getChild(int index) override; + IModelTrackedComponent* getValidChild(int index) override; + IModelTrackedComponent* getLastChild() override; + int size() override; + int validCount() override; + void setValid(bool v) override; + void triggerRecalcValid(); + + private: + int g_calcValid = 1; + int g_validCount = 0; + int _size = 0; + QString name; + }; } diff --git a/Src/Model/TrackedComponents/pose/FishPose.cpp b/Src/Model/TrackedComponents/pose/FishPose.cpp index af0bfcc53c71b4f18228e85ff5fa38c4c903b879..7442b3c93c315cf396d590998420868519fe626f 100644 --- a/Src/Model/TrackedComponents/pose/FishPose.cpp +++ b/Src/Model/TrackedComponents/pose/FishPose.cpp @@ -1,33 +1,44 @@ #include "FishPose.h" #include "../../../helper/CvHelper.h" -FishPose::FishPose(cv::Point2f pos_cm , cv::Point pos_px, float rad, float deg, float width, float height, float score) : - _position_cm(pos_cm), - _position_px(pos_px), - _radAngle(rad), - _degAngle(deg), - _width(width), - _height(height), - _score(score) +FishPose::FishPose(cv::Point2f pos_cm, + cv::Point pos_px, + float rad, + float deg, + float width, + float height, + float score) +: _position_cm(pos_cm) +, _position_px(pos_px) +, _radAngle(rad) +, _degAngle(deg) +, _width(width) +, _height(height) +, _score(score) { - assert(_degAngle >= -360.0f && _degAngle <= 360.0f); - time(&_timev); + assert(_degAngle >= -360.0f && _degAngle <= 360.0f); + time(&_timev); } - std::string FishPose::toString(bool rectified) { - std::ostringstream out; - if(rectified == false) - out << _position_px.x << ";" << _position_px.y << ";" << _degAngle << ";" << _radAngle; - else - out << _position_cm.x << ";" << _position_cm.y << ";" << _degAngle << ";" << _radAngle; - return out.str(); + std::ostringstream out; + if (rectified == false) + out << _position_px.x << ";" << _position_px.y << ";" << _degAngle + << ";" << _radAngle; + else + out << _position_cm.x << ";" << _position_cm.y << ";" << _degAngle + << ";" << _radAngle; + return out.str(); } -float FishPose::calculateProbabilityOfIdentity(const FishPose &first, const FishPose &second, float angleImportance) +float FishPose::calculateProbabilityOfIdentity(const FishPose& first, + const FishPose& second, + float angleImportance) { - //Preliminary method for calculating identity of entities. See Issue biotracker_core/issues/130 for a discussion of this topic. - float distance = CvHelper::getDistance(first.position_cm(), second.position_cm()); - return distance <= 0 ? std::numeric_limits<float>::max() : 1.0/distance; + // Preliminary method for calculating identity of entities. See Issue + // biotracker_core/issues/130 for a discussion of this topic. + float distance = CvHelper::getDistance(first.position_cm(), + second.position_cm()); + return distance <= 0 ? std::numeric_limits<float>::max() : 1.0 / distance; } diff --git a/Src/Model/TrackedComponents/pose/FishPose.h b/Src/Model/TrackedComponents/pose/FishPose.h index 39778f8c25714203b794b23f4b66232526b55078..57f19e29170d80a4101e64dca2eb35b8f93a6280 100644 --- a/Src/Model/TrackedComponents/pose/FishPose.h +++ b/Src/Model/TrackedComponents/pose/FishPose.h @@ -7,127 +7,186 @@ class FishPose : public IPose { public: - /** - * The standard constructor. - */ - FishPose(cv::Point2f pos_cm = cv::Point2f(-1,-1), cv::Point pos_px = cv::Point(-1,-1), float rad = 0, float deg = 0, float width = 0, float height = 0, float score = 0.0); - - /** - * Copy constructor. - */ - FishPose(const FishPose &other) : FishPose(other._position_cm, other._position_px, other._radAngle, other._degAngle, other._width, other._height, other._score) - { - time(&_timev); - } - - /* Simple identity of fish poses, based on orientation, position and dimensions - */ - inline bool operator == (const FishPose &b) const{ - if (b.orientation_rad() == orientation_rad() && - b.position_cm() == position_cm() && - b.width() == width() && - b.height() == height()) - return true; - return false; - } - - /** - * Gets the position of the pose in cm. - * @return: position in cm. - */ - cv::Point2f position_cm() const { return _position_cm; } - - /** - * Gets the position of the pose in pixel. - * @return: position in px. - */ - cv::Point position_px() const { return _position_px; } - - /** - * Gets the position of the pose in pixel as floating point values. - * @return: position in px. - */ - cv::Point2f position_pxf() const { return cv::Point2f(_position_px.x, _position_px.y); } - - - /** - * Gets the orientation of the pose as degree. - * @return: orientation angle. - */ - float orientation_deg() const { return _degAngle; } - - /** - * Sets the orientation of the pose as degree. - * @param: degAngle, the orientation angle to set. - */ - void set_orientation_deg(float degAngle) { _degAngle = degAngle; time(&_timev); assert(_degAngle >= -360.0f && _degAngle <= 360.0f); } - - /** - * Gets the orientation of the pose as radian. - * @return: orientation angle. - */ - float orientation_rad() const { return _radAngle; } - - /** - * Sets the orientation of the pose as radian. - * @param: radAngle, the orientation angle to set. - */ - void set_orientation_rad(float radAngle) { _radAngle = radAngle; time(&_timev); } - - /** - * Gets the width pose. - * @return: width of the pose - */ - float width() const { return _width; } - - /** - * Gets the height pose. - * @return: height of the pose - */ - float height() const { return _height; } - - /** - * Checks if the fish pose is valid. Means, x-pos != -1 and y-pose != -1. - * @return: true if position is valid, false otherwise. - */ - bool isValid() { return (_position_px.x != -1 && _position_px.y != -1) ? true : false; } - - /** - * @return: the score of the fish that comes from the mapper - usually between 0 and 1 - */ - float getScore() { return _score; } - - /** - * Sets the score of the fish pose. Conventionally, it should be between 0 and 1. - */ - void setScore(float score) { _score = score; } - /** - * Gets the time stamp. - * - */ - time_t ts() { return _timev; } - - /** - * Converts a pose to standard string. - * @param: rectified, specified whether the position is rectified. - * @return: a position as a standard string. - */ - std::string toString(bool rectified = false); - - /** - * Calculates the probability that two poses are the same. - * The influence of the angle can be set by the parameter angleImportance. - * @return probability between 0 and 1 - */ - static float calculateProbabilityOfIdentity(const FishPose &first, const FishPose &second, float angleImportance = 0.2f); + /** + * The standard constructor. + */ + FishPose(cv::Point2f pos_cm = cv::Point2f(-1, -1), + cv::Point pos_px = cv::Point(-1, -1), + float rad = 0, + float deg = 0, + float width = 0, + float height = 0, + float score = 0.0); + + /** + * Copy constructor. + */ + FishPose(const FishPose& other) + : FishPose(other._position_cm, + other._position_px, + other._radAngle, + other._degAngle, + other._width, + other._height, + other._score) + { + time(&_timev); + } + + /* Simple identity of fish poses, based on orientation, position and + * dimensions + */ + inline bool operator==(const FishPose& b) const + { + if (b.orientation_rad() == orientation_rad() && + b.position_cm() == position_cm() && b.width() == width() && + b.height() == height()) + return true; + return false; + } + + /** + * Gets the position of the pose in cm. + * @return: position in cm. + */ + cv::Point2f position_cm() const + { + return _position_cm; + } + + /** + * Gets the position of the pose in pixel. + * @return: position in px. + */ + cv::Point position_px() const + { + return _position_px; + } + + /** + * Gets the position of the pose in pixel as floating point values. + * @return: position in px. + */ + cv::Point2f position_pxf() const + { + return cv::Point2f(_position_px.x, _position_px.y); + } + + /** + * Gets the orientation of the pose as degree. + * @return: orientation angle. + */ + float orientation_deg() const + { + return _degAngle; + } + + /** + * Sets the orientation of the pose as degree. + * @param: degAngle, the orientation angle to set. + */ + void set_orientation_deg(float degAngle) + { + _degAngle = degAngle; + time(&_timev); + assert(_degAngle >= -360.0f && _degAngle <= 360.0f); + } + + /** + * Gets the orientation of the pose as radian. + * @return: orientation angle. + */ + float orientation_rad() const + { + return _radAngle; + } + + /** + * Sets the orientation of the pose as radian. + * @param: radAngle, the orientation angle to set. + */ + void set_orientation_rad(float radAngle) + { + _radAngle = radAngle; + time(&_timev); + } + + /** + * Gets the width pose. + * @return: width of the pose + */ + float width() const + { + return _width; + } + + /** + * Gets the height pose. + * @return: height of the pose + */ + float height() const + { + return _height; + } + + /** + * Checks if the fish pose is valid. Means, x-pos != -1 and y-pose != -1. + * @return: true if position is valid, false otherwise. + */ + bool isValid() + { + return (_position_px.x != -1 && _position_px.y != -1) ? true : false; + } + + /** + * @return: the score of the fish that comes from the mapper - usually + * between 0 and 1 + */ + float getScore() + { + return _score; + } + + /** + * Sets the score of the fish pose. Conventionally, it should be between 0 + * and 1. + */ + void setScore(float score) + { + _score = score; + } + /** + * Gets the time stamp. + * + */ + time_t ts() + { + return _timev; + } + + /** + * Converts a pose to standard string. + * @param: rectified, specified whether the position is rectified. + * @return: a position as a standard string. + */ + std::string toString(bool rectified = false); + + /** + * Calculates the probability that two poses are the same. + * The influence of the angle can be set by the parameter angleImportance. + * @return probability between 0 and 1 + */ + static float calculateProbabilityOfIdentity(const FishPose& first, + const FishPose& second, + float angleImportance = 0.2f); private: - cv::Point2f _position_cm; - cv::Point _position_px; - float _radAngle; - float _degAngle; - float _width; - float _height; - float _score; - time_t _timev; + cv::Point2f _position_cm; + cv::Point _position_px; + float _radAngle; + float _degAngle; + float _width; + float _height; + float _score; + time_t _timev; }; diff --git a/Src/Model/TrackedComponents/pose/IPose.h b/Src/Model/TrackedComponents/pose/IPose.h index 1d315abca9c7957a77d49fb50bd2dd44a6da048f..71c0752efb87c514bbb727084b1265088ff7e369 100644 --- a/Src/Model/TrackedComponents/pose/IPose.h +++ b/Src/Model/TrackedComponents/pose/IPose.h @@ -5,25 +5,27 @@ class IPose { public: - virtual ~IPose() {} + virtual ~IPose() + { + } - /** - * Gets the fish position as centimeter metric. - */ - virtual cv::Point2f position_cm() const = 0; + /** + * Gets the fish position as centimeter metric. + */ + virtual cv::Point2f position_cm() const = 0; - /** - * Gets the fish position as pixel metric. - */ - virtual cv::Point position_px() const = 0; + /** + * Gets the fish position as pixel metric. + */ + virtual cv::Point position_px() const = 0; - /** - * Gets the fish orientation in degree. - */ - virtual float orientation_deg() const = 0; + /** + * Gets the fish orientation in degree. + */ + virtual float orientation_deg() const = 0; - /** - * Gets the fish orientation in radian. - */ - virtual float orientation_rad() const = 0; + /** + * Gets the fish orientation in radian. + */ + virtual float orientation_rad() const = 0; }; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 645159c55329cf59a18f7aba7e1b19225e7cf966..365bc9ec46fa3464be4fdb422d935a692ecd0ce6 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -1,54 +1,53 @@ #include "TrackerParameter.h" #include "../Controller/ControllerTrackingAlgorithm.h" -TrackerParameter::TrackerParameter(QObject *parent) : - IModel(parent) +TrackerParameter::TrackerParameter(QObject* parent) +: IModel(parent) { - - _cfg = static_cast<ControllerTrackingAlgorithm*>(parent)->getConfig(); - - _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; - _BinarizationThreshold = _cfg->BinarizationThreshold; - _SizeErode = _cfg->SizeErode; - _SizeDilate = _cfg->SizeDilate; - _MinBlobSize = _cfg->MinBlobSize; - _MaxBlobSize = _cfg->MaxBlobSize; - _LearningRate = _cfg->LearningRate; + _cfg = static_cast<ControllerTrackingAlgorithm*>(parent)->getConfig(); - _doNetwork = _cfg->DoNetwork; - _networkPort = _cfg->NetworkPort; + _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; + _BinarizationThreshold = _cfg->BinarizationThreshold; + _SizeErode = _cfg->SizeErode; + _SizeDilate = _cfg->SizeDilate; + _MinBlobSize = _cfg->MinBlobSize; + _MaxBlobSize = _cfg->MaxBlobSize; - _doBackground = true; - _sendImage = 0; //Send no image - _resetBackground = false; + _LearningRate = _cfg->LearningRate; - _algorithm = "Custom"; + _doNetwork = _cfg->DoNetwork; + _networkPort = _cfg->NetworkPort; + + _doBackground = true; + _sendImage = 0; // Send no image + _resetBackground = false; + + _algorithm = "Custom"; Q_EMIT notifyView(); } void TrackerParameter::setBinarizationThreshold(int x) { - _BinarizationThreshold = x; - _cfg->BinarizationThreshold = x; - Q_EMIT notifyView(); + _BinarizationThreshold = x; + _cfg->BinarizationThreshold = x; + Q_EMIT notifyView(); } int TrackerParameter::getBinarizationThreshold() { - return _BinarizationThreshold; + return _BinarizationThreshold; } - void TrackerParameter::setUseAbsoluteDifference(bool value) { - _UseAbsoluteDifference = value; - _cfg->UseAbsoluteDifference = value; - Q_EMIT notifyView(); + _UseAbsoluteDifference = value; + _cfg->UseAbsoluteDifference = value; + Q_EMIT notifyView(); } bool TrackerParameter::getUseAbsoluteDifference() { - return _UseAbsoluteDifference; + return _UseAbsoluteDifference; } \ No newline at end of file diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 5ad37d159d212b0d26851ed914a0f62068bd2d47..4ee2f4b5f1dc38e26b82772a428358f8c26a6b35 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -1,7 +1,6 @@ #ifndef TRACKERPARAMETER_H #define TRACKERPARAMETER_H - #include "Interfaces/IModel/IModel.h" #include "../Config.h" @@ -9,117 +8,164 @@ class TrackerParameter : public IModel { Q_OBJECT public: - TrackerParameter(QObject *parent = 0); + TrackerParameter(QObject* parent = 0); public slots: - QString getAlgorithm() { return _algorithm; } - void setAlgorithm(QString algorithm) { - _algorithm = algorithm; - } - - void setUseAbsoluteDifference(bool x); - bool getUseAbsoluteDifference(); - - void setBinarizationThreshold(int x); - int getBinarizationThreshold(); - - int getSizeErode() { return _SizeErode; }; - void setSizeErode(int x) { - _SizeErode = x; - _cfg->SizeErode = x; - Q_EMIT notifyView(); - }; - - int getSizeDilate() { return _SizeDilate; }; - void setSizeDilate(int x) { - _SizeDilate = x; - _cfg->SizeDilate = x; - Q_EMIT notifyView(); - }; - - double getLearningRate() { return _LearningRate; }; - void setLearningRate(double x) { - _LearningRate = x; - _cfg->LearningRate = x; - Q_EMIT notifyView(); - }; - - double getMinBlobSize() { return _MinBlobSize; }; - void setMinBlobSize(double x) { - _MinBlobSize = x; - _cfg->MinBlobSize = x; - Q_EMIT notifyView(); - }; - - double getMaxBlobSize() { return _MaxBlobSize; }; - void setMaxBlobSize(double x) { - _MaxBlobSize = x; - _cfg->MaxBlobSize = x; - Q_EMIT notifyView(); - }; - - bool getDoBackground() { return _doBackground; }; - void setDoBackground(bool x) { - _doBackground = x; - _cfg->DoBackground = x; - Q_EMIT notifyView(); - }; - - bool getDoNetwork() { return _doNetwork; }; - void setDoNetwork(bool x) { - _doNetwork = x; - _cfg->DoNetwork = x; - Q_EMIT notifyView(); - }; - - int getSendImage() { return _sendImage; }; - void setSendImage(int x) { - _sendImage = x; - Q_EMIT notifyView(); - }; - - bool getResetBackground() { return _resetBackground; }; - void setResetBackground(bool x) { - _resetBackground = x; - Q_EMIT notifyView(); - }; - - int getNoFish() { return _noFish; }; - void setNoFish(int x) { - _noFish = x; - _cfg->NoFish = x; - Q_EMIT notifyView(); - }; - - std::string getNewSelection() { return _newSelection; }; - void setNewSelection(std::string x) { - _newSelection = x; - } + QString getAlgorithm() + { + return _algorithm; + } + void setAlgorithm(QString algorithm) + { + _algorithm = algorithm; + } + + void setUseAbsoluteDifference(bool x); + bool getUseAbsoluteDifference(); + + void setBinarizationThreshold(int x); + int getBinarizationThreshold(); + + int getSizeErode() + { + return _SizeErode; + }; + void setSizeErode(int x) + { + _SizeErode = x; + _cfg->SizeErode = x; + Q_EMIT notifyView(); + }; + + int getSizeDilate() + { + return _SizeDilate; + }; + void setSizeDilate(int x) + { + _SizeDilate = x; + _cfg->SizeDilate = x; + Q_EMIT notifyView(); + }; + + double getLearningRate() + { + return _LearningRate; + }; + void setLearningRate(double x) + { + _LearningRate = x; + _cfg->LearningRate = x; + Q_EMIT notifyView(); + }; + + double getMinBlobSize() + { + return _MinBlobSize; + }; + void setMinBlobSize(double x) + { + _MinBlobSize = x; + _cfg->MinBlobSize = x; + Q_EMIT notifyView(); + }; + + double getMaxBlobSize() + { + return _MaxBlobSize; + }; + void setMaxBlobSize(double x) + { + _MaxBlobSize = x; + _cfg->MaxBlobSize = x; + Q_EMIT notifyView(); + }; + + bool getDoBackground() + { + return _doBackground; + }; + void setDoBackground(bool x) + { + _doBackground = x; + _cfg->DoBackground = x; + Q_EMIT notifyView(); + }; + + bool getDoNetwork() + { + return _doNetwork; + }; + void setDoNetwork(bool x) + { + _doNetwork = x; + _cfg->DoNetwork = x; + Q_EMIT notifyView(); + }; + + int getSendImage() + { + return _sendImage; + }; + void setSendImage(int x) + { + _sendImage = x; + Q_EMIT notifyView(); + }; + + bool getResetBackground() + { + return _resetBackground; + }; + void setResetBackground(bool x) + { + _resetBackground = x; + Q_EMIT notifyView(); + }; + + int getNoFish() + { + return _noFish; + }; + void setNoFish(int x) + { + _noFish = x; + _cfg->NoFish = x; + Q_EMIT notifyView(); + }; + + std::string getNewSelection() + { + return _newSelection; + }; + void setNewSelection(std::string x) + { + _newSelection = x; + } private: + QString _algorithm; - QString _algorithm; - - bool _UseAbsoluteDifference; - int _BinarizationThreshold; + bool _UseAbsoluteDifference; + int _BinarizationThreshold; - int _SizeErode; - int _SizeDilate; - double _LearningRate; - int _MinBlobSize; - int _MaxBlobSize; + int _SizeErode; + int _SizeDilate; + double _LearningRate; + int _MinBlobSize; + int _MaxBlobSize; - bool _doBackground; - int _sendImage; - bool _resetBackground; - int _noFish; + bool _doBackground; + int _sendImage; + bool _resetBackground; + int _noFish; - int _networkPort; - bool _doNetwork; + int _networkPort; + bool _doNetwork; - std::string _newSelection; - Config *_cfg; + std::string _newSelection; + Config* _cfg; }; #endif // TRACKERPARAMETER_H diff --git a/Src/Model/TrackingAlgorithm/NN2dMapper.cpp b/Src/Model/TrackingAlgorithm/NN2dMapper.cpp index 447db500560ce153c759b8687ac867d6ad105b07..dc379a2f076b7ded14b02bf137a20f0c095aeb38 100644 --- a/Src/Model/TrackingAlgorithm/NN2dMapper.cpp +++ b/Src/Model/TrackingAlgorithm/NN2dMapper.cpp @@ -5,322 +5,376 @@ #include <tuple> #include <utility> -float dif(float a, float b) { - return fmod((std::abs(b - a)), CV_PI); +float dif(float a, float b) +{ + return fmod((std::abs(b - a)), CV_PI); } -NN2dMapper::NN2dMapper(BST::TrackedTrajectory *tree) { - _tree = tree; - - //Looks kinda complicated but is a rather simple thing: - //For every true trajectory below the tree's root (which are in fact, fish trajectories in out case) - //we want to arr a last confident angle to the map. - int cid = 0; - for (int i = 0; i < _tree->size(); i++) - { - TrackedTrajectory *t = dynamic_cast<TrackedTrajectory *>(_tree->getChild(i)); - if (t && t->getValid()){ - _mapLastConfidentAngle.insert(std::pair<int, float>(cid, std::numeric_limits<float>::quiet_NaN())); - cid++; - } - } +NN2dMapper::NN2dMapper(BST::TrackedTrajectory* tree) +{ + _tree = tree; + + // Looks kinda complicated but is a rather simple thing: + // For every true trajectory below the tree's root (which are in fact, fish + // trajectories in out case) we want to arr a last confident angle to the + // map. + int cid = 0; + for (int i = 0; i < _tree->size(); i++) { + TrackedTrajectory* t = dynamic_cast<TrackedTrajectory*>( + _tree->getChild(i)); + if (t && t->getValid()) { + _mapLastConfidentAngle.insert(std::pair<int, float>( + cid, + std::numeric_limits<float>::quiet_NaN())); + cid++; + } + } } -// Functor to compare by the Mth element, as per https://stackoverflow.com/questions/23030267/custom-sorting-a-vector-of-tuples +// Functor to compare by the Mth element, as per +// https://stackoverflow.com/questions/23030267/custom-sorting-a-vector-of-tuples struct TupleCompare { - bool operator()(std::tuple<float, FishPose> a, std::tuple<float, FishPose> b) const { - return std::get<0>(a) > std::get<0>(b); - } - + bool operator()(std::tuple<float, FishPose> a, + std::tuple<float, FishPose> b) const + { + return std::get<0>(a) > std::get<0>(b); + } }; -FishPose getFishpose(BST::TrackedTrajectory* traj, uint frameid, uint id) { +FishPose getFishpose(BST::TrackedTrajectory* traj, uint frameid, uint id) +{ IModelTrackedComponent* comp = traj->getValidChild(id); - BST::TrackedTrajectory* ct = dynamic_cast<BST::TrackedTrajectory*>(comp); + BST::TrackedTrajectory* ct = dynamic_cast<BST::TrackedTrajectory*>(comp); if (ct) { - BST::TrackedElement *el = dynamic_cast<BST::TrackedElement*>(ct->getChild(frameid-1)); + BST::TrackedElement* el = dynamic_cast<BST::TrackedElement*>( + ct->getChild(frameid - 1)); if (el) return el->getFishPose(); } return FishPose(); } -std::tuple<std::vector<FishPose>, std::vector<float>> NN2dMapper::getNewPoses(BST::TrackedTrajectory* traj, uint frameid, std::vector<BlobPose> blobPoses) { - /* The algorithm seems kinda inefficient, as there is many fish*blobs and fish*fish loops. - * But as N is expected to be pretty small (<10 for fish, <20 for blobs) this seems feasible. - */ - std::vector<FishPose> blobs = convertBlobPosesToFishPoses(blobPoses); - - int sizeF = traj->validCount(); - int sizeB = blobs.size(); - std::vector<std::vector<std::tuple<float, FishPose>>> propMap; - - //Create propability matrix and sort it - for (int i = 0; i < sizeF ; i++) { - std::vector<std::tuple<float, FishPose>> currentFish; +std::tuple<std::vector<FishPose>, std::vector<float>> NN2dMapper::getNewPoses( + BST::TrackedTrajectory* traj, + uint frameid, + std::vector<BlobPose> blobPoses) +{ + /* The algorithm seems kinda inefficient, as there is many fish*blobs and + * fish*fish loops. But as N is expected to be pretty small (<10 for fish, + * <20 for blobs) this seems feasible. + */ + std::vector<FishPose> blobs = convertBlobPosesToFishPoses(blobPoses); + + int sizeF = traj->validCount(); + int sizeB = blobs.size(); + std::vector<std::vector<std::tuple<float, FishPose>>> propMap; + + // Create propability matrix and sort it + for (int i = 0; i < sizeF; i++) { + std::vector<std::tuple<float, FishPose>> currentFish; FishPose cpose = getFishpose(traj, frameid, i); - for (int j = 0; j < sizeB ; j++) { - currentFish.push_back(std::tuple<float, FishPose>(FishPose::calculateProbabilityOfIdentity(cpose, blobs[j]), blobs[j])); - } - std::sort(begin(currentFish), end(currentFish), TupleCompare()); - propMap.push_back(currentFish); - } - - //I'm sorry for the goto/inefficient loop. But usually we will not have more than a - //hand full (<6) of blobs to walk through, so it's not worth the optimizing. - retry: - for (int i = 0; i < propMap.size(); i++) { - for (int j = 0; j < propMap.size(); j++) { - //Is this - if (!propMap[i].empty() && !propMap[j].empty() && i!=j) { - //Reads: If same blob, but i has higher props than j - bool samePose = std::get<1>(propMap[i][0]) == std::get<1>(propMap[j][0]); - bool propLess = std::get<0>(propMap[i][0]) <= std::get<0>(propMap[j][0]); - if (samePose && propLess) { - //...then remove the 0'th element from j and try again. - propMap[i].erase(propMap[i].begin()); - goto retry; - } - } - } - } - - - std::vector<float> bestMatchesProps; - std::vector<FishPose> bestMatchesPoses; - for (int i = 0; i < propMap.size(); i++) { - if (propMap[i].size() > 0) { - bestMatchesProps.push_back(std::get<0>(propMap[i][0])); - bestMatchesPoses.push_back(std::get<1>(propMap[i][0])); - } - else { - bestMatchesPoses.push_back(getFishpose(traj, frameid, i)); - bestMatchesProps.push_back(100); - } - } - - for (int i = 0; i < bestMatchesPoses.size(); i++) { - - //Look at what the fish did in the last 10 frames + for (int j = 0; j < sizeB; j++) { + currentFish.push_back(std::tuple<float, FishPose>( + FishPose::calculateProbabilityOfIdentity(cpose, blobs[j]), + blobs[j])); + } + std::sort(begin(currentFish), end(currentFish), TupleCompare()); + propMap.push_back(currentFish); + } + +// I'm sorry for the goto/inefficient loop. But usually we will not have more +// than a hand full (<6) of blobs to walk through, so it's not worth the +// optimizing. +retry: + for (int i = 0; i < propMap.size(); i++) { + for (int j = 0; j < propMap.size(); j++) { + // Is this + if (!propMap[i].empty() && !propMap[j].empty() && i != j) { + // Reads: If same blob, but i has higher props than j + bool samePose = std::get<1>(propMap[i][0]) == + std::get<1>(propMap[j][0]); + bool propLess = std::get<0>(propMap[i][0]) <= + std::get<0>(propMap[j][0]); + if (samePose && propLess) { + //...then remove the 0'th element from j and try again. + propMap[i].erase(propMap[i].begin()); + goto retry; + } + } + } + } + + std::vector<float> bestMatchesProps; + std::vector<FishPose> bestMatchesPoses; + for (int i = 0; i < propMap.size(); i++) { + if (propMap[i].size() > 0) { + bestMatchesProps.push_back(std::get<0>(propMap[i][0])); + bestMatchesPoses.push_back(std::get<1>(propMap[i][0])); + } else { + bestMatchesPoses.push_back(getFishpose(traj, frameid, i)); + bestMatchesProps.push_back(100); + } + } + + for (int i = 0; i < bestMatchesPoses.size(); i++) { + + // Look at what the fish did in the last 10 frames double historyDir; { - double lookBack = 10; - cv::Point2f p = getFishpose(traj, frameid - lookBack, i).position_cm(); + double lookBack = 10; + cv::Point2f p = + getFishpose(traj, frameid - lookBack, i).position_cm(); cv::Point2f pnow = bestMatchesPoses[i].position_cm(); while (CvHelper::getDistance(p, pnow) < 0.1 && lookBack < 100) { lookBack += 10; - cv::Point2f p = getFishpose(traj, frameid - lookBack, i).position_cm(); + cv::Point2f p = + getFishpose(traj, frameid - lookBack, i).position_cm(); cv::Point2f pnow = bestMatchesPoses[i].position_cm(); } double dir = CvHelper::getAngleToTarget(p, pnow); - //correct some weird angle definition + // correct some weird angle definition historyDir = dir + CV_PI / 2; } - //The blob detection will come up with an ellipse orientation, where front and back are ambigious. - //So check the history for movement direction. Use the history as an indicator where front and back are. - //This might be unstable iff the fish didn't move at all. - double dif = CvHelper::angleDifference(bestMatchesPoses[i].orientation_rad(), historyDir); + // The blob detection will come up with an ellipse orientation, where + // front and back are ambigious. So check the history for movement + // direction. Use the history as an indicator where front and back are. + // This might be unstable iff the fish didn't move at all. + double dif = CvHelper::angleDifference( + bestMatchesPoses[i].orientation_rad(), + historyDir); if (std::abs(dif) > CV_PI / 2) { double dir = bestMatchesPoses[i].orientation_rad() + CV_PI; - while (dir > 2 * CV_PI) dir -= 2 * CV_PI; - while (dir < -2 * CV_PI) dir += 2 * CV_PI; + while (dir > 2 * CV_PI) + dir -= 2 * CV_PI; + while (dir < -2 * CV_PI) + dir += 2 * CV_PI; bestMatchesPoses[i].set_orientation_rad(dir); bestMatchesPoses[i].set_orientation_deg(dir * 180.0f / CV_PI); } - - //TODO move this to algorithm because this does not really take user manipulation into consideration - //TODO include difference between estimated and current - //simple smoothing out big angle jumps - float lastConfidentAngle = _mapLastConfidentAngle.at(i); //this is mot really working if we jump some frmae back/fwd - double dir = bestMatchesPoses[i].orientation_rad(); - if(!std::isnan(lastConfidentAngle)){ - const float deviationFromLast = CvHelper::angleDifference(lastConfidentAngle, dir); - if (std::abs(deviationFromLast) > CV_PI * 0.2 ){ // 36° - dir += deviationFromLast * 0.5; //reduce big jumps - } - else{ - dir += deviationFromLast * 0.1;//smooth out small changes - } - while (dir > 2 * CV_PI) dir -= 2 * CV_PI; - while (dir < -2 * CV_PI) dir += 2 * CV_PI; - bestMatchesPoses[i].set_orientation_rad(dir); + // TODO move this to algorithm because this does not really take user + // manipulation into consideration + // TODO include difference between estimated and current + // simple smoothing out big angle jumps + float lastConfidentAngle = _mapLastConfidentAngle.at( + i); // this is mot really working if we jump some frmae back/fwd + double dir = bestMatchesPoses[i].orientation_rad(); + if (!std::isnan(lastConfidentAngle)) { + const float deviationFromLast = CvHelper::angleDifference( + lastConfidentAngle, + dir); + if (std::abs(deviationFromLast) > CV_PI * 0.2) { // 36° + dir += deviationFromLast * 0.5; // reduce big jumps + } else { + dir += deviationFromLast * 0.1; // smooth out small changes + } + while (dir > 2 * CV_PI) + dir -= 2 * CV_PI; + while (dir < -2 * CV_PI) + dir += 2 * CV_PI; + bestMatchesPoses[i].set_orientation_rad(dir); bestMatchesPoses[i].set_orientation_deg(dir * 180.0f / CV_PI); - } - _mapLastConfidentAngle[i] = dir; - } - return std::tuple<std::vector<FishPose>, std::vector<float>>(bestMatchesPoses,bestMatchesProps); + } + _mapLastConfidentAngle[i] = dir; + } + return std::tuple<std::vector<FishPose>, std::vector<float>>( + bestMatchesPoses, + bestMatchesProps); } -bool NN2dMapper::correctAngle(int trackid, FishPose &pose) +bool NN2dMapper::correctAngle(int trackid, FishPose& pose) { - // the current angle is a decent estimation of the direction; however, it might point into the wrong hemisphere - const float poseOrientation = pose.orientation_rad(); - - // start with the pose orientation for our estimate - float proposedAngle = poseOrientation; - - // we have more historical data to correct the new angle to at least be more plausible - float confidence = 0.0f; - const float historyAngle = estimateOrientationRad(trackid, &confidence); - //const float lastConfidentAngle = fish.getLastConfidentOrientationRad(); - float lastConfidentAngle = _mapLastConfidentAngle.at(trackid); //TODO Hauke check if this is an ok thing to do... - - // the current history orientation has a stronger meaning and is preferred - const float comparisonOrientation = std::isnan(historyAngle) ? lastConfidentAngle : historyAngle; - // can't correct the angle? - if (std::isnan(comparisonOrientation)) return false; - - // panic mode - what if nothing was measured? - if (std::isnan(poseOrientation)) - { - pose.set_orientation_rad(comparisonOrientation); - pose.set_orientation_deg(comparisonOrientation * 180.0f / CV_PI); - return false; - } - - const float angleDifference = CvHelper::angleDifference(proposedAngle, comparisonOrientation); - - // if the angles do not lie on the same hemisphere, mirror the proposed angle - if (!std::isnan(angleDifference) && std::abs(angleDifference) > 0.5f * CV_PI) - { - proposedAngle += CV_PI; - } - - // the angle is corrected into the correct hemisphere now; - // now smooth the angle to reduce the impact of outliers or directly remove a zero-measurement. - - if (std::isnan(lastConfidentAngle)) // nothing to smooth? Then simply assume the movement-angle to be a good first estimate - proposedAngle = historyAngle; - else - { - // smooth the change in the angle iff the new angle deviates too much from the last one - const float deviationFromLast = CvHelper::angleDifference(lastConfidentAngle, proposedAngle); - assert(!std::isnan(deviationFromLast)); - - if (std::abs(deviationFromLast) > 0.2f * CV_PI) - { - if (poseOrientation == 0.0f) // deviation AND zero-angle? Most likely not a decent estimation. - proposedAngle = lastConfidentAngle; - else // smooth outliers by a fixed margin - proposedAngle = lastConfidentAngle - 0.1f * deviationFromLast; - } - } - // angle should be between 0� and 360� - if (proposedAngle > 2.0f * CV_PI) proposedAngle -= 2.0f * CV_PI; - else if (proposedAngle < 0.0f) proposedAngle += 2.0f * CV_PI; - assert(!std::isnan(proposedAngle)); - - pose.set_orientation_rad(proposedAngle); - pose.set_orientation_deg(proposedAngle * 180.0f / CV_PI); - - // did we have ANY confident correction? - if (!std::isnan(lastConfidentAngle)) // if we simply adjusted the last position, assume to be confident - return true; - // otherwise, we need to intialize the confident angle. - // do that when we really are "confident" for the first time.. - const float differenceToHistoryAngle = std::abs(CvHelper::angleDifference(proposedAngle, historyAngle)); - assert(!std::isnan(differenceToHistoryAngle)); - if (differenceToHistoryAngle < 0.25f * CV_PI) - return true; - // neither updating nor a good initialization? - return false; + // the current angle is a decent estimation of the direction; however, it + // might point into the wrong hemisphere + const float poseOrientation = pose.orientation_rad(); + + // start with the pose orientation for our estimate + float proposedAngle = poseOrientation; + + // we have more historical data to correct the new angle to at least be + // more plausible + float confidence = 0.0f; + const float historyAngle = estimateOrientationRad(trackid, &confidence); + // const float lastConfidentAngle = fish.getLastConfidentOrientationRad(); + float lastConfidentAngle = _mapLastConfidentAngle.at( + trackid); // TODO Hauke check if this is an ok thing to do... + + // the current history orientation has a stronger meaning and is preferred + const float comparisonOrientation = std::isnan(historyAngle) + ? lastConfidentAngle + : historyAngle; + // can't correct the angle? + if (std::isnan(comparisonOrientation)) + return false; + + // panic mode - what if nothing was measured? + if (std::isnan(poseOrientation)) { + pose.set_orientation_rad(comparisonOrientation); + pose.set_orientation_deg(comparisonOrientation * 180.0f / CV_PI); + return false; + } + + const float angleDifference = CvHelper::angleDifference( + proposedAngle, + comparisonOrientation); + + // if the angles do not lie on the same hemisphere, mirror the proposed + // angle + if (!std::isnan(angleDifference) && + std::abs(angleDifference) > 0.5f * CV_PI) { + proposedAngle += CV_PI; + } + + // the angle is corrected into the correct hemisphere now; + // now smooth the angle to reduce the impact of outliers or directly remove + // a zero-measurement. + + if (std::isnan( + lastConfidentAngle)) // nothing to smooth? Then simply assume the + // movement-angle to be a good first estimate + proposedAngle = historyAngle; + else { + // smooth the change in the angle iff the new angle deviates too much + // from the last one + const float deviationFromLast = CvHelper::angleDifference( + lastConfidentAngle, + proposedAngle); + assert(!std::isnan(deviationFromLast)); + + if (std::abs(deviationFromLast) > 0.2f * CV_PI) { + if (poseOrientation == 0.0f) // deviation AND zero-angle? Most + // likely not a decent estimation. + proposedAngle = lastConfidentAngle; + else // smooth outliers by a fixed margin + proposedAngle = lastConfidentAngle - 0.1f * deviationFromLast; + } + } + // angle should be between 0� and 360� + if (proposedAngle > 2.0f * CV_PI) + proposedAngle -= 2.0f * CV_PI; + else if (proposedAngle < 0.0f) + proposedAngle += 2.0f * CV_PI; + assert(!std::isnan(proposedAngle)); + + pose.set_orientation_rad(proposedAngle); + pose.set_orientation_deg(proposedAngle * 180.0f / CV_PI); + + // did we have ANY confident correction? + if (!std::isnan(lastConfidentAngle)) // if we simply adjusted the last + // position, assume to be confident + return true; + // otherwise, we need to intialize the confident angle. + // do that when we really are "confident" for the first time.. + const float differenceToHistoryAngle = std::abs( + CvHelper::angleDifference(proposedAngle, historyAngle)); + assert(!std::isnan(differenceToHistoryAngle)); + if (differenceToHistoryAngle < 0.25f * CV_PI) + return true; + // neither updating nor a good initialization? + return false; } -BST::TrackedTrajectory* getChildOfType(BST::TrackedTrajectory* tree, int tid) { - int cid = 0; - for (int i = 0; i < tree->size(); i++) { - BST::TrackedTrajectory* t = dynamic_cast<BST::TrackedTrajectory*>(tree->getChild(i)); - if (t && cid==tid && t->getValid()) { - return t; - }else if (t && t->getValid()) - cid++; - } - return 0; +BST::TrackedTrajectory* getChildOfType(BST::TrackedTrajectory* tree, int tid) +{ + int cid = 0; + for (int i = 0; i < tree->size(); i++) { + BST::TrackedTrajectory* t = dynamic_cast<BST::TrackedTrajectory*>( + tree->getChild(i)); + if (t && cid == tid && t->getValid()) { + return t; + } else if (t && t->getValid()) + cid++; + } + return 0; } -float NN2dMapper::estimateOrientationRad(int trackid, float *confidence) +float NN2dMapper::estimateOrientationRad(int trackid, float* confidence) { - //Get corresponding trajectory - BST::TrackedTrajectory* t = getChildOfType((BST::TrackedTrajectory*)_tree, trackid); - //return 0; - - // can't give estimate if not enough poses available - if (t->size() < 3) return std::numeric_limits<float>::quiet_NaN(); - - //std::deque<FishPose>::const_reverse_iterator iter = _histComponents.rbegin(); - int start = std::max(t->size()-20, 0); - BST::TrackedElement* e = (BST::TrackedElement*)t->getChild(start); - if (!e) - return std::numeric_limits<float>::quiet_NaN(); - cv::Point2f nextPoint = e->getFishPose().position_cm(); - cv::Point2f positionDerivative(0.0f, 0.0f); - - // weights the last poses with falloff^k * pose[end - k] until falloff^k < falloffMargin - int posesUsed = 0; - float currentWeight = 1.0f; - float weightSum = 0.0f; - const float falloff = 0.9f; - const float falloffMargin = 0.4f; - - for (int i=start+1; i<t->size(); i++) - { - BST::TrackedElement* ecur = (BST::TrackedElement*)t->getChild(i); - if (!ecur) - return std::numeric_limits<float>::quiet_NaN(); - cv::Point2f currentPoint = ecur->getFishPose().position_cm(); - const cv::Point2f oneStepDerivative = nextPoint - currentPoint; - - positionDerivative += currentWeight * oneStepDerivative; - weightSum += currentWeight; - - currentWeight *= falloff; - if (currentWeight < falloffMargin) break; - - nextPoint = currentPoint; - ++posesUsed; - } - // calculate average (weighted) movement of the fish - if (weightSum != 0.0f) - { - positionDerivative.x /= weightSum; - positionDerivative.y /= weightSum; - } - // use the euclidian distance in cm - const float distance = std::sqrt(std::pow(positionDerivative.x, 2.0f) + std::pow(positionDerivative.y, 2.0f)); - // Calculate cm/s. - const float distanceNormalized = 1000.0f * distance / 33.3; // TODO Hauke static_cast<float>(FishTrackerThread::instance()->getRealTimePerFrameMs()) - const float confidenceDistanceMinCm = 2.0f; - const float confidenceDistanceMaxCm = 6.0f; - // if we have either nearly no data or are very unsure (left movement offsets right movement f.e.), just return nothing - if (distanceNormalized < confidenceDistanceMinCm) - return std::numeric_limits<float>::quiet_NaN(); - *confidence = std::min(distanceNormalized / confidenceDistanceMaxCm, 1.0f); - - // negative y coordinate to offset open cv coordinate system - return std::atan2(-positionDerivative.y, positionDerivative.x); + // Get corresponding trajectory + BST::TrackedTrajectory* t = getChildOfType((BST::TrackedTrajectory*) _tree, + trackid); + // return 0; + + // can't give estimate if not enough poses available + if (t->size() < 3) + return std::numeric_limits<float>::quiet_NaN(); + + // std::deque<FishPose>::const_reverse_iterator iter = + // _histComponents.rbegin(); + int start = std::max(t->size() - 20, 0); + BST::TrackedElement* e = (BST::TrackedElement*) t->getChild(start); + if (!e) + return std::numeric_limits<float>::quiet_NaN(); + cv::Point2f nextPoint = e->getFishPose().position_cm(); + cv::Point2f positionDerivative(0.0f, 0.0f); + + // weights the last poses with falloff^k * pose[end - k] until falloff^k < + // falloffMargin + int posesUsed = 0; + float currentWeight = 1.0f; + float weightSum = 0.0f; + const float falloff = 0.9f; + const float falloffMargin = 0.4f; + + for (int i = start + 1; i < t->size(); i++) { + BST::TrackedElement* ecur = (BST::TrackedElement*) t->getChild(i); + if (!ecur) + return std::numeric_limits<float>::quiet_NaN(); + cv::Point2f currentPoint = ecur->getFishPose().position_cm(); + const cv::Point2f oneStepDerivative = nextPoint - currentPoint; + + positionDerivative += currentWeight * oneStepDerivative; + weightSum += currentWeight; + + currentWeight *= falloff; + if (currentWeight < falloffMargin) + break; + + nextPoint = currentPoint; + ++posesUsed; + } + // calculate average (weighted) movement of the fish + if (weightSum != 0.0f) { + positionDerivative.x /= weightSum; + positionDerivative.y /= weightSum; + } + // use the euclidian distance in cm + const float distance = std::sqrt(std::pow(positionDerivative.x, 2.0f) + + std::pow(positionDerivative.y, 2.0f)); + // Calculate cm/s. + const float distanceNormalized = + 1000.0f * distance / + 33.3; // TODO Hauke + // static_cast<float>(FishTrackerThread::instance()->getRealTimePerFrameMs()) + const float confidenceDistanceMinCm = 2.0f; + const float confidenceDistanceMaxCm = 6.0f; + // if we have either nearly no data or are very unsure (left movement + // offsets right movement f.e.), just return nothing + if (distanceNormalized < confidenceDistanceMinCm) + return std::numeric_limits<float>::quiet_NaN(); + *confidence = std::min(distanceNormalized / confidenceDistanceMaxCm, 1.0f); + + // negative y coordinate to offset open cv coordinate system + return std::atan2(-positionDerivative.y, positionDerivative.x); } -std::vector<FishPose> NN2dMapper::convertBlobPosesToFishPoses(std::vector<BlobPose> blobPoses) +std::vector<FishPose> NN2dMapper::convertBlobPosesToFishPoses( + std::vector<BlobPose> blobPoses) { - std::vector<FishPose> fishPoses; - fishPoses.reserve(blobPoses.size()); - - for (BlobPose & blobPose : blobPoses) - { - fishPoses.push_back( - FishPose( - blobPose.posCm(), - blobPose.posPx(), - CvHelper::degToRad(blobPose.angleDegree()), - blobPose.angleDegree(), - blobPose.width(), - blobPose.height() - ) - ); - } - - return fishPoses; + std::vector<FishPose> fishPoses; + fishPoses.reserve(blobPoses.size()); + + for (BlobPose& blobPose : blobPoses) { + fishPoses.push_back( + FishPose(blobPose.posCm(), + blobPose.posPx(), + CvHelper::degToRad(blobPose.angleDegree()), + blobPose.angleDegree(), + blobPose.width(), + blobPose.height())); + } + + return fishPoses; } diff --git a/Src/Model/TrackingAlgorithm/NN2dMapper.h b/Src/Model/TrackingAlgorithm/NN2dMapper.h index 9851c6338fbe53ed6fcb629929f09d1e5e6b1705..5bb778604cb5269ac27cb04cce5d545482398c15 100644 --- a/Src/Model/TrackingAlgorithm/NN2dMapper.h +++ b/Src/Model/TrackingAlgorithm/NN2dMapper.h @@ -13,23 +13,24 @@ class NN2dMapper { public: + /** + * The contructor with parameters. + */ + NN2dMapper(BST::TrackedTrajectory* tree); - /** - * The contructor with parameters. - */ - NN2dMapper(BST::TrackedTrajectory *tree); - - ~NN2dMapper(void) {}; - - std::tuple<std::vector<FishPose>, std::vector<float>> getNewPoses(BST::TrackedTrajectory* traj, uint frameid, std::vector<BlobPose> blobPoses); - std::vector<FishPose> convertBlobPosesToFishPoses(std::vector<BlobPose> blobPoses); - float estimateOrientationRad(int trackid, float *confidence); - bool correctAngle(int trackid, FishPose &pose); - - std::map<int, float> _mapLastConfidentAngle; - BST::TrackedTrajectory *_tree; + ~NN2dMapper(void){}; -protected: + std::tuple<std::vector<FishPose>, std::vector<float>> getNewPoses( + BST::TrackedTrajectory* traj, + uint frameid, + std::vector<BlobPose> blobPoses); + std::vector<FishPose> convertBlobPosesToFishPoses( + std::vector<BlobPose> blobPoses); + float estimateOrientationRad(int trackid, float* confidence); + bool correctAngle(int trackid, FishPose& pose); -}; + std::map<int, float> _mapLastConfidentAngle; + BST::TrackedTrajectory* _tree; +protected: +}; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp index c2a0cbcd0d13cc74d321780d90ad8cbdc8431e2e..6865980eafff8aba27f5f875bfa0049a89821e61 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp @@ -4,159 +4,152 @@ CBlobContour::CBlobContour() { - m_startPoint.x = 0; - m_startPoint.y = 0; - m_area = -1; - m_perimeter = -1; - m_contourPoints = NULL; - m_moments.m00 = -1; - m_contour = NULL; - m_parentStorage = NULL; + m_startPoint.x = 0; + m_startPoint.y = 0; + m_area = -1; + m_perimeter = -1; + m_contourPoints = NULL; + m_moments.m00 = -1; + m_contour = NULL; + m_parentStorage = NULL; } -CBlobContour::CBlobContour(cv::Point startPoint, CvMemStorage *storage ) +CBlobContour::CBlobContour(cv::Point startPoint, CvMemStorage* storage) { - m_startPoint.x = startPoint.x; - m_startPoint.y = startPoint.y; - m_area = -1; - m_perimeter = -1; - m_moments.m00 = -1; - - m_parentStorage = storage; - - m_contourPoints = NULL; - - // contour sequence: must be compatible with opencv functions - m_contour = cvCreateSeq( CV_SEQ_ELTYPE_CODE | CV_SEQ_KIND_CURVE | CV_SEQ_FLAG_CLOSED, - sizeof(CvContour), - sizeof(t_chainCode),m_parentStorage); - + m_startPoint.x = startPoint.x; + m_startPoint.y = startPoint.y; + m_area = -1; + m_perimeter = -1; + m_moments.m00 = -1; + + m_parentStorage = storage; + + m_contourPoints = NULL; + + // contour sequence: must be compatible with opencv functions + m_contour = cvCreateSeq(CV_SEQ_ELTYPE_CODE | CV_SEQ_KIND_CURVE | + CV_SEQ_FLAG_CLOSED, + sizeof(CvContour), + sizeof(t_chainCode), + m_parentStorage); } - //! Copy constructor -CBlobContour::CBlobContour( CBlobContour *source ) +CBlobContour::CBlobContour(CBlobContour* source) { - if (source != NULL ) - { - *this = *source; - } + if (source != NULL) { + *this = *source; + } } CBlobContour::~CBlobContour() { - // let parent blob deallocate all contour and contour point memory - m_contour = NULL; - m_contourPoints = NULL; + // let parent blob deallocate all contour and contour point memory + m_contour = NULL; + m_contourPoints = NULL; } - //! Copy operator -CBlobContour& CBlobContour::operator=( const CBlobContour &source ) +CBlobContour& CBlobContour::operator=(const CBlobContour& source) { - if( this != &source ) - { - m_startPoint = source.m_startPoint; - - m_parentStorage = source.m_parentStorage; - - if (m_contour) - { - cvClearSeq( m_contour ); - } - - if (source.m_contour) - { - m_contour = cvCloneSeq( source.m_contour, m_parentStorage); - } - - if( source.m_contourPoints ) - { - if( m_contourPoints ) - cvClearSeq( m_contourPoints ); - m_contourPoints = cvCloneSeq( source.m_contourPoints, m_parentStorage); - } - - m_area = source.m_area; - m_perimeter = source.m_area; - m_moments = source.m_moments; - } - return *this; + if (this != &source) { + m_startPoint = source.m_startPoint; + + m_parentStorage = source.m_parentStorage; + + if (m_contour) { + cvClearSeq(m_contour); + } + + if (source.m_contour) { + m_contour = cvCloneSeq(source.m_contour, m_parentStorage); + } + + if (source.m_contourPoints) { + if (m_contourPoints) + cvClearSeq(m_contourPoints); + m_contourPoints = cvCloneSeq(source.m_contourPoints, + m_parentStorage); + } + + m_area = source.m_area; + m_perimeter = source.m_area; + m_moments = source.m_moments; + } + return *this; } - /** - FUNCI�: AddChainCode - FUNCIONALITAT: Add chain code to contour - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ void CBlobContour::AddChainCode(t_chainCode chaincode) { - cvSeqPush(m_contour, &chaincode); + cvSeqPush(m_contour, &chaincode); } //! Clears chain code contour and points void CBlobContour::ResetChainCode() { - if( m_contour ) - { - cvClearSeq( m_contour ); - m_contour = NULL; - } - if( m_contourPoints ) - { - cvClearSeq( m_contourPoints ); - m_contourPoints = NULL; - } + if (m_contour) { + cvClearSeq(m_contour); + m_contour = NULL; + } + if (m_contourPoints) { + cvClearSeq(m_contourPoints); + m_contourPoints = NULL; + } } /** - FUNCI�: GetPerimeter -- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and horizontal and vertical codes 1 +- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and +horizontal and vertical codes 1 - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: Algorithm derived from "Methods to estimate area and perimeters of blob-like objects: A comparison", L.Yang +- NOTA: Algorithm derived from "Methods to estimate area and perimeters of +blob-like objects: A comparison", L.Yang */ double CBlobContour::GetPerimeter() { - // is calculated? - if (m_perimeter != -1) - { - return m_perimeter; - } + // is calculated? + if (m_perimeter != -1) { + return m_perimeter; + } - if( IsEmpty() ) - return 0; + if (IsEmpty()) + return 0; - m_perimeter = cvContourPerimeter( GetContourPoints() ); + m_perimeter = cvContourPerimeter(GetContourPoints()); - return m_perimeter; + return m_perimeter; } /** - FUNCI�: GetArea - FUNCIONALITAT: Computes area from chain code - PAR�METRES: - - + - - RESULTAT: - - May give negative areas for clock wise contours + - May give negative areas for clock wise contours - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. @@ -164,97 +157,93 @@ double CBlobContour::GetPerimeter() */ double CBlobContour::GetArea() { - // is calculated? - if (m_area != -1) - { - return m_area; - } - - if( IsEmpty() ) - return 0; - - m_area = fabs( cvContourArea( GetContourPoints() )); - - return m_area; + // is calculated? + if (m_area != -1) { + return m_area; + } + + if (IsEmpty()) + return 0; + + m_area = fabs(cvContourArea(GetContourPoints())); + + return m_area; } //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) double CBlobContour::GetMoment(int p, int q) { - // is a valid moment? - if ( p < 0 || q < 0 || p > MAX_MOMENTS_ORDER || q > MAX_MOMENTS_ORDER ) - { - return -1; - } - - if( IsEmpty() ) - return 0; - - // it is calculated? - if( m_moments.m00 == -1) - { - cvMoments( GetContourPoints(), &m_moments ); - } - - return cvGetSpatialMoment( &m_moments, p, q ); - - + // is a valid moment? + if (p < 0 || q < 0 || p > MAX_MOMENTS_ORDER || q > MAX_MOMENTS_ORDER) { + return -1; + } + + if (IsEmpty()) + return 0; + + // it is calculated? + if (m_moments.m00 == -1) { + cvMoments(GetContourPoints(), &m_moments); + } + + return cvGetSpatialMoment(&m_moments, p, q); } //! Calculate contour points from crack codes t_PointList CBlobContour::GetContourPoints() { - // it is calculated? - if( m_contourPoints != NULL ) - return m_contourPoints; - - if ( m_contour == NULL || m_contour->total <= 0 ) - { - return NULL; - } - - CvSeq *tmpPoints; - CvSeqReader reader; - CvSeqWriter writer; - cv::Point actualPoint; - CvRect boundingBox; - - // if aproximation is different than simple extern perimeter will not work - tmpPoints = cvApproxChains( m_contour, m_parentStorage, CV_CHAIN_APPROX_NONE); - - - // apply an offset to contour points to recover real coordinates - - cvStartReadSeq( tmpPoints, &reader); - - m_contourPoints = cvCreateSeq( tmpPoints->flags, tmpPoints->header_size, tmpPoints->elem_size, m_parentStorage ); - cvStartAppendToSeq(m_contourPoints, &writer ); - - // also calculate bounding box of the contour to allow cvPointPolygonTest - // work correctly on the generated polygon - boundingBox.x = boundingBox.y = 10000; - boundingBox.width = boundingBox.height = 0; - - for( int i=0; i< tmpPoints->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - actualPoint.x += m_startPoint.x; - actualPoint.y += m_startPoint.y; - - boundingBox.x = MIN( boundingBox.x, actualPoint.x ); - boundingBox.y = MIN( boundingBox.y, actualPoint.y ); - boundingBox.width = MAX( boundingBox.width, actualPoint.x ); - boundingBox.height = MAX( boundingBox.height, actualPoint.y ); - - CV_WRITE_SEQ_ELEM( actualPoint, writer ); - } - cvEndWriteSeq( &writer ); - cvClearSeq( tmpPoints ); - - // assign calculated bounding box - ((CvContour*)m_contourPoints)->rect = boundingBox; - - - return m_contourPoints; + // it is calculated? + if (m_contourPoints != NULL) + return m_contourPoints; + + if (m_contour == NULL || m_contour->total <= 0) { + return NULL; + } + + CvSeq* tmpPoints; + CvSeqReader reader; + CvSeqWriter writer; + cv::Point actualPoint; + CvRect boundingBox; + + // if aproximation is different than simple extern perimeter will not work + tmpPoints = cvApproxChains(m_contour, + m_parentStorage, + CV_CHAIN_APPROX_NONE); + + // apply an offset to contour points to recover real coordinates + + cvStartReadSeq(tmpPoints, &reader); + + m_contourPoints = cvCreateSeq(tmpPoints->flags, + tmpPoints->header_size, + tmpPoints->elem_size, + m_parentStorage); + cvStartAppendToSeq(m_contourPoints, &writer); + + // also calculate bounding box of the contour to allow cvPointPolygonTest + // work correctly on the generated polygon + boundingBox.x = boundingBox.y = 10000; + boundingBox.width = boundingBox.height = 0; + + for (int i = 0; i < tmpPoints->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + actualPoint.x += m_startPoint.x; + actualPoint.y += m_startPoint.y; + + boundingBox.x = MIN(boundingBox.x, actualPoint.x); + boundingBox.y = MIN(boundingBox.y, actualPoint.y); + boundingBox.width = MAX(boundingBox.width, actualPoint.x); + boundingBox.height = MAX(boundingBox.height, actualPoint.y); + + CV_WRITE_SEQ_ELEM(actualPoint, writer); + } + cvEndWriteSeq(&writer); + cvClearSeq(tmpPoints); + + // assign calculated bounding box + ((CvContour*) m_contourPoints)->rect = boundingBox; + + return m_contourPoints; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h index 83d2eb97dd327b2e46230c752b371243e55ba464..982349b8dae7ddc8f63310f4c6fbbe9c83923f13 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h @@ -12,86 +12,77 @@ typedef CvSeq* t_chainCodeList; //! Type of list of points typedef CvSeq* t_PointList; - //! Max order of calculated moments -#define MAX_MOMENTS_ORDER 3 - +#define MAX_MOMENTS_ORDER 3 //! Blob contour class (in crack code) class CBlobContour { - friend class CBlob; - friend class CBlobProperties; //AO - + friend class CBlob; + friend class CBlobProperties; // AO + public: - //! Constructors - CBlobContour(); - CBlobContour(cv::Point startPoint, CvMemStorage *storage ); - //! Copy constructor - CBlobContour( CBlobContour *source ); - - ~CBlobContour(); - //! Assigment operator - CBlobContour& operator=( const CBlobContour &source ); - - //! Add chain code to contour - void AddChainCode(t_chainCode code); - - //! Return freeman chain coded contour - t_chainCodeList GetChainCode() - { - return m_contour; - } - - bool IsEmpty() - { - return m_contour == NULL || m_contour->total == 0; - } - - //! Return all contour points - t_chainCodeList GetContourPoints(); - -protected: - - cv::Point GetStartPoint() const - { - return m_startPoint; - } - - //! Clears chain code contour - void ResetChainCode(); - - - - //! Computes area from contour - double GetArea(); - //! Computes perimeter from contour - double GetPerimeter(); - //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) - double GetMoment(int p, int q); - - //! Crack code list - t_chainCodeList m_contour; + //! Constructors + CBlobContour(); + CBlobContour(cv::Point startPoint, CvMemStorage* storage); + //! Copy constructor + CBlobContour(CBlobContour* source); + + ~CBlobContour(); + //! Assigment operator + CBlobContour& operator=(const CBlobContour& source); + + //! Add chain code to contour + void AddChainCode(t_chainCode code); + + //! Return freeman chain coded contour + t_chainCodeList GetChainCode() + { + return m_contour; + } + + bool IsEmpty() + { + return m_contour == NULL || m_contour->total == 0; + } + + //! Return all contour points + t_chainCodeList GetContourPoints(); + +protected: + cv::Point GetStartPoint() const + { + return m_startPoint; + } + + //! Clears chain code contour + void ResetChainCode(); + + //! Computes area from contour + double GetArea(); + //! Computes perimeter from contour + double GetPerimeter(); + //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) + double GetMoment(int p, int q); + + //! Crack code list + t_chainCodeList m_contour; private: - //! Starting point of the contour - cv::Point m_startPoint; - //! All points from the contour - t_PointList m_contourPoints; - - - - //! Computed area from contour - double m_area; - //! Computed perimeter from contour - double m_perimeter; - //! Computed moments from contour - CvMoments m_moments; - - //! Pointer to storage - CvMemStorage *m_parentStorage; + //! Starting point of the contour + cv::Point m_startPoint; + //! All points from the contour + t_PointList m_contourPoints; + + //! Computed area from contour + double m_area; + //! Computed perimeter from contour + double m_perimeter; + //! Computed moments from contour + CvMoments m_moments; + + //! Pointer to storage + CvMemStorage* m_parentStorage; }; -#endif //!BLOBCONTOUR_H_INCLUDED - - +#endif //! BLOBCONTOUR_H_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h index f1a02a7393f9a313c08c5c11e0ca3c932144a174..158d2f7eaca138e33d49cf00d4e0600e55075e7e 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h @@ -1,6 +1,6 @@ /************************************************************************ - BlobLibraryConfiguration.h - + BlobLibraryConfiguration.h + FUNCIONALITAT: Configuraci� del comportament global de la llibreria AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp index cfdae2d425d7461a8804373847415e5365a71581..0c3cb10e78b98e5d6030654138cfbeaf3fddfcb1 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp @@ -15,28 +15,28 @@ - FUNCTIONALITY: Calculates the pq moment of the blob - PARAMETERS: - RESULT: - - returns the pq moment or 0 if the moment it is not implemented + - returns the pq moment or 0 if the moment it is not implemented - RESTRICTIONS: - - Currently, implemented moments up to 3 + - Currently, implemented moments up to 3 - AUTHOR: Ricard Borr�s - CREATION DATE: 20-07-2004. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMoment::operator()(CBlob &blob) +double CBlobGetMoment::operator()(CBlob& blob) { - return blob.Moment(m_p, m_q); + return blob.Moment(m_p, m_q); } /** - FUNCI�: HullPerimeter - FUNCIONALITAT: Calcula la longitud del perimetre convex del blob. - Fa servir la funci� d'OpenCV cvConvexHull2 per a - calcular el perimetre convex. - + Fa servir la funci� d'OpenCV cvConvexHull2 per a + calcular el perimetre convex. + - PAR�METRES: - RESULTAT: - - retorna la longitud del per�metre convex del blob. Si el blob no t� coordenades - associades retorna el per�metre normal del blob. + - retorna la longitud del per�metre convex del blob. Si el blob no t� +coordenades associades retorna el per�metre normal del blob. - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 20-07-2004. @@ -47,45 +47,45 @@ double CBlobGetMoment::operator()(CBlob &blob) - FUNCTIONALITY: Calculates the convex hull perimeter of the blob - PARAMETERS: - RESULT: - - returns the convex hull perimeter of the blob or the perimeter if the - blob edges could not be retrieved + - returns the convex hull perimeter of the blob or the perimeter if the + blob edges could not be retrieved - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetHullPerimeter::operator()(CBlob &blob) +double CBlobGetHullPerimeter::operator()(CBlob& blob) { - CvSeq *convexHull; - double perimeter; + CvSeq* convexHull; + double perimeter; - convexHull = blob.GetConvexHull(); + convexHull = blob.GetConvexHull(); - if( convexHull ) - perimeter = fabs(cvArcLength(convexHull,CV_WHOLE_SEQ,1)); - else - return 0; + if (convexHull) + perimeter = fabs(cvArcLength(convexHull, CV_WHOLE_SEQ, 1)); + else + return 0; - cvClearSeq(convexHull); + cvClearSeq(convexHull); - return perimeter; + return perimeter; } -double CBlobGetHullArea::operator()(CBlob &blob) +double CBlobGetHullArea::operator()(CBlob& blob) { - CvSeq *convexHull; - double area; + CvSeq* convexHull; + double area; - convexHull = blob.GetConvexHull(); + convexHull = blob.GetConvexHull(); - if( convexHull ) - area = fabs(cvContourArea(convexHull)); - else - return 0; + if (convexHull) + area = fabs(cvContourArea(convexHull)); + else + return 0; - cvClearSeq(convexHull); + cvClearSeq(convexHull); - return area; + return area; } /** @@ -98,29 +98,28 @@ double CBlobGetHullArea::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMinXatMinY::operator()(CBlob &blob) +double CBlobGetMinXatMinY::operator()(CBlob& blob) { - double result = LONG_MAX; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - cvStartReadSeq( externContour, &reader); - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.y == blob.MinY()) && (actualPoint.x < result) ) - { - result = actualPoint.x; - } - } - - return result; + double result = LONG_MAX; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.y == blob.MinY()) && (actualPoint.x < result)) { + result = actualPoint.x; + } + } + + return result; } /** @@ -133,29 +132,28 @@ double CBlobGetMinXatMinY::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMinYatMaxX::operator()(CBlob &blob) +double CBlobGetMinYatMaxX::operator()(CBlob& blob) { - double result = LONG_MAX; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - cvStartReadSeq( externContour, &reader); - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.x == blob.MaxX()) && (actualPoint.y < result) ) - { - result = actualPoint.y; - } - } - - return result; + double result = LONG_MAX; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.x == blob.MaxX()) && (actualPoint.y < result)) { + result = actualPoint.y; + } + } + + return result; } /** @@ -168,30 +166,29 @@ double CBlobGetMinYatMaxX::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMaxXatMaxY::operator()(CBlob &blob) +double CBlobGetMaxXatMaxY::operator()(CBlob& blob) { - double result = LONG_MIN; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - - cvStartReadSeq( externContour, &reader); - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.y == blob.MaxY()) && (actualPoint.x > result) ) - { - result = actualPoint.x; - } - } - - return result; + double result = LONG_MIN; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.y == blob.MaxY()) && (actualPoint.x > result)) { + result = actualPoint.x; + } + } + + return result; } /** @@ -204,33 +201,30 @@ double CBlobGetMaxXatMaxY::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMaxYatMinX::operator()(CBlob &blob) +double CBlobGetMaxYatMinX::operator()(CBlob& blob) { - double result = LONG_MIN; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - - cvStartReadSeq( externContour, &reader); - - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.x == blob.MinX()) && (actualPoint.y > result) ) - { - result = actualPoint.y; - } - } - - return result; -} + double result = LONG_MIN; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.x == blob.MinX()) && (actualPoint.y > result)) { + result = actualPoint.y; + } + } + + return result; +} /** - FUNCTION: CBlobGetElongation @@ -238,41 +232,42 @@ double CBlobGetMaxYatMinX::operator()(CBlob &blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - - See below to see how the lenght and the breadth are aproximated + - See below to see how the lenght and the breadth are aproximated - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetElongation::operator()(CBlob &blob) +double CBlobGetElongation::operator()(CBlob& blob) { - double ampladaC,longitudC,amplada,longitud; + double ampladaC, longitudC, amplada, longitud; - double tmp; + double tmp; - tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); + tmp = blob.Perimeter() * blob.Perimeter() - 16 * blob.Area(); - if( tmp > 0.0 ) - ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; - // error intr�nsec en els c�lculs de l'�rea i el per�metre - else - ampladaC = (double) (blob.Perimeter())/4; + if (tmp > 0.0) + ampladaC = (double) (blob.Perimeter() + sqrt(tmp)) / 4; + // error intr�nsec en els c�lculs de l'�rea i el per�metre + else + ampladaC = (double) (blob.Perimeter()) / 4; - if(ampladaC<=0.0) return 0; - longitudC=(double) blob.Area()/ampladaC; + if (ampladaC <= 0.0) + return 0; + longitudC = (double) blob.Area() / ampladaC; - longitud=MAX( longitudC , ampladaC ); - amplada=MIN( longitudC , ampladaC ); + longitud = MAX(longitudC, ampladaC); + amplada = MIN(longitudC, ampladaC); - return (double) longitud/amplada; + return (double) longitud / amplada; } /** - Retorna la compacitat del blob + Retorna la compacitat del blob */ /** - FUNCTION: CBlobGetCompactness -- FUNCTIONALITY: Calculates the compactness of the blob - ( maximum for circle shaped blobs, minimum for the rest) +- FUNCTIONALITY: Calculates the compactness of the blob + ( maximum for circle shaped blobs, minimum for the rest) - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -280,21 +275,21 @@ double CBlobGetElongation::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetCompactness::operator()(CBlob &blob) +double CBlobGetCompactness::operator()(CBlob& blob) { - if( blob.Area() != 0.0 ) - return (double) pow(blob.Perimeter(),2)/(4*CV_PI*blob.Area()); - else - return 0.0; + if (blob.Area() != 0.0) + return (double) pow(blob.Perimeter(), 2) / (4 * CV_PI * blob.Area()); + else + return 0.0; } /** - Retorna la rugositat del blob + Retorna la rugositat del blob */ /** - FUNCTION: CBlobGetRoughness -- FUNCTIONALITY: Calculates the roughness of the blob - ( ratio between perimeter and convex hull perimeter) +- FUNCTIONALITY: Calculates the roughness of the blob + ( ratio between perimeter and convex hull perimeter) - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -302,91 +297,95 @@ double CBlobGetCompactness::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetRoughness::operator()(CBlob &blob) +double CBlobGetRoughness::operator()(CBlob& blob) { - CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter(); - - double hullPerimeter = getHullPerimeter(blob); + CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter(); + + double hullPerimeter = getHullPerimeter(blob); - if( hullPerimeter != 0.0 ) - return blob.Perimeter() / hullPerimeter;//HullPerimeter(); + if (hullPerimeter != 0.0) + return blob.Perimeter() / hullPerimeter; // HullPerimeter(); - return 0.0; + return 0.0; } /** - Retorna la longitud del blob + Retorna la longitud del blob */ /** - FUNCTION: CBlobGetLength -- FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the blob) +- FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the +blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - - The lenght is an aproximation to the real lenght + - The lenght is an aproximation to the real lenght - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetLength::operator()(CBlob &blob) +double CBlobGetLength::operator()(CBlob& blob) { - double ampladaC,longitudC; - double tmp; + double ampladaC, longitudC; + double tmp; - tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); + tmp = blob.Perimeter() * blob.Perimeter() - 16 * blob.Area(); - if( tmp > 0.0 ) - ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; - // error intr�nsec en els c�lculs de l'�rea i el per�metre - else - ampladaC = (double) (blob.Perimeter())/4; + if (tmp > 0.0) + ampladaC = (double) (blob.Perimeter() + sqrt(tmp)) / 4; + // error intr�nsec en els c�lculs de l'�rea i el per�metre + else + ampladaC = (double) (blob.Perimeter()) / 4; - if(ampladaC<=0.0) return 0; - longitudC=(double) blob.Area()/ampladaC; + if (ampladaC <= 0.0) + return 0; + longitudC = (double) blob.Area() / ampladaC; - return MAX( longitudC , ampladaC ); + return MAX(longitudC, ampladaC); } /** - Retorna l'amplada del blob + Retorna l'amplada del blob */ /** - FUNCTION: CBlobGetBreadth -- FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the blob) +- FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the +blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - - The breadth is an aproximation to the real breadth + - The breadth is an aproximation to the real breadth - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetBreadth::operator()(CBlob &blob) +double CBlobGetBreadth::operator()(CBlob& blob) { - double ampladaC,longitudC; - double tmp; + double ampladaC, longitudC; + double tmp; - tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); + tmp = blob.Perimeter() * blob.Perimeter() - 16 * blob.Area(); - if( tmp > 0.0 ) - ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; - // error intr�nsec en els c�lculs de l'�rea i el per�metre - else - ampladaC = (double) (blob.Perimeter())/4; + if (tmp > 0.0) + ampladaC = (double) (blob.Perimeter() + sqrt(tmp)) / 4; + // error intr�nsec en els c�lculs de l'�rea i el per�metre + else + ampladaC = (double) (blob.Perimeter()) / 4; - if(ampladaC<=0.0) return 0; - longitudC = (double) blob.Area()/ampladaC; + if (ampladaC <= 0.0) + return 0; + longitudC = (double) blob.Area() / ampladaC; - return MIN( longitudC , ampladaC ); + return MIN(longitudC, ampladaC); } /** - Calcula la dist�ncia entre un punt i el centre del blob + Calcula la dist�ncia entre un punt i el centre del blob */ /** - FUNCTION: CBlobGetDistanceFromPoint -- FUNCTIONALITY: Calculates the euclidean distance between the blob center and - the point specified in the constructor +- FUNCTIONALITY: Calculates the euclidean distance between the blob center and + the point specified in the constructor - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -394,16 +393,16 @@ double CBlobGetBreadth::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetDistanceFromPoint::operator()(CBlob &blob) +double CBlobGetDistanceFromPoint::operator()(CBlob& blob) { - double xmitjana, ymitjana; - CBlobGetXCenter getXCenter; - CBlobGetYCenter getYCenter; + double xmitjana, ymitjana; + CBlobGetXCenter getXCenter; + CBlobGetYCenter getYCenter; - xmitjana = m_x - getXCenter( blob ); - ymitjana = m_y - getYCenter( blob ); + xmitjana = m_x - getXCenter(blob); + ymitjana = m_y - getYCenter(blob); - return sqrt((xmitjana*xmitjana)+(ymitjana*ymitjana)); + return sqrt((xmitjana * xmitjana) + (ymitjana * ymitjana)); } /** @@ -412,18 +411,20 @@ double CBlobGetDistanceFromPoint::operator()(CBlob &blob) rectangular bounding box of a blob - PARAMETERS: - RESULT: - - returns 1 if it is inside; o if not + - returns 1 if it is inside; o if not - RESTRICTIONS: - AUTHOR: Francesc Pinyol Margalef - CREATION DATE: 16-01-2006. - MODIFICATION: Date. Author. Description. */ -double CBlobGetXYInside::operator()(CBlob &blob) +double CBlobGetXYInside::operator()(CBlob& blob) { - if( blob.GetExternalContour()->GetContourPoints() ) - { - return cvPointPolygonTest( blob.GetExternalContour()->GetContourPoints(), m_p,0) >= 0; - } - - return 0; + if (blob.GetExternalContour()->GetContourPoints()) { + return cvPointPolygonTest( + blob.GetExternalContour()->GetContourPoints(), + m_p, + 0) >= 0; + } + + return 0; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h index fbe233fdb49354da62c97f04a10f6e0140a26b0f..4c8b435344b60c4032c600233dfee6c0ea431b56 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h @@ -4,731 +4,739 @@ #include "blob.h" /************************************************************************** - Definici� de les classes per a fer operacions sobre els blobs + Definici� de les classes per a fer operacions sobre els blobs - Helper classes to perform operations on blobs + Helper classes to perform operations on blobs **************************************************************************/ //! Factor de conversi� de graus a radians -#define DEGREE2RAD (CV_PI / 180.0) - +#define DEGREE2RAD (CV_PI / 180.0) //! Classe d'on derivarem totes les operacions sobre els blobs //! Interface to derive all blob operations class COperadorBlob { public: - virtual ~COperadorBlob(){}; + virtual ~COperadorBlob(){}; - //! Aply operator to blob - virtual double operator()(CBlob &blob) = 0; - //! Get operator name - virtual const char *GetNom() = 0; + //! Aply operator to blob + virtual double operator()(CBlob& blob) = 0; + //! Get operator name + virtual const char* GetNom() = 0; - operator COperadorBlob*() - { - return (COperadorBlob*)this; - } + operator COperadorBlob*() + { + return (COperadorBlob*) this; + } }; typedef COperadorBlob funcio_calculBlob; - //! Classe per calcular l'etiqueta d'un blob //! Class to get ID of a blob class CBlobGetID : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.GetID(); - } - const char *GetNom() - { - return "CBlobGetID"; - } + double operator()(CBlob& blob) + { + return blob.GetID(); + } + const char* GetNom() + { + return "CBlobGetID"; + } }; - //! Classe per calcular l'�rea d'un blob //! Class to get the area of a blob class CBlobGetArea : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.Area(); - } - const char *GetNom() - { - return "CBlobGetArea"; - } + double operator()(CBlob& blob) + { + return blob.Area(); + } + const char* GetNom() + { + return "CBlobGetArea"; + } }; //! Classe per calcular el perimetre d'un blob //! Class to get the perimeter of a blob -class CBlobGetPerimeter: public COperadorBlob +class CBlobGetPerimeter : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.Perimeter(); - } - const char *GetNom() - { - return "CBlobGetPerimeter"; - } + double operator()(CBlob& blob) + { + return blob.Perimeter(); + } + const char* GetNom() + { + return "CBlobGetPerimeter"; + } }; //! Classe que diu si un blob �s extern o no //! Class to get the extern flag of a blob -class CBlobGetExterior: public COperadorBlob -{ -public: - CBlobGetExterior() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExterior(IplImage *mask, bool xBorder = true, bool yBorder = true) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - return blob.Exterior(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExterior"; - } +class CBlobGetExterior : public COperadorBlob +{ +public: + CBlobGetExterior() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExterior(IplImage* mask, bool xBorder = true, bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + return blob.Exterior(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExterior"; + } + private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; //! Classe per calcular la mitjana de nivells de gris d'un blob //! Class to get the mean grey level of a blob -class CBlobGetMean: public COperadorBlob -{ -public: - CBlobGetMean() - { - m_image = NULL; - } - CBlobGetMean( IplImage *image ) - { - m_image = image; - }; - - double operator()(CBlob &blob) - { - return blob.Mean(m_image); - } - const char *GetNom() - { - return "CBlobGetMean"; - } -private: +class CBlobGetMean : public COperadorBlob +{ +public: + CBlobGetMean() + { + m_image = NULL; + } + CBlobGetMean(IplImage* image) + { + m_image = image; + }; + + double operator()(CBlob& blob) + { + return blob.Mean(m_image); + } + const char* GetNom() + { + return "CBlobGetMean"; + } - IplImage *m_image; +private: + IplImage* m_image; }; //! Classe per calcular la desviaci� est�ndard dels nivells de gris d'un blob //! Class to get the standard deviation of the grey level values of a blob -class CBlobGetStdDev: public COperadorBlob -{ -public: - CBlobGetStdDev() - { - m_image = NULL; - } - CBlobGetStdDev( IplImage *image ) - { - m_image = image; - }; - double operator()(CBlob &blob) - { - return blob.StdDev(m_image); - } - const char *GetNom() - { - return "CBlobGetStdDev"; - } -private: - - IplImage *m_image; +class CBlobGetStdDev : public COperadorBlob +{ +public: + CBlobGetStdDev() + { + m_image = NULL; + } + CBlobGetStdDev(IplImage* image) + { + m_image = image; + }; + double operator()(CBlob& blob) + { + return blob.StdDev(m_image); + } + const char* GetNom() + { + return "CBlobGetStdDev"; + } +private: + IplImage* m_image; }; //! Classe per calcular la compacitat d'un blob //! Class to calculate the compactness of a blob -class CBlobGetCompactness: public COperadorBlob +class CBlobGetCompactness : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetCompactness"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetCompactness"; + } }; //! Classe per calcular la longitud d'un blob //! Class to calculate the length of a blob -class CBlobGetLength: public COperadorBlob +class CBlobGetLength : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetLength"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetLength"; + } }; //! Classe per calcular l'amplada d'un blob //! Class to calculate the breadth of a blob -class CBlobGetBreadth: public COperadorBlob +class CBlobGetBreadth : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetBreadth"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetBreadth"; + } }; //! Classe per calcular la difer�ncia en X del blob -class CBlobGetDiffX: public COperadorBlob +class CBlobGetDiffX : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.GetBoundingBox().width; - } - const char *GetNom() - { - return "CBlobGetDiffX"; - } + double operator()(CBlob& blob) + { + return blob.GetBoundingBox().width; + } + const char* GetNom() + { + return "CBlobGetDiffX"; + } }; //! Classe per calcular la difer�ncia en X del blob -class CBlobGetDiffY: public COperadorBlob +class CBlobGetDiffY : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.GetBoundingBox().height; - } - const char *GetNom() - { - return "CBlobGetDiffY"; - } + double operator()(CBlob& blob) + { + return blob.GetBoundingBox().height; + } + const char* GetNom() + { + return "CBlobGetDiffY"; + } }; //! Classe per calcular el moment PQ del blob //! Class to calculate the P,Q moment of a blob -class CBlobGetMoment: public COperadorBlob -{ -public: - //! Constructor est�ndard - //! Standard constructor (gets the 00 moment) - CBlobGetMoment() - { - m_p = m_q = 0; - } - //! Constructor: indiquem el moment p,q a calcular - //! Constructor: gets the PQ moment - CBlobGetMoment( int p, int q ) - { - m_p = p; - m_q = q; - }; - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMoment"; - } +class CBlobGetMoment : public COperadorBlob +{ +public: + //! Constructor est�ndard + //! Standard constructor (gets the 00 moment) + CBlobGetMoment() + { + m_p = m_q = 0; + } + //! Constructor: indiquem el moment p,q a calcular + //! Constructor: gets the PQ moment + CBlobGetMoment(int p, int q) + { + m_p = p; + m_q = q; + }; + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMoment"; + } private: - //! moment que volem calcular - int m_p, m_q; + //! moment que volem calcular + int m_p, m_q; }; //! Classe per calcular el perimetre del poligon convex d'un blob //! Class to calculate the convex hull perimeter of a blob -class CBlobGetHullPerimeter: public COperadorBlob +class CBlobGetHullPerimeter : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetHullPerimeter"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetHullPerimeter"; + } }; //! Classe per calcular l'�rea del poligon convex d'un blob //! Class to calculate the convex hull area of a blob -class CBlobGetHullArea: public COperadorBlob +class CBlobGetHullArea : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetHullArea"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetHullArea"; + } }; //! Classe per calcular la x minima en la y minima //! Class to calculate the minimum x on the minimum y -class CBlobGetMinXatMinY: public COperadorBlob +class CBlobGetMinXatMinY : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMinXatMinY"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMinXatMinY"; + } }; //! Classe per calcular la y minima en la x maxima //! Class to calculate the minimum y on the maximum x -class CBlobGetMinYatMaxX: public COperadorBlob +class CBlobGetMinYatMaxX : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMinYatMaxX"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMinYatMaxX"; + } }; //! Classe per calcular la x maxima en la y maxima //! Class to calculate the maximum x on the maximum y -class CBlobGetMaxXatMaxY: public COperadorBlob +class CBlobGetMaxXatMaxY : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMaxXatMaxY"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMaxXatMaxY"; + } }; //! Classe per calcular la y maxima en la x minima //! Class to calculate the maximum y on the minimum y -class CBlobGetMaxYatMinX: public COperadorBlob +class CBlobGetMaxYatMinX : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMaxYatMinX"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMaxYatMinX"; + } }; //! Classe per a calcular la x m�nima //! Class to get the minimum x -class CBlobGetMinX: public COperadorBlob +class CBlobGetMinX : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinX(); - } - const char *GetNom() - { - return "CBlobGetMinX"; - } + double operator()(CBlob& blob) + { + return blob.MinX(); + } + const char* GetNom() + { + return "CBlobGetMinX"; + } }; //! Classe per a calcular la x m�xima //! Class to get the maximum x -class CBlobGetMaxX: public COperadorBlob +class CBlobGetMaxX : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MaxX(); - } - const char *GetNom() - { - return "CBlobGetMaxX"; - } + double operator()(CBlob& blob) + { + return blob.MaxX(); + } + const char* GetNom() + { + return "CBlobGetMaxX"; + } }; //! Classe per a calcular la y m�nima //! Class to get the minimum y -class CBlobGetMinY: public COperadorBlob +class CBlobGetMinY : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinY(); - } - const char *GetNom() - { - return "CBlobGetMinY"; - } + double operator()(CBlob& blob) + { + return blob.MinY(); + } + const char* GetNom() + { + return "CBlobGetMinY"; + } }; //! Classe per a calcular la y m�xima //! Class to get the maximum y -class CBlobGetMaxY: public COperadorBlob +class CBlobGetMaxY : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MaxY(); - } - const char *GetNom() - { - return "CBlobGetMaxY"; - } + double operator()(CBlob& blob) + { + return blob.MaxY(); + } + const char* GetNom() + { + return "CBlobGetMaxY"; + } }; - //! Classe per calcular l'elongacio d'un blob //! Class to calculate the elongation of the blob -class CBlobGetElongation: public COperadorBlob +class CBlobGetElongation : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetElongation"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetElongation"; + } }; //! Classe per calcular la rugositat d'un blob //! Class to calculate the roughness of the blob -class CBlobGetRoughness: public COperadorBlob +class CBlobGetRoughness : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetRoughness"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetRoughness"; + } }; //! Classe per calcular la dist�ncia entre el centre del blob i un punt donat -//! Class to calculate the euclidean distance between the center of a blob and a given point -class CBlobGetDistanceFromPoint: public COperadorBlob -{ -public: - //! Standard constructor (distance to point 0,0) - CBlobGetDistanceFromPoint() - { - m_x = m_y = 0.0; - } - //! Constructor (distance to point x,y) - CBlobGetDistanceFromPoint( const double x, const double y ) - { - m_x = x; - m_y = y; - } - - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetDistanceFromPoint"; - } +//! Class to calculate the euclidean distance between the center of a blob and +//! a given point +class CBlobGetDistanceFromPoint : public COperadorBlob +{ +public: + //! Standard constructor (distance to point 0,0) + CBlobGetDistanceFromPoint() + { + m_x = m_y = 0.0; + } + //! Constructor (distance to point x,y) + CBlobGetDistanceFromPoint(const double x, const double y) + { + m_x = x; + m_y = y; + } + + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetDistanceFromPoint"; + } private: - // coordenades del punt on volem calcular la dist�ncia - double m_x, m_y; + // coordenades del punt on volem calcular la dist�ncia + double m_x, m_y; }; //! Classe per calcular el nombre de pixels externs d'un blob //! Class to get the number of extern pixels of a blob -class CBlobGetExternPerimeter: public COperadorBlob -{ -public: - CBlobGetExternPerimeter() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExternPerimeter( IplImage *mask, bool xBorder = true, bool yBorder = true ) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExternPerimeter"; - } +class CBlobGetExternPerimeter : public COperadorBlob +{ +public: + CBlobGetExternPerimeter() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExternPerimeter(IplImage* mask, + bool xBorder = true, + bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExternPerimeter"; + } + private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; //! Classe per calcular el ratio entre el perimetre i nombre pixels externs //! valors propers a 0 indiquen que la majoria del blob �s intern //! valors propers a 1 indiquen que la majoria del blob �s extern -//! Class to calculate the ratio between the perimeter and the number of extern pixels -class CBlobGetExternPerimeterRatio: public COperadorBlob -{ -public: - CBlobGetExternPerimeterRatio() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExternPerimeterRatio( IplImage *mask, bool xBorder = true, bool yBorder = true ) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - if( blob.Perimeter() != 0 ) - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / blob.Perimeter(); - else - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExternPerimeterRatio"; - } +//! Class to calculate the ratio between the perimeter and the number of extern +//! pixels +class CBlobGetExternPerimeterRatio : public COperadorBlob +{ +public: + CBlobGetExternPerimeterRatio() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExternPerimeterRatio(IplImage* mask, + bool xBorder = true, + bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + if (blob.Perimeter() != 0) + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / + blob.Perimeter(); + else + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExternPerimeterRatio"; + } + private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; -//! Classe per calcular el ratio entre el perimetre convex i nombre pixels externs -//! valors propers a 0 indiquen que la majoria del blob �s intern +//! Classe per calcular el ratio entre el perimetre convex i nombre pixels +//! externs valors propers a 0 indiquen que la majoria del blob �s intern //! valors propers a 1 indiquen que la majoria del blob �s extern -//! Class to calculate the ratio between the perimeter and the number of extern pixels -class CBlobGetExternHullPerimeterRatio: public COperadorBlob -{ -public: - CBlobGetExternHullPerimeterRatio() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExternHullPerimeterRatio( IplImage *mask, bool xBorder = true, bool yBorder = true ) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - CBlobGetHullPerimeter getHullPerimeter; - double hullPerimeter; - - if( (hullPerimeter = getHullPerimeter( blob ) ) != 0 ) - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / hullPerimeter; - else - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExternHullPerimeterRatio"; - } -private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; +//! Class to calculate the ratio between the perimeter and the number of extern +//! pixels +class CBlobGetExternHullPerimeterRatio : public COperadorBlob +{ +public: + CBlobGetExternHullPerimeterRatio() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExternHullPerimeterRatio(IplImage* mask, + bool xBorder = true, + bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + CBlobGetHullPerimeter getHullPerimeter; + double hullPerimeter; + + if ((hullPerimeter = getHullPerimeter(blob)) != 0) + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / + hullPerimeter; + else + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExternHullPerimeterRatio"; + } +private: + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; //! Classe per calcular el centre en el eix X d'un blob //! Class to calculate the center in the X direction -class CBlobGetXCenter: public COperadorBlob +class CBlobGetXCenter : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinX() + (( blob.MaxX() - blob.MinX() ) / 2.0); - } - const char *GetNom() - { - return "CBlobGetXCenter"; - } + double operator()(CBlob& blob) + { + return blob.MinX() + ((blob.MaxX() - blob.MinX()) / 2.0); + } + const char* GetNom() + { + return "CBlobGetXCenter"; + } }; //! Classe per calcular el centre en el eix Y d'un blob //! Class to calculate the center in the Y direction -class CBlobGetYCenter: public COperadorBlob +class CBlobGetYCenter : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinY() + (( blob.MaxY() - blob.MinY() ) / 2.0); - } - const char *GetNom() - { - return "CBlobGetYCenter"; - } + double operator()(CBlob& blob) + { + return blob.MinY() + ((blob.MaxY() - blob.MinY()) / 2.0); + } + const char* GetNom() + { + return "CBlobGetYCenter"; + } }; //! Classe per calcular la longitud de l'eix major d'un blob -//! Class to calculate the length of the major axis of the ellipse that fits the blob edges -class CBlobGetMajorAxisLength: public COperadorBlob +//! Class to calculate the length of the major axis of the ellipse that fits +//! the blob edges +class CBlobGetMajorAxisLength : public COperadorBlob { public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); + double operator()(CBlob& blob) + { + CvBox2D elipse = blob.GetEllipse(); - return elipse.size.width; - } - const char *GetNom() - { - return "CBlobGetMajorAxisLength"; - } + return elipse.size.width; + } + const char* GetNom() + { + return "CBlobGetMajorAxisLength"; + } }; //! Classe per calcular el ratio entre l'area de la elipse i la de la taca -//! Class -class CBlobGetAreaElipseRatio: public COperadorBlob +//! Class +class CBlobGetAreaElipseRatio : public COperadorBlob { public: - double operator()(CBlob &blob) - { - if( blob.Area()==0.0 ) return 0.0; + double operator()(CBlob& blob) + { + if (blob.Area() == 0.0) + return 0.0; - CvBox2D elipse = blob.GetEllipse(); - double ratioAreaElipseAreaTaca = ( (elipse.size.width/2.0) - * - (elipse.size.height/2.0) - *CV_PI - ) - / - blob.Area(); + CvBox2D elipse = blob.GetEllipse(); + double ratioAreaElipseAreaTaca = ((elipse.size.width / 2.0) * + (elipse.size.height / 2.0) * CV_PI) / + blob.Area(); - return ratioAreaElipseAreaTaca; - } - const char *GetNom() - { - return "CBlobGetAreaElipseRatio"; - } + return ratioAreaElipseAreaTaca; + } + const char* GetNom() + { + return "CBlobGetAreaElipseRatio"; + } }; //! Classe per calcular la longitud de l'eix menor d'un blob -//! Class to calculate the length of the minor axis of the ellipse that fits the blob edges -class CBlobGetMinorAxisLength: public COperadorBlob +//! Class to calculate the length of the minor axis of the ellipse that fits +//! the blob edges +class CBlobGetMinorAxisLength : public COperadorBlob { public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); + double operator()(CBlob& blob) + { + CvBox2D elipse = blob.GetEllipse(); - return elipse.size.height; - } - const char *GetNom() - { - return "CBlobGetMinorAxisLength"; - } + return elipse.size.height; + } + const char* GetNom() + { + return "CBlobGetMinorAxisLength"; + } }; //! Classe per calcular l'orientaci� de l'ellipse del blob en radians -//! Class to calculate the orientation of the ellipse that fits the blob edges in radians -class CBlobGetOrientation: public COperadorBlob -{ -public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); -/* - if( elipse.angle > 180.0 ) - return (( elipse.angle - 180.0 )* DEGREE2RAD); - else - return ( elipse.angle * DEGREE2RAD); -*/ - return elipse.angle; - } - const char *GetNom() - { - return "CBlobGetOrientation"; - } +//! Class to calculate the orientation of the ellipse that fits the blob edges +//! in radians +class CBlobGetOrientation : public COperadorBlob +{ +public: + double operator()(CBlob& blob) + { + CvBox2D elipse = blob.GetEllipse(); + /* + if( elipse.angle > 180.0 ) + return (( elipse.angle - 180.0 )* DEGREE2RAD); + else + return ( elipse.angle * DEGREE2RAD); + */ + return elipse.angle; + } + const char* GetNom() + { + return "CBlobGetOrientation"; + } }; //! Classe per calcular el cosinus de l'orientaci� de l'ellipse del blob -//! Class to calculate the cosinus of the orientation of the ellipse that fits the blob edges -class CBlobGetOrientationCos: public COperadorBlob +//! Class to calculate the cosinus of the orientation of the ellipse that fits +//! the blob edges +class CBlobGetOrientationCos : public COperadorBlob { public: - double operator()(CBlob &blob) - { - CBlobGetOrientation getOrientation; - return fabs( cos( getOrientation(blob)*DEGREE2RAD )); - } - const char *GetNom() - { - return "CBlobGetOrientationCos"; - } + double operator()(CBlob& blob) + { + CBlobGetOrientation getOrientation; + return fabs(cos(getOrientation(blob) * DEGREE2RAD)); + } + const char* GetNom() + { + return "CBlobGetOrientationCos"; + } }; - //! Classe per calcular el ratio entre l'eix major i menor de la el�lipse //! Class to calculate the ratio between both axes of the ellipse -class CBlobGetAxisRatio: public COperadorBlob +class CBlobGetAxisRatio : public COperadorBlob { public: - double operator()(CBlob &blob) - { - double major,minor; - CBlobGetMajorAxisLength getMajor; - CBlobGetMinorAxisLength getMinor; + double operator()(CBlob& blob) + { + double major, minor; + CBlobGetMajorAxisLength getMajor; + CBlobGetMinorAxisLength getMinor; - major = getMajor(blob); - minor = getMinor(blob); + major = getMajor(blob); + minor = getMinor(blob); - if( major != 0 ) - return minor / major; - else - return 0; - } - const char *GetNom() - { - return "CBlobGetAxisRatio"; - } + if (major != 0) + return minor / major; + else + return 0; + } + const char* GetNom() + { + return "CBlobGetAxisRatio"; + } }; - //! Classe per calcular si un punt cau dins del blob //! Class to calculate whether a point is inside a blob -class CBlobGetXYInside: public COperadorBlob -{ -public: - //! Constructor est�ndard - //! Standard constructor - CBlobGetXYInside() - { - m_p.x = 0; - m_p.y = 0; - } - //! Constructor: indiquem el punt - //! Constructor: sets the point - CBlobGetXYInside( CvPoint2D32f p ) - { - m_p = p; - }; - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetXYInside"; - } +class CBlobGetXYInside : public COperadorBlob +{ +public: + //! Constructor est�ndard + //! Standard constructor + CBlobGetXYInside() + { + m_p.x = 0; + m_p.y = 0; + } + //! Constructor: indiquem el punt + //! Constructor: sets the point + CBlobGetXYInside(CvPoint2D32f p) + { + m_p = p; + }; + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetXYInside"; + } private: - //! punt que considerem - //! point to be considered - CvPoint2D32f m_p; + //! punt que considerem + //! point to be considered + CvPoint2D32f m_p; }; -#endif //!BLOB_OPERATORS_H_INCLUDED +#endif //! BLOB_OPERATORS_H_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp index 64b72654f0f77cd518afabd65976ee77ba87eeea..dd1e49570dd37f19d1ff0aef016d5b96385c96b9 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp @@ -1,31 +1,33 @@ #include "BlobProperties.h" - /** - FUNCI�: GetPerimeter -- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and horizontal and vertical codes 1 +- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and +horizontal and vertical codes 1 - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: Algorithm derived from "Methods to estimate area and perimeters of blob-like objects: A comparison", L.Yang +- NOTA: Algorithm derived from "Methods to estimate area and perimeters of +blob-like objects: A comparison", L.Yang */ #define SQRT2 1.414213562 /** - FUNCI�: GetPerimeter -- FUNCIONALITAT: Get blob area, ie. external contour area minus internal contours area +- FUNCIONALITAT: Get blob area, ie. external contour area minus internal +contours area - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. @@ -33,49 +35,45 @@ double CBlobProperties::GetArea() { - double area; - t_contourList::iterator itContour; + double area; + t_contourList::iterator itContour; + + area = m_externalContour.GetArea(); - area = m_externalContour.GetArea(); + itContour = m_internalContours.begin(); - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - area += (*itContour).GetArea(); - itContour++; - } - return area; + while (itContour != m_internalContours.end()) { + area += (*itContour).GetArea(); + itContour++; + } + return area; } /** - FUNCI�: GetPerimeter - FUNCIONALITAT: Get blob perimeter, ie. sum of the lenght of all the contours - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ double CBlobProperties::GetPerimeter() { - double perimeter; - t_contourList::iterator itContour; + double perimeter; + t_contourList::iterator itContour; - perimeter = m_externalContour.GetPerimeter(); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - perimeter += (*itContour).GetPerimeter(); - itContour++; - } - return perimeter; -} + perimeter = m_externalContour.GetPerimeter(); + itContour = m_internalContours.begin(); + while (itContour != m_internalContours.end()) { + perimeter += (*itContour).GetPerimeter(); + itContour++; + } + return perimeter; +} diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h index 97d028a14f87af36b3a04813dcb4ba5518f0f165..46f3e1e2397f51c03445a3fbff592dce0d242f83 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h @@ -1,67 +1,59 @@ //! Disable warnings referred to 255 character truncation for the std:map -#pragma warning( disable : 4786 ) +#pragma warning(disable : 4786) #ifndef BLOB_PROPERTIES_H_INCLUDED -#define BLOB_PROPERTIES_H_INCLUDED + #define BLOB_PROPERTIES_H_INCLUDED -#include <list> + #include <list> -#include <opencv2/opencv.hpp> - -#include "BlobLibraryConfiguration.h" -#include "BlobContour.h" + #include <opencv2/opencv.hpp> + #include "BlobLibraryConfiguration.h" + #include "BlobContour.h" //! Type of labelled images typedef unsigned int t_labelType; -//! Max order of calculated moments -#define MAX_MOMENTS_ORDER 3 - + //! Max order of calculated moments + #define MAX_MOMENTS_ORDER 3 //! Blob class class CBlobProperties { - typedef std::list<CBlobContour> t_contourList; + typedef std::list<CBlobContour> t_contourList; public: + CBlobProperties(); + virtual ~CBlobProperties(); - CBlobProperties(); - virtual ~CBlobProperties(); - - //! Get blob area - double GetArea(); + //! Get blob area + double GetArea(); - //! Get blob perimeter - double GetPerimeter(); + //! Get blob perimeter + double GetPerimeter(); - //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) - double GetMoment(int p, int q); - + //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) + double GetMoment(int p, int q); - ////////////////////////////////////////////////////////////////////////// - // Blob contours - ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // Blob contours + ////////////////////////////////////////////////////////////////////////// - - //! Contour storage memory - CvMemStorage *m_storage; - //! External contour of the blob (crack codes) - CBlobContour m_externalContour; - //! Internal contours (crack codes) - t_contourList m_internalContours; + //! Contour storage memory + CvMemStorage* m_storage; + //! External contour of the blob (crack codes) + CBlobContour m_externalContour; + //! Internal contours (crack codes) + t_contourList m_internalContours; private: - - //! Computed area from blob - double m_area; - //! Computed perimeter from blob - double m_perimeter; - // Computed moment from the blob - double m_moment[MAX_MOMENTS_ORDER*MAX_MOMENTS_ORDER]; - + //! Computed area from blob + double m_area; + //! Computed perimeter from blob + double m_perimeter; + // Computed moment from the blob + double m_moment[MAX_MOMENTS_ORDER * MAX_MOMENTS_ORDER]; }; -#endif //!BLOB_PROPERTIES_H_INCLUDED - +#endif //! BLOB_PROPERTIES_H_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp index 7e84c531f5b62877f5b34fb6848e3102c73fd2b5..02b23e9da65db7a809d683e2374d7b04686f9f8b 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp @@ -1,10 +1,10 @@ /************************************************************************ - BlobResult.cpp - + BlobResult.cpp + FUNCIONALITAT: Implementaci� de la classe CBlobResult AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): - + **************************************************************************/ #include <limits.h> @@ -14,10 +14,9 @@ MODIFICACIONS (Modificaci�, Autor, Data): #include "BlobResult.h" /************************************************************************** - Constructors / Destructors + Constructors / Destructors **************************************************************************/ - /** - FUNCI�: CBlobResult - FUNCIONALITAT: Constructor estandard. @@ -34,7 +33,7 @@ MODIFICACIONS (Modificaci�, Autor, Data): - FUNCTIONALITY: Standard constructor - PARAMETERS: - RESULT: - - creates an empty set of blobs + - creates an empty set of blobs - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. @@ -42,25 +41,27 @@ MODIFICACIONS (Modificaci�, Autor, Data): */ CBlobResult::CBlobResult() { - m_blobs = Blob_vector(); + m_blobs = Blob_vector(); } /** - FUNCI�: CBlobResult -- FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seq��ncia de blobs - amb els blobs resultants de l'an�lisi de blobs de la imatge. +- FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seq��ncia de +blobs amb els blobs resultants de l'an�lisi de blobs de la imatge. - PAR�METRES: - - source: imatge d'on s'extreuran els blobs - - mask: m�scara a aplicar. Nom�s es calcularan els blobs on la m�scara sigui - diferent de 0. Els blobs que toquin a un pixel 0 de la m�scara seran - considerats exteriors. - - threshold: llindar que s'aplicar� a la imatge source abans de calcular els blobs - - findmoments: indica si s'han de calcular els moments de cada blob - - blackBlobs: true per buscar blobs negres a la binaritzazi� (it will join all extern white blobs). - false per buscar blobs negres a la binaritzazi� (it will join all extern black blobs). + - source: imatge d'on s'extreuran els blobs + - mask: m�scara a aplicar. Nom�s es calcularan els blobs on la m�scara +sigui diferent de 0. Els blobs que toquin a un pixel 0 de la m�scara seran + considerats exteriors. + - threshold: llindar que s'aplicar� a la imatge source abans de calcular +els blobs + - findmoments: indica si s'han de calcular els moments de cada blob + - blackBlobs: true per buscar blobs negres a la binaritzazi� (it will join +all extern white blobs). false per buscar blobs negres a la binaritzazi� (it +will join all extern black blobs). - RESULTAT: - - objecte CBlobResult amb els blobs de la imatge source + - objecte CBlobResult amb els blobs de la imatge source - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -68,48 +69,48 @@ CBlobResult::CBlobResult() */ /** - FUNCTION: CBlob -- FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs in - the image +- FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs +in the image - PARAMETERS: - - source: image to extract the blobs from - - mask: optional mask to apply. The blobs will be extracted where the mask is - not 0. All the neighboring blobs where the mask is 0 will be extern blobs - - threshold: threshold level to apply to the image before computing blobs - - findmoments: true to calculate the blob moments (slower) (needed to calculate elipses!) - - blackBlobs: true to search for black blobs in the binarization (it will join all extern white blobs). - false to search for white blobs in the binarization (it will join all extern black blobs). + - source: image to extract the blobs from + - mask: optional mask to apply. The blobs will be extracted where the mask +is not 0. All the neighboring blobs where the mask is 0 will be extern blobs + - threshold: threshold level to apply to the image before computing blobs + - findmoments: true to calculate the blob moments (slower) (needed to +calculate elipses!) + - blackBlobs: true to search for black blobs in the binarization (it will +join all extern white blobs). false to search for white blobs in the +binarization (it will join all extern black blobs). - RESULT: - - object with all the blobs in the image. It throws an EXCEPCIO_CALCUL_BLOBS - if some error appears in the BlobAnalysis function + - object with all the blobs in the image. It throws an +EXCEPCIO_CALCUL_BLOBS if some error appears in the BlobAnalysis function - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -CBlobResult::CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor ) +CBlobResult::CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor) { - bool success; - - try - { - success = ComponentLabeling( source, mask, backgroundColor, m_blobs ); - } - catch(...) - { - success = false; - } - - if( !success ) throw EXCEPCIO_CALCUL_BLOBS; + bool success; + + try { + success = ComponentLabeling(source, mask, backgroundColor, m_blobs); + } catch (...) { + success = false; + } + + if (!success) + throw EXCEPCIO_CALCUL_BLOBS; } /** - FUNCI�: CBlobResult -- FUNCIONALITAT: Constructor de c�pia. Inicialitza la seq��ncia de blobs - amb els blobs del par�metre. +- FUNCIONALITAT: Constructor de c�pia. Inicialitza la seq��ncia de blobs + amb els blobs del par�metre. - PAR�METRES: - - source: objecte que es copiar� + - source: objecte que es copiar� - RESULTAT: - - objecte CBlobResult amb els blobs de l'objecte source + - objecte CBlobResult amb els blobs de l'objecte source - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -119,42 +120,39 @@ CBlobResult::CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor ) - FUNCTION: CBlobResult - FUNCTIONALITY: Copy constructor - PARAMETERS: - - source: object to copy + - source: object to copy - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -CBlobResult::CBlobResult( const CBlobResult &source ) +CBlobResult::CBlobResult(const CBlobResult& source) { - m_blobs = Blob_vector( source.GetNumBlobs() ); - - // creem el nou a partir del passat com a par�metre - m_blobs = Blob_vector( source.GetNumBlobs() ); - // copiem els blobs de l'origen a l'actual - Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); - Blob_vector::iterator pBlobsDst = m_blobs.begin(); - - while( pBlobsSrc != source.m_blobs.end() ) - { - // no podem cridar a l'operador = ja que Blob_vector �s un - // vector de CBlob*. Per tant, creem un blob nou a partir del - // blob original - *pBlobsDst = new CBlob(**pBlobsSrc); - pBlobsSrc++; - pBlobsDst++; - } + m_blobs = Blob_vector(source.GetNumBlobs()); + + // creem el nou a partir del passat com a par�metre + m_blobs = Blob_vector(source.GetNumBlobs()); + // copiem els blobs de l'origen a l'actual + Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); + Blob_vector::iterator pBlobsDst = m_blobs.begin(); + + while (pBlobsSrc != source.m_blobs.end()) { + // no podem cridar a l'operador = ja que Blob_vector �s un + // vector de CBlob*. Per tant, creem un blob nou a partir del + // blob original + *pBlobsDst = new CBlob(**pBlobsSrc); + pBlobsSrc++; + pBlobsDst++; + } } - - /** - FUNCI�: ~CBlobResult - FUNCIONALITAT: Destructor estandard. - PAR�METRES: - RESULTAT: - - Allibera la mem�ria reservada de cadascun dels blobs de la classe + - Allibera la mem�ria reservada de cadascun dels blobs de la classe - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -172,21 +170,20 @@ CBlobResult::CBlobResult( const CBlobResult &source ) */ CBlobResult::~CBlobResult() { - ClearBlobs(); + ClearBlobs(); } /************************************************************************** - Operadors / Operators + Operadors / Operators **************************************************************************/ - /** - FUNCI�: operador = - FUNCIONALITAT: Assigna un objecte source a l'actual - PAR�METRES: - - source: objecte a assignar + - source: objecte a assignar - RESULTAT: - - Substitueix els blobs actuals per els de l'objecte source + - Substitueix els blobs actuals per els de l'objecte source - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -194,7 +191,7 @@ CBlobResult::~CBlobResult() */ /** - FUNCTION: Assigment operator -- FUNCTIONALITY: +- FUNCTIONALITY: - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -204,42 +201,38 @@ CBlobResult::~CBlobResult() */ CBlobResult& CBlobResult::operator=(const CBlobResult& source) { - // si ja s�n el mateix, no cal fer res - if (this != &source) - { - // alliberem el conjunt de blobs antic - for( int i = 0; i < GetNumBlobs(); i++ ) - { - delete m_blobs[i]; - } - m_blobs.clear(); - // creem el nou a partir del passat com a par�metre - m_blobs = Blob_vector( source.GetNumBlobs() ); - // copiem els blobs de l'origen a l'actual - Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); - Blob_vector::iterator pBlobsDst = m_blobs.begin(); - - while( pBlobsSrc != source.m_blobs.end() ) - { - // no podem cridar a l'operador = ja que Blob_vector �s un - // vector de CBlob*. Per tant, creem un blob nou a partir del - // blob original - *pBlobsDst = new CBlob(**pBlobsSrc); - pBlobsSrc++; - pBlobsDst++; - } - } - return *this; + // si ja s�n el mateix, no cal fer res + if (this != &source) { + // alliberem el conjunt de blobs antic + for (int i = 0; i < GetNumBlobs(); i++) { + delete m_blobs[i]; + } + m_blobs.clear(); + // creem el nou a partir del passat com a par�metre + m_blobs = Blob_vector(source.GetNumBlobs()); + // copiem els blobs de l'origen a l'actual + Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); + Blob_vector::iterator pBlobsDst = m_blobs.begin(); + + while (pBlobsSrc != source.m_blobs.end()) { + // no podem cridar a l'operador = ja que Blob_vector �s un + // vector de CBlob*. Per tant, creem un blob nou a partir del + // blob original + *pBlobsDst = new CBlob(**pBlobsSrc); + pBlobsSrc++; + pBlobsDst++; + } + } + return *this; } - /** - FUNCI�: operador + - FUNCIONALITAT: Concatena els blobs de dos CBlobResult - PAR�METRES: - - source: d'on s'agafaran els blobs afegits a l'actual + - source: d'on s'agafaran els blobs afegits a l'actual - RESULTAT: - - retorna un nou CBlobResult amb els dos CBlobResult concatenats + - retorna un nou CBlobResult amb els dos CBlobResult concatenats - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -250,67 +243,66 @@ CBlobResult& CBlobResult::operator=(const CBlobResult& source) - FUNCTION: + operator - FUNCTIONALITY: Joins the blobs in source with the current ones - PARAMETERS: - - source: object to copy the blobs + - source: object to copy the blobs - RESULT: - - object with the actual blobs and the source blobs + - object with the actual blobs and the source blobs - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -CBlobResult CBlobResult::operator+( const CBlobResult& source ) const -{ - //creem el resultat a partir dels blobs actuals - CBlobResult resultat( *this ); - - // reservem mem�ria per als nous blobs - resultat.m_blobs.resize( resultat.GetNumBlobs() + source.GetNumBlobs() ); - - // declarem els iterador per rec�rrer els blobs d'origen i desti - Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); - Blob_vector::iterator pBlobsDst = resultat.m_blobs.end(); - - // insertem els blobs de l'origen a l'actual - while( pBlobsSrc != source.m_blobs.end() ) - { - pBlobsDst--; - *pBlobsDst = new CBlob(**pBlobsSrc); - pBlobsSrc++; - } - - return resultat; +CBlobResult CBlobResult::operator+(const CBlobResult& source) const +{ + // creem el resultat a partir dels blobs actuals + CBlobResult resultat(*this); + + // reservem mem�ria per als nous blobs + resultat.m_blobs.resize(resultat.GetNumBlobs() + source.GetNumBlobs()); + + // declarem els iterador per rec�rrer els blobs d'origen i desti + Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); + Blob_vector::iterator pBlobsDst = resultat.m_blobs.end(); + + // insertem els blobs de l'origen a l'actual + while (pBlobsSrc != source.m_blobs.end()) { + pBlobsDst--; + *pBlobsDst = new CBlob(**pBlobsSrc); + pBlobsSrc++; + } + + return resultat; } /************************************************************************** - Operacions / Operations + Operacions / Operations **************************************************************************/ /** - FUNCI�: AddBlob - FUNCIONALITAT: Afegeix un blob al conjunt - PAR�METRES: - - blob: blob a afegir + - blob: blob a afegir - RESULTAT: - - modifica el conjunt de blobs actual + - modifica el conjunt de blobs actual - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 2006/03/01 - MODIFICACI�: Data. Autor. Descripci�. */ -void CBlobResult::AddBlob( CBlob *blob ) +void CBlobResult::AddBlob(CBlob* blob) { - if( blob != NULL ) - m_blobs.push_back( new CBlob( blob ) ); + if (blob != NULL) + m_blobs.push_back(new CBlob(blob)); } - /** - FUNCI�: GetSTLResult -- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe +- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la +classe - PAR�METRES: - - evaluador: Qualsevol objecte derivat de COperadorBlob + - evaluador: Qualsevol objecte derivat de COperadorBlob - RESULTAT: - - Retorna un array de double's STL amb el resultat per cada blob + - Retorna un array de double's STL amb el resultat per cada blob - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -319,48 +311,47 @@ void CBlobResult::AddBlob( CBlob *blob ) /** - FUNCTION: GetResult - FUNCTIONALITY: Computes the function evaluador on all the blobs of the class - and returns a vector with the result + and returns a vector with the result - PARAMETERS: - - evaluador: function to apply to each blob (any object derived from the - COperadorBlob class ) + - evaluador: function to apply to each blob (any object derived from the + COperadorBlob class ) - RESULT: - - vector with all the results in the same order as the blobs + - vector with all the results in the same order as the blobs - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double_stl_vector CBlobResult::GetSTLResult( funcio_calculBlob *evaluador ) const +double_stl_vector CBlobResult::GetSTLResult(funcio_calculBlob* evaluador) const { - if( GetNumBlobs() <= 0 ) - { - return double_stl_vector(); - } - - // definim el resultat - double_stl_vector result = double_stl_vector( GetNumBlobs() ); - // i iteradors sobre els blobs i el resultat - double_stl_vector::iterator itResult = result.begin(); - Blob_vector::const_iterator itBlobs = m_blobs.begin(); - - // avaluem la funci� en tots els blobs - while( itBlobs != m_blobs.end() ) - { - *itResult = (*evaluador)(**itBlobs); - itBlobs++; - itResult++; - } - return result; + if (GetNumBlobs() <= 0) { + return double_stl_vector(); + } + + // definim el resultat + double_stl_vector result = double_stl_vector(GetNumBlobs()); + // i iteradors sobre els blobs i el resultat + double_stl_vector::iterator itResult = result.begin(); + Blob_vector::const_iterator itBlobs = m_blobs.begin(); + + // avaluem la funci� en tots els blobs + while (itBlobs != m_blobs.end()) { + *itResult = (*evaluador)(**itBlobs); + itBlobs++; + itResult++; + } + return result; } /** - FUNCI�: GetNumber -- FUNCIONALITAT: Calcula el resultat especificat sobre un �nic blob de la classe +- FUNCIONALITAT: Calcula el resultat especificat sobre un �nic blob de la +classe - PAR�METRES: - - evaluador: Qualsevol objecte derivat de COperadorBlob - - indexblob: n�mero de blob del que volem calcular el resultat. + - evaluador: Qualsevol objecte derivat de COperadorBlob + - indexblob: n�mero de blob del que volem calcular el resultat. - RESULTAT: - - Retorna un double amb el resultat + - Retorna un double amb el resultat - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -370,46 +361,50 @@ double_stl_vector CBlobResult::GetSTLResult( funcio_calculBlob *evaluador ) cons - FUNCTION: GetNumber - FUNCTIONALITY: Computes the function evaluador on a blob of the class - PARAMETERS: - - indexBlob: index of the blob to compute the function - - evaluador: function to apply to each blob (any object derived from the - COperadorBlob class ) + - indexBlob: index of the blob to compute the function + - evaluador: function to apply to each blob (any object derived from the + COperadorBlob class ) - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobResult::GetNumber( int indexBlob, funcio_calculBlob *evaluador ) const +double CBlobResult::GetNumber(int indexBlob, + funcio_calculBlob* evaluador) const { - if( indexBlob < 0 || indexBlob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); - return (*evaluador)( *m_blobs[indexBlob] ); + if (indexBlob < 0 || indexBlob >= GetNumBlobs()) + RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS); + return (*evaluador)(*m_blobs[indexBlob]); } -/////////////////////////// FILTRAT DE BLOBS //////////////////////////////////// +/////////////////////////// FILTRAT DE BLOBS +/////////////////////////////////////// /** - FUNCI�: Filter -- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s - els blobs que han passat el filtre. - El filtrat es basa en especificar condicions sobre un resultat dels blobs - i seleccionar (o excloure) aquells blobs que no compleixen una determinada - condicio +- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s + els blobs que han passat el filtre. + El filtrat es basa en especificar condicions sobre un resultat +dels blobs i seleccionar (o excloure) aquells blobs que no compleixen una +determinada condicio - PAR�METRES: - - dst: variable per deixar els blobs filtrats - - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), - o excloure els blobs trobats (B_EXCLUDE) - - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de COperadorBlob - - Condition: tipus de condici� que ha de superar la mesura (FilterType) - sobre cada blob per a ser considerat. - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - (nom�s t� sentit per a aquelles condicions que tenen dos valors - (B_INSIDE, per exemple). + - dst: variable per deixar els blobs filtrats + - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), + o excloure els blobs trobats (B_EXCLUDE) + - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de +COperadorBlob + - Condition: tipus de condici� que ha de superar la mesura (FilterType) + sobre cada blob per a ser considerat. + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) + - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) (nom�s t� sentit per a aquelles condicions que tenen dos valors + (B_INSIDE, per exemple). - RESULTAT: - - Deixa els blobs resultants del filtrat a destination + - Deixa els blobs resultants del filtrat a destination - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -418,60 +413,63 @@ double CBlobResult::GetNumber( int indexBlob, funcio_calculBlob *evaluador ) con /** - FUNCTION: Filter - FUNCTIONALITY: Get some blobs from the class based on conditions on measures - of the blobs. + of the blobs. - PARAMETERS: - - dst: where to store the selected blobs - - filterAction: B_INCLUDE: include the blobs which pass the filter in the result - B_EXCLUDE: exclude the blobs which pass the filter in the result - - evaluador: Object to evaluate the blob - - Condition: How to decide if the result returned by evaluador on each blob - is included or not. It can be: - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: numerical value to evaluate the Condition on evaluador(blob) - - HighLimit: numerical value to evaluate the Condition on evaluador(blob). - Only useful for B_INSIDE and B_OUTSIDE + - dst: where to store the selected blobs + - filterAction: B_INCLUDE: include the blobs which pass the filter in the +result B_EXCLUDE: exclude the blobs which pass the filter in the result + - evaluador: Object to evaluate the blob + - Condition: How to decide if the result returned by evaluador on each +blob is included or not. It can be: + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: numerical value to evaluate the Condition on evaluador(blob) + - HighLimit: numerical value to evaluate the Condition on evaluador(blob). + Only useful for B_INSIDE and B_OUTSIDE - RESULT: - - It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE) - the Condition on the result returned by evaluador on each blob + - It returns on dst the blobs that accomplish (B_INCLUDE) or discards +(B_EXCLUDE) the Condition on the result returned by evaluador on each blob - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::Filter(CBlobResult &dst, - int filterAction, - funcio_calculBlob *evaluador, - int condition, - double lowLimit, double highLimit /*=0*/) const - +void CBlobResult::Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit /*=0*/) const + { - // do the job - DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit ); + // do the job + DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit); } /** - FUNCI�: Filter (const version) -- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s - els blobs que han passat el filtre. - El filtrat es basa en especificar condicions sobre un resultat dels blobs - i seleccionar (o excloure) aquells blobs que no compleixen una determinada - condicio +- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s + els blobs que han passat el filtre. + El filtrat es basa en especificar condicions sobre un resultat +dels blobs i seleccionar (o excloure) aquells blobs que no compleixen una +determinada condicio - PAR�METRES: - - dst: variable per deixar els blobs filtrats - - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), - o excloure els blobs trobats (B_EXCLUDE) - - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de COperadorBlob - - Condition: tipus de condici� que ha de superar la mesura (FilterType) - sobre cada blob per a ser considerat. - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - (nom�s t� sentit per a aquelles condicions que tenen dos valors - (B_INSIDE, per exemple). + - dst: variable per deixar els blobs filtrats + - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), + o excloure els blobs trobats (B_EXCLUDE) + - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de +COperadorBlob + - Condition: tipus de condici� que ha de superar la mesura (FilterType) + sobre cada blob per a ser considerat. + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) + - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) (nom�s t� sentit per a aquelles condicions que tenen dos valors + (B_INSIDE, per exemple). - RESULTAT: - - Deixa els blobs resultants del filtrat a destination + - Deixa els blobs resultants del filtrat a destination - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -480,167 +478,156 @@ void CBlobResult::Filter(CBlobResult &dst, /** - FUNCTION: Filter (const version) - FUNCTIONALITY: Get some blobs from the class based on conditions on measures - of the blobs. + of the blobs. - PARAMETERS: - - dst: where to store the selected blobs - - filterAction: B_INCLUDE: include the blobs which pass the filter in the result - B_EXCLUDE: exclude the blobs which pass the filter in the result - - evaluador: Object to evaluate the blob - - Condition: How to decide if the result returned by evaluador on each blob - is included or not. It can be: - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: numerical value to evaluate the Condition on evaluador(blob) - - HighLimit: numerical value to evaluate the Condition on evaluador(blob). - Only useful for B_INSIDE and B_OUTSIDE + - dst: where to store the selected blobs + - filterAction: B_INCLUDE: include the blobs which pass the filter in the +result B_EXCLUDE: exclude the blobs which pass the filter in the result + - evaluador: Object to evaluate the blob + - Condition: How to decide if the result returned by evaluador on each +blob is included or not. It can be: + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: numerical value to evaluate the Condition on evaluador(blob) + - HighLimit: numerical value to evaluate the Condition on evaluador(blob). + Only useful for B_INSIDE and B_OUTSIDE - RESULT: - - It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE) - the Condition on the result returned by evaluador on each blob + - It returns on dst the blobs that accomplish (B_INCLUDE) or discards +(B_EXCLUDE) the Condition on the result returned by evaluador on each blob - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::Filter(CBlobResult &dst, - int filterAction, - funcio_calculBlob *evaluador, - int condition, - double lowLimit, double highLimit /*=0*/) - +void CBlobResult::Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit /*=0*/) + { - int numBlobs = GetNumBlobs(); - - // do the job - DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit ); - - // inline operation: remove previous blobs - if( &dst == this ) - { - // esborrem els primers blobs ( que s�n els originals ) - // ja que els tindrem replicats al final si passen el filtre - Blob_vector::iterator itBlobs = m_blobs.begin(); - for( int i = 0; i < numBlobs; i++ ) - { - delete *itBlobs; - itBlobs++; - } - m_blobs.erase( m_blobs.begin(), itBlobs ); - } + int numBlobs = GetNumBlobs(); + + // do the job + DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit); + + // inline operation: remove previous blobs + if (&dst == this) { + // esborrem els primers blobs ( que s�n els originals ) + // ja que els tindrem replicats al final si passen el filtre + Blob_vector::iterator itBlobs = m_blobs.begin(); + for (int i = 0; i < numBlobs; i++) { + delete *itBlobs; + itBlobs++; + } + m_blobs.erase(m_blobs.begin(), itBlobs); + } } - //! Does the Filter method job -void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit/* = 0*/) const +void CBlobResult::DoFilter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit /* = 0*/) const { - int i, numBlobs; - bool resultavaluacio; - double_stl_vector avaluacioBlobs; - double_stl_vector::iterator itavaluacioBlobs; - - if( GetNumBlobs() <= 0 ) return; - if( !evaluador ) return; - //avaluem els blobs amb la funci� pertinent - avaluacioBlobs = GetSTLResult(evaluador); - itavaluacioBlobs = avaluacioBlobs.begin(); - numBlobs = GetNumBlobs(); - switch(condition) - { - case B_EQUAL: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio= *itavaluacioBlobs == lowLimit; - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_NOT_EQUAL: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio = *itavaluacioBlobs != lowLimit; - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_GREATER: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio= *itavaluacioBlobs > lowLimit; - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_LESS: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio= *itavaluacioBlobs < lowLimit; - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_GREATER_OR_EQUAL: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio= *itavaluacioBlobs>= lowLimit; - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_LESS_OR_EQUAL: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio= *itavaluacioBlobs <= lowLimit; - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_INSIDE: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio=( *itavaluacioBlobs >= lowLimit) && ( *itavaluacioBlobs <= highLimit); - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - case B_OUTSIDE: - for(i=0;i<numBlobs;i++, itavaluacioBlobs++) - { - resultavaluacio=( *itavaluacioBlobs < lowLimit) || ( *itavaluacioBlobs > highLimit); - if( ( resultavaluacio && filterAction == B_INCLUDE ) || - ( !resultavaluacio && filterAction == B_EXCLUDE )) - { - dst.m_blobs.push_back( new CBlob( GetBlob( i ) )); - } - } - break; - } + int i, numBlobs; + bool resultavaluacio; + double_stl_vector avaluacioBlobs; + double_stl_vector::iterator itavaluacioBlobs; + + if (GetNumBlobs() <= 0) + return; + if (!evaluador) + return; + // avaluem els blobs amb la funci� pertinent + avaluacioBlobs = GetSTLResult(evaluador); + itavaluacioBlobs = avaluacioBlobs.begin(); + numBlobs = GetNumBlobs(); + switch (condition) { + case B_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs == lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_NOT_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs != lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_GREATER: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs > lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_LESS: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs < lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_GREATER_OR_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs >= lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_LESS_OR_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs <= lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_INSIDE: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = (*itavaluacioBlobs >= lowLimit) && + (*itavaluacioBlobs <= highLimit); + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_OUTSIDE: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = (*itavaluacioBlobs < lowLimit) || + (*itavaluacioBlobs > highLimit); + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + } } /** - FUNCI�: GetBlob - FUNCIONALITAT: Retorna un blob si aquest existeix (index != -1) - PAR�METRES: - - indexblob: index del blob a retornar + - indexblob: index del blob a retornar - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borr�s @@ -651,7 +638,7 @@ void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob - FUNCTION: GetBlob - FUNCTIONALITY: Gets the n-th blob (without ordering the blobs) - PARAMETERS: - - indexblob: index in the blob array + - indexblob: index in the blob array - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s @@ -659,32 +646,33 @@ void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob - MODIFICATION: Date. Author. Description. */ CBlob CBlobResult::GetBlob(int indexblob) const -{ - if( indexblob < 0 || indexblob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); +{ + if (indexblob < 0 || indexblob >= GetNumBlobs()) + RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS); - return *m_blobs[indexblob]; + return *m_blobs[indexblob]; } -CBlob *CBlobResult::GetBlob(int indexblob) -{ - if( indexblob < 0 || indexblob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); +CBlob* CBlobResult::GetBlob(int indexblob) +{ + if (indexblob < 0 || indexblob >= GetNumBlobs()) + RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS); - return m_blobs[indexblob]; + return m_blobs[indexblob]; } /** - FUNCI�: GetNthBlob - FUNCIONALITAT: Retorna l'en�ssim blob segons un determinat criteri - PAR�METRES: - - criteri: criteri per ordenar els blobs (objectes derivats de COperadorBlob) - - nBlob: index del blob a retornar - - dst: on es retorna el resultat + - criteri: criteri per ordenar els blobs (objectes derivats de +COperadorBlob) + - nBlob: index del blob a retornar + - dst: on es retorna el resultat - RESULTAT: - - retorna el blob nBlob a dst ordenant els blobs de la classe segons el criteri - en ordre DESCENDENT. Per exemple, per obtenir el blob major: - GetNthBlob( CBlobGetArea(), 0, blobMajor ); - GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob m�s gran) + - retorna el blob nBlob a dst ordenant els blobs de la classe segons el +criteri en ordre DESCENDENT. Per exemple, per obtenir el blob major: + GetNthBlob( CBlobGetArea(), 0, blobMajor ); + GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob m�s gran) - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -694,65 +682,64 @@ CBlob *CBlobResult::GetBlob(int indexblob) - FUNCTION: GetNthBlob - FUNCTIONALITY: Gets the n-th blob ordering first the blobs with some criteria - PARAMETERS: - - criteri: criteria to order the blob array - - nBlob: index of the returned blob in the ordered blob array - - dst: where to store the result + - criteri: criteria to order the blob array + - nBlob: index of the returned blob in the ordered blob array + - dst: where to store the result - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst ) const +void CBlobResult::GetNthBlob(funcio_calculBlob* criteri, + int nBlob, + CBlob& dst) const { - // verifiquem que no estem accedint fora el vector de blobs - if( nBlob < 0 || nBlob >= GetNumBlobs() ) - { - //RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); - dst = CBlob(); - return; - } - - double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat; - double valorEnessim; - - //avaluem els blobs amb la funci� pertinent - avaluacioBlobs = GetSTLResult(criteri); - - avaluacioBlobsOrdenat = double_stl_vector( GetNumBlobs() ); - - // obtenim els nBlob primers resultats (en ordre descendent) - std::partial_sort_copy( avaluacioBlobs.begin(), - avaluacioBlobs.end(), - avaluacioBlobsOrdenat.begin(), - avaluacioBlobsOrdenat.end(), - std::greater<double>() ); - - valorEnessim = avaluacioBlobsOrdenat[nBlob]; - - // busquem el primer blob que t� el valor n-ssim - double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin(); - - bool trobatBlob = false; - int indexBlob = 0; - while( itAvaluacio != avaluacioBlobs.end() && !trobatBlob ) - { - if( *itAvaluacio == valorEnessim ) - { - trobatBlob = true; - dst = CBlob( GetBlob(indexBlob)); - } - itAvaluacio++; - indexBlob++; - } + // verifiquem que no estem accedint fora el vector de blobs + if (nBlob < 0 || nBlob >= GetNumBlobs()) { + // RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); + dst = CBlob(); + return; + } + + double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat; + double valorEnessim; + + // avaluem els blobs amb la funci� pertinent + avaluacioBlobs = GetSTLResult(criteri); + + avaluacioBlobsOrdenat = double_stl_vector(GetNumBlobs()); + + // obtenim els nBlob primers resultats (en ordre descendent) + std::partial_sort_copy(avaluacioBlobs.begin(), + avaluacioBlobs.end(), + avaluacioBlobsOrdenat.begin(), + avaluacioBlobsOrdenat.end(), + std::greater<double>()); + + valorEnessim = avaluacioBlobsOrdenat[nBlob]; + + // busquem el primer blob que t� el valor n-ssim + double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin(); + + bool trobatBlob = false; + int indexBlob = 0; + while (itAvaluacio != avaluacioBlobs.end() && !trobatBlob) { + if (*itAvaluacio == valorEnessim) { + trobatBlob = true; + dst = CBlob(GetBlob(indexBlob)); + } + itAvaluacio++; + indexBlob++; + } } /** - FUNCI�: ClearBlobs - FUNCIONALITAT: Elimina tots els blobs de l'objecte - PAR�METRES: -- RESULTAT: - - Allibera tota la mem�ria dels blobs +- RESULTAT: + - Allibera tota la mem�ria dels blobs - RESTRICCIONS: - AUTOR: Ricard Borr�s Navarra - DATA DE CREACI�: 25-05-2005. @@ -760,7 +747,8 @@ void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst */ /* - FUNCTION: ClearBlobs -- FUNCTIONALITY: Clears all the blobs from the object and releases all its memory +- FUNCTIONALITY: Clears all the blobs from the object and releases all its +memory - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -770,24 +758,23 @@ void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst */ void CBlobResult::ClearBlobs() { - Blob_vector::iterator itBlobs = m_blobs.begin(); - while( itBlobs != m_blobs.end() ) - { - delete *itBlobs; - itBlobs++; - } - - m_blobs.clear(); + Blob_vector::iterator itBlobs = m_blobs.begin(); + while (itBlobs != m_blobs.end()) { + delete *itBlobs; + itBlobs++; + } + + m_blobs.clear(); } /** - FUNCI�: RaiseError - FUNCIONALITAT: Funci� per a notificar errors al l'usuari (en debug) i llen�a - les excepcions + les excepcions - PAR�METRES: - - errorCode: codi d'error -- RESULTAT: - - Ensenya un missatge a l'usuari (en debug) i llen�a una excepci� + - errorCode: codi d'error +- RESULTAT: + - Ensenya un missatge a l'usuari (en debug) i llen�a una excepci� - RESTRICCIONS: - AUTOR: Ricard Borr�s Navarra - DATA DE CREACI�: 25-05-2005. @@ -797,9 +784,9 @@ void CBlobResult::ClearBlobs() - FUNCTION: RaiseError - FUNCTIONALITY: Error handling function - PARAMETERS: - - errorCode: reason of the error + - errorCode: reason of the error - RESULT: - - Throws an exception with the error. + - Throws an exception with the error. - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. @@ -807,22 +794,19 @@ void CBlobResult::ClearBlobs() */ void CBlobResult::RaiseError(const int errorCode) const { - throw errorCode; + throw errorCode; } - - /************************************************************************** - Auxiliars / Auxiliary functions + Auxiliars / Auxiliary functions **************************************************************************/ - /** - FUNCI�: PrintBlobs -- FUNCIONALITAT: Escriu els par�metres (�rea, per�metre, exterior, mitjana) - de tots els blobs a un fitxer. +- FUNCIONALITAT: Escriu els par�metres (�rea, per�metre, exterior, mitjana) + de tots els blobs a un fitxer. - PAR�METRES: - - nom_fitxer: path complet del fitxer amb el resultat + - nom_fitxer: path complet del fitxer amb el resultat - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borr�s @@ -833,35 +817,35 @@ void CBlobResult::RaiseError(const int errorCode) const - FUNCTION: PrintBlobs - FUNCTIONALITY: Prints some blob features in an ASCII file - PARAMETERS: - - nom_fitxer: full path + filename to generate + - nom_fitxer: full path + filename to generate - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::PrintBlobs( char *nom_fitxer ) const +void CBlobResult::PrintBlobs(char* nom_fitxer) const { - double_stl_vector area, /*perimetre,*/ exterior, compacitat, longitud, - externPerimeter, perimetreConvex, perimetre; - int i; - FILE *fitxer_sortida; - - area = GetSTLResult( CBlobGetArea()); - perimetre = GetSTLResult( CBlobGetPerimeter()); - exterior = GetSTLResult( CBlobGetExterior()); - compacitat = GetSTLResult(CBlobGetCompactness()); - longitud = GetSTLResult( CBlobGetLength()); - externPerimeter = GetSTLResult( CBlobGetExternPerimeter()); - perimetreConvex = GetSTLResult( CBlobGetHullPerimeter()); - - fitxer_sortida = fopen( nom_fitxer, "w" ); - - for(i=0; i<GetNumBlobs(); i++) - { -// fprintf( fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n", -// i, area[i], perimetre[i], externPerimeter[i], perimetreConvex[i], exterior[i], compacitat[i], longitud[i] ); - } - fclose( fitxer_sortida ); - + double_stl_vector area, /*perimetre,*/ exterior, compacitat, longitud, + externPerimeter, perimetreConvex, perimetre; + int i; + FILE* fitxer_sortida; + + area = GetSTLResult(CBlobGetArea()); + perimetre = GetSTLResult(CBlobGetPerimeter()); + exterior = GetSTLResult(CBlobGetExterior()); + compacitat = GetSTLResult(CBlobGetCompactness()); + longitud = GetSTLResult(CBlobGetLength()); + externPerimeter = GetSTLResult(CBlobGetExternPerimeter()); + perimetreConvex = GetSTLResult(CBlobGetHullPerimeter()); + + fitxer_sortida = fopen(nom_fitxer, "w"); + + for (i = 0; i < GetNumBlobs(); i++) { + // fprintf( fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f + //extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n", + // i, area[i], perimetre[i], externPerimeter[i], + //perimetreConvex[i], exterior[i], compacitat[i], longitud[i] ); + } + fclose(fitxer_sortida); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h index cf5c18209ea04c27953853d887f2fe9b03f340a8..f9f9ec83b36ae400d9097f1dfe39c35fb2e815e4 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h @@ -1,6 +1,6 @@ /************************************************************************ - BlobResult.h - + BlobResult.h + FUNCIONALITAT: Definici� de la classe CBlobResult AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): @@ -11,151 +11,155 @@ MODIFICATIONS (Modification, Author, Date): **************************************************************************/ - #if !defined(_CLASSE_BLOBRESULT_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED + #define _CLASSE_BLOBRESULT_INCLUDED -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 + #if _MSC_VER > 1000 + #pragma once + #endif // _MSC_VER > 1000 -#include "BlobLibraryConfiguration.h" -#include <math.h> -#include <opencv2/opencv.hpp> + #include "BlobLibraryConfiguration.h" + #include <math.h> + #include <opencv2/opencv.hpp> -#include <vector> // vectors de la STL -#include <functional> -#include "blob.h" -#include "BlobOperators.h" -#include "ComponentLabeling.h" + #include <vector> // vectors de la STL + #include <functional> + #include "blob.h" + #include "BlobOperators.h" + #include "ComponentLabeling.h" //! Vector de doubles typedef std::vector<double> double_stl_vector; -/************************************************************************** - Filtres / Filters -**************************************************************************/ - -//! accions que es poden fer amb els filtres -//! Actions performed by a filter (include or exclude blobs) -#define B_INCLUDE 1L -#define B_EXCLUDE 2L - -//! condicions sobre els filtres -//! Conditions to apply the filters -#define B_EQUAL 3L -#define B_NOT_EQUAL 4L -#define B_GREATER 5L -#define B_LESS 6L -#define B_GREATER_OR_EQUAL 7L -#define B_LESS_OR_EQUAL 8L -#define B_INSIDE 9L -#define B_OUTSIDE 10L - - -/************************************************************************** - Excepcions / Exceptions -**************************************************************************/ - -//! Excepcions llen�ades per les funcions: -#define EXCEPTION_BLOB_OUT_OF_BOUNDS 1000 -#define EXCEPCIO_CALCUL_BLOBS 1001 - -/** - Classe que cont� un conjunt de blobs i permet extreure'n propietats - o filtrar-los segons determinats criteris. - Class to calculate the blobs of an image and calculate some properties - on them. Also, the class provides functions to filter the blobs using - some criteria. + /************************************************************************** + Filtres / Filters + **************************************************************************/ + + //! accions que es poden fer amb els filtres + //! Actions performed by a filter (include or exclude blobs) + #define B_INCLUDE 1L + #define B_EXCLUDE 2L + + //! condicions sobre els filtres + //! Conditions to apply the filters + #define B_EQUAL 3L + #define B_NOT_EQUAL 4L + #define B_GREATER 5L + #define B_LESS 6L + #define B_GREATER_OR_EQUAL 7L + #define B_LESS_OR_EQUAL 8L + #define B_INSIDE 9L + #define B_OUTSIDE 10L + + /************************************************************************** + Excepcions / Exceptions + **************************************************************************/ + + //! Excepcions llen�ades per les funcions: + #define EXCEPTION_BLOB_OUT_OF_BOUNDS 1000 + #define EXCEPCIO_CALCUL_BLOBS 1001 + +/** + Classe que cont� un conjunt de blobs i permet extreure'n propietats + o filtrar-los segons determinats criteris. + Class to calculate the blobs of an image and calculate some properties + on them. Also, the class provides functions to filter the blobs using + some criteria. */ -class CBlobResult +class CBlobResult { public: - - //! constructor estandard, crea un conjunt buit de blobs - //! Standard constructor, it creates an empty set of blobs - CBlobResult(); - //! constructor a partir d'una imatge - //! Image constructor, it creates an object with the blobs of the image - CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor); - //! constructor de c�pia - //! Copy constructor - CBlobResult( const CBlobResult &source ); - //! Destructor - virtual ~CBlobResult(); - - //! operador = per a fer assignacions entre CBlobResult - //! Assigment operator - CBlobResult& operator=(const CBlobResult& source); - //! operador + per concatenar dos CBlobResult - //! Addition operator to concatenate two sets of blobs - CBlobResult operator+( const CBlobResult& source ) const; - - //! Afegeix un blob al conjunt - //! Adds a blob to the set of blobs - void AddBlob( CBlob *blob ); - - //! Calcula un valor sobre tots els blobs de la classe retornant un std::vector<double> - //! Computes some property on all the blobs of the class - double_stl_vector GetSTLResult( funcio_calculBlob *evaluador ) const; - - //! Calcula un valor sobre un blob de la classe - //! Computes some property on one blob of the class - double GetNumber( int indexblob, funcio_calculBlob *evaluador ) const; - - //! Retorna aquells blobs que compleixen les condicions del filtre en el destination - //! Filters the blobs of the class using some property - void Filter(CBlobResult &dst, - int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit = 0 ); - void Filter(CBlobResult &dst, - int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit = 0 ) const; - - //! Retorna l'en�ssim blob segons un determinat criteri - //! Sorts the blobs of the class acording to some criteria and returns the n-th blob - void GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst ) const; - - //! Retorna el blob en�ssim - //! Gets the n-th blob of the class ( without sorting ) - CBlob GetBlob(int indexblob) const; - CBlob *GetBlob(int indexblob); - - //! Elimina tots els blobs de l'objecte - //! Clears all the blobs of the class - void ClearBlobs(); - - //! Escriu els blobs a un fitxer - //! Prints some features of all the blobs in a file - void PrintBlobs( char *nom_fitxer ) const; - - -//Metodes GET/SET - - //! Retorna el total de blobs - //! Gets the total number of blobs - int GetNumBlobs() const - { - return(m_blobs.size()); - } - + //! constructor estandard, crea un conjunt buit de blobs + //! Standard constructor, it creates an empty set of blobs + CBlobResult(); + //! constructor a partir d'una imatge + //! Image constructor, it creates an object with the blobs of the image + CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor); + //! constructor de c�pia + //! Copy constructor + CBlobResult(const CBlobResult& source); + //! Destructor + virtual ~CBlobResult(); + + //! operador = per a fer assignacions entre CBlobResult + //! Assigment operator + CBlobResult& operator=(const CBlobResult& source); + //! operador + per concatenar dos CBlobResult + //! Addition operator to concatenate two sets of blobs + CBlobResult operator+(const CBlobResult& source) const; + + //! Afegeix un blob al conjunt + //! Adds a blob to the set of blobs + void AddBlob(CBlob* blob); + + //! Calcula un valor sobre tots els blobs de la classe retornant un + //! std::vector<double> Computes some property on all the blobs of the + //! class + double_stl_vector GetSTLResult(funcio_calculBlob* evaluador) const; + + //! Calcula un valor sobre un blob de la classe + //! Computes some property on one blob of the class + double GetNumber(int indexblob, funcio_calculBlob* evaluador) const; + + //! Retorna aquells blobs que compleixen les condicions del filtre en el + //! destination Filters the blobs of the class using some property + void Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit = 0); + void Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit = 0) const; + + //! Retorna l'en�ssim blob segons un determinat criteri + //! Sorts the blobs of the class acording to some criteria and returns the + //! n-th blob + void GetNthBlob(funcio_calculBlob* criteri, int nBlob, CBlob& dst) const; + + //! Retorna el blob en�ssim + //! Gets the n-th blob of the class ( without sorting ) + CBlob GetBlob(int indexblob) const; + CBlob* GetBlob(int indexblob); + + //! Elimina tots els blobs de l'objecte + //! Clears all the blobs of the class + void ClearBlobs(); + + //! Escriu els blobs a un fitxer + //! Prints some features of all the blobs in a file + void PrintBlobs(char* nom_fitxer) const; + + // Metodes GET/SET + + //! Retorna el total de blobs + //! Gets the total number of blobs + int GetNumBlobs() const + { + return (m_blobs.size()); + } private: - - //! Funci� per gestionar els errors - //! Function to manage the errors - void RaiseError(const int errorCode) const; - - //! Does the Filter method job - void DoFilter(CBlobResult &dst, - int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit = 0) const; + //! Funci� per gestionar els errors + //! Function to manage the errors + void RaiseError(const int errorCode) const; + + //! Does the Filter method job + void DoFilter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit = 0) const; protected: - - //! Vector amb els blobs - //! Vector with all the blobs - Blob_vector m_blobs; + //! Vector amb els blobs + //! Vector with all the blobs + Blob_vector m_blobs; }; #endif // !defined(_CLASSE_BLOBRESULT_INCLUDED) diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp index 6bfaa09af4966b9389490cb3a9915195ec79d830..a046cb503488e8b60a2c622390e8282556f11466 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp @@ -7,416 +7,429 @@ //! Conversion from freeman code to coordinate increments (counterclockwise) static const cv::Point freemanCodeIncrement[8] = - { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} }; + {{1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}}; - -inline unsigned char GET_IMAGE_PIXEL( cv::Mat image, cv::Point p ) +inline unsigned char GET_IMAGE_PIXEL(cv::Mat image, cv::Point p) { - return image.at<unsigned char>(p); + return image.at<unsigned char>(p); } -inline bool GET_IMAGEMASK_PIXEL( cv::Mat* mask, cv::Point p ) +inline bool GET_IMAGEMASK_PIXEL(cv::Mat* mask, cv::Point p) { - if(mask) - return mask->at<unsigned char>(p) > 0; - else - return true; + if (mask) + return mask->at<unsigned char>(p) > 0; + else + return true; } -inline bool GET_BELOW_VISITEDPIXEL( bool *currentPixel, int imageWidth ) +inline bool GET_BELOW_VISITEDPIXEL(bool* currentPixel, int imageWidth) { - return *( currentPixel + imageWidth ); + return *(currentPixel + imageWidth); } /** - FUNCI�: ASSIGN_LABEL - FUNCIONALITAT: Assigns label value to label image - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/29 - MODIFICACI�: Data. Autor. Descripci�. */ -inline void ASSIGN_LABEL( cv::Point p, t_labelType *labels, int imageWidth, int newLabel ) +inline void ASSIGN_LABEL(cv::Point p, + t_labelType* labels, + int imageWidth, + int newLabel) { - *(labels + p.y * imageWidth + p.x) = newLabel; + *(labels + p.y * imageWidth + p.x) = newLabel; } - -inline void ASSIGN_VISITED( cv::Point p, bool *visitedPoints, int imageWidth ) +inline void ASSIGN_VISITED(cv::Point p, bool* visitedPoints, int imageWidth) { - *(visitedPoints + p.y * imageWidth + p.x) = true; + *(visitedPoints + p.y * imageWidth + p.x) = true; } /** - FUNCI�: ComponentLabeling -- FUNCIONALITAT: Calcula els components binaris (blobs) d'una imatge amb connectivitat a 8 +- FUNCIONALITAT: Calcula els components binaris (blobs) d'una imatge amb +connectivitat a 8 - PAR�METRES: - - inputImage: image to segment (pixel values different than blobColor are treated as background) - - maskImage: if not NULL, all the pixels equal to 0 in mask are skipped in input image - - backgroundColor: color of background (ignored pixels) - - blobs: blob vector destination + - inputImage: image to segment (pixel values different than blobColor are +treated as background) + - maskImage: if not NULL, all the pixels equal to 0 in mask are skipped in +input image + - backgroundColor: color of background (ignored pixels) + - blobs: blob vector destination - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/21 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: Algorithm based on "A linear-time component labeling algorithm using contour tracing technique", - F.Chang et al +- NOTA: Algorithm based on "A linear-time component labeling algorithm using +contour tracing technique", F.Chang et al */ -bool ComponentLabeling(cv::Mat inputImage, - cv::Mat* maskImage, - unsigned char backgroundColor, - Blob_vector &blobs ) +bool ComponentLabeling(cv::Mat inputImage, + cv::Mat* maskImage, + unsigned char backgroundColor, + Blob_vector& blobs) { - // row major vector with visited points - bool internalContour, externalContour; - int imageWidth, imageHeight, currentLabel, contourLabel; - //! current blob pointer - CBlob *currentBlob; - cv::Size imageSizes; - cv::Point currentPoint; - - // verify input image - if (!inputImage.empty()) - return false; - - // verify that input image and mask image has same size - if (maskImage) - { - if (inputImage.size() != maskImage->size()) - return false; - } - - imageSizes = inputImage.size(); - - imageWidth = imageSizes.width; - imageHeight = imageSizes.height; - - // create auxiliary buffers that are initialized to 0 - t_labelType *labelledImage = (t_labelType*) calloc(imageWidth * imageHeight, sizeof(t_labelType)); - bool *visitedPoints = (bool*) calloc(imageWidth * imageHeight, sizeof(bool)); - - // Execute the POI detection parallel. - // This basically just filters out the background (which is the majority of points). - // The result will be an ordered list of non-background points for the blob-detector to work on. - std::vector<cv::Point2d> foregroundPoints; - - const int totalRegionsX = 4; - const int totalRegionsY = 4; - const int totalRegions = totalRegionsX * totalRegionsY; - const int regionWidth = imageWidth / totalRegionsX; - const int regionHeight = imageHeight / totalRegionsY; - - // get the pixel data from an image at a certain position - auto getImageData = [](cv::Mat image, const int row, const int column) - { - return image.data + row * image.step + column; - }; - - // to allow each thread to acces the main list directly (saves us some merging later) - std::mutex foregroundPointAccessMutex; - - auto workOnRegion = [&](int x, int y) { - const int startingX = x * regionWidth; - const int startingY = y * regionHeight; - - for (int j = 0; j < regionHeight; ++j) - for (int i = 0; i < regionWidth; ++i) - { - const int pointX = startingX + i; - const int pointY = startingY + j; - // ignore background pixels or 0 pixels in mask - const unsigned char * pInputImage = getImageData(inputImage, pointY, pointX); - if ((*pInputImage == backgroundColor) || (maskImage && *getImageData(*maskImage, pointY, pointX) == 0)) - { - continue; - } - else // remember all non-background pixels - { - std::lock_guard<std::mutex> lock(foregroundPointAccessMutex); - foregroundPoints.emplace_back(pointX, pointY); - } - } - }; - - // start one parallel thread for each region - std::vector<std::future<void>> merger; - merger.reserve(totalRegions); - - for (int y = 0; y < totalRegionsY; ++y) - { - for (int x = 0; x < totalRegionsX; ++x) - { - merger.push_back(std::async([&, x, y] { workOnRegion(x, y); })); - } - } - - // and wait until all have completed; the results are alrady in the main list - for (const auto & asyncResult : merger) - { - asyncResult.wait(); - } - - // need to sort for coordinate as the loop below is written in a way that depends on the order - std::sort(foregroundPoints.begin(), foregroundPoints.end(), - [](const cv::Point2d & a, const cv::Point2d & b) -> bool - { - return (a.y < b.y) || (a.y == b.y && a.x < b.x); - } - ); - - // initialize pointers and label counter - currentLabel = 1; - - auto getImageDataVisited = [&](const int &row, const int &column) - { - return visitedPoints + row * inputImage.step + column; - }; - - auto getImageDataLabelled = [&](const int &row, const int &column) - { - return labelledImage + row * inputImage.step + column; - }; - - for (const cv::Point2d & point : foregroundPoints) - { - const int i = point.x; - const int j = point.y; - - t_labelType * pLabels = getImageDataLabelled(j, i); - bool * pVisitedPoints = getImageDataVisited(j, i); - - // new external contour: current label == 0 and above pixel is background - if( j > 0 ) - { - const unsigned char * pAboveInputImage = getImageData(inputImage, j - 1, i); - - externalContour = ((*pAboveInputImage == backgroundColor) || - (maskImage && *getImageData(*maskImage, j - 1, i) == 0)) && - (*pLabels == 0); - } - else - externalContour = (*pLabels == 0); - - // new internal contour: below pixel is background and not visited - if( !externalContour && j < imageHeight - 1 ) - { - const unsigned char * pBelowInputImage = getImageData(inputImage, j + 1, i); - internalContour = *pBelowInputImage == backgroundColor && - !GET_BELOW_VISITEDPIXEL( pVisitedPoints, imageWidth); - } - else - { - internalContour = false; - } - - - if( externalContour ) - { - currentPoint = cv::Point(i,j); - // assign label to labelled image - *pLabels = currentLabel; - - // create new blob - currentBlob = new CBlob(currentLabel, currentPoint, imageSizes ); - - // contour tracing with currentLabel - contourTracing( inputImage, maskImage, currentPoint, - labelledImage, visitedPoints, - currentLabel, false, backgroundColor, currentBlob->GetExternalContour() ); - - // add new created blob - blobs.push_back(currentBlob); - - currentLabel++; - } - else - { - if( internalContour ) - { - currentPoint = cv::Point(i,j); - - if( *pLabels == 0 ) - { - // take left neightbour value as current - if( i > 0 ) - contourLabel = *(pLabels - 1); - } - else - { - contourLabel = *pLabels; - } - - if(contourLabel>0) - { - currentBlob = blobs[contourLabel-1]; - CBlobContour newContour(currentPoint, currentBlob->GetStorage()); - - - // contour tracing with contourLabel - contourTracing( inputImage, maskImage, currentPoint, labelledImage, visitedPoints, - contourLabel, true, backgroundColor, &newContour ); - - currentBlob->AddInternalContour( newContour ); - } - } - // neither internal nor external contour - else - { - // take left neightbour value as current if it is not labelled - if( i > 0 && *pLabels == 0 ) - *pLabels = *(pLabels - 1); - } - - } - } - - - // free auxiliary buffers - free( labelledImage ); - free( visitedPoints ); - - return true; + // row major vector with visited points + bool internalContour, externalContour; + int imageWidth, imageHeight, currentLabel, contourLabel; + //! current blob pointer + CBlob* currentBlob; + cv::Size imageSizes; + cv::Point currentPoint; + + // verify input image + if (!inputImage.empty()) + return false; + + // verify that input image and mask image has same size + if (maskImage) { + if (inputImage.size() != maskImage->size()) + return false; + } + + imageSizes = inputImage.size(); + + imageWidth = imageSizes.width; + imageHeight = imageSizes.height; + + // create auxiliary buffers that are initialized to 0 + t_labelType* labelledImage = (t_labelType*) calloc(imageWidth * + imageHeight, + sizeof(t_labelType)); + bool* visitedPoints = (bool*) calloc(imageWidth * imageHeight, + sizeof(bool)); + + // Execute the POI detection parallel. + // This basically just filters out the background (which is the majority of + // points). The result will be an ordered list of non-background points for + // the blob-detector to work on. + std::vector<cv::Point2d> foregroundPoints; + + const int totalRegionsX = 4; + const int totalRegionsY = 4; + const int totalRegions = totalRegionsX * totalRegionsY; + const int regionWidth = imageWidth / totalRegionsX; + const int regionHeight = imageHeight / totalRegionsY; + + // get the pixel data from an image at a certain position + auto getImageData = [](cv::Mat image, const int row, const int column) { + return image.data + row * image.step + column; + }; + + // to allow each thread to acces the main list directly (saves us some + // merging later) + std::mutex foregroundPointAccessMutex; + + auto workOnRegion = [&](int x, int y) { + const int startingX = x * regionWidth; + const int startingY = y * regionHeight; + + for (int j = 0; j < regionHeight; ++j) + for (int i = 0; i < regionWidth; ++i) { + const int pointX = startingX + i; + const int pointY = startingY + j; + // ignore background pixels or 0 pixels in mask + const unsigned char* pInputImage = getImageData(inputImage, + pointY, + pointX); + if ((*pInputImage == backgroundColor) || + (maskImage && + *getImageData(*maskImage, pointY, pointX) == 0)) { + continue; + } else // remember all non-background pixels + { + std::lock_guard<std::mutex> lock( + foregroundPointAccessMutex); + foregroundPoints.emplace_back(pointX, pointY); + } + } + }; + + // start one parallel thread for each region + std::vector<std::future<void>> merger; + merger.reserve(totalRegions); + + for (int y = 0; y < totalRegionsY; ++y) { + for (int x = 0; x < totalRegionsX; ++x) { + merger.push_back(std::async([&, x, y] { workOnRegion(x, y); })); + } + } + + // and wait until all have completed; the results are alrady in the main + // list + for (const auto& asyncResult : merger) { + asyncResult.wait(); + } + + // need to sort for coordinate as the loop below is written in a way that + // depends on the order + std::sort(foregroundPoints.begin(), + foregroundPoints.end(), + [](const cv::Point2d& a, const cv::Point2d& b) -> bool { + return (a.y < b.y) || (a.y == b.y && a.x < b.x); + }); + + // initialize pointers and label counter + currentLabel = 1; + + auto getImageDataVisited = [&](const int& row, const int& column) { + return visitedPoints + row * inputImage.step + column; + }; + + auto getImageDataLabelled = [&](const int& row, const int& column) { + return labelledImage + row * inputImage.step + column; + }; + + for (const cv::Point2d& point : foregroundPoints) { + const int i = point.x; + const int j = point.y; + + t_labelType* pLabels = getImageDataLabelled(j, i); + bool* pVisitedPoints = getImageDataVisited(j, i); + + // new external contour: current label == 0 and above pixel is + // background + if (j > 0) { + const unsigned char* pAboveInputImage = getImageData(inputImage, + j - 1, + i); + + externalContour = ((*pAboveInputImage == backgroundColor) || + (maskImage && + *getImageData(*maskImage, j - 1, i) == 0)) && + (*pLabels == 0); + } else + externalContour = (*pLabels == 0); + + // new internal contour: below pixel is background and not visited + if (!externalContour && j < imageHeight - 1) { + const unsigned char* pBelowInputImage = getImageData(inputImage, + j + 1, + i); + internalContour = *pBelowInputImage == backgroundColor && + !GET_BELOW_VISITEDPIXEL(pVisitedPoints, + imageWidth); + } else { + internalContour = false; + } + + if (externalContour) { + currentPoint = cv::Point(i, j); + // assign label to labelled image + *pLabels = currentLabel; + + // create new blob + currentBlob = new CBlob(currentLabel, currentPoint, imageSizes); + + // contour tracing with currentLabel + contourTracing(inputImage, + maskImage, + currentPoint, + labelledImage, + visitedPoints, + currentLabel, + false, + backgroundColor, + currentBlob->GetExternalContour()); + + // add new created blob + blobs.push_back(currentBlob); + + currentLabel++; + } else { + if (internalContour) { + currentPoint = cv::Point(i, j); + + if (*pLabels == 0) { + // take left neightbour value as current + if (i > 0) + contourLabel = *(pLabels - 1); + } else { + contourLabel = *pLabels; + } + + if (contourLabel > 0) { + currentBlob = blobs[contourLabel - 1]; + CBlobContour newContour(currentPoint, + currentBlob->GetStorage()); + + // contour tracing with contourLabel + contourTracing(inputImage, + maskImage, + currentPoint, + labelledImage, + visitedPoints, + contourLabel, + true, + backgroundColor, + &newContour); + + currentBlob->AddInternalContour(newContour); + } + } + // neither internal nor external contour + else { + // take left neightbour value as current if it is not labelled + if (i > 0 && *pLabels == 0) + *pLabels = *(pLabels - 1); + } + } + } + + // free auxiliary buffers + free(labelledImage); + free(visitedPoints); + + return true; } /** -- FUNCI�: -- FUNCIONALITAT: +- FUNCI�: +- FUNCIONALITAT: - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/29 - MODIFICACI�: Data. Autor. Descripci�. */ -void contourTracing( cv::Mat image, - cv::Mat* maskImage, - cv::Point contourStart, t_labelType *labels, bool *visitedPoints, t_labelType label, - bool internalContour, unsigned char backgroundColor, CBlobContour *currentBlobcontour ) +void contourTracing(cv::Mat image, + cv::Mat* maskImage, + cv::Point contourStart, + t_labelType* labels, + bool* visitedPoints, + t_labelType label, + bool internalContour, + unsigned char backgroundColor, + CBlobContour* currentBlobcontour) { - cv::Point t, tnext, tsecond; - short initialMovement, movement; - - if( internalContour ) - { - initialMovement = 7;//3; - } - else - { - initialMovement = 3;//7; - } - - tsecond = tracer( image, maskImage, contourStart, visitedPoints, initialMovement, - backgroundColor, movement ); - - // assign current label to tnext - ASSIGN_LABEL( contourStart, labels, image.size().width, label ); - - - // contour corresponds to isolated pixel? - if( tsecond.x == contourStart.x && tsecond.y == contourStart.y ) - { - // we are finished with the contour - return; - } - - // add chain code to current contour - currentBlobcontour->AddChainCode(movement); - - // assign label to next point - ASSIGN_LABEL( tsecond, labels, image.size().width, label ); - - tnext.x = tsecond.x; - tnext.y = tsecond.y; - t.x = tnext.x; - t.y = tnext.y; - - // while T is different than contourStart and Tnext is different than T - // follow contour until start point is reached again - while (!(t.x == contourStart.x && t.y == contourStart.y) - || !(tsecond.x == tnext.x && tsecond.y == tnext.y)) - { - - t.x = tnext.x; - t.y = tnext.y; - initialMovement = (movement + 5) % 8; - - // search for next contour point - tnext = tracer( image, maskImage, t, visitedPoints, initialMovement, - backgroundColor, movement ); - - // assign label to contour point - ASSIGN_LABEL( tnext, labels, image.size().width, label ); - - // add chain code to current contour - currentBlobcontour->AddChainCode(movement); - } - + cv::Point t, tnext, tsecond; + short initialMovement, movement; + + if (internalContour) { + initialMovement = 7; // 3; + } else { + initialMovement = 3; // 7; + } + + tsecond = tracer(image, + maskImage, + contourStart, + visitedPoints, + initialMovement, + backgroundColor, + movement); + + // assign current label to tnext + ASSIGN_LABEL(contourStart, labels, image.size().width, label); + + // contour corresponds to isolated pixel? + if (tsecond.x == contourStart.x && tsecond.y == contourStart.y) { + // we are finished with the contour + return; + } + + // add chain code to current contour + currentBlobcontour->AddChainCode(movement); + + // assign label to next point + ASSIGN_LABEL(tsecond, labels, image.size().width, label); + + tnext.x = tsecond.x; + tnext.y = tsecond.y; + t.x = tnext.x; + t.y = tnext.y; + + // while T is different than contourStart and Tnext is different than T + // follow contour until start point is reached again + while (!(t.x == contourStart.x && t.y == contourStart.y) || + !(tsecond.x == tnext.x && tsecond.y == tnext.y)) { + + t.x = tnext.x; + t.y = tnext.y; + initialMovement = (movement + 5) % 8; + + // search for next contour point + tnext = tracer(image, + maskImage, + t, + visitedPoints, + initialMovement, + backgroundColor, + movement); + + // assign label to contour point + ASSIGN_LABEL(tnext, labels, image.size().width, label); + + // add chain code to current contour + currentBlobcontour->AddChainCode(movement); + } } /** - FUNCI�: tracer - FUNCIONALITAT: Searches for next point of a contour - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ -cv::Point tracer( cv::Mat image, cv::Mat* maskImage, cv::Point P, bool *visitedPoints, - short initialMovement, - unsigned char backgroundColor, short &movement ) +cv::Point tracer(cv::Mat image, + cv::Mat* maskImage, + cv::Point P, + bool* visitedPoints, + short initialMovement, + unsigned char backgroundColor, + short& movement) { - int d; - cv::Point pNext; - - for (d = 0; d <= 7; d++ ) - { - movement = (initialMovement + d) % 8; - - pNext.x = P.x + freemanCodeIncrement[movement].x; - pNext.y = P.y + freemanCodeIncrement[movement].y; - - // the point is inside image ? - if( pNext.x < 0 || pNext.x >= image.size().width || - pNext.y < 0 || pNext.y >= image.size().height ) - { - // try other movement - continue; - } - - // image has blobColor value in the new point? - if( (GET_IMAGE_PIXEL( image, pNext ) != backgroundColor ) && GET_IMAGEMASK_PIXEL(maskImage, pNext ) ) - { - return pNext; - } - else - { - // mark point as visited - ASSIGN_VISITED( pNext, visitedPoints, image.size().width ); - } - } - - // no possible movement was found - movement = -1; - pNext.x = P.x; - pNext.y = P.y; - - return pNext; + int d; + cv::Point pNext; + + for (d = 0; d <= 7; d++) { + movement = (initialMovement + d) % 8; + + pNext.x = P.x + freemanCodeIncrement[movement].x; + pNext.y = P.y + freemanCodeIncrement[movement].y; + + // the point is inside image ? + if (pNext.x < 0 || pNext.x >= image.size().width || pNext.y < 0 || + pNext.y >= image.size().height) { + // try other movement + continue; + } + + // image has blobColor value in the new point? + if ((GET_IMAGE_PIXEL(image, pNext) != backgroundColor) && + GET_IMAGEMASK_PIXEL(maskImage, pNext)) { + return pNext; + } else { + // mark point as visited + ASSIGN_VISITED(pNext, visitedPoints, image.size().width); + } + } + + // no possible movement was found + movement = -1; + pNext.x = P.x; + pNext.y = P.y; + + return pNext; } - - diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h index 5aa8ee58af70bd531dbb15cf7f3baee4660351a1..a51c0328047ba02bf1ff954ef050a65b33d600ab 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h @@ -1,30 +1,34 @@ #if !defined(_COMPONENT_LABELING_H_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED - -#include "vector" -#include "BlobContour.h" -#include "blob.h" + #define _CLASSE_BLOBRESULT_INCLUDED + #include "vector" + #include "BlobContour.h" + #include "blob.h" //! definici� de que es un vector de blobs -typedef std::vector<CBlob*> Blob_vector; - - - -bool ComponentLabeling(cv::Mat inputImage, - cv::Mat* maskImage, - unsigned char backgroundColor, - Blob_vector &blobs ); - - -void contourTracing( cv::Mat image, cv::Mat* mask, cv::Point contourStart, t_labelType *labels, - bool *visitedPoints, t_labelType label, - bool internalContour, unsigned char backgroundColor, - CBlobContour *currentBlobContour ); - -cv::Point tracer( cv::Mat image, cv::Mat* mask, cv::Point P, bool *visitedPoints, - short initialMovement, - unsigned char backgroundColor, short &movement ); - - -#endif //!_CLASSE_BLOBRESULT_INCLUDED +typedef std::vector<CBlob*> Blob_vector; + +bool ComponentLabeling(cv::Mat inputImage, + cv::Mat* maskImage, + unsigned char backgroundColor, + Blob_vector& blobs); + +void contourTracing(cv::Mat image, + cv::Mat* mask, + cv::Point contourStart, + t_labelType* labels, + bool* visitedPoints, + t_labelType label, + bool internalContour, + unsigned char backgroundColor, + CBlobContour* currentBlobContour); + +cv::Point tracer(cv::Mat image, + cv::Mat* mask, + cv::Point P, + bool* visitedPoints, + short initialMovement, + unsigned char backgroundColor, + short& movement); + +#endif //!_CLASSE_BLOBRESULT_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp index 8842c5fc716278998026ec847c85b160d01b61d5..059ab8b47c0b154319f1161aadf1b73cb041d125 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp @@ -1,555 +1,554 @@ /************************************************************************ - Blob.cpp - + Blob.cpp + - FUNCIONALITAT: Implementaci� de la classe CBlob - AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): - -FUNCTIONALITY: Implementation of the CBlob class and some helper classes to perform - some calculations on it -AUTHOR: Inspecta S.L. -MODIFICATIONS (Modification, Author, Date): -**************************************************************************/ +FUNCTIONALITY: Implementation of the CBlob class and some helper classes to +perform some calculations on it AUTHOR: Inspecta S.L. MODIFICATIONS +(Modification, Author, Date): +**************************************************************************/ #include "blob.h" #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc_c.h> - CBlob::CBlob() { - m_area = m_perimeter = -1; - m_externPerimeter = m_meanGray = m_stdDevGray = -1; - m_boundingBox.width = -1; - m_ellipse.size.width = -1; - m_storage = NULL; - m_id = -1; + m_area = m_perimeter = -1; + m_externPerimeter = m_meanGray = m_stdDevGray = -1; + m_boundingBox.width = -1; + m_ellipse.size.width = -1; + m_storage = NULL; + m_id = -1; } -CBlob::CBlob( t_labelType id, cv::Point startPoint, cv::Size originalImageSize ) +CBlob::CBlob(t_labelType id, cv::Point startPoint, cv::Size originalImageSize) { - m_id = id; - m_area = m_perimeter = -1; - m_externPerimeter = m_meanGray = m_stdDevGray = -1; - m_boundingBox.width = -1; - m_ellipse.size.width = -1; - m_storage = cvCreateMemStorage(); - m_externalContour = CBlobContour(startPoint, m_storage); - m_originalImageSize = originalImageSize; + m_id = id; + m_area = m_perimeter = -1; + m_externPerimeter = m_meanGray = m_stdDevGray = -1; + m_boundingBox.width = -1; + m_ellipse.size.width = -1; + m_storage = cvCreateMemStorage(); + m_externalContour = CBlobContour(startPoint, m_storage); + m_originalImageSize = originalImageSize; } //! Copy constructor -CBlob::CBlob( const CBlob &src ) +CBlob::CBlob(const CBlob& src) { - m_storage = NULL; - *this = src; + m_storage = NULL; + *this = src; } -CBlob::CBlob( const CBlob *src ) +CBlob::CBlob(const CBlob* src) { - if (src != NULL ) - { - m_storage = NULL; - *this = *src; - } + if (src != NULL) { + m_storage = NULL; + *this = *src; + } } -CBlob& CBlob::operator=(const CBlob &src ) +CBlob& CBlob::operator=(const CBlob& src) { - if( this != &src ) - { - m_id = src.m_id; - m_area = src.m_area; - m_perimeter = src.m_perimeter; - m_externPerimeter = src.m_externPerimeter; - m_meanGray = src.m_meanGray; - m_stdDevGray = src.m_stdDevGray; - m_boundingBox = src.m_boundingBox; - m_ellipse = src.m_ellipse; - m_originalImageSize = src.m_originalImageSize; - - // clear all current blob contours - ClearContours(); - - if( m_storage ) - cvReleaseMemStorage( &m_storage ); - - m_storage = cvCreateMemStorage(); - - m_externalContour = CBlobContour(src.m_externalContour.GetStartPoint(), m_storage ); - if( src.m_externalContour.m_contour ) - m_externalContour.m_contour = cvCloneSeq( src.m_externalContour.m_contour, m_storage); - m_internalContours.clear(); - - // copy all internal contours - if( src.m_internalContours.size() ) - { - m_internalContours = t_contourList( src.m_internalContours.size() ); - t_contourList::const_iterator itSrc; - t_contourList::iterator it; - - itSrc = src.m_internalContours.begin(); - it = m_internalContours.begin(); - - while (itSrc != src.m_internalContours.end()) - { - *it = CBlobContour((*itSrc).GetStartPoint(), m_storage); - if( (*itSrc).m_contour ) - (*it).m_contour = cvCloneSeq( (*itSrc).m_contour, m_storage); - - it++; - itSrc++; - } - } - } - - return *this; + if (this != &src) { + m_id = src.m_id; + m_area = src.m_area; + m_perimeter = src.m_perimeter; + m_externPerimeter = src.m_externPerimeter; + m_meanGray = src.m_meanGray; + m_stdDevGray = src.m_stdDevGray; + m_boundingBox = src.m_boundingBox; + m_ellipse = src.m_ellipse; + m_originalImageSize = src.m_originalImageSize; + + // clear all current blob contours + ClearContours(); + + if (m_storage) + cvReleaseMemStorage(&m_storage); + + m_storage = cvCreateMemStorage(); + + m_externalContour = CBlobContour(src.m_externalContour.GetStartPoint(), + m_storage); + if (src.m_externalContour.m_contour) + m_externalContour.m_contour = cvCloneSeq( + src.m_externalContour.m_contour, + m_storage); + m_internalContours.clear(); + + // copy all internal contours + if (src.m_internalContours.size()) { + m_internalContours = t_contourList(src.m_internalContours.size()); + t_contourList::const_iterator itSrc; + t_contourList::iterator it; + + itSrc = src.m_internalContours.begin(); + it = m_internalContours.begin(); + + while (itSrc != src.m_internalContours.end()) { + *it = CBlobContour((*itSrc).GetStartPoint(), m_storage); + if ((*itSrc).m_contour) + (*it).m_contour = cvCloneSeq((*itSrc).m_contour, + m_storage); + + it++; + itSrc++; + } + } + } + + return *this; } CBlob::~CBlob() { - ClearContours(); - - if( m_storage ) - cvReleaseMemStorage( &m_storage ); + ClearContours(); + + if (m_storage) + cvReleaseMemStorage(&m_storage); } void CBlob::ClearContours() { - t_contourList::iterator it; + t_contourList::iterator it; - it = m_internalContours.begin(); + it = m_internalContours.begin(); - while (it != m_internalContours.end()) - { - (*it).ResetChainCode(); - it++; - } - m_internalContours.clear(); + while (it != m_internalContours.end()) { + (*it).ResetChainCode(); + it++; + } + m_internalContours.clear(); - m_externalContour.ResetChainCode(); - + m_externalContour.ResetChainCode(); } -void CBlob::AddInternalContour( const CBlobContour &newContour ) +void CBlob::AddInternalContour(const CBlobContour& newContour) { - m_internalContours.push_back(newContour); + m_internalContours.push_back(newContour); } //! Indica si el blob est� buit ( no t� cap info associada ) //! Shows if the blob has associated information bool CBlob::IsEmpty() { - return GetExternalContour()->m_contour == NULL; + return GetExternalContour()->m_contour == NULL; } /** - FUNCI�: Area -- FUNCIONALITAT: Get blob area, ie. external contour area minus internal contours area +- FUNCIONALITAT: Get blob area, ie. external contour area minus internal +contours area - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ double CBlob::Area() { - double area; - t_contourList::iterator itContour; - - area = m_externalContour.GetArea(); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - area -= (*itContour).GetArea(); - itContour++; - } - return area; + double area; + t_contourList::iterator itContour; + + area = m_externalContour.GetArea(); + + itContour = m_internalContours.begin(); + + while (itContour != m_internalContours.end()) { + area -= (*itContour).GetArea(); + itContour++; + } + return area; } /** - FUNCI�: Perimeter - FUNCIONALITAT: Get blob perimeter, ie. sum of the lenght of all the contours - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ double CBlob::Perimeter() { - double perimeter; - t_contourList::iterator itContour; + double perimeter; + t_contourList::iterator itContour; - perimeter = m_externalContour.GetPerimeter(); + perimeter = m_externalContour.GetPerimeter(); - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - perimeter += (*itContour).GetPerimeter(); - itContour++; - } - return perimeter; + itContour = m_internalContours.begin(); + while (itContour != m_internalContours.end()) { + perimeter += (*itContour).GetPerimeter(); + itContour++; + } + return perimeter; } /** - FUNCI�: Exterior - FUNCIONALITAT: Return true for extern blobs - PAR�METRES: - - xBorder: true to consider blobs touching horizontal borders as extern - - yBorder: true to consider blobs touching vertical borders as extern + - xBorder: true to consider blobs touching horizontal borders as extern + - yBorder: true to consider blobs touching vertical borders as extern - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ -int CBlob::Exterior(IplImage *mask, bool xBorder /* = true */, bool yBorder /* = true */) +int CBlob::Exterior(IplImage* mask, + bool xBorder /* = true */, + bool yBorder /* = true */) { - if (ExternPerimeter(mask, xBorder, yBorder ) > 0 ) - { - return 1; - } - - return 0; + if (ExternPerimeter(mask, xBorder, yBorder) > 0) { + return 1; + } + + return 0; } /** - FUNCI�: ExternPerimeter - FUNCIONALITAT: Get extern perimeter (perimeter touching image borders) - PAR�METRES: - - maskImage: if != NULL, counts maskImage black pixels as external pixels and contour points touching - them are counted as external contour points. - - xBorder: true to consider blobs touching horizontal borders as extern - - yBorder: true to consider blobs touching vertical borders as extern + - maskImage: if != NULL, counts maskImage black pixels as external pixels +and contour points touching them are counted as external contour points. + - xBorder: true to consider blobs touching horizontal borders as extern + - yBorder: true to consider blobs touching vertical borders as extern - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/05 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: If CBlobContour::GetContourPoints aproximates contours with a method different that NONE, - this function will not give correct results +- NOTA: If CBlobContour::GetContourPoints aproximates contours with a method +different that NONE, this function will not give correct results */ -double CBlob::ExternPerimeter( IplImage *maskImage, bool xBorder /* = true */, bool yBorder /* = true */) +double CBlob::ExternPerimeter(IplImage* maskImage, + bool xBorder /* = true */, + bool yBorder /* = true */) { - t_PointList externContour, externalPoints; - CvSeqReader reader; - CvSeqWriter writer; - cv::Point actualPoint, previousPoint; - bool find = false; - int i,j; - int delta = 0; - - // it is calculated? - if( m_externPerimeter != -1 ) - { - return m_externPerimeter; - } - - // get contour pixels - externContour = m_externalContour.GetContourPoints(); - - m_externPerimeter = 0; - - // there are contour pixels? - if( externContour == NULL ) - { - return m_externPerimeter; - } - - cvStartReadSeq( externContour, &reader); - - // create a sequence with the external points of the blob - externalPoints = cvCreateSeq( externContour->flags, externContour->header_size, externContour->elem_size, - m_storage ); - cvStartAppendToSeq( externalPoints, &writer ); - previousPoint.x = -1; - - // which contour pixels touch border? - for( j=0; j< externContour->total; j++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - find = false; - - // pixel is touching border? - if ( xBorder & ((actualPoint.x == 0) || (actualPoint.x == m_originalImageSize.width - 1 )) || - yBorder & ((actualPoint.y == 0) || (actualPoint.y == m_originalImageSize.height - 1 ))) - { - find = true; - } - else - { - if( maskImage != NULL ) - { - // verify if some of 8-connected neighbors is black in mask - char *pMask; - - pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y - 1) * maskImage->widthStep); - - for ( i = 0; i < 3; i++, pMask++ ) - { - if(*pMask == 0 && !find ) - { - find = true; - break; - } - } - - if(!find) - { - pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y ) * maskImage->widthStep); - - for ( i = 0; i < 3; i++, pMask++ ) - { - if(*pMask == 0 && !find ) - { - find = true; - break; - } - } - } - - if(!find) - { - pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y + 1) * maskImage->widthStep); - - for ( i = 0; i < 3; i++, pMask++ ) - { - if(*pMask == 0 && !find ) - { - find = true; - break; - } - } - } - } - } - - if( find ) - { - if( previousPoint.x > 0 ) - delta = abs(previousPoint.x - actualPoint.x) + abs(previousPoint.y - actualPoint.y); - - // calculate separately each external contour segment - if( delta > 2 ) - { - cvEndWriteSeq( &writer ); - m_externPerimeter += cvArcLength( externalPoints, CV_WHOLE_SEQ, 0 ); - - cvClearSeq( externalPoints ); - cvStartAppendToSeq( externalPoints, &writer ); - delta = 0; - previousPoint.x = -1; - } - - CV_WRITE_SEQ_ELEM( actualPoint, writer ); - previousPoint = actualPoint; - } - - } - - cvEndWriteSeq( &writer ); - - m_externPerimeter += cvArcLength( externalPoints, CV_WHOLE_SEQ, 0 ); - - cvClearSeq( externalPoints ); - - // divide by two because external points have one side inside the blob and the other outside - // Perimeter of external points counts both sides, so it must be divided - m_externPerimeter /= 2.0; - - return m_externPerimeter; + t_PointList externContour, externalPoints; + CvSeqReader reader; + CvSeqWriter writer; + cv::Point actualPoint, previousPoint; + bool find = false; + int i, j; + int delta = 0; + + // it is calculated? + if (m_externPerimeter != -1) { + return m_externPerimeter; + } + + // get contour pixels + externContour = m_externalContour.GetContourPoints(); + + m_externPerimeter = 0; + + // there are contour pixels? + if (externContour == NULL) { + return m_externPerimeter; + } + + cvStartReadSeq(externContour, &reader); + + // create a sequence with the external points of the blob + externalPoints = cvCreateSeq(externContour->flags, + externContour->header_size, + externContour->elem_size, + m_storage); + cvStartAppendToSeq(externalPoints, &writer); + previousPoint.x = -1; + + // which contour pixels touch border? + for (j = 0; j < externContour->total; j++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + find = false; + + // pixel is touching border? + if (xBorder & ((actualPoint.x == 0) || + (actualPoint.x == m_originalImageSize.width - 1)) || + yBorder & ((actualPoint.y == 0) || + (actualPoint.y == m_originalImageSize.height - 1))) { + find = true; + } else { + if (maskImage != NULL) { + // verify if some of 8-connected neighbors is black in mask + char* pMask; + + pMask = (maskImage->imageData + actualPoint.x - 1 + + (actualPoint.y - 1) * maskImage->widthStep); + + for (i = 0; i < 3; i++, pMask++) { + if (*pMask == 0 && !find) { + find = true; + break; + } + } + + if (!find) { + pMask = (maskImage->imageData + actualPoint.x - 1 + + (actualPoint.y) * maskImage->widthStep); + + for (i = 0; i < 3; i++, pMask++) { + if (*pMask == 0 && !find) { + find = true; + break; + } + } + } + + if (!find) { + pMask = (maskImage->imageData + actualPoint.x - 1 + + (actualPoint.y + 1) * maskImage->widthStep); + + for (i = 0; i < 3; i++, pMask++) { + if (*pMask == 0 && !find) { + find = true; + break; + } + } + } + } + } + + if (find) { + if (previousPoint.x > 0) + delta = abs(previousPoint.x - actualPoint.x) + + abs(previousPoint.y - actualPoint.y); + + // calculate separately each external contour segment + if (delta > 2) { + cvEndWriteSeq(&writer); + m_externPerimeter += cvArcLength(externalPoints, + CV_WHOLE_SEQ, + 0); + + cvClearSeq(externalPoints); + cvStartAppendToSeq(externalPoints, &writer); + delta = 0; + previousPoint.x = -1; + } + + CV_WRITE_SEQ_ELEM(actualPoint, writer); + previousPoint = actualPoint; + } + } + + cvEndWriteSeq(&writer); + + m_externPerimeter += cvArcLength(externalPoints, CV_WHOLE_SEQ, 0); + + cvClearSeq(externalPoints); + + // divide by two because external points have one side inside the blob and + // the other outside Perimeter of external points counts both sides, so it + // must be divided + m_externPerimeter /= 2.0; + + return m_externPerimeter; } //! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS) double CBlob::Moment(int p, int q) { - double moment; - t_contourList::iterator itContour; - - moment = m_externalContour.GetMoment(p,q); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - moment -= (*itContour).GetMoment(p,q); - itContour++; - } - return moment; + double moment; + t_contourList::iterator itContour; + + moment = m_externalContour.GetMoment(p, q); + + itContour = m_internalContours.begin(); + + while (itContour != m_internalContours.end()) { + moment -= (*itContour).GetMoment(p, q); + itContour++; + } + return moment; } /** - FUNCI�: Mean - FUNCIONALITAT: Get blob mean color in input image - PAR�METRES: - - image: image from gray color are extracted + - image: image from gray color are extracted - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ -double CBlob::Mean( IplImage *image ) +double CBlob::Mean(IplImage* image) { - // it is calculated? -/* if( m_meanGray != -1 ) - { - return m_meanGray; - } -*/ - // Create a mask with same size as blob bounding box - IplImage *mask; - CvScalar mean, std; - cv::Point offset; - - GetBoundingBox(); - - if (m_boundingBox.height == 0 ||m_boundingBox.width == 0 || !CV_IS_IMAGE( image )) - { - m_meanGray = 0; - return m_meanGray; - } - - // apply ROI and mask to input image to compute mean gray and standard deviation - mask = cvCreateImage( cvSize(m_boundingBox.width, m_boundingBox.height), IPL_DEPTH_8U, 1); - cvSetZero(mask); - - offset.x = -m_boundingBox.x; - offset.y = -m_boundingBox.y; - - // draw contours on mask - cvDrawContours( mask, m_externalContour.GetContourPoints(), cvScalar(CV_RGB(255,255,255)), cvScalar(CV_RGB(255,255,255)),0, CV_FILLED, 8, - cvPoint(offset) ); - - // draw internal contours - t_contourList::iterator it = m_internalContours.begin(); - while(it != m_internalContours.end() ) - { - cvDrawContours( mask, (*it).GetContourPoints(), cvScalar(CV_RGB(0,0,0)), cvScalar(CV_RGB(0,0,0)),0, CV_FILLED, 8, - cvPoint(offset) ); - it++; - } - - cvSetImageROI( image, m_boundingBox ); - cvAvgSdv( image, &mean, &std, mask ); - - m_meanGray = mean.val[0]; - m_stdDevGray = std.val[0]; - - cvReleaseImage( &mask ); - cvResetImageROI( image ); - - return m_meanGray; + // it is calculated? + /* if( m_meanGray != -1 ) + { + return m_meanGray; + } + */ + // Create a mask with same size as blob bounding box + IplImage* mask; + CvScalar mean, std; + cv::Point offset; + + GetBoundingBox(); + + if (m_boundingBox.height == 0 || m_boundingBox.width == 0 || + !CV_IS_IMAGE(image)) { + m_meanGray = 0; + return m_meanGray; + } + + // apply ROI and mask to input image to compute mean gray and standard + // deviation + mask = cvCreateImage(cvSize(m_boundingBox.width, m_boundingBox.height), + IPL_DEPTH_8U, + 1); + cvSetZero(mask); + + offset.x = -m_boundingBox.x; + offset.y = -m_boundingBox.y; + + // draw contours on mask + cvDrawContours(mask, + m_externalContour.GetContourPoints(), + cvScalar(CV_RGB(255, 255, 255)), + cvScalar(CV_RGB(255, 255, 255)), + 0, + CV_FILLED, + 8, + cvPoint(offset)); + + // draw internal contours + t_contourList::iterator it = m_internalContours.begin(); + while (it != m_internalContours.end()) { + cvDrawContours(mask, + (*it).GetContourPoints(), + cvScalar(CV_RGB(0, 0, 0)), + cvScalar(CV_RGB(0, 0, 0)), + 0, + CV_FILLED, + 8, + cvPoint(offset)); + it++; + } + + cvSetImageROI(image, m_boundingBox); + cvAvgSdv(image, &mean, &std, mask); + + m_meanGray = mean.val[0]; + m_stdDevGray = std.val[0]; + + cvReleaseImage(&mask); + cvResetImageROI(image); + + return m_meanGray; } -double CBlob::StdDev( IplImage *image ) +double CBlob::StdDev(IplImage* image) { - // it is calculated? -/* if( m_stdDevGray != -1 ) - { - return m_stdDevGray; - } -*/ - // call mean calculation (where also standard deviation is calculated) - Mean( image ); - - return m_stdDevGray; + // it is calculated? + /* if( m_stdDevGray != -1 ) + { + return m_stdDevGray; + } + */ + // call mean calculation (where also standard deviation is calculated) + Mean(image); + + return m_stdDevGray; } /** - FUNCI�: GetBoundingBox - FUNCIONALITAT: Get bounding box (without rotation) of a blob - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ CvRect CBlob::GetBoundingBox() { - // it is calculated? - if( m_boundingBox.width != -1 ) - { - return m_boundingBox; - } - - t_PointList externContour; - CvSeqReader reader; - cv::Point actualPoint; - - // get contour pixels - externContour = m_externalContour.GetContourPoints(); - - // it is an empty blob? - if( !externContour ) - { - m_boundingBox.x = 0; - m_boundingBox.y = 0; - m_boundingBox.width = 0; - m_boundingBox.height = 0; - - return m_boundingBox; - } - - cvStartReadSeq( externContour, &reader); - - m_boundingBox.x = m_originalImageSize.width; - m_boundingBox.y = m_originalImageSize.height; - m_boundingBox.width = 0; - m_boundingBox.height = 0; - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - m_boundingBox.x = MIN( actualPoint.x, m_boundingBox.x ); - m_boundingBox.y = MIN( actualPoint.y, m_boundingBox.y ); - - m_boundingBox.width = MAX( actualPoint.x, m_boundingBox.width ); - m_boundingBox.height = MAX( actualPoint.y, m_boundingBox.height ); - } - - //m_boundingBox.x = max( m_boundingBox.x , 0 ); - //m_boundingBox.y = max( m_boundingBox.y , 0 ); - - m_boundingBox.width -= m_boundingBox.x; - m_boundingBox.height -= m_boundingBox.y; - - return m_boundingBox; + // it is calculated? + if (m_boundingBox.width != -1) { + return m_boundingBox; + } + + t_PointList externContour; + CvSeqReader reader; + cv::Point actualPoint; + + // get contour pixels + externContour = m_externalContour.GetContourPoints(); + + // it is an empty blob? + if (!externContour) { + m_boundingBox.x = 0; + m_boundingBox.y = 0; + m_boundingBox.width = 0; + m_boundingBox.height = 0; + + return m_boundingBox; + } + + cvStartReadSeq(externContour, &reader); + + m_boundingBox.x = m_originalImageSize.width; + m_boundingBox.y = m_originalImageSize.height; + m_boundingBox.width = 0; + m_boundingBox.height = 0; + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + m_boundingBox.x = MIN(actualPoint.x, m_boundingBox.x); + m_boundingBox.y = MIN(actualPoint.y, m_boundingBox.y); + + m_boundingBox.width = MAX(actualPoint.x, m_boundingBox.width); + m_boundingBox.height = MAX(actualPoint.y, m_boundingBox.height); + } + + // m_boundingBox.x = max( m_boundingBox.x , 0 ); + // m_boundingBox.y = max( m_boundingBox.y , 0 ); + + m_boundingBox.width -= m_boundingBox.x; + m_boundingBox.height -= m_boundingBox.y; + + return m_boundingBox; } /** - FUNCI�: GetEllipse - FUNCIONALITAT: Calculates bounding ellipse of external contour points - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. @@ -557,111 +556,104 @@ CvRect CBlob::GetBoundingBox() */ CvBox2D CBlob::GetEllipse() { - // it is calculated? - if( m_ellipse.size.width != -1 ) - return m_ellipse; - - double u00,u11,u01,u10,u20,u02, delta, num, den, temp; - - // central moments calculation - u00 = Moment(0,0); - - // empty blob? - if ( u00 <= 0 ) - { - m_ellipse.size.width = 0; - m_ellipse.size.height = 0; - m_ellipse.center.x = 0; - m_ellipse.center.y = 0; - m_ellipse.angle = 0; - return m_ellipse; - } - u10 = Moment(1,0) / u00; - u01 = Moment(0,1) / u00; - - u11 = -(Moment(1,1) - Moment(1,0) * Moment(0,1) / u00 ) / u00; - u20 = (Moment(2,0) - Moment(1,0) * Moment(1,0) / u00 ) / u00; - u02 = (Moment(0,2) - Moment(0,1) * Moment(0,1) / u00 ) / u00; - - - // elipse calculation - delta = sqrt( 4*u11*u11 + (u20-u02)*(u20-u02) ); - m_ellipse.center.x = float(u10); - m_ellipse.center.y = float(u01); - - temp = u20 + u02 + delta; - if( temp > 0 ) - { - m_ellipse.size.width = sqrt(float( 2*(u20 + u02 + delta ))); - } - else - { - m_ellipse.size.width = 0; - return m_ellipse; - } - - temp = u20 + u02 - delta; - if( temp > 0 ) - { - m_ellipse.size.height = sqrt(float( 2*(u20 + u02 - delta ) )); - } - else - { - m_ellipse.size.height = 0; - return m_ellipse; - } - - // elipse orientation - if (u20 > u02) - { - num = u02 - u20 + sqrt((u02 - u20)*(u02 - u20) + 4*u11*u11); - den = 2*u11; - } - else - { - num = 2*u11; - den = u20 - u02 + sqrt((u20 - u02)*(u20 - u02) + 4*u11*u11); + // it is calculated? + if (m_ellipse.size.width != -1) + return m_ellipse; + + double u00, u11, u01, u10, u20, u02, delta, num, den, temp; + + // central moments calculation + u00 = Moment(0, 0); + + // empty blob? + if (u00 <= 0) { + m_ellipse.size.width = 0; + m_ellipse.size.height = 0; + m_ellipse.center.x = 0; + m_ellipse.center.y = 0; + m_ellipse.angle = 0; + return m_ellipse; + } + u10 = Moment(1, 0) / u00; + u01 = Moment(0, 1) / u00; + + u11 = -(Moment(1, 1) - Moment(1, 0) * Moment(0, 1) / u00) / u00; + u20 = (Moment(2, 0) - Moment(1, 0) * Moment(1, 0) / u00) / u00; + u02 = (Moment(0, 2) - Moment(0, 1) * Moment(0, 1) / u00) / u00; + + // elipse calculation + delta = sqrt(4 * u11 * u11 + (u20 - u02) * (u20 - u02)); + m_ellipse.center.x = float(u10); + m_ellipse.center.y = float(u01); + + temp = u20 + u02 + delta; + if (temp > 0) { + m_ellipse.size.width = sqrt(float(2 * (u20 + u02 + delta))); + } else { + m_ellipse.size.width = 0; + return m_ellipse; } - if( num != 0 && den != 00 ) - { - m_ellipse.angle = float( 180.0 + (180.0 / CV_PI) * atan( num / den ) ); - } - else - { - m_ellipse.angle = 0; - } - - return m_ellipse; + temp = u20 + u02 - delta; + if (temp > 0) { + m_ellipse.size.height = sqrt(float(2 * (u20 + u02 - delta))); + } else { + m_ellipse.size.height = 0; + return m_ellipse; + } + + // elipse orientation + if (u20 > u02) { + num = u02 - u20 + sqrt((u02 - u20) * (u02 - u20) + 4 * u11 * u11); + den = 2 * u11; + } else { + num = 2 * u11; + den = u20 - u02 + sqrt((u20 - u02) * (u20 - u02) + 4 * u11 * u11); + } + if (num != 0 && den != 00) { + m_ellipse.angle = float(180.0 + (180.0 / CV_PI) * atan(num / den)); + } else { + m_ellipse.angle = 0; + } + + return m_ellipse; } /** - FUNCTION: FillBlob -- FUNCTIONALITY: - - Fills the blob with a specified colour +- FUNCTIONALITY: + - Fills the blob with a specified colour - PARAMETERS: - - imatge: where to paint - - color: colour to paint the blob + - imatge: where to paint + - color: colour to paint the blob - RESULT: - - modifies input image and returns the seed point used to fill the blob + - modifies input image and returns the seed point used to fill the blob - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlob::FillBlob( IplImage *imatge, CvScalar color, int offsetX /*=0*/, int offsetY /*=0*/) +void CBlob::FillBlob(IplImage* imatge, + CvScalar color, + int offsetX /*=0*/, + int offsetY /*=0*/) { - cvDrawContours( imatge, m_externalContour.GetContourPoints(), color, color,0, CV_FILLED, 8 ); + cvDrawContours(imatge, + m_externalContour.GetContourPoints(), + color, + color, + 0, + CV_FILLED, + 8); } - /** - FUNCTION: GetConvexHull - FUNCTIONALITY: Calculates the convex hull polygon of the blob - PARAMETERS: - - dst: where to store the result + - dst: where to store the result - RESULT: - - true if no error ocurred + - true if no error ocurred - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. @@ -669,41 +661,42 @@ void CBlob::FillBlob( IplImage *imatge, CvScalar color, int offsetX /*=0*/, int */ t_PointList CBlob::GetConvexHull() { - CvSeq *convexHull = NULL; + CvSeq* convexHull = NULL; - if( m_externalContour.GetContourPoints() ) - convexHull = cvConvexHull2( m_externalContour.GetContourPoints(), m_storage, - CV_COUNTER_CLOCKWISE, 1 ); + if (m_externalContour.GetContourPoints()) + convexHull = cvConvexHull2(m_externalContour.GetContourPoints(), + m_storage, + CV_COUNTER_CLOCKWISE, + 1); - return convexHull; + return convexHull; } /** - FUNCTION: JoinBlob - FUNCTIONALITY: Add's external contour to current external contour - PARAMETERS: - - blob: blob from which extract the added external contour + - blob: blob from which extract the added external contour - RESULT: - - true if no error ocurred + - true if no error ocurred - RESTRICTIONS: Only external contours are added - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlob::JoinBlob( CBlob *blob ) +void CBlob::JoinBlob(CBlob* blob) { - CvSeqWriter writer; - CvSeqReader reader; - t_chainCode chainCode; + CvSeqWriter writer; + CvSeqReader reader; + t_chainCode chainCode; - cvStartAppendToSeq( m_externalContour.GetChainCode(), &writer ); - cvStartReadSeq( blob->GetExternalContour()->GetChainCode(), &reader ); - - for (int i = 0; i < blob->GetExternalContour()->GetChainCode()->total; i++ ) - { - CV_READ_SEQ_ELEM( chainCode, reader ); - CV_WRITE_SEQ_ELEM( chainCode, writer ); - } - cvEndWriteSeq( &writer ); + cvStartAppendToSeq(m_externalContour.GetChainCode(), &writer); + cvStartReadSeq(blob->GetExternalContour()->GetChainCode(), &reader); + for (int i = 0; i < blob->GetExternalContour()->GetChainCode()->total; + i++) { + CV_READ_SEQ_ELEM(chainCode, reader); + CV_WRITE_SEQ_ELEM(chainCode, writer); + } + cvEndWriteSeq(&writer); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h index 2d30a4d57bc6a09fa666c7ea940042d52e29d25f..16b7e097cc6bfcdef65bae5b271a02f9d12014ab 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h @@ -1,169 +1,171 @@ /************************************************************************ - Blob.h - + Blob.h + FUNCIONALITAT: Definici� de la classe CBlob AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): FUNCTIONALITY: Definition of the CBlob class and some helper classes to perform - some calculations on it + some calculations on it AUTHOR: Inspecta S.L. MODIFICATIONS (Modification, Author, Date): **************************************************************************/ //! Disable warnings referred to 255 character truncation for the std:map -#pragma warning( disable : 4786 ) +#pragma warning(disable : 4786) #ifndef CBLOB_INSPECTA_INCLUDED -#define CBLOB_INSPECTA_INCLUDED - -#include <list> + #define CBLOB_INSPECTA_INCLUDED -#include <opencv2/opencv.hpp> + #include <list> -#include "BlobLibraryConfiguration.h" -#include "BlobContour.h" + #include <opencv2/opencv.hpp> + #include "BlobLibraryConfiguration.h" + #include "BlobContour.h" //! Type of labelled images typedef unsigned int t_labelType; - //! Blob class class CBlob { - typedef std::list<CBlobContour> t_contourList; + typedef std::list<CBlobContour> t_contourList; public: - CBlob(); - CBlob( t_labelType id, cv::Point startPoint, cv::Size originalImageSize ); - ~CBlob(); - - //! Copy constructor - CBlob( const CBlob &src ); - CBlob( const CBlob *src ); - - //! Operador d'assignaci� - //! Assigment operator - CBlob& operator=(const CBlob &src ); - - //! Adds a new internal contour to the blob - void AddInternalContour( const CBlobContour &newContour ); - - //! Retrieves contour in Freeman's chain code - CBlobContour *GetExternalContour() - { - return &m_externalContour; - } - - //! Retrieves blob storage - CvMemStorage *GetStorage() - { - return m_storage; - } - - //! Get label ID - t_labelType GetID() - { - return m_id; - } - //! > 0 for extern blobs, 0 if not - int Exterior( IplImage *mask, bool xBorder = true, bool yBorder = true ); - //! Compute blob's area - double Area(); - //! Compute blob's perimeter - double Perimeter(); - //! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS) - double Moment(int p, int q); - - //! Compute extern perimeter - double ExternPerimeter( IplImage *mask, bool xBorder = true, bool yBorder = true ); - - //! Get mean grey color - double Mean( IplImage *image ); - - //! Get standard deviation grey color - double StdDev( IplImage *image ); - - //! Indica si el blob est� buit ( no t� cap info associada ) - //! Shows if the blob has associated information - bool IsEmpty(); - - //! Retorna el poligon convex del blob - //! Calculates the convex hull of the blob - t_PointList GetConvexHull(); - - //! Pinta l'interior d'un blob d'un color determinat - //! Paints the blob in an image - void FillBlob( IplImage *imatge, CvScalar color, int offsetX = 0, int offsetY = 0 ); - - //! Join a blob to current one (add's contour - void JoinBlob( CBlob *blob ); - - //! Get bounding box - CvRect GetBoundingBox(); - //! Get bounding ellipse - CvBox2D GetEllipse(); - - //! Minimun X - double MinX() - { - return GetBoundingBox().x; - } - //! Minimun Y - double MinY() - { - return GetBoundingBox().y; - } - //! Maximun X - double MaxX() - { - return GetBoundingBox().x + GetBoundingBox().width; - } - //! Maximun Y - double MaxY() - { - return GetBoundingBox().y + GetBoundingBox().height; - } + CBlob(); + CBlob(t_labelType id, cv::Point startPoint, cv::Size originalImageSize); + ~CBlob(); + + //! Copy constructor + CBlob(const CBlob& src); + CBlob(const CBlob* src); + + //! Operador d'assignaci� + //! Assigment operator + CBlob& operator=(const CBlob& src); + + //! Adds a new internal contour to the blob + void AddInternalContour(const CBlobContour& newContour); + + //! Retrieves contour in Freeman's chain code + CBlobContour* GetExternalContour() + { + return &m_externalContour; + } + + //! Retrieves blob storage + CvMemStorage* GetStorage() + { + return m_storage; + } + + //! Get label ID + t_labelType GetID() + { + return m_id; + } + //! > 0 for extern blobs, 0 if not + int Exterior(IplImage* mask, bool xBorder = true, bool yBorder = true); + //! Compute blob's area + double Area(); + //! Compute blob's perimeter + double Perimeter(); + //! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS) + double Moment(int p, int q); + + //! Compute extern perimeter + double ExternPerimeter(IplImage* mask, + bool xBorder = true, + bool yBorder = true); + + //! Get mean grey color + double Mean(IplImage* image); + + //! Get standard deviation grey color + double StdDev(IplImage* image); + + //! Indica si el blob est� buit ( no t� cap info associada ) + //! Shows if the blob has associated information + bool IsEmpty(); + + //! Retorna el poligon convex del blob + //! Calculates the convex hull of the blob + t_PointList GetConvexHull(); + + //! Pinta l'interior d'un blob d'un color determinat + //! Paints the blob in an image + void FillBlob(IplImage* imatge, + CvScalar color, + int offsetX = 0, + int offsetY = 0); + + //! Join a blob to current one (add's contour + void JoinBlob(CBlob* blob); + + //! Get bounding box + CvRect GetBoundingBox(); + //! Get bounding ellipse + CvBox2D GetEllipse(); + + //! Minimun X + double MinX() + { + return GetBoundingBox().x; + } + //! Minimun Y + double MinY() + { + return GetBoundingBox().y; + } + //! Maximun X + double MaxX() + { + return GetBoundingBox().x + GetBoundingBox().width; + } + //! Maximun Y + double MaxY() + { + return GetBoundingBox().y + GetBoundingBox().height; + } + private: - - //! Deallocates all contours - void ClearContours(); - ////////////////////////////////////////////////////////////////////////// - // Blob contours - ////////////////////////////////////////////////////////////////////////// - - - //! Contour storage memory - CvMemStorage *m_storage; - //! External contour of the blob (crack codes) - CBlobContour m_externalContour; - //! Internal contours (crack codes) - t_contourList m_internalContours; - - ////////////////////////////////////////////////////////////////////////// - // Blob features - ////////////////////////////////////////////////////////////////////////// - - //! Label number - t_labelType m_id; - //! Area - double m_area; - //! Perimeter - double m_perimeter; - //! Extern perimeter from blob - double m_externPerimeter; - //! Mean gray color - double m_meanGray; - //! Standard deviation from gray color blob distribution - double m_stdDevGray; - //! Bounding box - CvRect m_boundingBox; - //! Bounding ellipse - CvBox2D m_ellipse; - //! Sizes from image where blob is extracted - cv::Size m_originalImageSize; + //! Deallocates all contours + void ClearContours(); + ////////////////////////////////////////////////////////////////////////// + // Blob contours + ////////////////////////////////////////////////////////////////////////// + + //! Contour storage memory + CvMemStorage* m_storage; + //! External contour of the blob (crack codes) + CBlobContour m_externalContour; + //! Internal contours (crack codes) + t_contourList m_internalContours; + + ////////////////////////////////////////////////////////////////////////// + // Blob features + ////////////////////////////////////////////////////////////////////////// + + //! Label number + t_labelType m_id; + //! Area + double m_area; + //! Perimeter + double m_perimeter; + //! Extern perimeter from blob + double m_externPerimeter; + //! Mean gray color + double m_meanGray; + //! Standard deviation from gray color blob distribution + double m_stdDevGray; + //! Bounding box + CvRect m_boundingBox; + //! Bounding ellipse + CvBox2D m_ellipse; + //! Sizes from image where blob is extracted + cv::Size m_originalImageSize; }; -#endif //CBLOB_INSPECTA_INCLUDED +#endif // CBLOB_INSPECTA_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp index 15fc6f1370aa75a16ae2ac8e4172405d047f5f64..7cc18cbbeeaf7065480426e859a8c36fffd0619a 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp @@ -1,26 +1,23 @@ #include "IDetector.h" #include "../../../../helper/CvHelper.h" -template <typename T> +template<typename T> -std::vector<FishPose> IDetector<T>::convertBlobPosesToFishPoses(std::vector<BlobPose> blobPoses) +std::vector<FishPose> IDetector<T>::convertBlobPosesToFishPoses( + std::vector<BlobPose> blobPoses) { - std::vector<FishPose> fishPoses; - fishPoses.reserve(blobPoses.size()); + std::vector<FishPose> fishPoses; + fishPoses.reserve(blobPoses.size()); - for (BlobPose & blobPose : blobPoses) - { - fishPoses.push_back( - FishPose( - blobPose.posCm(), - blobPose.posPx(), - CvHelper::degToRad(blobPose.angleDegree()), - blobPose.angleDegree(), - blobPose.width(), - blobPose.height() - ) - ); - } + for (BlobPose& blobPose : blobPoses) { + fishPoses.push_back( + FishPose(blobPose.posCm(), + blobPose.posPx(), + CvHelper::degToRad(blobPose.angleDegree()), + blobPose.angleDegree(), + blobPose.width(), + blobPose.height())); + } - return fishPoses; + return fishPoses; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h index 8aa5db6bb6c63202c88d5606558bd528a04fd9f6..1e2b70d0428d584005dc671cf70a0c130e4c87df 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h @@ -4,63 +4,69 @@ #include "Interfaces/IModel/IModelAreaDescriptor.h" #include "blob/BlobPose.h" -template <typename T> +template<typename T> class IDetector { public: + /** + * The contructor with parameters. + * @param: rectification, the rectification object for calculation the real + * world coordinate. + * @param: systemProperty, the set of parameters for tracking property. + */ + IDetector(void) + { + } - /** - * The contructor with parameters. - * @param: rectification, the rectification object for calculation the real world coordinate. - * @param: systemProperty, the set of parameters for tracking property. - */ - IDetector(void) {} + /** + * The standard abtract destructor. + */ + ~IDetector(void) + { + } - /** - * The standard abtract destructor. - */ - ~IDetector(void) {} + /** + * Interface function to get the fish poses from a binarzied image. + * @param: binarized_image_mat, binarized image. + * @return: a list of fish poses. + */ + virtual std::vector<T> getPoses(cv::Mat& binImage, cv::Mat& oriImage) = 0; - /** - * Interface function to get the fish poses from a binarzied image. - * @param: binarized_image_mat, binarized image. - * @return: a list of fish poses. - */ - virtual std::vector<T> getPoses(cv::Mat& binImage, cv::Mat& oriImage) = 0; + /** + * Convert vector of blob poses to fishes poses. + * @param: blobPoses, vector of blob poses, + * @return: vector of fish poses. + */ + static std::vector<FishPose> convertBlobPosesToFishPoses( + std::vector<BlobPose> blobPoses); + /** + * Sets specified parameter with a double value. + * @param: spec_param, the specified parameter to set, + * @param: value, the value double to set, + * @return: void. + */ + virtual void setDouble(std::string spec_param, double value) = 0; - /** - * Convert vector of blob poses to fishes poses. - * @param: blobPoses, vector of blob poses, - * @return: vector of fish poses. - */ - static std::vector<FishPose> convertBlobPosesToFishPoses(std::vector<BlobPose> blobPoses); + /** + * Gets the specified parameter. + * @param: spec_param, the specified parameter to set, + * @return: the double value of the specifed paramter. + */ + // virtual void getDouble(std::string spec_param) = 0; - /** - * Sets specified parameter with a double value. - * @param: spec_param, the specified parameter to set, - * @param: value, the value double to set, - * @return: void. - */ - virtual void setDouble(std::string spec_param, double value) = 0; - - /** - * Gets the specified parameter. - * @param: spec_param, the specified parameter to set, - * @return: the double value of the specifed paramter. - */ - //virtual void getDouble(std::string spec_param) = 0; - - /** - * - */ - void setAreaInfo(IModelAreaDescriptor* ai) { - _areaInfo = ai; - } + /** + * + */ + void setAreaInfo(IModelAreaDescriptor* ai) + { + _areaInfo = ai; + } private: - virtual std::vector<T> findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) = 0; + virtual std::vector<T> findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage) = 0; protected: - IModelAreaDescriptor* _areaInfo; + IModelAreaDescriptor* _areaInfo; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp index aa7d449b8bec85247ed8b6eaaa3dd8601df1766f..7e550b9aa8dc49bddd3aa8bc5d81a594abe4f215 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp @@ -4,14 +4,20 @@ BlobPose::BlobPose(void) { } -BlobPose::BlobPose(cv::Point2f center_cm, cv::Point center_px, float angle_degree, float width, float height, bool use) : - _center_cm(center_cm), - _center_px(center_px), - _angle_degree(angle_degree), - _width(width), - _height(height), - _used(use) -{} +BlobPose::BlobPose(cv::Point2f center_cm, + cv::Point center_px, + float angle_degree, + float width, + float height, + bool use) +: _center_cm(center_cm) +, _center_px(center_px) +, _angle_degree(angle_degree) +, _width(width) +, _height(height) +, _used(use) +{ +} BlobPose::~BlobPose(void) { diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h index 4ebaf7b514c00dfcf12c45b95736541f2a7f27a6..94b710c017177c7f850acf7e8490fbcb14c0dc8e 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h @@ -5,82 +5,112 @@ class BlobPose { public: - /** - * The standard contructor. - */ - BlobPose(void); + /** + * The standard contructor. + */ + BlobPose(void); - /** - * The contructor with parameters. - * @param: pos_cm, position in real world coordinate. - * @param: pos_px, position in pixel coordinate. - * @param: angle_degree, orientation angle in degree. - * @param: width, width in px. - * @param: height, height in px. - * @param: used, check if this blob pose is currently in use. - */ - BlobPose(cv::Point2f pos_cm, cv::Point pos_px, float angle_degree, float width, float height, bool use = false); + /** + * The contructor with parameters. + * @param: pos_cm, position in real world coordinate. + * @param: pos_px, position in pixel coordinate. + * @param: angle_degree, orientation angle in degree. + * @param: width, width in px. + * @param: height, height in px. + * @param: used, check if this blob pose is currently in use. + */ + BlobPose(cv::Point2f pos_cm, + cv::Point pos_px, + float angle_degree, + float width, + float height, + bool use = false); - /** - * The standard destructor. - */ - ~BlobPose(void); + /** + * The standard destructor. + */ + ~BlobPose(void); - /** - * Gets the pixel position of the pose. - * @return pixel position. - */ - cv::Point posPx() { return _center_px; } + /** + * Gets the pixel position of the pose. + * @return pixel position. + */ + cv::Point posPx() + { + return _center_px; + } - /** - * Gets the real world position of the pose. - * @return real world position. - */ - cv::Point2f posCm() { return _center_cm; } + /** + * Gets the real world position of the pose. + * @return real world position. + */ + cv::Point2f posCm() + { + return _center_cm; + } - /** - * Gets the orientation angle as degree of the pose. - * @return degree angle. - */ - float angleDegree() { return _angle_degree; } + /** + * Gets the orientation angle as degree of the pose. + * @return degree angle. + */ + float angleDegree() + { + return _angle_degree; + } - /** - * Gets the width of the blob pose. - * @return width in px. - */ - float width() { return _width; } + /** + * Gets the width of the blob pose. + * @return width in px. + */ + float width() + { + return _width; + } - /** - * Gets the height of the blob pose. - * @return height in px. - */ - float height() { return _height; } + /** + * Gets the height of the blob pose. + * @return height in px. + */ + float height() + { + return _height; + } - /** - * Gets the flag whether this pose blob is already in use. - * @return true if is used, false otherwise. - */ - bool isUsed() { return _used; } + /** + * Gets the flag whether this pose blob is already in use. + * @return true if is used, false otherwise. + */ + bool isUsed() + { + return _used; + } - /** - * Sets the pixel position of the pose. - * @param int x, int y - * @return void. - */ - void setposPx(int x, int y) { cv::Point point(x,y); _center_px = point; } + /** + * Sets the pixel position of the pose. + * @param int x, int y + * @return void. + */ + void setposPx(int x, int y) + { + cv::Point point(x, y); + _center_px = point; + } - /** - * Sets the angle in degree. - * @param float angleDegree - * @return void. - */ - void setAngle(float angleDegree) { _angle_degree = angleDegree; } + /** + * Sets the angle in degree. + * @param float angleDegree + * @return void. + */ + void setAngle(float angleDegree) + { + _angle_degree = angleDegree; + } private: - bool _used; - cv::Point2f _center_cm; - cv::Point _center_px; - float _angle_degree; - float _width; - float _height; + bool _used; + cv::Point2f _center_cm; + cv::Point _center_px; + float _angle_degree; + float _width; + float _height; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp index cfd62a6ce774a2260960d741c62d458e19b850ba..4d302ce499e4a4ed439a84205706a02597f62ef5 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp @@ -2,79 +2,95 @@ #include "../../../../../../helper/CvHelper.h" #include <assert.h> -BlobsDetector::BlobsDetector(void) : - _mask(nullptr), - _minBlobSize(1), //TODO Min blob size - _maxBlobSize(99999) //TODO Max blob size -{} - +BlobsDetector::BlobsDetector(void) +: _mask(nullptr) +, _minBlobSize(1) +, // TODO Min blob size +_maxBlobSize(99999) // TODO Max blob size +{ +} void BlobsDetector::filterBlobsBySize(CBlobResult& blobs) { - // blobs smaller than the provided blob size - blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER_OR_EQUAL, minBlobSize()); - - // blobs bigger than the provided blob size - blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_LESS_OR_EQUAL, maxBlobSize()); + // blobs smaller than the provided blob size + blobs.Filter(blobs, + B_INCLUDE, + CBlobGetArea(), + B_GREATER_OR_EQUAL, + minBlobSize()); + + // blobs bigger than the provided blob size + blobs.Filter(blobs, + B_INCLUDE, + CBlobGetArea(), + B_LESS_OR_EQUAL, + maxBlobSize()); } -bool isLeft(cv::Point a, cv::Point b, cv::Point c) { - return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0; +bool isLeft(cv::Point a, cv::Point b, cv::Point c) +{ + return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) > 0; } -std::vector<BlobPose> BlobsDetector::findBlobs(const cv::Mat& processedImage, const cv::Mat& oriImage) +std::vector<BlobPose> BlobsDetector::findBlobs(const cv::Mat& processedImage, + const cv::Mat& oriImage) { - std::vector<BlobPose> blobPoses; + std::vector<BlobPose> blobPoses; + + CBlob* currentBlob; + CBlobResult blobs(processedImage, _mask, 0); - CBlob *currentBlob; - CBlobResult blobs(processedImage, _mask, 0); + // filter the blobs by size criteria + filterBlobsBySize(blobs); - // filter the blobs by size criteria - filterBlobsBySize(blobs); + for (int i = 0; i < blobs.GetNumBlobs(); i++) { + currentBlob = blobs.GetBlob(i); - for (int i = 0; i < blobs.GetNumBlobs(); i++) - { - currentBlob = blobs.GetBlob(i); + // gets blob center + int x = currentBlob->GetEllipse().center.x; + int y = currentBlob->GetEllipse().center.y; + cv::Point blobPose_px = cv::Point(x, y); - // gets blob center - int x = currentBlob->GetEllipse().center.x; - int y = currentBlob->GetEllipse().center.y; - cv::Point blobPose_px = cv::Point(x, y); + // apply homography + cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); - // apply homography - cv::Point2f blobPose_cm =_areaInfo->pxToCm(blobPose_px); + // ignore blobs outside the tracking area + if (!_areaInfo->inTrackingArea(blobPose_px)) + continue; - // ignore blobs outside the tracking area - if (!_areaInfo->inTrackingArea(blobPose_px)) - continue; - - float blobPose_angle_deg = currentBlob->GetEllipse().angle; - float blobPose_angle_rad = currentBlob->GetEllipse().angle * CV_PI / float(180.0); - assert(blobPose_angle_deg >= 0.0f && blobPose_angle_deg <= 360.0f); + float blobPose_angle_deg = currentBlob->GetEllipse().angle; + float blobPose_angle_rad = currentBlob->GetEllipse().angle * CV_PI / + float(180.0); + assert(blobPose_angle_deg >= 0.0f && blobPose_angle_deg <= 360.0f); - float blobPose_width = currentBlob->GetEllipse().size.width; - float blobPose_height = currentBlob->GetEllipse().size.height; + float blobPose_width = currentBlob->GetEllipse().size.width; + float blobPose_height = currentBlob->GetEllipse().size.height; - blobPoses.push_back(BlobPose(blobPose_cm, blobPose_px, blobPose_angle_deg, blobPose_angle_rad, blobPose_width, blobPose_height)); - } + blobPoses.push_back(BlobPose(blobPose_cm, + blobPose_px, + blobPose_angle_deg, + blobPose_angle_rad, + blobPose_width, + blobPose_height)); + } - return blobPoses; + return blobPoses; } -std::vector<BlobPose> BlobsDetector::getPoses(cv::Mat& processedImage, cv::Mat& oriImage) -{ - return findBlobs(processedImage, oriImage); +std::vector<BlobPose> BlobsDetector::getPoses(cv::Mat& processedImage, + cv::Mat& oriImage) +{ + return findBlobs(processedImage, oriImage); } void BlobsDetector::setDouble(std::string spec_param, double value) -{ - if(spec_param.compare("1") == 0) { - this->setMinBlobSize(value); - } - else if (spec_param.compare("999999") == 0) { - this->setMaxBlobSize(value); - } - else { - std::cout << "BlobsDetector::Warning - Parameter: " << spec_param << " not found!" << std::endl; - } +{ + if (spec_param.compare("1") == 0) { + this->setMinBlobSize(value); + } else if (spec_param.compare("999999") == 0) { + this->setMaxBlobSize(value); + } else { + std::cout << "BlobsDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h index e6e339ff0da796ef6ae67e30118867252ba0e46d..4d8a45d71f180b93a81f042fe352bad1c95ada3c 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h @@ -7,48 +7,65 @@ class BlobsDetector : public IDetector<BlobPose> { public: + /** + * The contructor with parameters. + * @param: rectification, the rectification object for calculation the real + * world coordinate. + * @param: systemProperty, the set of parameters for tracking property. + */ + BlobsDetector(void); - /** - * The contructor with parameters. - * @param: rectification, the rectification object for calculation the real world coordinate. - * @param: systemProperty, the set of parameters for tracking property. - */ - BlobsDetector(void); + virtual ~BlobsDetector(void) + { + } - virtual ~BlobsDetector(void) {} + void setMask(cv::Mat* mask) + { + _mask = mask; + } - void setMask(cv::Mat *mask) { _mask = mask; } + std::vector<BlobPose> getPoses(cv::Mat& binImage, cv::Mat& oriImage); - std::vector<BlobPose> getPoses(cv::Mat& binImage, cv::Mat& oriImage); - + void setDouble(std::string spec_param, double value); - void setDouble(std::string spec_param, double value); - - double minBlobSize() { return _minBlobSize; }; - double maxBlobSize() { return _maxBlobSize; }; - void setMinBlobSize(double x) { _minBlobSize = x; }; - void setMaxBlobSize(double x) { _maxBlobSize = x; }; + double minBlobSize() + { + return _minBlobSize; + }; + double maxBlobSize() + { + return _maxBlobSize; + }; + void setMinBlobSize(double x) + { + _minBlobSize = x; + }; + void setMaxBlobSize(double x) + { + _maxBlobSize = x; + }; private: + /** + * Removes blobs, which are too big for the further hanlding. + * @param: blobs, all possible blobs with all possible size. + * @return: void. + */ + void filterBlobsBySize(CBlobResult& blobs); + + /** + * Find all blobs within an image. + * @param: binarized_image_mat, image contains blobs and is already + * binarized, + * @return: all found blobs within the image. + */ + + // TODO: can we make binImage a reference?? + std::vector<BlobPose> findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage); + + double _minBlobSize; + double _maxBlobSize; - /** - * Removes blobs, which are too big for the further hanlding. - * @param: blobs, all possible blobs with all possible size. - * @return: void. - */ - void filterBlobsBySize(CBlobResult& blobs); - - /** - * Find all blobs within an image. - * @param: binarized_image_mat, image contains blobs and is already binarized, - * @return: all found blobs within the image. - */ - - // TODO: can we make binImage a reference?? - std::vector<BlobPose> findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - double _minBlobSize; - double _maxBlobSize; - - cv::Mat *_mask; + cv::Mat* _mask; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp index 4c5ae928ad3256ebdacd268984392cb949ef76c6..feb8be708c0c3b3889f04cf601774f3e24b502cf 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp @@ -2,79 +2,89 @@ #include "../../../../../../helper/CvHelper.h" #include <limits> -SimpleBlobsDetector::SimpleBlobsDetector(void) : _mask(nullptr) +SimpleBlobsDetector::SimpleBlobsDetector(void) +: _mask(nullptr) { - initParams(); + initParams(); } void SimpleBlobsDetector::initParams() { - _params.minThreshold = 15; - _params.maxThreshold = 50; - _params.thresholdStep = 5; - _params.filterByArea = true; - _params.minArea = 1; - _params.maxArea = 999999; - _params.filterByInertia = false; - _params.filterByColor = true; - _params.blobColor = 255; - _params.filterByCircularity = false; - _params.minDistBetweenBlobs = 0; + _params.minThreshold = 15; + _params.maxThreshold = 50; + _params.thresholdStep = 5; + _params.filterByArea = true; + _params.minArea = 1; + _params.maxArea = 999999; + _params.filterByInertia = false; + _params.filterByColor = true; + _params.blobColor = 255; + _params.filterByCircularity = false; + _params.minDistBetweenBlobs = 0; } - -std::vector<BlobPose> SimpleBlobsDetector::findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) +std::vector<BlobPose> SimpleBlobsDetector::findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage) { - std::vector<BlobPose> blobPoses; - - std::vector<cv::KeyPoint> keyPoints; + std::vector<BlobPose> blobPoses; - cv::Ptr<cv::SimpleBlobDetector> blobDetector = cv::SimpleBlobDetector::create(_params); + std::vector<cv::KeyPoint> keyPoints; - blobDetector->detect( binImage, keyPoints); + cv::Ptr<cv::SimpleBlobDetector> blobDetector = + cv::SimpleBlobDetector::create(_params); - for (int i = 0; i < keyPoints.size(); i++) - { - // gets blob center - int x = keyPoints.at(i).pt.x; - int y = keyPoints.at(i).pt.y; - cv::Point blobPose_px = cv::Point(x, y); + blobDetector->detect(binImage, keyPoints); - // apply homography - cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); + for (int i = 0; i < keyPoints.size(); i++) { + // gets blob center + int x = keyPoints.at(i).pt.x; + int y = keyPoints.at(i).pt.y; + cv::Point blobPose_px = cv::Point(x, y); - if (!_areaInfo->inTrackingArea(blobPose_px)) - continue; + // apply homography + cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); - float blobPose_angleDegree = keyPoints.at(i).angle; // as degree (0..360) - float blobPose_angleRadian = keyPoints.at(i).angle * float(CV_PI) / float(180.0); - float blobPose_width = keyPoints.at(i).size; - float blobPose_height = keyPoints.at(i).size; + if (!_areaInfo->inTrackingArea(blobPose_px)) + continue; - blobPoses.push_back(BlobPose(blobPose_cm, blobPose_px, blobPose_angleDegree, blobPose_angleRadian, blobPose_width, blobPose_height)); - } + float blobPose_angleDegree = + keyPoints.at(i).angle; // as degree (0..360) + float blobPose_angleRadian = keyPoints.at(i).angle * float(CV_PI) / + float(180.0); + float blobPose_width = keyPoints.at(i).size; + float blobPose_height = keyPoints.at(i).size; + blobPoses.push_back(BlobPose(blobPose_cm, + blobPose_px, + blobPose_angleDegree, + blobPose_angleRadian, + blobPose_width, + blobPose_height)); + } - return blobPoses; + return blobPoses; } - -std::vector<BlobPose> SimpleBlobsDetector::getPoses(cv::Mat& binarized_image_mat, cv::Mat& original_image_mat) -{ - return findBlobs(binarized_image_mat,original_image_mat); +std::vector<BlobPose> SimpleBlobsDetector::getPoses( + cv::Mat& binarized_image_mat, + cv::Mat& original_image_mat) +{ + return findBlobs(binarized_image_mat, original_image_mat); } void SimpleBlobsDetector::setDouble(std::string spec_param, double value) -{ - if(spec_param.compare("1") == 0) { //TRACKERPARAM::MIN_BLOB_SIZE - _params.minArea = value; - } else { - std::cout << "SimpleBlobsDetector::Warning - Parameter: " << spec_param << " not found!" << std::endl; - } - - if(spec_param.compare("999999") == 0) { //TRACKERPARAM::MAX_BLOB_SIZE - _params.maxArea = value; - } else { - std::cout << "SimpleBlobsDetector::Warning - Parameter: " << spec_param << " not found!" << std::endl; - } +{ + if (spec_param.compare("1") == 0) { // TRACKERPARAM::MIN_BLOB_SIZE + _params.minArea = value; + } else { + std::cout << "SimpleBlobsDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; + } + + if (spec_param.compare("999999") == 0) { // TRACKERPARAM::MAX_BLOB_SIZE + _params.maxArea = value; + } else { + std::cout << "SimpleBlobsDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h index e5b3be4c1d4dc30f8f95f42611543baaa8e5f8eb..8abc0ad6466d3f4ca56c066b977ad61d78c6f06f 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h @@ -11,39 +11,42 @@ class SimpleBlobsDetector : public IDetector<BlobPose> { public: + /** + * The contructor with parameters. + */ + SimpleBlobsDetector(void); - /** - * The contructor with parameters. - */ - SimpleBlobsDetector(void); + virtual ~SimpleBlobsDetector(void) + { + } - virtual ~SimpleBlobsDetector(void) {} + void setMask(cv::Mat* mask) + { + _mask = mask; + } - void setMask(cv::Mat *mask) { _mask = mask; } - - std::vector<BlobPose> getPoses(cv::Mat& binImage, cv::Mat& oriImage); + std::vector<BlobPose> getPoses(cv::Mat& binImage, cv::Mat& oriImage); - void setDouble(std::string spec_param, double value); + void setDouble(std::string spec_param, double value); private: - - cv::Mat *_mask; - cv::SimpleBlobDetector::Params _params; - - /** - * Initialized the parameter for setting up the blob detector. - * @return: void. - */ - void initParams(); - - /** - * Find all blobs within an image. - * @param: binarized_image_mat, image contains blobs and is already binarized, - * @return: all found blobs within the image. - */ - - // TODO: can we make binImage a reference?? - std::vector<BlobPose> findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - + cv::Mat* _mask; + cv::SimpleBlobDetector::Params _params; + + /** + * Initialized the parameter for setting up the blob detector. + * @return: void. + */ + void initParams(); + + /** + * Find all blobs within an image. + * @param: binarized_image_mat, image contains blobs and is already + * binarized, + * @return: all found blobs within the image. + */ + + // TODO: can we make binImage a reference?? + std::vector<BlobPose> findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage); }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp index cd65b94fd423c311606e01f2ee7a2c3842c36c58..2bc733f2c5c72a1c3dc3aeaaaa90fb629b5162d9 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp @@ -4,14 +4,20 @@ ContourPose::ContourPose(void) { } -ContourPose::ContourPose(cv::Point2f center_cm, cv::Point center_px, float angle_degree, float width, float height, bool use) : - _center_cm(center_cm), - _center_px(center_px), - _angle_degree(angle_degree), - _width(width), - _height(height), - _used(use) -{} +ContourPose::ContourPose(cv::Point2f center_cm, + cv::Point center_px, + float angle_degree, + float width, + float height, + bool use) +: _center_cm(center_cm) +, _center_px(center_px) +, _angle_degree(angle_degree) +, _width(width) +, _height(height) +, _used(use) +{ +} ContourPose::~ContourPose(void) { diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h index 4e7e3da2fa1cd423b05a676987c0906beeaeb7a2..3323b96063b8e7fca84e360fbc6ad238249022ed 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h @@ -1,72 +1,94 @@ -#pragma once +#pragma once #include <opencv2/opencv.hpp> class ContourPose { public: - /** - * The standard contructor. - */ - ContourPose(void); + /** + * The standard contructor. + */ + ContourPose(void); - /** - * The contructor with parameters. - * @param: pos_cm, position in real world coordinate. - * @param: pos_px, position in pixel coordinate. - * @param: angle_degree, orientation angle in degree. - * @param: width, width in px. - * @param: height, height in px. - * @param: used, check if this blob pose is currently in use. - */ - ContourPose(cv::Point2f pos_cm, cv::Point pos_px, float angle_degree, float width, float height, bool use = false); + /** + * The contructor with parameters. + * @param: pos_cm, position in real world coordinate. + * @param: pos_px, position in pixel coordinate. + * @param: angle_degree, orientation angle in degree. + * @param: width, width in px. + * @param: height, height in px. + * @param: used, check if this blob pose is currently in use. + */ + ContourPose(cv::Point2f pos_cm, + cv::Point pos_px, + float angle_degree, + float width, + float height, + bool use = false); - /** - * The standard destructor. - */ - ~ContourPose(void); + /** + * The standard destructor. + */ + ~ContourPose(void); - /** - * Gets the pixel position of the pose. - * @return pixel position. - */ - cv::Point posPx() { return _center_px; } + /** + * Gets the pixel position of the pose. + * @return pixel position. + */ + cv::Point posPx() + { + return _center_px; + } - /** - * Gets the real world position of the pose. - * @return real world position. - */ - cv::Point2f posCm() { return _center_cm; } + /** + * Gets the real world position of the pose. + * @return real world position. + */ + cv::Point2f posCm() + { + return _center_cm; + } - /** - * Gets the orientation angle as degree of the pose. - * @return degree angle. - */ - float angleDegree() { return _angle_degree; } + /** + * Gets the orientation angle as degree of the pose. + * @return degree angle. + */ + float angleDegree() + { + return _angle_degree; + } - /** - * Gets the width of the blob pose. - * @return width in px. - */ - float width() { return _width; } + /** + * Gets the width of the blob pose. + * @return width in px. + */ + float width() + { + return _width; + } - /** - * Gets the height of the blob pose. - * @return height in px. - */ - float height() { return _height; } - - /** - * Gets the flag whether this pose blob is already in use. - * @return true if is used, false otherwise. - */ - bool isUsed() { return _used; } + /** + * Gets the height of the blob pose. + * @return height in px. + */ + float height() + { + return _height; + } + /** + * Gets the flag whether this pose blob is already in use. + * @return true if is used, false otherwise. + */ + bool isUsed() + { + return _used; + } private: - bool _used; - cv::Point2f _center_cm; - cv::Point _center_px; - float _angle_degree; - float _width; - float _height; + bool _used; + cv::Point2f _center_cm; + cv::Point _center_px; + float _angle_degree; + float _width; + float _height; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp index 59e7a93119c23e8709586820651ba2c68ffbcce6..6a76e59786859b05472b6744c5935fb238a30b86 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp @@ -1,33 +1,38 @@ #include "ContoursDetector.h" #include "../../../../../helper/CvHelper.h" -std::vector<ContourPose> ContoursDetector::findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) +std::vector<ContourPose> ContoursDetector::findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage) { - std::vector<ContourPose> contourPoses; + std::vector<ContourPose> contourPoses; - return contourPoses; + return contourPoses; } -std::vector<ContourPose> ContoursDetector::findContours(const cv::Mat& binImage, const cv::Mat& oriImage) +std::vector<ContourPose> ContoursDetector::findContours( + const cv::Mat& binImage, + const cv::Mat& oriImage) { - return findBlobs(binImage,oriImage); + return findBlobs(binImage, oriImage); } void ContoursDetector::createMask(std::vector<cv::Point> points) -{} +{ +} // if (_xRes == 0 || _yRes == 0) // return; // -// mask = cvCreateImage(cvSize(_xRes, _yRes), IPL_DEPTH_8U,1);//erstellt schwarzwei� bild +// mask = cvCreateImage(cvSize(_xRes, _yRes), IPL_DEPTH_8U,1);//erstellt +//schwarzwei� bild // // //folgender Block setzt die Pixel schwarz -// for( int y=0; y<mask->height; y++ ) { -// uchar* ptr = (uchar*) ( mask->imageData + y * mask->widthStep ); -// for( int x=0; x<mask->width; x++ ) { -// ptr[x+2] = 0; +// for( int y=0; y<mask->height; y++ ) { +// uchar* ptr = (uchar*) ( mask->imageData + y * mask->widthStep ); +// for( int x=0; x<mask->width; x++ ) { +// ptr[x+2] = 0; // } // } -// +// // cv::Point maskPoints[4]; // // for(int z=0;z<4;z++) @@ -56,13 +61,14 @@ void ContoursDetector::createMask(std::vector<cv::Point> points) // //cvDestroyWindow("MyWindow"); //} - -std::vector<ContourPose> ContoursDetector::getPoses(cv::Mat& image_mat, cv::Mat& image_ori) -{ - return findContours(image_mat,image_ori); +std::vector<ContourPose> ContoursDetector::getPoses(cv::Mat& image_mat, + cv::Mat& image_ori) +{ + return findContours(image_mat, image_ori); } void ContoursDetector::setDouble(std::string spec_param, double value) -{ - std::cout << "ContoursDetector::Warning - Parameter: " << spec_param << " not found!" << std::endl; +{ + std::cout << "ContoursDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; } \ No newline at end of file diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h index 71fd301b855b5dbe8c9bbb78a5fe7924d1db55e2..d24a454fcfdfec48539632fccf1a7ca11427fe40 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h @@ -7,30 +7,35 @@ class ContoursDetector : public IDetector<ContourPose> { public: + /** + * The contructor with parameters. + */ + ContoursDetector(void) + { + } - /** - * The contructor with parameters. - */ - ContoursDetector(void) {} + ~ContoursDetector(void) + { + } - ~ContoursDetector(void) {} + std::vector<ContourPose> getPoses(cv::Mat& binImage, cv::Mat& oriImage); - std::vector<ContourPose> getPoses(cv::Mat& binImage, cv::Mat& oriImage); - - void setDouble(std::string spec_param, double value); + void setDouble(std::string spec_param, double value); private: + /** + * Find all cntours within an image. + * @param: binarized_image_mat, image contains blobs and is already + * binarized, + * @return: all found blobs within the image. + */ + std::vector<ContourPose> findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage); - /** - * Find all cntours within an image. - * @param: binarized_image_mat, image contains blobs and is already binarized, - * @return: all found blobs within the image. - */ - std::vector<ContourPose> findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - std::vector<ContourPose> findContours(const cv::Mat& binImage, const cv::Mat& oriImage); + std::vector<ContourPose> findContours(const cv::Mat& binImage, + const cv::Mat& oriImage); - void createMask(std::vector<cv::Point> points); + void createMask(std::vector<cv::Point> points); - cv::Mat _mask; + cv::Mat _mask; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp index cf8f62a7d65f875b594b606ba52e6ae2e2161f6b..fab85807a338c7ca8626302b827886c23f526027 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -9,77 +9,83 @@ CustomBackgroundSubtractor::CustomBackgroundSubtractor() : m_useAbsoluteDifference{true} , m_binarizationThreshold{8} { - } void CustomBackgroundSubtractor::setUseAbsoluteDifference(bool value) { - m_useAbsoluteDifference = value; + m_useAbsoluteDifference = value; } void CustomBackgroundSubtractor::setBinarizationThreshold(int value) { - m_binarizationThreshold = value; + m_binarizationThreshold = value; } -void CustomBackgroundSubtractor::getBackgroundImage(cv::OutputArray backgroundImage) const +void CustomBackgroundSubtractor::getBackgroundImage( + cv::OutputArray backgroundImage) const { - m_background.copyTo(backgroundImage); + m_background.copyTo(backgroundImage); } -void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate) +void CustomBackgroundSubtractor::apply(cv::InputArray image, + cv::OutputArray fgmask, + double learningRate) { - if (!m_background.data) { - image.copyTo(m_background); - } - - const int imageWidth = m_background.cols; - const int imageHeight = m_background.rows; - const int totalRegionsX = 4; - const int totalRegionsY = 4; - const int totalRegions = totalRegionsX * totalRegionsY; - const int regionWidth = imageWidth / totalRegionsX; - const int regionHeight = imageHeight / totalRegionsY; - - fgmask.create(imageHeight, imageWidth, image.type()); - - auto fgmaskmat = fgmask.getMat(); - - const auto useAbsoluteDifference = m_useAbsoluteDifference; - - auto workOnRegion = [&, useAbsoluteDifference](int x, int y) { - const int startingX = x * regionWidth; - const int startingY = y * regionHeight; - const cv::Rect subArea = cv::Rect(startingX, startingY, regionWidth, regionHeight); - cv::Mat subBackground = m_background(subArea); - cv::Mat subImage = image.getMat()(subArea); - cv::Mat subResults = fgmaskmat(subArea); - - if (useAbsoluteDifference) { - cv::absdiff(subBackground, subImage, subResults); - } else { - cv::subtract(subBackground, subImage, subResults); - } - - subBackground = (1.0 - learningRate) * subBackground + learningRate * subImage; - }; - - std::vector<std::future<void>> merger; - merger.reserve(totalRegions); - - for (int x = 0; x < totalRegionsX; ++x) - { - for (int y = 0; y < totalRegionsY; ++y) - { - merger.push_back(std::async([&, x, y] { workOnRegion(x, y); })); - } - } - - for (const auto & asyncResult : merger) { - asyncResult.wait(); - } - - if (fgmaskmat.data) { - cv::threshold(fgmaskmat, fgmaskmat, m_binarizationThreshold, 255, cv::THRESH_BINARY); - } + if (!m_background.data) { + image.copyTo(m_background); + } + + const int imageWidth = m_background.cols; + const int imageHeight = m_background.rows; + const int totalRegionsX = 4; + const int totalRegionsY = 4; + const int totalRegions = totalRegionsX * totalRegionsY; + const int regionWidth = imageWidth / totalRegionsX; + const int regionHeight = imageHeight / totalRegionsY; + + fgmask.create(imageHeight, imageWidth, image.type()); + + auto fgmaskmat = fgmask.getMat(); + + const auto useAbsoluteDifference = m_useAbsoluteDifference; + + auto workOnRegion = [&, useAbsoluteDifference](int x, int y) { + const int startingX = x * regionWidth; + const int startingY = y * regionHeight; + const cv::Rect subArea = + cv::Rect(startingX, startingY, regionWidth, regionHeight); + cv::Mat subBackground = m_background(subArea); + cv::Mat subImage = image.getMat()(subArea); + cv::Mat subResults = fgmaskmat(subArea); + + if (useAbsoluteDifference) { + cv::absdiff(subBackground, subImage, subResults); + } else { + cv::subtract(subBackground, subImage, subResults); + } + + subBackground = (1.0 - learningRate) * subBackground + + learningRate * subImage; + }; + + std::vector<std::future<void>> merger; + merger.reserve(totalRegions); + + for (int x = 0; x < totalRegionsX; ++x) { + for (int y = 0; y < totalRegionsY; ++y) { + merger.push_back(std::async([&, x, y] { workOnRegion(x, y); })); + } + } + + for (const auto& asyncResult : merger) { + asyncResult.wait(); + } + + if (fgmaskmat.data) { + cv::threshold(fgmaskmat, + fgmaskmat, + m_binarizationThreshold, + 255, + cv::THRESH_BINARY); + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h index 94c79b0acfa95a8bbfa390f6b20fe03dfbc3389b..9d611ca9665e7c74673b31a4c3a8222aba755ae7 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h @@ -5,19 +5,21 @@ class CustomBackgroundSubtractor : public cv::BackgroundSubtractor { public: - CustomBackgroundSubtractor(); + CustomBackgroundSubtractor(); - void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = -1) override; + void apply(cv::InputArray image, + cv::OutputArray fgmask, + double learningRate = -1) override; - void getBackgroundImage(cv::OutputArray backgroundImage) const override; + void getBackgroundImage(cv::OutputArray backgroundImage) const override; - void setUseAbsoluteDifference(bool value); - void setBinarizationThreshold(int value); + void setUseAbsoluteDifference(bool value); + void setBinarizationThreshold(int value); private: - cv::Mat m_background; + cv::Mat m_background; - bool m_useAbsoluteDifference; + bool m_useAbsoluteDifference; - int m_binarizationThreshold; + int m_binarizationThreshold; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 9f241aa4f59e97245e2461e13e392b19a7dde86f..ab6d428433a5878e730e72b3781e0abf5a57c24a 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -10,122 +10,136 @@ QMutex bgsMutex; -ImagePreProcessor::ImagePreProcessor(TrackerParameter* TrackingParameter) : - m_subtractor(nullptr), - m_TrackingParameter{TrackingParameter} +ImagePreProcessor::ImagePreProcessor(TrackerParameter* TrackingParameter) +: m_subtractor(nullptr) +, m_TrackingParameter{TrackingParameter} { - init(); + init(); } ImagePreProcessor::~ImagePreProcessor(void) { } - void ImagePreProcessor::init() { - QMutexLocker locker(&bgsMutex); - - auto algorithm = m_TrackingParameter->getAlgorithm(); - if (algorithm == QString("Custom")) { - m_subtractor = new CustomBackgroundSubtractor(); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - m_backgroundImage = std::make_shared<cv::Mat>(); - m_foregroundMask = std::make_shared<cv::Mat>(); - - _backgroundSubtractionEnabled = true; - _backgroundEnabled = true; - _erodeEnabled = true; - _dilateEnabled = true; - _gaussianBlurEnabled = false; - _binarizeEnabled = true; - _resetBackgroundImageEnabled = false; + QMutexLocker locker(&bgsMutex); + + auto algorithm = m_TrackingParameter->getAlgorithm(); + if (algorithm == QString("Custom")) { + m_subtractor = new CustomBackgroundSubtractor(); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + m_backgroundImage = std::make_shared<cv::Mat>(); + m_foregroundMask = std::make_shared<cv::Mat>(); + + _backgroundSubtractionEnabled = true; + _backgroundEnabled = true; + _erodeEnabled = true; + _dilateEnabled = true; + _gaussianBlurEnabled = false; + _binarizeEnabled = true; + _resetBackgroundImageEnabled = false; } cv::Mat ImagePreProcessor::erode(cv::Mat& image) { - cv::Mat erodedImage; - cv::Mat erodeKernel; - int sizeErode = m_TrackingParameter->getSizeErode(); - if (sizeErode > 0) - { - erodeKernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(sizeErode, sizeErode)); - } - else { - return image; - } - if (image.data) - cv::erode(image, erodedImage, erodeKernel); - return erodedImage; + cv::Mat erodedImage; + cv::Mat erodeKernel; + int sizeErode = m_TrackingParameter->getSizeErode(); + if (sizeErode > 0) { + erodeKernel = cv::getStructuringElement( + cv::MORPH_CROSS, + cv::Size(sizeErode, sizeErode)); + } else { + return image; + } + if (image.data) + cv::erode(image, erodedImage, erodeKernel); + return erodedImage; } cv::Mat ImagePreProcessor::dilate(cv::Mat& image) { - cv::Mat dilatedImage; - cv::Mat dilateKernel; - int sizeDilate = m_TrackingParameter->getSizeDilate(); - if (sizeDilate > 0) - { - dilateKernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(sizeDilate, sizeDilate)); - } - else { - return image; - } - if (image.data) - cv::dilate(image, dilatedImage, dilateKernel); - return dilatedImage; + cv::Mat dilatedImage; + cv::Mat dilateKernel; + int sizeDilate = m_TrackingParameter->getSizeDilate(); + if (sizeDilate > 0) { + dilateKernel = cv::getStructuringElement( + cv::MORPH_RECT, + cv::Size(sizeDilate, sizeDilate)); + } else { + return image; + } + if (image.data) + cv::dilate(image, dilatedImage, dilateKernel); + return dilatedImage; } cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) { - if (auto subtractor = m_subtractor.dynamicCast<CustomBackgroundSubtractor>(); subtractor) { - if (m_TrackingParameter->getAlgorithm() != QString("Custom")) { - init(); - } - subtractor->setUseAbsoluteDifference(m_TrackingParameter->getUseAbsoluteDifference()); - subtractor->setBinarizationThreshold(m_TrackingParameter->getBinarizationThreshold()); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - cv::Mat fgmask; - m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate()); - m_subtractor->getBackgroundImage(*m_backgroundImage); - return fgmask; + if (auto subtractor = + m_subtractor.dynamicCast<CustomBackgroundSubtractor>(); + subtractor) { + if (m_TrackingParameter->getAlgorithm() != QString("Custom")) { + init(); + } + subtractor->setUseAbsoluteDifference( + m_TrackingParameter->getUseAbsoluteDifference()); + subtractor->setBinarizationThreshold( + m_TrackingParameter->getBinarizationThreshold()); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + cv::Mat fgmask; + m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate()); + m_subtractor->getBackgroundImage(*m_backgroundImage); + return fgmask; } -std::map<std::string, std::shared_ptr<cv::Mat>> ImagePreProcessor::preProcess(std::shared_ptr<cv::Mat> p_image) +std::map<std::string, std::shared_ptr<cv::Mat>> ImagePreProcessor::preProcess( + std::shared_ptr<cv::Mat> p_image) { - std::shared_ptr<cv::Mat> greyMat = std::make_shared<cv::Mat>(); - std::shared_ptr<cv::Mat> erodedImage = std::make_shared<cv::Mat>(); - std::shared_ptr<cv::Mat> dilatedImage = std::make_shared<cv::Mat>(); - - cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); - - // 1. step: do the background subtraction - *m_foregroundMask = backgroundSubtraction(*greyMat); - - // 2. step: erode the image - *erodedImage = erode(*m_foregroundMask); - - // 3. step: dilate the image - *dilatedImage = dilate(*erodedImage); - - std::map<std::string, std::shared_ptr<cv::Mat>> all; - all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Greyscale"), greyMat)); - all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Background"), m_backgroundImage)); - all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Foreground Mask"), m_foregroundMask)); - all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Eroded"), erodedImage)); - all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Dilated"), dilatedImage)); - - return all; + std::shared_ptr<cv::Mat> greyMat = std::make_shared<cv::Mat>(); + std::shared_ptr<cv::Mat> erodedImage = std::make_shared<cv::Mat>(); + std::shared_ptr<cv::Mat> dilatedImage = std::make_shared<cv::Mat>(); + + cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); + + // 1. step: do the background subtraction + *m_foregroundMask = backgroundSubtraction(*greyMat); + + // 2. step: erode the image + *erodedImage = erode(*m_foregroundMask); + + // 3. step: dilate the image + *dilatedImage = dilate(*erodedImage); + + std::map<std::string, std::shared_ptr<cv::Mat>> all; + all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>( + std::string("Greyscale"), + greyMat)); + all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>( + std::string("Background"), + m_backgroundImage)); + all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>( + std::string("Foreground Mask"), + m_foregroundMask)); + all.insert( + std::pair<std::string, std::shared_ptr<cv::Mat>>(std::string("Eroded"), + erodedImage)); + all.insert(std::pair<std::string, std::shared_ptr<cv::Mat>>( + std::string("Dilated"), + dilatedImage)); + + return all; } void ImagePreProcessor::resetBackgroundImage() { - // this will reset the background at the next opportunity - init(); + // this will reset the background at the next opportunity + init(); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index bb03f38eddc924a97fbb7e6ade66480a1fb0cc48..b190f3941da64fa48b76edacc5bb343c9fb64b4e 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -4,87 +4,83 @@ #include <opencv2/opencv.hpp> -#include "../../../../helper/StringHelper.h" #include "../../../TrackerParameter.h" - class ImagePreProcessor { public: + /** + * The standard constructor. + */ + ImagePreProcessor(TrackerParameter* TrackingParameter); + + /** + * The standard destructor. + */ + ~ImagePreProcessor(); + + /** + * Init function. Sets the property for the imge pre-processing. + * @return void. + */ + void init(); + + /** + * A mathematical morphology operation using in computer vision to erode an + * image. Erode image with 3x3 4-connectivity. + * @param: image, image to erode, + * @return: an eroded image. + */ + cv::Mat erode(cv::Mat& image); + + /** + * A mathematical morphology operation using in computer vision to dilate + * an image. Dilate image with 6x6 8-connectivity. + * @param: image, image to dilate, + * @return: a dilated image. + */ + cv::Mat dilate(cv::Mat& image); + + /** + * A computer vision methode to calculate the image difference. + * Background image subtracts the foreground image. + * @param: image, image to background subtract, + * @return: the background subtracted image. + */ + cv::Mat backgroundSubtraction(cv::Mat& image); + + /** + * Pre-process an image, if all methods enabled, this function: + * - does the background subtraction + * - erodes the image + * - dilates the image + * @param: image, image to process, + * @return: a pre-process image. + */ + std::map<std::string, std::shared_ptr<cv::Mat>> preProcess( + std::shared_ptr<cv::Mat> p_image); + + /** + * The method updates the image background. + * @return: void. + */ + void resetBackgroundImage(); + TrackerParameter* m_TrackingParameter; - /** - * The standard constructor. - */ - ImagePreProcessor(TrackerParameter* TrackingParameter); - - /** - * The standard destructor. - */ - ~ImagePreProcessor(); - - /** - * Init function. Sets the property for the imge pre-processing. - * @return void. - */ - void init(); - - /** - * A mathematical morphology operation using in computer vision to erode an image. - * Erode image with 3x3 4-connectivity. - * @param: image, image to erode, - * @return: an eroded image. - */ - cv::Mat erode(cv::Mat& image); - - /** - * A mathematical morphology operation using in computer vision to dilate an image. - * Dilate image with 6x6 8-connectivity. - * @param: image, image to dilate, - * @return: a dilated image. - */ - cv::Mat dilate(cv::Mat& image); - - /** - * A computer vision methode to calculate the image difference. - * Background image subtracts the foreground image. - * @param: image, image to background subtract, - * @return: the background subtracted image. - */ - cv::Mat backgroundSubtraction(cv::Mat& image); - - /** - * Pre-process an image, if all methods enabled, this function: - * - does the background subtraction - * - erodes the image - * - dilates the image - * @param: image, image to process, - * @return: a pre-process image. - */ - std::map<std::string, std::shared_ptr<cv::Mat>> preProcess(std::shared_ptr<cv::Mat> p_image); - - /** - * The method updates the image background. - * @return: void. - */ - void resetBackgroundImage(); - TrackerParameter* m_TrackingParameter; - private: + cv::Mat _outputImage; + std::shared_ptr<cv::Mat> m_backgroundImage; + std::shared_ptr<cv::Mat> m_foregroundMask; - cv::Mat _outputImage; - - std::shared_ptr<cv::Mat> m_backgroundImage; - std::shared_ptr<cv::Mat> m_foregroundMask; - - //parameters for image pre-processing - bool _backgroundSubtractionEnabled; - bool _backgroundEnabled; - bool _binarizeEnabled; - bool _erodeEnabled; - bool _dilateEnabled; - bool _gaussianBlurEnabled; - bool _resetBackgroundImageEnabled; + // parameters for image pre-processing + bool _backgroundSubtractionEnabled; + bool _backgroundEnabled; + bool _binarizeEnabled; + bool _erodeEnabled; + bool _dilateEnabled; + bool _gaussianBlurEnabled; + bool _resetBackgroundImageEnabled; - cv::Ptr<cv::BackgroundSubtractor> m_subtractor; + cv::Ptr<cv::BackgroundSubtractor> m_subtractor; }; diff --git a/Src/Model/null_Model.cpp b/Src/Model/null_Model.cpp index db2793d0195a5d1ce8905db2a5496bf564288d16..4328117f9fb70975895be8119d05c4648c87ee7d 100644 --- a/Src/Model/null_Model.cpp +++ b/Src/Model/null_Model.cpp @@ -2,5 +2,4 @@ null_Model::null_Model() { - } diff --git a/Src/PluginContext.cpp b/Src/PluginContext.cpp index 3501bae01d9d7f581589e4ab06708cf629d47da0..7ce0a5c4dcc295b3ba05fb937d8e8631ccf656a2 100644 --- a/Src/PluginContext.cpp +++ b/Src/PluginContext.cpp @@ -3,35 +3,39 @@ #include "Controller/ControllerTrackingAlgorithm.h" #include "Controller/ControllerTrackedComponent.h" -PluginContext::PluginContext(QObject *parent, Config *cfg) : - IBioTrackerContext(parent) +PluginContext::PluginContext(QObject* parent, Config* cfg) +: IBioTrackerContext(parent) { - _cfg = cfg; - ControllerTrackedComponent* ComponentController = new ControllerTrackedComponent(this, this, ENUMS::CONTROLLERTYPE::COMPONENT); - ControllerTrackingAlgorithm* TrackingController = new ControllerTrackingAlgorithm(this, this, ENUMS::CONTROLLERTYPE::TRACKING); - ComponentController->setConfig(_cfg); - TrackingController->setConfig(_cfg); + _cfg = cfg; + ControllerTrackedComponent* ComponentController = + new ControllerTrackedComponent(this, + this, + ENUMS::CONTROLLERTYPE::COMPONENT); + ControllerTrackingAlgorithm* TrackingController = + new ControllerTrackingAlgorithm(this, + this, + ENUMS::CONTROLLERTYPE::TRACKING); + ComponentController->setConfig(_cfg); + TrackingController->setConfig(_cfg); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMPONENT, ComponentController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKING, TrackingController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMPONENT, + ComponentController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKING, + TrackingController); } void PluginContext::createAppController() { - QMap<ENUMS::CONTROLLERTYPE, IController *>::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->createComponents(); - } + QMap<ENUMS::CONTROLLERTYPE, IController*>::iterator i; + for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) { + i.value()->createComponents(); + } } void PluginContext::connectController() { - QMap<ENUMS::CONTROLLERTYPE, IController *>::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->connectComponents(); - } + QMap<ENUMS::CONTROLLERTYPE, IController*>::iterator i; + for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) { + i.value()->connectComponents(); + } } - - diff --git a/Src/PluginContext.h b/Src/PluginContext.h index 403ff4da799a9fff939396a90470098c9bedc33a..395728e958e32581ba1a6a64cd0999c4b9ee3605 100644 --- a/Src/PluginContext.h +++ b/Src/PluginContext.h @@ -5,17 +5,16 @@ class PluginContext : public IBioTrackerContext { - Q_OBJECT + Q_OBJECT public: - PluginContext(QObject *parent, Config *cfg); + PluginContext(QObject* parent, Config* cfg); - // IBioTrackerContext interface + // IBioTrackerContext interface protected: - void createAppController() override; - void connectController() override; + void createAppController() override; + void connectController() override; private: - Config *_cfg; + Config* _cfg; }; - diff --git a/Src/View/TrackedElementView.cpp b/Src/View/TrackedElementView.cpp index 8b29f6afa260ed716aa0c8cb1a9b9bedea71f2dd..c203911a02942511097fb52190c15df4dde89789 100644 --- a/Src/View/TrackedElementView.cpp +++ b/Src/View/TrackedElementView.cpp @@ -10,14 +10,17 @@ class QGraphicsSceneHoverEvent; -TrackedElementView::TrackedElementView(QGraphicsItem *parent, IController *controller, IModel *model) : - IViewTrackedComponent(parent, controller, model) +TrackedElementView::TrackedElementView(QGraphicsItem* parent, + IController* controller, + IModel* model) +: IViewTrackedComponent(parent, controller, model) { - BST::TrackedElement *elem = dynamic_cast<BST::TrackedElement *>(getModel()); - _boundingRect = QRectF(0,0, 100, 100); + BST::TrackedElement* elem = dynamic_cast<BST::TrackedElement*>(getModel()); + _boundingRect = QRectF(0, 0, 100, 100); } -void TrackedElementView::rcvDimensionUpdate(int x, int y) { +void TrackedElementView::rcvDimensionUpdate(int x, int y) +{ _boundingRect = QRectF(0, 0, x, y); update(); } @@ -28,17 +31,17 @@ QRectF TrackedElementView::boundingRect() const return _boundingRect; } - -void TrackedElementView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +void TrackedElementView::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) { - QGraphicsScene *scene = this->scene(); + QGraphicsScene* scene = this->scene(); - //Dev note: You could do some meaningful drawing here. - //So far, the core does everything we need. + // Dev note: You could do some meaningful drawing here. + // So far, the core does everything we need. } void TrackedElementView::getNotified() { update(); } - diff --git a/Src/View/TrackedElementView.h b/Src/View/TrackedElementView.h index 420fd76927e08a1deacd061aa41b53a3e7fb2058..1eddf3258f11e25953c59a6e1dc551884343cc25 100644 --- a/Src/View/TrackedElementView.h +++ b/Src/View/TrackedElementView.h @@ -5,30 +5,34 @@ /** * This class is an example of how a TrackedElementView could be visualized. - * This class inherits from the IViewTrackedComponent class and is therefor part of the Composite Pattern. + * This class inherits from the IViewTrackedComponent class and is therefor + * part of the Composite Pattern. */ class TrackedElementView : public IViewTrackedComponent { Q_OBJECT public: - TrackedElementView(QGraphicsItem *parent = 0, IController *controller = 0, IModel *model = 0); + TrackedElementView(QGraphicsItem* parent = 0, + IController* controller = 0, + IModel* model = 0); // QGraphicsItem interface public: QRectF boundingRect() const override; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; // IViewTrackedComponent interface public Q_SLOTS: - void getNotified() override; - void rcvDimensionUpdate(int x, int y); + void getNotified() override; + void rcvDimensionUpdate(int x, int y); -public Q_SIGNAL: - void emitUpdateCornersChanged(int id, int relX, int relY); +public + Q_SIGNAL : void emitUpdateCornersChanged(int id, int relX, int relY); private: QRectF _boundingRect; - }; #endif // TRACKEDELEMENTVIEW_H diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 5f21a2fa521ed47c7fa63841589281586459b201..8099a850170d99d9b7f44a60d75bc6e2307c0efe 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -3,111 +3,167 @@ #include <iostream> -TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : IViewWidget(parent, controller, model), - _ui(new Ui::TrackerParameterView), - _useAbsDiff(nullptr), - _binThres(nullptr) +TrackerParameterView::TrackerParameterView(QWidget* parent, + IController* controller, + IModel* model) +: IViewWidget(parent, controller, model) +, _ui(new Ui::TrackerParameterView) +, _useAbsDiff(nullptr) +, _binThres(nullptr) { - _ui->setupUi(this); - getNotified(); - - auto parameter = qobject_cast<TrackerParameter *>(getModel()); - - connect(_ui->algorithmCB, &QComboBox::currentTextChanged, parameter, &TrackerParameter::setAlgorithm); - connect(_ui->algorithmCB, &QComboBox::currentTextChanged, this, &TrackerParameterView::initSubtractorSpecificUI); - - connect(_ui->lineEdit_3_SizeErode, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeErode); - connect(_ui->lineEdit_3_SizeErode, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_4_SizeDilate, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeDilate); - connect(_ui->lineEdit_4_SizeDilate, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_8_MinBlob, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMinBlobSize); - connect(_ui->lineEdit_8_MinBlob, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_9MaxBlob, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize); - connect(_ui->lineEdit_9MaxBlob, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_7_learningRate, qOverload<double>(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setLearningRate); - connect(_ui->lineEdit_7_learningRate, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - initSubtractorSpecificUI(_ui->algorithmCB->currentText()); - - _ui->algorithmCB->setEnabled(false); + _ui->setupUi(this); + getNotified(); + + auto parameter = qobject_cast<TrackerParameter*>(getModel()); + + connect(_ui->algorithmCB, + &QComboBox::currentTextChanged, + parameter, + &TrackerParameter::setAlgorithm); + connect(_ui->algorithmCB, + &QComboBox::currentTextChanged, + this, + &TrackerParameterView::initSubtractorSpecificUI); + + connect(_ui->lineEdit_3_SizeErode, + qOverload<int>(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setSizeErode); + connect(_ui->lineEdit_3_SizeErode, + qOverload<int>(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_4_SizeDilate, + qOverload<int>(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setSizeDilate); + connect(_ui->lineEdit_4_SizeDilate, + qOverload<int>(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_8_MinBlob, + qOverload<int>(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMinBlobSize); + connect(_ui->lineEdit_8_MinBlob, + qOverload<int>(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_9MaxBlob, + qOverload<int>(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMaxBlobSize); + connect(_ui->lineEdit_9MaxBlob, + qOverload<int>(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_7_learningRate, + qOverload<double>(&QDoubleSpinBox::valueChanged), + parameter, + &TrackerParameter::setLearningRate); + connect(_ui->lineEdit_7_learningRate, + qOverload<double>(&QDoubleSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + initSubtractorSpecificUI(_ui->algorithmCB->currentText()); + + _ui->algorithmCB->setEnabled(false); } TrackerParameterView::~TrackerParameterView() { - delete _ui; + delete _ui; } void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) { - auto parameter = qobject_cast<TrackerParameter *>(getModel()); - - while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { - _ui->algorithmSpecificParameterLayout->removeRow(0); - } - - _useAbsDiff = nullptr; - _binThres = nullptr; - - if (algorithm == QString("Custom")) { - _useAbsDiff = new QCheckBox(); - _useAbsDiff->setText(" "); - _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); - _ui->algorithmSpecificParameterLayout->addRow(tr("Use Absolute Difference:"), _useAbsDiff); - - connect(_useAbsDiff, &QCheckBox::toggled, parameter, &TrackerParameter::setUseAbsoluteDifference); - connect(_useAbsDiff, &QCheckBox::toggled, this, &TrackerParameterView::parametersChanged); - - _binThres = new QSpinBox(); - _binThres->setMinimum(1); - _binThres->setMaximum(255); - _binThres->setValue(parameter->getBinarizationThreshold()); - _ui->algorithmSpecificParameterLayout->addRow(tr("Binarization Threshold:"), _binThres); - - connect(_binThres, qOverload<int>(&QSpinBox::valueChanged), parameter, &TrackerParameter::setBinarizationThreshold); - connect(_binThres, qOverload<int>(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - emit parametersChanged(); + auto parameter = qobject_cast<TrackerParameter*>(getModel()); + + while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { + _ui->algorithmSpecificParameterLayout->removeRow(0); + } + + _useAbsDiff = nullptr; + _binThres = nullptr; + + if (algorithm == QString("Custom")) { + _useAbsDiff = new QCheckBox(); + _useAbsDiff->setText(" "); + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Use Absolute Difference:"), + _useAbsDiff); + + connect(_useAbsDiff, + &QCheckBox::toggled, + parameter, + &TrackerParameter::setUseAbsoluteDifference); + connect(_useAbsDiff, + &QCheckBox::toggled, + this, + &TrackerParameterView::parametersChanged); + + _binThres = new QSpinBox(); + _binThres->setMinimum(1); + _binThres->setMaximum(255); + _binThres->setValue(parameter->getBinarizationThreshold()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Binarization Threshold:"), + _binThres); + + connect(_binThres, + qOverload<int>(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setBinarizationThreshold); + connect(_binThres, + qOverload<int>(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + emit parametersChanged(); } void TrackerParameterView::on_pushButtonResetBackground_clicked() { - TrackerParameter *parameter = qobject_cast<TrackerParameter *>(getModel()); - parameter->setResetBackground(true); + TrackerParameter* parameter = qobject_cast<TrackerParameter*>(getModel()); + parameter->setResetBackground(true); } void TrackerParameterView::on_comboBoxSendImage_currentIndexChanged(int v) { - TrackerParameter *parameter = qobject_cast<TrackerParameter *>(getModel()); - parameter->setSendImage(v); - parameter->setNewSelection(_ui->comboBoxSendImage->currentText().toStdString()); + TrackerParameter* parameter = qobject_cast<TrackerParameter*>(getModel()); + parameter->setSendImage(v); + parameter->setNewSelection( + _ui->comboBoxSendImage->currentText().toStdString()); } void TrackerParameterView::getNotified() { - TrackerParameter *parameter = qobject_cast<TrackerParameter *>(getModel()); + TrackerParameter* parameter = qobject_cast<TrackerParameter*>(getModel()); - _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); + _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); - if (_useAbsDiff) { - _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); - } + if (_useAbsDiff) { + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + } - if (_binThres) { - _binThres->setValue(parameter->getBinarizationThreshold()); - } + if (_binThres) { + _binThres->setValue(parameter->getBinarizationThreshold()); + } - _ui->lineEdit_3_SizeErode->setValue(parameter->getSizeErode()); + _ui->lineEdit_3_SizeErode->setValue(parameter->getSizeErode()); - _ui->lineEdit_4_SizeDilate->setValue(parameter->getSizeDilate()); + _ui->lineEdit_4_SizeDilate->setValue(parameter->getSizeDilate()); - _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); + _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); - _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); + _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); } diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index 172a0e9cbb07bd4512803d98a453f0140bfdd5a5..ad1c99f000b71f4546a08154a18c2a14fc4c0922 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -7,8 +7,9 @@ #include <QSpinBox> #include <QCheckBox> -namespace Ui { - class TrackerParameterView; +namespace Ui +{ + class TrackerParameterView; } class TrackerParameterView : public IViewWidget @@ -16,21 +17,22 @@ class TrackerParameterView : public IViewWidget Q_OBJECT public: - explicit TrackerParameterView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); + explicit TrackerParameterView(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); ~TrackerParameterView(); private slots: - void on_pushButtonResetBackground_clicked(); - void on_comboBoxSendImage_currentIndexChanged(int v); + void on_pushButtonResetBackground_clicked(); + void on_comboBoxSendImage_currentIndexChanged(int v); - public: - signals: +signals: void trackingAreaType(int v); void parametersChanged(); private: - Ui::TrackerParameterView *_ui; + Ui::TrackerParameterView* _ui; QCheckBox* _useAbsDiff; diff --git a/Src/helper/CvHelper.cpp b/Src/helper/CvHelper.cpp index 5cf0a91f9c3a7ab1f832d491870689c0c7045187..38a255bfecd05f0354203acca28204859ecff3f4 100644 --- a/Src/helper/CvHelper.cpp +++ b/Src/helper/CvHelper.cpp @@ -4,150 +4,177 @@ cv::Point CvHelper::subtractTwoCvPoints(cv::Point a, cv::Point b) { - return cv::Point(a.x - b.x, a.y - b.y); + return cv::Point(a.x - b.x, a.y - b.y); } cv::Point CvHelper::addTwoCvPoints(cv::Point a, cv::Point b) { - return cv::Point(a.x + b.x, a.y + b.y); + return cv::Point(a.x + b.x, a.y + b.y); } cv::Point CvHelper::multCvPoint(double scalar, cv::Point p) { - return cv::Point(scalar * p.x, scalar * p.y); + return cv::Point(scalar * p.x, scalar * p.y); } QPointF CvHelper::norm(double x, double y) { - double distance = qSqrt(x * x + y * y); + double distance = qSqrt(x * x + y * y); - if (distance == 0) { - return QPointF(0, 0); - } - return QPointF(x / distance, y / distance); + if (distance == 0) { + return QPointF(0, 0); + } + return QPointF(x / distance, y / distance); } QPointF CvHelper::norm(QPoint p) { - return CvHelper::norm((double) p.x(), (double) p.y()); + return CvHelper::norm((double) p.x(), (double) p.y()); } QPointF CvHelper::norm(QPointF p) { - return CvHelper::norm(p.x(), p.y()); + return CvHelper::norm(p.x(), p.y()); } double CvHelper::getDistance(double x1, double y1, double x2, double y2) { - return qSqrt( ( (x1 - x2) * (x1 - x2) ) + ( (y1 - y2) * (y1 - y2) ) ); + return qSqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2))); } -double CvHelper::getDistance(double x1, double y1, double z1, double x2, double y2, double z2 ) +double CvHelper::getDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2) { - return qSqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + ((z1 - z2) * (z1 - z2))); + return qSqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + + ((z1 - z2) * (z1 - z2))); } double CvHelper::getSqDistance(double x1, double y1, double x2, double y2) { - return ( (x1 - x2) * (x1 - x2) ) + ( (y1 - y2) * (y1 - y2) ); + return ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)); } -double CvHelper::getSqDistance(double x1, double y1, double z1, double x2, double y2, double z2) +double CvHelper::getSqDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2) { - return ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + ((z1 - z2) * (z1 - z2)); + return ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + + ((z1 - z2) * (z1 - z2)); } double CvHelper::getDistance(QPoint p1, QPoint p2) { - return getDistance((double) p1.x(), (double) p1.y(), (double) p2.x(), (double) p2.y()); + return getDistance((double) p1.x(), + (double) p1.y(), + (double) p2.x(), + (double) p2.y()); } double CvHelper::getDistance(QPointF p1, QPointF p2) { - return getDistance(p1.x(), p1.y(), p2.x(), p2.y()); + return getDistance(p1.x(), p1.y(), p2.x(), p2.y()); } double CvHelper::getDistance(cv::Point2f p1, cv::Point2f p2) { - return getDistance(p1.x, p1.y, p2.x, p2.y); + return getDistance(p1.x, p1.y, p2.x, p2.y); } double CvHelper::getDistance(cv::Point3f p1, cv::Point3f p2) { - return getDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); + return getDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); } double CvHelper::getDistance(cv::Point p1, cv::Point p2) { - return sqrt(double((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))); + return sqrt( + double((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))); } double CvHelper::getSqDistance(cv::Point2f p1, cv::Point2f p2) { - return getSqDistance(p1.x, p1.y, p2.x, p2.y); + return getSqDistance(p1.x, p1.y, p2.x, p2.y); } double CvHelper::getSqDistance(cv::Point3f p1, cv::Point3f p2) { - return getSqDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); + return getSqDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); } double CvHelper::orientation(cv::Point2f front, cv::Point2f back) { - cv::Point2f diff = front - back; - //return qAtan2(diff.x, diff.y); + cv::Point2f diff = front - back; + // return qAtan2(diff.x, diff.y); - // need to check the origin of coorindiates - return qAtan2(diff.x, diff.y) + CV_PI / 2.0; + // need to check the origin of coorindiates + return qAtan2(diff.x, diff.y) + CV_PI / 2.0; } double CvHelper::orientation(QPointF front, QPointF back) { - //QPointF diff = front - back; - //return qAtan2(diff.x(), diff.y()); - return orientation(cv::Point2f(front.x(),front.y()),cv::Point2f(back.x(),back.y())); + // QPointF diff = front - back; + // return qAtan2(diff.x(), diff.y()); + return orientation(cv::Point2f(front.x(), front.y()), + cv::Point2f(back.x(), back.y())); } float CvHelper::angleDifference(float alpha, float beta) { - float difference = alpha - beta; - while (difference < -CV_PI) difference += 2.0f * CV_PI; - while (difference > +CV_PI) difference -= 2.0f * CV_PI; - return difference; + float difference = alpha - beta; + while (difference < -CV_PI) + difference += 2.0f * CV_PI; + while (difference > +CV_PI) + difference -= 2.0f * CV_PI; + return difference; } -float CvHelper::findMin(float n1, float n2, float n3) { - return (n1 < n2 && n1 < n3) ? n1 : (n2 < n3 ? n2 : n3); +float CvHelper::findMin(float n1, float n2, float n3) +{ + return (n1 < n2 && n1 < n3) ? n1 : (n2 < n3 ? n2 : n3); } -float CvHelper::findMax(float n1, float n2, float n3) { - return (n1 > n2 && n1 > n3) ? n1 : (n2 > n3 ? n2 : n3); +float CvHelper::findMax(float n1, float n2, float n3) +{ + return (n1 > n2 && n1 > n3) ? n1 : (n2 > n3 ? n2 : n3); } -float CvHelper::normalDist(float x, float mean, float variance) { - return 1.0 / (variance *qSqrt(2*CV_PI)) * qExp(- ((x - mean) * (x - mean)) / (2 * variance * variance)); +float CvHelper::normalDist(float x, float mean, float variance) +{ + return 1.0 / (variance * qSqrt(2 * CV_PI)) * + qExp(-((x - mean) * (x - mean)) / (2 * variance * variance)); } -float CvHelper::sigmoid(float x, float shrink) { - return (2.0 / (1.0 + qExp(-x * shrink)) - 1.0); +float CvHelper::sigmoid(float x, float shrink) +{ + return (2.0 / (1.0 + qExp(-x * shrink)) - 1.0); } -float CvHelper::sigmoidAbsInv(float x, float shrink) { - return 1.0 - qAbs((2.0 / (1.0 + qExp(-x * shrink)) - 1.0)); +float CvHelper::sigmoidAbsInv(float x, float shrink) +{ + return 1.0 - qAbs((2.0 / (1.0 + qExp(-x * shrink)) - 1.0)); } -double CvHelper::getAngleDifference(double dirToTargetAsRad, double currOrientationAsRad) { - /*double angleDiff = dirToTargetAsRad - currOrientationAsRad + CV_PI / 2.0; - while (angleDiff < -CV_PI) angleDiff += 2 * CV_PI; - while (angleDiff > CV_PI) angleDiff -= 2 * CV_PI; - return angleDiff;*/ +double CvHelper::getAngleDifference(double dirToTargetAsRad, + double currOrientationAsRad) +{ + /*double angleDiff = dirToTargetAsRad - currOrientationAsRad + CV_PI / 2.0; + while (angleDiff < -CV_PI) angleDiff += 2 * CV_PI; + while (angleDiff > CV_PI) angleDiff -= 2 * CV_PI; + return angleDiff;*/ - double a = dirToTargetAsRad - currOrientationAsRad; - a += (a > CV_PI) ? -(2*CV_PI) : (a < -CV_PI) ? (2*CV_PI) : 0; - return a; + double a = dirToTargetAsRad - currOrientationAsRad; + a += (a > CV_PI) ? -(2 * CV_PI) : (a < -CV_PI) ? (2 * CV_PI) : 0; + return a; } -//double CvHelper::getAngleToTarget(cv::Point2f A, cv::Point2f B) { +// double CvHelper::getAngleToTarget(cv::Point2f A, cv::Point2f B) { // double ab = A.x*B.x + A.y*B.y; // double a = qSqrt(A.x*A.x + A.y*A.y); // double b = qSqrt(B.x*B.x + B.y*B.y); @@ -155,251 +182,275 @@ double CvHelper::getAngleDifference(double dirToTargetAsRad, double currOrientat // return qAcos(cosT); //} -double CvHelper::getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos) { - return qAtan2(targetPos.x - currentPos.x, targetPos.y - currentPos.y); +double CvHelper::getAngleToTarget(cv::Point2f currentPos, + cv::Point2f targetPos) +{ + return qAtan2(targetPos.x - currentPos.x, targetPos.y - currentPos.y); } std::deque<cv::Point2f> CvHelper::convertMat2Point2fDeque(cv::Mat mat) { - std::deque<cv::Point2f> point2fS; + std::deque<cv::Point2f> point2fS; - if(mat.cols != 2) - return point2fS; + if (mat.cols != 2) + return point2fS; - for (int row = 0; row < mat.rows; row++) - { - float x = mat.at<float>(row,0); - float y = mat.at<float>(row,1); - point2fS.push_back(cv::Point2f(x,y)); - } + for (int row = 0; row < mat.rows; row++) { + float x = mat.at<float>(row, 0); + float y = mat.at<float>(row, 1); + point2fS.push_back(cv::Point2f(x, y)); + } - return point2fS; + return point2fS; } cv::Mat CvHelper::convertPoint2fDeque2Mat(std::deque<cv::Point2f> points) { - cv::Mat mat; + cv::Mat mat; - if(points.empty()) - return mat; + if (points.empty()) + return mat; - mat = cv::Mat(points.size(), 2, CV_32F); + mat = cv::Mat(points.size(), 2, CV_32F); - for (int i = 0; i < points.size(); i++) - { - cv::Point2f p = points.at(i); - mat.at<float>(i,0)= p.x; - mat.at<float>(i,1)= p.y; - } - - return mat; + for (int i = 0; i < points.size(); i++) { + cv::Point2f p = points.at(i); + mat.at<float>(i, 0) = p.x; + mat.at<float>(i, 1) = p.y; + } + + return mat; } -QList<std::deque<cv::Point2f>> CvHelper::convertMatList2Point2fDequeList(QList<cv::Mat> mats) +QList<std::deque<cv::Point2f>> CvHelper::convertMatList2Point2fDequeList( + QList<cv::Mat> mats) { - QList<std::deque<cv::Point2f>> pointList; - cv::Mat mat; - foreach (mat , mats) - { - pointList << CvHelper::convertMat2Point2fDeque(mat); - } - return pointList; + QList<std::deque<cv::Point2f>> pointList; + cv::Mat mat; + foreach (mat, mats) { + pointList << CvHelper::convertMat2Point2fDeque(mat); + } + return pointList; } -cv::Point2f CvHelper::getMirrowPoint(cv::Point2f point2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad) -{ - //Convert angelAsGrad to radian - float angelAsRadian = (angelAsGrad * CV_PI / 180.0); +cv::Point2f CvHelper::getMirrowPoint(cv::Point2f point2Mirror, + cv::Point2f pointOfOrigin, + float angelAsGrad) +{ + // Convert angelAsGrad to radian + float angelAsRadian = (angelAsGrad * CV_PI / 180.0); - cv::Mat G = (cv::Mat_<float>(2,2) << cos(2.0 * angelAsRadian), sin(2.0 * angelAsRadian), sin(2.0 * angelAsRadian), -cos(2.0 * angelAsRadian)); + cv::Mat G = (cv::Mat_<float>(2, 2) << cos(2.0 * angelAsRadian), + sin(2.0 * angelAsRadian), + sin(2.0 * angelAsRadian), + -cos(2.0 * angelAsRadian)); - cv::Mat point2MirrorMat(1/*rows*/,2 /* cols */,CV_32F); - point2MirrorMat.at<float>(0,0) = point2Mirror.x; - point2MirrorMat.at<float>(0,1) = point2Mirror.y; + cv::Mat point2MirrorMat(1 /*rows*/, 2 /* cols */, CV_32F); + point2MirrorMat.at<float>(0, 0) = point2Mirror.x; + point2MirrorMat.at<float>(0, 1) = point2Mirror.y; - cv::Mat pointOfOriginMat(1/*rows*/,2 /* cols */,CV_32F); - pointOfOriginMat.at<float>(0,0) = pointOfOrigin.x; - pointOfOriginMat.at<float>(0,1) = pointOfOrigin.y; + cv::Mat pointOfOriginMat(1 /*rows*/, 2 /* cols */, CV_32F); + pointOfOriginMat.at<float>(0, 0) = pointOfOrigin.x; + pointOfOriginMat.at<float>(0, 1) = pointOfOrigin.y; - cv::Mat point2MirrorFromOrigin = point2MirrorMat - pointOfOriginMat; + cv::Mat point2MirrorFromOrigin = point2MirrorMat - pointOfOriginMat; - cv::Mat point2MirrorMatT; + cv::Mat point2MirrorMatT; cv::transpose(point2MirrorFromOrigin, point2MirrorMatT); - cv::Mat mirrowedPointMat = (G * point2MirrorMatT); + cv::Mat mirrowedPointMat = (G * point2MirrorMatT); - cv::Mat mirrowedPointMatT; - cv::transpose(mirrowedPointMat, mirrowedPointMatT); + cv::Mat mirrowedPointMatT; + cv::transpose(mirrowedPointMat, mirrowedPointMatT); - cv::Mat finalMat = mirrowedPointMatT + pointOfOriginMat; + cv::Mat finalMat = mirrowedPointMatT + pointOfOriginMat; - return cv::Point2f(finalMat.at<float>(0,0),finalMat.at<float>(0,1)); + return cv::Point2f(finalMat.at<float>(0, 0), finalMat.at<float>(0, 1)); } -std::deque<cv::Point2f> CvHelper::getMirrowPoints(std::deque<cv::Point2f> points2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad) +std::deque<cv::Point2f> CvHelper::getMirrowPoints( + std::deque<cv::Point2f> points2Mirror, + cv::Point2f pointOfOrigin, + float angelAsGrad) { - std::deque<cv::Point2f> mirrowedPoints; - - for(int i = 0; i < points2Mirror.size(); i++) - { - cv::Point2f p = CvHelper::getMirrowPoint(points2Mirror.at(i), pointOfOrigin, angelAsGrad); - mirrowedPoints.push_back(p); - } - return mirrowedPoints; + std::deque<cv::Point2f> mirrowedPoints; + for (int i = 0; i < points2Mirror.size(); i++) { + cv::Point2f p = CvHelper::getMirrowPoint(points2Mirror.at(i), + pointOfOrigin, + angelAsGrad); + mirrowedPoints.push_back(p); + } + return mirrowedPoints; } -std::deque<cv::Point2f> CvHelper::getMirrowLine(cv::Point2f pointOfOrigin, float width, float height, float angelAsGrad) -{ - float angle = angelAsGrad * CV_PI / 180.0; +std::deque<cv::Point2f> CvHelper::getMirrowLine(cv::Point2f pointOfOrigin, + float width, + float height, + float angelAsGrad) +{ + float angle = angelAsGrad * CV_PI / 180.0; - float r = CvHelper::getDistance(pointOfOrigin, cv::Point2f(width, height)); + float r = CvHelper::getDistance(pointOfOrigin, cv::Point2f(width, height)); - float xOff1 = pointOfOrigin.x + r * cos(angle); - float yOff1 = pointOfOrigin.y + r * sin(angle); + float xOff1 = pointOfOrigin.x + r * cos(angle); + float yOff1 = pointOfOrigin.y + r * sin(angle); - float xOff2 = pointOfOrigin.x - r * cos(angle); - float yOff2 = pointOfOrigin.y - r * sin(angle); + float xOff2 = pointOfOrigin.x - r * cos(angle); + float yOff2 = pointOfOrigin.y - r * sin(angle); - cv::Point2f front(xOff2,yOff2); - cv::Point2f back(xOff1,yOff1); + cv::Point2f front(xOff2, yOff2); + cv::Point2f back(xOff1, yOff1); - std::deque<cv::Point2f> points; + std::deque<cv::Point2f> points; - points.push_back(front); - points.push_back(back); - return points; + points.push_back(front); + points.push_back(back); + return points; } - std::vector<cv::Point> CvHelper::convertMat2Vector(cv::Mat mat) { - std::vector<cv::Point> value(mat.rows); - for (int i = 0; i < value.size(); i++) - { - cv::Point p((int)mat.at<float>(i,0),(int)mat.at<float>(i,1)); - value.at(i) = p; - } - return value; + std::vector<cv::Point> value(mat.rows); + for (int i = 0; i < value.size(); i++) { + cv::Point p((int) mat.at<float>(i, 0), (int) mat.at<float>(i, 1)); + value.at(i) = p; + } + return value; } cv::Mat CvHelper::convertVector2Mat(std::vector<cv::Point> vect) { - cv::Mat mat(vect.size(),2,CV_32F); - for (int i = 0; i < vect.size(); i++) - { - mat.at<float>(i,0) = (float)vect.at(i).x; - mat.at<float>(i,1) = (float)vect.at(i).y; - } - return mat; + cv::Mat mat(vect.size(), 2, CV_32F); + for (int i = 0; i < vect.size(); i++) { + mat.at<float>(i, 0) = (float) vect.at(i).x; + mat.at<float>(i, 1) = (float) vect.at(i).y; + } + return mat; } float CvHelper::degToRad(float deg) { - return deg * CV_PI / 180.0; + return deg * CV_PI / 180.0; } float CvHelper::radToDeg(float rad) { - return rad * 180.0 / CV_PI; + return rad * 180.0 / CV_PI; } int CvHelper::stdStringToInt(std::string string) { - int numb; - std::istringstream iss(string); - if (!(iss >> numb)) - { - throw "String cannot convert to float number!"; - } - return numb; + int numb; + std::istringstream iss(string); + if (!(iss >> numb)) { + throw "String cannot convert to float number!"; + } + return numb; } float CvHelper::stdStringToFloat(std::string string) { - float numb; - std::istringstream iss(string); - if (!(iss >> numb)) - { - throw "String cannot convert to float number!"; - } - - return numb; + float numb; + std::istringstream iss(string); + if (!(iss >> numb)) { + throw "String cannot convert to float number!"; + } + + return numb; } -std::string CvHelper::convertStdVectorCvPointToStdString(std::vector<cv::Point> points) +std::string CvHelper::convertStdVectorCvPointToStdString( + std::vector<cv::Point> points) { - std::string pointListString; - for (int i = 0; i < points.size(); i++) - { - int x = points.at(i).x; - int y = points.at(i).y; - if(i < points.size() - 1) - pointListString.append(StringHelper::iToSS(x)).append(":").append(StringHelper::iToSS(y)).append(" "); - else - pointListString.append(StringHelper::iToSS(x)).append(":").append(StringHelper::iToSS(y)); - } - return pointListString; + std::string pointListString; + for (int i = 0; i < points.size(); i++) { + int x = points.at(i).x; + int y = points.at(i).y; + if (i < points.size() - 1) + pointListString.append(StringHelper::iToSS(x)) + .append(":") + .append(StringHelper::iToSS(y)) + .append(" "); + else + pointListString.append(StringHelper::iToSS(x)) + .append(":") + .append(StringHelper::iToSS(y)); + } + return pointListString; } std::string CvHelper::convertCvScalarToStdString(cv::Scalar scalar) { - std::string scalarString; - - int r = scalar.val[0,0]; - int g = scalar.val[0,1]; - int b = scalar.val[0,2]; + std::string scalarString; - scalarString.append(StringHelper::iToSS(r)).append(" ").append(StringHelper::iToSS(g)).append(" ").append(StringHelper::iToSS(b)).append(" "); + int r = scalar.val[0, 0]; + int g = scalar.val[0, 1]; + int b = scalar.val[0, 2]; - return scalarString; + scalarString.append(StringHelper::iToSS(r)) + .append(" ") + .append(StringHelper::iToSS(g)) + .append(" ") + .append(StringHelper::iToSS(b)) + .append(" "); + return scalarString; } std::string CvHelper::cvSizeToSS(cv::Size cvSize_value) { - std::string cvSizeString; + std::string cvSizeString; - int width = cvSize_value.width; - int height = cvSize_value.height; + int width = cvSize_value.width; + int height = cvSize_value.height; - cvSizeString.append(StringHelper::iToSS(height)).append("x").append(StringHelper::iToSS(width)); + cvSizeString.append(StringHelper::iToSS(height)) + .append("x") + .append(StringHelper::iToSS(width)); - return cvSizeString; + return cvSizeString; } std::string CvHelper::cvSize2fToSS(cv::Size2f cvSize2f_value) { - std::string cvSize2fString; + std::string cvSize2fString; - float width = cvSize2f_value.width; - float height = cvSize2f_value.height; + float width = cvSize2f_value.width; + float height = cvSize2f_value.height; - cvSize2fString.append(StringHelper::fToSS(height)).append("x").append(StringHelper::fToSS(width)); + cvSize2fString.append(StringHelper::fToSS(height)) + .append("x") + .append(StringHelper::fToSS(width)); - return cvSize2fString; + return cvSize2fString; } std::string CvHelper::cvSize2fToSS(QString width, QString height) { - std::string cvSize2fString; + std::string cvSize2fString; - cvSize2fString.append(height.toStdString()).append("x").append(width.toStdString()); + cvSize2fString.append(height.toStdString()) + .append("x") + .append(width.toStdString()); - return cvSize2fString; + return cvSize2fString; } std::string CvHelper::getCurrentDatetimeAsStd() { - return QDateTime::currentDateTime().toString("_yyMMddThhmmss").toUtf8().constData(); + return QDateTime::currentDateTime() + .toString("_yyMMddThhmmss") + .toUtf8() + .constData(); } bool CvHelper::isFrameSizeEqual(cv::Size o1, cv::Size o2) { - bool equal = false; + bool equal = false; - if (o1.width == o2.width && o1.height == o2.height) - equal = true; + if (o1.width == o2.width && o1.height == o2.height) + equal = true; - return equal; + return equal; } \ No newline at end of file diff --git a/Src/helper/CvHelper.h b/Src/helper/CvHelper.h index 2c842dfba435466512f58d1038f5b941dcba5b5a..b64dff9b994092594209a9d4af55f3903bd89f84 100644 --- a/Src/helper/CvHelper.h +++ b/Src/helper/CvHelper.h @@ -9,189 +9,211 @@ #include <opencv2/opencv.hpp> - /** * Computer vision helper class, contains only static methods */ namespace CvHelper { - /** - * Subtract operation for two CvPoints. - * @return: the difference of the CvPoints. - */ - cv::Point subtractTwoCvPoints(cv::Point a, cv::Point b); - - /** - * Add operation for two CvPoints. - * @return: the sum of the CvPoints. - */ - cv::Point addTwoCvPoints(cv::Point a, cv::Point b); - - cv::Point multCvPoint(double scalar, cv::Point p); - - /** - * Normalizes a coordinate point. - * @param x, the x coordinate. - * @param y, the y coordinate. - * @return the normlized point as floating number. - */ - QPointF norm(double x, double y); - - /** - * Normalizes a point. - * @param p, point to normalize. - * @return the normalized point as floating number. - */ - QPointF norm(QPoint p); - - /** - * Normalizes a floating number point. - * @param p, point to normalize. - * @return the normalized point as floating number. - */ - QPointF norm(QPointF p); - - /** - * Calculates the distance between two coordinates. - * @param x1, x-coordinate of the source point. - * @param y1, y-coordinate of the source point. - * @param x2, x-coordinate of the destination point. - * @param y2, y-coordinate of the destination point. - * @return the distance between the provided coordinates as floating number. - */ - double getDistance(double x1, double y1, double x2, double y2); - double getSqDistance(double x1, double y1, double x2, double y2); - - /** - * Calculates the distance between two coordinates. - * @param x1, x-coordinate of the source point. - * @param y1, y-coordinate of the source point. - * @param z1, z-coordinate of the source point. - * @param x2, x-coordinate of the destination point. - * @param y2, y-coordinate of the destination point. - * @param z2, y-coordinate of the destination point. - * @return the distance between the provided coordinates as floating number. - */ - double getDistance(double x1, double y1, double z1, double x2, double y2, double z2); - double getSqDistance(double x1, double y1, double z1, double x2, double y2, double z2); - - /** - * Calculates the distance between two points. - * @param p1, source point. - * @param p2, destination point. - * @return the distance between p1 and p2 as floating number. - */ - double getDistance(QPoint p1, QPoint p2); - - /** - * Calculates the distance between two floating number points. - * @param p1, source point. - * @param p2, destination point. - * @return the distance between p1 and p2 as floating number. - */ - double getDistance(QPointF p1, QPointF p2); - - double getDistance(cv::Point2f p1, cv::Point2f p2); - double getDistance(cv::Point p1, cv::Point p2); - double getSqDistance(cv::Point2f p1, cv::Point2f p2); - - double getDistance(cv::Point3f p1, cv::Point3f p2); - double getSqDistance(cv::Point3f p1, cv::Point3f p2); - - double orientation(cv::Point2f front, cv::Point2f back); - double orientation(QPointF front, QPointF back); - - float angleDifference(float alpha, float beta); - - /** - * Convert degree to radian. - * @param: deg, degree value, - * @return: rad value. - */ - float degToRad(float deg); - - /** - * Convert radian to degree. - * @param: rad, radian value, - * @return: degree value. - */ - float radToDeg(float rad); - - /** - * This function finds the minimal number of three numbers. - */ - float findMin(float n1, float n2, float n3); - - /** - * This function finds the maximal number of three numbers. - */ - float findMax(float n1, float n2, float n3); - - float normalDist(float x, float mean, float variance); - - float sigmoid(float x, float shrink); - - float sigmoidAbsInv(float x, float shrink); - - double getAngleDifference(double dirToTargetAsRad, double currOrientationAsRad); - double getAngleToTarget(cv::Point2f A, cv::Point2f B); - //double getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos); - - cv::Point2f getMirrowPoint(cv::Point2f point2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad); - std::deque<cv::Point2f> getMirrowPoints(std::deque<cv::Point2f> points2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad); - std::deque<cv::Point2f> getMirrowLine(cv::Point2f pointOfOrigin, float width, float height, float angelAsGrad); - - - std::deque<cv::Point2f> convertMat2Point2fDeque(cv::Mat mat); - cv::Mat convertPoint2fDeque2Mat(std::deque<cv::Point2f> points); - QList<std::deque<cv::Point2f>> convertMatList2Point2fDequeList(QList<cv::Mat> mats); - std::vector<cv::Point> convertMat2Vector(cv::Mat mat); - cv::Mat convertVector2Mat(std::vector<cv::Point> vect); - - /** - * Converts a string to an integer number. - * @param: string, a string containing a number. - * @return: a converted integer number. - */ - int stdStringToInt(std::string string); - - /** - * Converts a string to a float number. - * @param: string, a string containing a number. - * @return: a converted float number. - */ - float stdStringToFloat(std::string string); - - /** - * Converts a list of cv::Point to a proper string, which could be save into the config.ini file. - * @param: points, a list of cv::Point. - * @return: a converted formated string for the config.ini file. - */ - std::string convertStdVectorCvPointToStdString(std::vector<cv::Point> points); - - /** - * Converts a cv::Scalar to a proper standard string, which could be save into the config.ini file. - * @param: scalar, a scalar. - * @return: a converted formated string for the config.ini file. - */ - std::string convertCvScalarToStdString(cv::Scalar scalar); - - /** - * Gets the current date time as std string. - * @return: the current formated date time as standard string. - */ - std::string getCurrentDatetimeAsStd(); - - std::string cvSizeToSS(cv::Size cvSize_value); - std::string cvSize2fToSS(cv::Size2f cvSize2f_value); - std::string cvSize2fToSS(QString width, QString height); - - - /** - * Checks if image sizes are equal. - * @param: size of first object - * @param: size of second object - * @return: true if equal, false otherwise - */ - bool isFrameSizeEqual(cv::Size o1, cv::Size o2); + /** + * Subtract operation for two CvPoints. + * @return: the difference of the CvPoints. + */ + cv::Point subtractTwoCvPoints(cv::Point a, cv::Point b); + + /** + * Add operation for two CvPoints. + * @return: the sum of the CvPoints. + */ + cv::Point addTwoCvPoints(cv::Point a, cv::Point b); + + cv::Point multCvPoint(double scalar, cv::Point p); + + /** + * Normalizes a coordinate point. + * @param x, the x coordinate. + * @param y, the y coordinate. + * @return the normlized point as floating number. + */ + QPointF norm(double x, double y); + + /** + * Normalizes a point. + * @param p, point to normalize. + * @return the normalized point as floating number. + */ + QPointF norm(QPoint p); + + /** + * Normalizes a floating number point. + * @param p, point to normalize. + * @return the normalized point as floating number. + */ + QPointF norm(QPointF p); + + /** + * Calculates the distance between two coordinates. + * @param x1, x-coordinate of the source point. + * @param y1, y-coordinate of the source point. + * @param x2, x-coordinate of the destination point. + * @param y2, y-coordinate of the destination point. + * @return the distance between the provided coordinates as floating + * number. + */ + double getDistance(double x1, double y1, double x2, double y2); + double getSqDistance(double x1, double y1, double x2, double y2); + + /** + * Calculates the distance between two coordinates. + * @param x1, x-coordinate of the source point. + * @param y1, y-coordinate of the source point. + * @param z1, z-coordinate of the source point. + * @param x2, x-coordinate of the destination point. + * @param y2, y-coordinate of the destination point. + * @param z2, y-coordinate of the destination point. + * @return the distance between the provided coordinates as floating + * number. + */ + double getDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2); + double getSqDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2); + + /** + * Calculates the distance between two points. + * @param p1, source point. + * @param p2, destination point. + * @return the distance between p1 and p2 as floating number. + */ + double getDistance(QPoint p1, QPoint p2); + + /** + * Calculates the distance between two floating number points. + * @param p1, source point. + * @param p2, destination point. + * @return the distance between p1 and p2 as floating number. + */ + double getDistance(QPointF p1, QPointF p2); + + double getDistance(cv::Point2f p1, cv::Point2f p2); + double getDistance(cv::Point p1, cv::Point p2); + double getSqDistance(cv::Point2f p1, cv::Point2f p2); + + double getDistance(cv::Point3f p1, cv::Point3f p2); + double getSqDistance(cv::Point3f p1, cv::Point3f p2); + + double orientation(cv::Point2f front, cv::Point2f back); + double orientation(QPointF front, QPointF back); + + float angleDifference(float alpha, float beta); + + /** + * Convert degree to radian. + * @param: deg, degree value, + * @return: rad value. + */ + float degToRad(float deg); + + /** + * Convert radian to degree. + * @param: rad, radian value, + * @return: degree value. + */ + float radToDeg(float rad); + + /** + * This function finds the minimal number of three numbers. + */ + float findMin(float n1, float n2, float n3); + + /** + * This function finds the maximal number of three numbers. + */ + float findMax(float n1, float n2, float n3); + + float normalDist(float x, float mean, float variance); + + float sigmoid(float x, float shrink); + + float sigmoidAbsInv(float x, float shrink); + + double getAngleDifference(double dirToTargetAsRad, + double currOrientationAsRad); + double getAngleToTarget(cv::Point2f A, cv::Point2f B); + // double getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos); + + cv::Point2f getMirrowPoint(cv::Point2f point2Mirror, + cv::Point2f pointOfOrigin, + float angelAsGrad); + std::deque<cv::Point2f> getMirrowPoints( + std::deque<cv::Point2f> points2Mirror, + cv::Point2f pointOfOrigin, + float angelAsGrad); + std::deque<cv::Point2f> getMirrowLine(cv::Point2f pointOfOrigin, + float width, + float height, + float angelAsGrad); + + std::deque<cv::Point2f> convertMat2Point2fDeque(cv::Mat mat); + cv::Mat convertPoint2fDeque2Mat(std::deque<cv::Point2f> points); + QList<std::deque<cv::Point2f>> convertMatList2Point2fDequeList( + QList<cv::Mat> mats); + std::vector<cv::Point> convertMat2Vector(cv::Mat mat); + cv::Mat convertVector2Mat(std::vector<cv::Point> vect); + + /** + * Converts a string to an integer number. + * @param: string, a string containing a number. + * @return: a converted integer number. + */ + int stdStringToInt(std::string string); + + /** + * Converts a string to a float number. + * @param: string, a string containing a number. + * @return: a converted float number. + */ + float stdStringToFloat(std::string string); + + /** + * Converts a list of cv::Point to a proper string, which could be save + * into the config.ini file. + * @param: points, a list of cv::Point. + * @return: a converted formated string for the config.ini file. + */ + std::string convertStdVectorCvPointToStdString( + std::vector<cv::Point> points); + + /** + * Converts a cv::Scalar to a proper standard string, which could be save + * into the config.ini file. + * @param: scalar, a scalar. + * @return: a converted formated string for the config.ini file. + */ + std::string convertCvScalarToStdString(cv::Scalar scalar); + + /** + * Gets the current date time as std string. + * @return: the current formated date time as standard string. + */ + std::string getCurrentDatetimeAsStd(); + + std::string cvSizeToSS(cv::Size cvSize_value); + std::string cvSize2fToSS(cv::Size2f cvSize2f_value); + std::string cvSize2fToSS(QString width, QString height); + + /** + * Checks if image sizes are equal. + * @param: size of first object + * @param: size of second object + * @return: true if equal, false otherwise + */ + bool isFrameSizeEqual(cv::Size o1, cv::Size o2); } diff --git a/Src/helper/StringHelper.cpp b/Src/helper/StringHelper.cpp index 4f4b3f8dd8b0fe75af1c2381324388651d8be0a3..e3543b6d3a1f687837713fd4fb58e24e7c71ac4d 100644 --- a/Src/helper/StringHelper.cpp +++ b/Src/helper/StringHelper.cpp @@ -3,103 +3,103 @@ #include <algorithm> #include <string> - -bool StringHelper::hasEnding(std::string const &fullString, std::string const &ending) +bool StringHelper::hasEnding(std::string const& fullString, + std::string const& ending) { - if (fullString.length() >= ending.length()) - return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); - else - return false; + if (fullString.length() >= ending.length()) + return (0 == fullString.compare(fullString.length() - ending.length(), + ending.length(), + ending)); + else + return false; } - -bool StringHelper::startsWithDigit(std::string const &fullString) +bool StringHelper::startsWithDigit(std::string const& fullString) { - if(fullString.empty()) - return false; - + if (fullString.empty()) + return false; - if(isdigit(fullString.at(0))) - { - return true; - } - - return false; + if (isdigit(fullString.at(0))) { + return true; + } + return false; } bool StringHelper::startsWithDigitQ(QString fullString) { - return StringHelper::startsWithDigit(fullString.toLocal8Bit().data()); + return StringHelper::startsWithDigit(fullString.toLocal8Bit().data()); } bool StringHelper::isNumber(QString fullStringQ) -{ - std::string fullString = fullStringQ.toLocal8Bit().data(); - - for(int i = 0; i < fullString.length(); i++) - { - if(isdigit(fullString.at(i))) - { - return true; - } +{ + std::string fullString = fullStringQ.toLocal8Bit().data(); - } + for (int i = 0; i < fullString.length(); i++) { + if (isdigit(fullString.at(i))) { + return true; + } + } - return false; + return false; } std::string StringHelper::iToSS(int int_num) { - return QString::number(int_num).toUtf8().constData(); + return QString::number(int_num).toUtf8().constData(); } std::string StringHelper::boolToSS(bool bool_value) { - if(bool_value) - return std::string("true"); - return std::string("false"); + if (bool_value) + return std::string("true"); + return std::string("false"); } std::string StringHelper::fToSS(float float_num) { - return QString::number(float_num).toUtf8().constData(); + return QString::number(float_num).toUtf8().constData(); } - std::string StringHelper::toStdString(QString qString) { - return qString.toUtf8().constData(); + return qString.toUtf8().constData(); } QString StringHelper::toQString(std::string stdString) { - return QString::fromUtf8(stdString.c_str()); + return QString::fromUtf8(stdString.c_str()); } std::string StringHelper::toLowerCase(std::string stringValue) { - std::string lowCaseString(stringValue); - std::transform(lowCaseString.begin(), lowCaseString.end(), lowCaseString.begin(), tolower); - return lowCaseString; + std::string lowCaseString(stringValue); + std::transform(lowCaseString.begin(), + lowCaseString.end(), + lowCaseString.begin(), + tolower); + return lowCaseString; } -int StringHelper::split(std::string &txt, std::vector<std::string> &strs, char ch) +int StringHelper::split(std::string& txt, + std::vector<std::string>& strs, + char ch) { - std::string::size_type pos = txt.find( ch ); - std::string::size_type initialPos = 0; + std::string::size_type pos = txt.find(ch); + std::string::size_type initialPos = 0; strs.clear(); // Decompose statement - while( pos != std::string::npos ) { - strs.push_back( txt.substr( initialPos, pos - initialPos ) ); + while (pos != std::string::npos) { + strs.push_back(txt.substr(initialPos, pos - initialPos)); initialPos = pos + 1; - pos = txt.find( ch, initialPos ); + pos = txt.find(ch, initialPos); } // Add the last one - strs.push_back(txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1)); + strs.push_back( + txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1)); return strs.size(); } \ No newline at end of file diff --git a/Src/helper/StringHelper.h b/Src/helper/StringHelper.h index 10f05d6a03410f3debe4eb02aa08f8f160ec71e2..1d820d3c21eeb6f8788878c2412c34052d9c77ce 100644 --- a/Src/helper/StringHelper.h +++ b/Src/helper/StringHelper.h @@ -10,71 +10,80 @@ class StringHelper { public: - StringHelper(void) {} - ~StringHelper(void) {} + StringHelper(void) + { + } + ~StringHelper(void) + { + } - /** - * This method is used to check whether the full string contains the provided ending. - * @param: fullString, the specifies the string which needs to be checked. - * @param: ending, string specifes the ending string. - * @return: true if ending string is at the end of fullString, otherwise false - */ - static bool hasEnding(std::string const &fullString, std::string const &ending); + /** + * This method is used to check whether the full string contains the + * provided ending. + * @param: fullString, the specifies the string which needs to be checked. + * @param: ending, string specifes the ending string. + * @return: true if ending string is at the end of fullString, otherwise + * false + */ + static bool hasEnding(std::string const& fullString, + std::string const& ending); - - static bool startsWithDigitQ(QString fullString); - static bool startsWithDigit(std::string const &fullString); + static bool startsWithDigitQ(QString fullString); + static bool startsWithDigit(std::string const& fullString); - static bool isNumber(QString fullString); + static bool isNumber(QString fullString); - /** - * Convert QString to standard string. - * @param: qString, the string to convert, - * @return: a standard string. - */ - static std::string toStdString(QString qString); + /** + * Convert QString to standard string. + * @param: qString, the string to convert, + * @return: a standard string. + */ + static std::string toStdString(QString qString); - /** - * Convert standard string to QString - * @param: stdString, the string to convert, - * @return: a qt string. - */ - static QString toQString(std::string stdString); + /** + * Convert standard string to QString + * @param: stdString, the string to convert, + * @return: a qt string. + */ + static QString toQString(std::string stdString); - /** - * Convert integer to standard string. - * @param: int_num, integer number to convert, - * @return: a standard string. - */ - static std::string iToSS(int int_num); + /** + * Convert integer to standard string. + * @param: int_num, integer number to convert, + * @return: a standard string. + */ + static std::string iToSS(int int_num); - /** - * Convert a bool to standard string. - * @param: bool_value, bool valueto convert, - * @return: a standard string. - */ - static std::string boolToSS(bool bool_value); + /** + * Convert a bool to standard string. + * @param: bool_value, bool valueto convert, + * @return: a standard string. + */ + static std::string boolToSS(bool bool_value); - /** - * Convert float to standard string. - * @param: float_num, float number to convert, - * @return: a standard string. - */ - static std::string fToSS(float float_num); + /** + * Convert float to standard string. + * @param: float_num, float number to convert, + * @return: a standard string. + */ + static std::string fToSS(float float_num); - /** - * Convert a given string to lower case string. - * @param: stringValue, string to convert, - * @return: a standard string. - */ - static std::string toLowerCase(std::string stringValue); + /** + * Convert a given string to lower case string. + * @param: stringValue, string to convert, + * @return: a standard string. + */ + static std::string toLowerCase(std::string stringValue); - /** - * Use from here: http://stackoverflow.com/questions/5888022/split-string-by-single-spaces - * Method to split a string by a given character. - * @param: txt, a reference to the string, which will be split, - * @param: strs, a reference to a vector containing the splitted result, - * @param: ch, the split character. - **/ - static int split(std::string &txt, std::vector<std::string> &strs, char ch); + /** + * Use from here: + *http://stackoverflow.com/questions/5888022/split-string-by-single-spaces + * Method to split a string by a given character. + * @param: txt, a reference to the string, which will be split, + * @param: strs, a reference to a vector containing the splitted result, + * @param: ch, the split character. + **/ + static int split(std::string& txt, + std::vector<std::string>& strs, + char ch); };