diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..b3b525e7 --- /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: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + 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 00000000..7b80d1c5 --- /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/.gitignore b/.gitignore index 129cebfa..8b9398b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ GeneratedFiles/ -CMakeLists.txt.user desktop.ini *.swp *.opensdf @@ -16,12 +15,10 @@ desktop.ini .gitignore.swp *.bak_* *.ini -*.json # ignore editor ~ files .tags* Doxyfile -CMakeCache.txt Makefile cmake_install.cmake doxygen_sqlite3.db @@ -58,7 +55,6 @@ doxygen_sqlite3.db *.db *.opendb CMakeFiles -*.txt /BioTracker/*.vspx *.cache *.csv diff --git a/.gitignore.save b/.gitignore.save deleted file mode 100644 index 48e435b2..00000000 --- a/.gitignore.save +++ /dev/null @@ -1,43 +0,0 @@ -BioTracker/Interfaces/build-BioTrackerInterfaces-BioTracker-Debug/ - -GeneratedFiles/ -CMakeLists.txt.user -desktop.ini -*.swp -*.opensdf -*.sdf -*.suo -*.exe -*.psess -*.vsp -*.ipch -*.sln -*.vcxproj -*.vcxproj.filters -*.vcxproj.vspscc -.gitignore.swp -*.bak_* -BioTracker.apparmor -CMakeLists.txt.user.3.2-pre1 -manifest.json - -# ignore editor ~ files -.tags* -Doxyfile -CMakeCache.txt -Makefile -cmake_install.cmake -doxygen_sqlite3.db -*~ -.idea/ - -/CMakeFiles -/doc -/html -/Debug -/Release -/build -*.kate-swp - -# astyle original files -*.orig diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..859f75b5 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,92 @@ +stages: + - build + - package + - deploy + +.centos: + tags: [linux, docker] + image: git.imp.fu-berlin.de:5000/bioroboticslab/auto/ci/centos:latest + +.windows: + tags: [windows, docker] + image: git.imp.fu-berlin.de:5000/bioroboticslab/auto/ci/windows:latest-devel + before_script: + - . $Profile.AllUsersAllHosts + +.release: &release + CMAKE_BUILD_TYPE: Release + +.pylon: &pylon + WITH_PYLON: 1 + +.build: &build + stage: build + artifacts: + paths: + - vendor + - build + expire_in: 1 day + script: + - ./ci/prepare.py + - ./ci/configure.py + - ./ci/compile.py + +.package: &package + stage: package + artifacts: + paths: + - build/*.AppImage + - build/*.msi + expire_in: 1 week + script: + - ./ci/package.py + +"build: [centos]": + extends: .centos + <<: *build + variables: + <<: [*release] + +"build [pylon]: [centos]": + extends: .centos + <<: *build + variables: + <<: [*release, *pylon] + +"build: [windows]": + extends: .windows + <<: *build + variables: + <<: [*release] + +"build [pylon]: [windows]": + extends: .windows + <<: *build + variables: + <<: [*release, *pylon] + +"package: [centos]": + extends: .centos + dependencies: + - "build: [centos]" + <<: *package + +"package [pylon]: [centos]": + extends: .centos + dependencies: + - "build [pylon]: [centos]" + variables: + <<: [*pylon] + <<: *package + +"package: [windows]": + extends: .windows + dependencies: + - "build: [windows]" + <<: *package + +"package [pylon]: [windows]": + extends: .windows + dependencies: + - "build [pylon]: [windows]" + <<: *package diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29b..00000000 diff --git a/BioTracker/CMakeLists.txt b/BioTracker/CMakeLists.txt deleted file mode 100644 index 0a111994..00000000 --- a/BioTracker/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -#(Minimal benötigte CMake-Version wenn z.B. bestimmte CMake-Kommandos benutzt werden) - -cmake_policy(SET CMP0020 NEW) -cmake_policy(SET CMP0054 NEW) - -# Der Projektname -project(Biotracker) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -find_package(Qt5 REQUIRED Core Gui Xml Network Widgets OpenGL Multimedia MultimediaWidgets) -find_package(OpenCV REQUIRED) -set (QT_DIR_CMAKE $ENV{QT_DIR}) - -set(HMNVLibDir "Not Found" CACHE FILEPATH "") - -if(CMAKE_SYSTEM MATCHES "Windows") - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) -endif() -find_package(Boost REQUIRED system filesystem chrono thread timer program_options) - -exec_program("git" ${CMAKE_CURRENT_SOURCE_DIR} ARGS "log --pretty=format:%h -n 1" OUTPUT_VARIABLE VERSION ) -add_definitions( -DGIT_HASH="${VERSION}" ) -message(STATUS "Configured git hash=${VERSION}") -message(STATUS "Configured CV version=${OpenCV_VERSION}") -message(STATUS "Configured QT version=${Qt5Core_VERSION}") -add_definitions( -DMyQT_VERSION="${Qt5Core_VERSION}" ) -add_definitions( -DMyCV_VERSION="${OpenCV_VERSION}" ) -add_definitions( -DMyBT_VERSION="${Boost_LIB_VERSION}" ) - - -add_subdirectory(Interfaces/BioTrackerInterfaces) -add_subdirectory(Utils/BioTrackerUtils) -add_subdirectory(Plugin/BackgroundSubtraction) -add_subdirectory(Plugin/LukasKanade) -add_subdirectory(CoreApp/BioTracker) - - - diff --git a/BioTracker/CoreApp/BioTracker/BioTracker.pro b/BioTracker/CoreApp/BioTracker/BioTracker.pro deleted file mode 100644 index 57950d21..00000000 --- a/BioTracker/CoreApp/BioTracker/BioTracker.pro +++ /dev/null @@ -1,146 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-11-18T19:15:02 -# by Andreas Jörg -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -QT += opengl -QT += multimedia -QT += multimediawidgets - - -TARGET = BioTracker -TEMPLATE = app - -LIBS += -L/usr/include/boost -lboost_system -#LIBS += -L/usr/include/boost -lboost_chrono -#LIBS += -L/usr/include/boost -lboost_thread -#LIBS += -L/usr/include/boost -lboost_timer -LIBS += -L/usr/include/boost -lboost_filesystem - -INCLUDEPATH += /usr/local/include/opencv -LIBS += -L/usr/local/lib \ --lopencv_core \ --lopencv_imgproc \ --lopencv_highgui \ --lopencv_ml \ --lopencv_video \ --lopencv_features2d \ --lopencv_calib3d \ --lopencv_objdetect \ --lopencv_contrib \ --lopencv_legacy \ --lopencv_flann - - -SOURCES += main.cpp\ - BioTracker3App.cpp \ - GuiContext.cpp \ - Controller/ControllerGraphicScene.cpp \ - Controller/ControllerMainWindow.cpp \ - Controller/ControllerPlayer.cpp \ - Controller/ControllerTextureObject.cpp \ - Model/BioTracker3ProxyMat.cpp \ - Model/null_Model.cpp \ - View/GraphicsScene.cpp \ - View/GraphicsView.cpp \ - View/TrackedImageView.cpp \ - Model/PluginLoader.cpp \ - View/CameraDevice.cpp \ - Controller/null_Controller.cpp \ - Controller/ControllerPlugin.cpp \ - View/MainWindow.cpp \ - View/VideoControllWidget.cpp \ - View/GLVideoView.cpp \ - Model/ImageStream.cpp \ - Model/TextureObject.cpp \ - View/TextureObjectView.cpp \ - IStates/IPlayerState.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp \ - Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp \ - Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp \ - Model/MediaPlayer.cpp - -HEADERS += BioTracker3App.h \ - GuiContext.h \ - Controller/ControllerGraphicScene.h \ - Controller/ControllerMainWindow.h \ - Controller/ControllerPlayer.h \ - Controller/ControllerTextureObject.h \ - Model/BioTracker3ProxyMat.h \ - Model/null_Model.h \ - View/GraphicsScene.h \ - View/GraphicsView.h \ - View/TrackedImageView.h \ - Model/PluginLoader.h \ - View/CameraDevice.h \ - Controller/null_Controller.h \ - Controller/ControllerPlugin.h \ - View/MainWindow.h \ - View/VideoControllWidget.h \ - View/GLVideoView.h \ - Model/ImageStream.h \ - Model/TextureObject.h \ - View/TextureObjectView.h \ - IStates/IPlayerState.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h \ - Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h \ - Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h \ - Model/MediaPlayer.h \ - Model/MediaPlayerStateMachine/PlayerParameters.h - -FORMS += \ - View/CameraDevice.ui \ - View/MainWindow.ui \ - View/VideoControllWidget.ui - -RESOURCES += \ - guiresources.qrc - - - -# Include the BioTrackerInterfaces Library -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/release/ -lBioTrackerInterfaces -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/debug/ -lBioTrackerInterfaces -else:unix: LIBS += -L$$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/ -lBioTrackerInterfaces - -INCLUDEPATH += $$PWD/../../Interfaces/BioTrackerInterfaces -DEPENDPATH += $$PWD/../../Interfaces/BioTrackerInterfaces - -win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/release/libBioTrackerInterfaces.a -else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/debug/libBioTrackerInterfaces.a -else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/release/BioTrackerInterfaces.lib -else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/debug/BioTrackerInterfaces.lib -else:unix: PRE_TARGETDEPS += $$PWD/../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/libBioTrackerInterfaces.a - - -# Include the BioTrackerUtils Library - -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/release/ -lBioTrackerUtils -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/debug/ -lBioTrackerUtils -else:unix: LIBS += -L$$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/ -lBioTrackerUtils - -INCLUDEPATH += $$PWD/../../Utils/BioTrackerUtils -DEPENDPATH += $$PWD/../../Utils/BioTrackerUtils - -win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/release/libBioTrackerUtils.a -else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/debug/libBioTrackerUtils.a -else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/release/BioTrackerUtils.lib -else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/debug/BioTrackerUtils.lib -else:unix: PRE_TARGETDEPS += $$PWD/../../Utils/build-BioTrackerUtils-Desktop-Debug/libBioTrackerUtils.a diff --git a/BioTracker/CoreApp/BioTracker/CMakeLists.txt b/BioTracker/CoreApp/BioTracker/CMakeLists.txt deleted file mode 100644 index 17fdb7da..00000000 --- a/BioTracker/CoreApp/BioTracker/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -############################################################## -#### Biotracker: Core -############################################################## - -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) - - -# Visual studio out-of-source friendly source groups -include(${util_cmakes}CMakeVSSugar.txt) - -message("Configuring Biotracker_core..." ) -set(EXE_NAME Biotracker_core) -add_executable(${EXE_NAME} ${_util_source_list} guiresources.qrc) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIRS}) -target_link_libraries (${EXE_NAME} Qt5::Core Qt5::Gui Qt5::Xml Qt5::Network Qt5::Widgets) -target_link_libraries (${EXE_NAME} Qt5::Multimedia Qt5::MultimediaWidgets Qt5::OpenGL ) -target_link_libraries(${EXE_NAME} Biotracker_interfaces Biotracker_utility) -target_link_libraries(${EXE_NAME} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES}) -IF("${HMNVLibDir}" MATCHES "Not Found") -ELSE() - target_link_libraries(${EXE_NAME} ${HMNVLibDir}/lib/NvEncInterace.lib) - target_compile_definitions(${EXE_NAME} PRIVATE WITH_CUDA=1) -ENDIF() - -set_target_properties(${EXE_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) -set_target_properties(${EXE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO -) \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerAnnotations.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerAnnotations.cpp deleted file mode 100644 index d3487918..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerAnnotations.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include "ControllerAnnotations.h" -#include "View/MainWindow.h" -#include "Controller/ControllerGraphicScene.h" -#include "Controller/ControllerPlayer.h" -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -#include "Model/Annotations.h" -#include "View/AnnotationsView.h" -#include "Model/MediaPlayerStateMachine/PlayerParameters.h" - -ControllerAnnotations::~ControllerAnnotations() -{ - delete getModel(); - delete getView(); -} - -void ControllerAnnotations::cleanup() { - // Delete the model to trigger serialization - delete getModel(); -} - -void ControllerAnnotations::reset(std::string filepath) -{ - // Replace the model with a fresh one. - delete getModel(); - createModel(filepath); - connectModelToController(); -} - -ControllerAnnotations::ControllerAnnotations(QObject* parent, IBioTrackerContext* context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) { -} - -void ControllerAnnotations::connectControllerToController() { - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - auto viewController = qobject_cast(ctr); - auto view = dynamic_cast (viewController->getView()); - view->addGraphicsItem(static_cast(getView())); - - QObject::connect(view, &GraphicsView::onMousePressEvent, this, &ControllerAnnotations::mousePressEvent, Qt::DirectConnection); - QObject::connect(view, &GraphicsView::onMouseReleaseEvent, this, &ControllerAnnotations::mouseReleaseEvent, Qt::DirectConnection); - QObject::connect(view, &GraphicsView::onMouseMoveEvent, this, &ControllerAnnotations::mouseMoveEvent, Qt::DirectConnection); - //QObject::connect(view, &GraphicsView::onKeyReleaseEvent, this, &ControllerAnnotations::keyReleaseEvent, Qt::DirectConnection); - QObject::connect(view, &GraphicsView::onKeyPressEvent, this, &ControllerAnnotations::keyPressEvent, Qt::DirectConnection); - - - QWidget *viewport = view->viewport(); - QObject::connect(this, SIGNAL(onRepaintRequired()), viewport, SLOT(repaint())); - } - - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - auto mediaPlayerController = dynamic_cast (ctr); - assert(mediaPlayerController); - MediaPlayer *player = dynamic_cast (mediaPlayerController->getModel()); - assert(player); - QObject::connect(player, &MediaPlayer::fwdPlayerParameters, this, &ControllerAnnotations::setPlayerParameters); - } -} - -void ControllerAnnotations::createModel(std::string filepath) { - m_Model = new Annotations(filepath); -} - -void ControllerAnnotations::createView() { - assert(m_Model); - m_View = new AnnotationsView(this, m_Model); -} - -void ControllerAnnotations::connectModelToController() { - auto model = static_cast(getModel()); - auto view = static_cast(getView()); - view->setNewModel(model); -} - -void ControllerAnnotations::updateView() -{ - auto view = static_cast(getView()); - view->prepareUpdate(); - emit(onRepaintRequired()); -} - -void ControllerAnnotations::keyPressEvent(QKeyEvent *event) -{ - auto model = static_cast(getModel()); - actionQueued = ActionQueued::None; - bool handled = true; - if (event->modifiers()&Qt::AltModifier) { - switch (event->key()) - { - case Qt::Key::Key_A: - actionQueued = ActionQueued::CreateArrow; - break; - case Qt::Key::Key_L: - actionQueued = ActionQueued::CreateLabel; - break; - case Qt::Key::Key_R: - actionQueued = ActionQueued::CreateRect; - break; - case Qt::Key::Key_E: - actionQueued = ActionQueued::CreateEllipse; - break; - case Qt::Key::Key_Delete: - // Remove existing selected annotation at current frame. - if (model->removeSelection()) - { - updateView(); - } - else - handled = false; - break; - default: - handled = false; - break; - } - } - - - if (handled) - event->accept(); -} - -void ControllerAnnotations::mousePressEvent(QMouseEvent *event, const QPoint &pos) -{ - // left-click: add annotation in pos or try start dragging annotation - if (event->button() == Qt::LeftButton) { - auto model = static_cast(getModel()); - bool handled = true; - - switch (actionQueued) - { - case ActionQueued::CreateArrow: - model->startArrow(pos, model->getCurrentFrame()); - break; - case ActionQueued::CreateLabel: - model->startLabel(pos, model->getCurrentFrame()); - break; - case ActionQueued::CreateRect: - model->startRect(pos, model->getCurrentFrame()); - break; - case ActionQueued::CreateEllipse: - model->startEllipse(pos, model->getCurrentFrame()); - break; - default: - if (model->tryStartDragging(pos)) { - updateView(); - } - else { - handled = false; - } - updateView(); - break; - } - if (handled) - event->accept(); - actionQueued = ActionQueued::None; - } - - // right-click: set text for annotation in pos - else if (event->button() == Qt::RightButton) { - auto model = static_cast(getModel()); - bool handled = true; - - if (model->trySetText(pos)) { - updateView(); - } - else { - handled = false; - } - if (handled) { - event->accept(); - } - - } - -} - -void ControllerAnnotations::mouseReleaseEvent(QMouseEvent*event, const QPoint &pos) -{ - auto model = static_cast(getModel()); - - if (model->endAnnotation(pos)) - { - updateView(); - event->accept(); - } -} - -void ControllerAnnotations::mouseMoveEvent(QMouseEvent*event, const QPoint &pos) -{ - auto model = static_cast(getModel()); - - if (event->buttons() == Qt::LeftButton && model->updateAnnotation(pos)) - { - updateView(); - event->accept(); - } -} - -void ControllerAnnotations::setPlayerParameters(playerParameters* parameters) -{ - auto model = static_cast(getModel()); - model->setCurrentFrame(parameters->m_CurrentFrameNumber); - emit(onRepaintRequired()); -} - -void ControllerAnnotations::receiveAddLabelAnno(){ - actionQueued = ActionQueued::CreateLabel; -} -void ControllerAnnotations::receiveAddRectAnno(){ - actionQueued = ActionQueued::CreateRect; -} -void ControllerAnnotations::receiveAddArrAnno(){ - actionQueued = ActionQueued::CreateArrow; -} -void ControllerAnnotations::receiveAddEllAnno(){ - actionQueued = ActionQueued::CreateEllipse; -} -void ControllerAnnotations::receiveDelSelAnno(){ - auto model = static_cast(getModel()); - if (model->removeSelection()){ - updateView(); - } -} - -void ControllerAnnotations::receiveSetAnnoColor(QColor color) -{ - AnnotationsView* view = dynamic_cast(m_View); - if (view) { - view->setColor(color); - } -} - diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerAnnotations.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerAnnotations.h deleted file mode 100644 index 0e6d0905..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerAnnotations.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include "Interfaces/IController/IController.h" -#include "QString" -#include -#include -#include - -struct playerParameters; - -/** -* The ControllerAnnotations inherits IController -* It is the management unit of the annotation component. -* It controls user input -> creates new annotations in model, forwards moves and deletes them -*/ -class ControllerAnnotations : public IController -{ - Q_OBJECT -public: - ControllerAnnotations(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::ANNOTATIONS); - virtual ~ControllerAnnotations(); - void cleanup(); - - // IController interface -public: - void connectControllerToController() override; - - public Q_SLOTS: - - /// - void reset(std::string filepath); - void mousePressEvent(QMouseEvent *event, const QPoint &pos); - void mouseReleaseEvent(QMouseEvent*event, const QPoint &pos); - void mouseMoveEvent(QMouseEvent*event, const QPoint &pos); - void keyPressEvent(QKeyEvent *event); - void setPlayerParameters(playerParameters* parameters); - - //annotation receivers - void receiveAddLabelAnno(); - void receiveAddRectAnno(); - void receiveAddArrAnno(); - void receiveAddEllAnno(); - void receiveDelSelAnno(); - void receiveSetAnnoColor(QColor color); - -protected: - void createModel(std::string filepath = ""); - void createModel() override { createModel(""); } - void createView() override; - void connectModelToController() override; - - enum class ActionQueued - { - None, - CreateArrow, - CreateLabel, - CreateRect, - CreateEllipse, - }; - ActionQueued actionQueued{ ActionQueued::None }; - void updateView(); -Q_SIGNALS: - void onRepaintRequired(); -}; diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerAreaDescriptor.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerAreaDescriptor.cpp deleted file mode 100644 index 8c5d3410..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerAreaDescriptor.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include "ControllerAreaDescriptor.h" - -#include "Model/AreaDescriptor/AreaInfo.h" -#include "View/AreaDesciptor/AreaDescriptor.h" -#include "View/AreaDesciptor/RectDescriptor.h" -#include "View/AreaDesciptor/EllipseDescriptor.h" -#include "settings/Settings.h" -#include "util/types.h" - -#include "ControllerGraphicScene.h" -#include "View/GraphicsView.h" -#include "Model/AreaDescriptor/Rectification.h" -#include "Controller/ControllerPlayer.h" -#include "Controller/ControllerCoreParameter.h" - -#include - -#include "Model/AreaDescriptor/AreaMemory.h" -using namespace AreaMemory; - -ControllerAreaDescriptor::ControllerAreaDescriptor(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - _watchingVertice = -1; - _watchingVerticeType = BiotrackerTypes::AreaType::NONE; - m_ViewApperture = nullptr; -} - -void ControllerAreaDescriptor::triggerUpdateAreaDescriptor() { - - IModelAreaDescriptor* area = dynamic_cast(getModel()); - Q_EMIT updateAreaDescriptor(area); -} - -void ControllerAreaDescriptor::createView() -{ - assert(m_Model); - AreaInfo* mInf = dynamic_cast (getModel()); - RectDescriptor* view = new RectDescriptor(this, mInf->_rect.get()); - m_View = view; - QObject::connect(this, &ControllerAreaDescriptor::currentVectorDrag, view, &RectDescriptor::receiveDragUpdate); - - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - auto viewController = qobject_cast(ctr); - auto gview = dynamic_cast (viewController->getView()); - gview->addGraphicsItem(view); - - AreaInfo* area = dynamic_cast(getModel()); - - BioTracker::Core::Settings *_settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - int v = _settings->getValueOrDefault(AREADESCRIPTOR::CN_APPERTURE_TYPE, 0); - trackingAreaType(v); - -} - -void ControllerAreaDescriptor::connectModelToController() -{ - -} - -void ControllerAreaDescriptor::trackingAreaType(int v) { - - IController* ctr1 = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - auto viewController = qobject_cast(ctr1); - auto gview = dynamic_cast (viewController->getView()); - - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - RectDescriptor* view = dynamic_cast(m_View); - AreaInfo* area = dynamic_cast(getModel()); - if (m_ViewApperture) { - gview->removeGraphicsItem(static_cast(m_ViewApperture)); - delete m_ViewApperture; - } - - BioTracker::Core::Settings *_settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - if (v == 0) { - m_ViewApperture = new RectDescriptor(this, area->_apperture.get()); - area->_apperture->setType(0); - static_cast(m_ViewApperture)->setBrush(QBrush(Qt::red)); - QObject::connect(this, &ControllerAreaDescriptor::currentVectorDrag, static_cast(m_ViewApperture), &RectDescriptor::receiveDragUpdate); - _settings->setParam(AREADESCRIPTOR::CN_APPERTURE_TYPE, 0); - } - else if (v > 0) { - m_ViewApperture = new EllipseDescriptor(this, area->_apperture.get()); - area->_apperture->setType(1); - static_cast(m_ViewApperture)->setBrush(QBrush(Qt::red)); - static_cast(m_ViewApperture)->setDimensions(_w, _h); - QObject::connect(this, &ControllerAreaDescriptor::currentVectorDrag, static_cast(m_ViewApperture), &EllipseDescriptor::receiveDragUpdate); - _settings->setParam(AREADESCRIPTOR::CN_APPERTURE_TYPE, 1); - } - - if (!_visibleApperture) - static_cast(m_ViewApperture)->hide(); - if (!_visibleRectification) - static_cast(m_View)->hide(); - - gview->addGraphicsItem(static_cast(m_ViewApperture)); -} - -void ControllerAreaDescriptor::rcvPlayerParameters(playerParameters* parameters) -{ - //Best effort to save performance... - //File has changed - if (_currentFilename != parameters->m_CurrentFilename) - { - _currentFilename = parameters->m_CurrentFilename; - - //Set area descriptor dimensions - AreaDescriptor* ad = static_cast(m_ViewApperture); - std::shared_ptr m = parameters->m_CurrentFrame; - if (ad && m != nullptr) { - _w = m->size().width; - _h = m->size().height; - ad->setDimensions(_w, _h); - } - QVector v = getVertices(_currentFilename); - if (!v.empty()) { - changeAreaDescriptorType(v[2]); - } - } - -} - -void ControllerAreaDescriptor::connectControllerToController() -{ - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - auto viewController = qobject_cast(ctr); - auto view = dynamic_cast (viewController->getView()); - - QObject::connect(view, &GraphicsView::onMousePressEvent, this, &ControllerAreaDescriptor::mousePressEvent, Qt::DirectConnection); - QObject::connect(view, &GraphicsView::onMouseReleaseEvent, this, &ControllerAreaDescriptor::mouseReleaseEvent, Qt::DirectConnection); - QObject::connect(view, &GraphicsView::onMouseMoveEvent, this, &ControllerAreaDescriptor::mouseMoveEvent, Qt::DirectConnection); - QObject::connect(view, &GraphicsView::onKeyReleaseEvent, this, &ControllerAreaDescriptor::keyReleaseEvent, Qt::DirectConnection); - - //Area info model needs to know video dimensions - auto model = static_cast(getModel()); - IController* ctrPl = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - auto mediaPlayerController = static_cast (ctrPl); - MediaPlayer *player = static_cast (mediaPlayerController->getModel()); - QObject::connect(player, &MediaPlayer::fwdPlayerParameters, model, &AreaInfo::rcvPlayerParameters, Qt::DirectConnection); - QObject::connect(player, &MediaPlayer::fwdPlayerParameters, this, &ControllerAreaDescriptor::rcvPlayerParameters, Qt::DirectConnection); - - - IController* ctrParms = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - auto parmsController = qobject_cast(ctrParms); - QObject::connect(this, &ControllerAreaDescriptor::changeAreaDescriptorType, parmsController, &ControllerCoreParameter::changeAreaDescriptorType, Qt::DirectConnection); - - - AreaInfo* area = dynamic_cast(getModel()); - QObject::connect(area->_rect.get(), SIGNAL(updatedVertices()), this, SLOT(updateView())); - QObject::connect(area->_apperture.get(), SIGNAL(updatedVertices()), this, SLOT(updateView())); - } - { - //View stuff from the parameter view - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - auto viewController = qobject_cast(ctr); - } - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - ControllerCoreParameter *cctr = static_cast(ctr); - cctr->triggerUpdate(); - } -} - -void ControllerAreaDescriptor::createModel() -{ - m_Model = new AreaInfo(0); -} - -void ControllerAreaDescriptor::updateView() { - - AreaInfo* area = static_cast(getModel()); - RectDescriptor* rd = static_cast(getView()); - rd->updateRect(); - AreaDescriptor* ad = static_cast(m_ViewApperture); - ad->updateRect(); - area->updateRectification(); - area->updateApperture(); -} - - -void ControllerAreaDescriptor::keyReleaseEvent(QKeyEvent *event) -{ -} - -void ControllerAreaDescriptor::mousePressEvent(QMouseEvent *event, const QPoint &pos) -{ - auto model = static_cast(getModel()); - - //check if rectification vertice is grabbed and visible - RectDescriptor* rd = static_cast(getView()); - int verticeRect = -1; - if (rd->isVisible()) { - verticeRect = model->_rect->getVerticeAtLocation(pos); - if (verticeRect >= 0) { - _watchingVertice = verticeRect; - _watchingVerticeType = BiotrackerTypes::AreaType::RECT; - event->accept(); - } - } - - - //check if apperture vertice is grabbed and visible - AreaDescriptor* ad = static_cast(m_ViewApperture); - int verticeApp = -1; - if (ad->isVisible()) { - verticeApp = model->_apperture->getVerticeAtLocation(pos); - if (verticeApp >= 0) { - _watchingVertice = verticeApp; - _watchingVerticeType = BiotrackerTypes::AreaType::APPERTURE; - event->accept(); - } - } - - //else none is grabbed - if (verticeRect < 0 && verticeApp < 0) { - _watchingVertice = -1; - _watchingVerticeType = BiotrackerTypes::AreaType::NONE; - } - - //disable use entire screen when one vertice is grabbed - if (verticeRect > 0 || verticeApp > 0) { - AreaInfo* area = static_cast(getModel()); - area->setUseEntireScreen(false); - } - - Q_EMIT currentVectorDrag(_watchingVerticeType, _watchingVertice, pos.x(), pos.y()); -} - -void ControllerAreaDescriptor::mouseReleaseEvent(QMouseEvent*event, const QPoint &pos) -{ - auto model = static_cast(getModel()); - - if (_watchingVertice >= 0 && _watchingVerticeType == BiotrackerTypes::AreaType::RECT) { - model->_rect->setVerticeAtLocation(pos, _watchingVertice); - event->accept(); - triggerUpdateAreaDescriptor(); - } - - if (_watchingVertice >= 0 && _watchingVerticeType == BiotrackerTypes::AreaType::APPERTURE) { - model->_apperture->setVerticeAtLocation(pos, _watchingVertice); - event->accept(); - triggerUpdateAreaDescriptor(); - } - - _watchingVerticeType = BiotrackerTypes::AreaType::NONE; - _watchingVertice = -1; - Q_EMIT currentVectorDrag(_watchingVerticeType, _watchingVertice, pos.x(), pos.y()); -} - -void ControllerAreaDescriptor::mouseMoveEvent(QMouseEvent*event, const QPoint &pos) -{ - Q_EMIT currentVectorDrag(_watchingVerticeType, _watchingVertice, pos.x(), pos.y()); -} - -void ControllerAreaDescriptor::setRectificationDimensions(double w, double h) { - - BioTracker::Core::Settings *_settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - _settings->setParam(AREADESCRIPTOR::RECT_W, w); - _settings->setParam(AREADESCRIPTOR::RECT_H, h); - - AreaInfo* area = static_cast(getModel()); - area->setRectificationDimensions(w, h); - triggerUpdateAreaDescriptor(); - - RectDescriptor* rd = static_cast(getView()); - rd->updateRect(); -} - -void ControllerAreaDescriptor::setDisplayRectificationDefinition(bool b) { - _visibleRectification = b; - RectDescriptor* rd = static_cast(getView()); - rd->setVisible(b); -} - -void ControllerAreaDescriptor::setDisplayTrackingAreaDefinition(bool b) { - _visibleApperture = b; - AreaDescriptor* ad = static_cast(m_ViewApperture); - ad->setVisible(b); -} - -void ControllerAreaDescriptor::setTrackingAreaAsEllipse(bool b) { - //Not passing b as a parameter for clarification reasons - if (b) { - trackingAreaType(1); - } - else { - trackingAreaType(0); - } -} - - diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerAreaDescriptor.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerAreaDescriptor.h deleted file mode 100644 index 1e96dbcf..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerAreaDescriptor.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "Interfaces/IController/IController.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include -#include -#include "util/types.h" -#include "Model/MediaPlayerStateMachine/PlayerParameters.h" - -class ControllerAreaDescriptor : public IController -{ - Q_OBJECT -public: - ControllerAreaDescriptor(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); - - void triggerUpdateAreaDescriptor(); - -signals: - void updateAreaDescriptor(IModelAreaDescriptor *ad); - void currentVectorDrag(BiotrackerTypes::AreaType vectorType, int id, double x, double y); - void changeAreaDescriptorType(QString type); - -public slots: - void setRectificationDimensions(double w, double h); - void setDisplayRectificationDefinition(bool b); - void setDisplayTrackingAreaDefinition(bool b); - void setTrackingAreaAsEllipse(bool b); - void rcvPlayerParameters(playerParameters* parameters); - -private slots: - void trackingAreaType(int v); - - void mousePressEvent(QMouseEvent *event, const QPoint &pos); - void mouseReleaseEvent(QMouseEvent*event, const QPoint &pos); - void mouseMoveEvent(QMouseEvent*event, const QPoint &pos); - void keyReleaseEvent(QKeyEvent *event); - void updateView(); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; -private: - int _watchingVertice; - BiotrackerTypes::AreaType _watchingVerticeType; - - IView *m_ViewApperture; - int _w = 1; - int _h = 1; - bool _visibleApperture = false; - bool _visibleRectification = false; - QString _currentFilename = "No Media"; -}; \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerCommands.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerCommands.cpp deleted file mode 100644 index e8da6014..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerCommands.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "Controller/ControllerCommands.h" -#include "QDebug" - -ControllerCommands::ControllerCommands(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ -} - -ControllerCommands::~ControllerCommands() -{ -} - -void ControllerCommands::receiveAddTrackCommand(QPoint pos, int id) { - AddTrackCommand* addCmd = new AddTrackCommand(id, pos); - QObject::connect(addCmd, &AddTrackCommand::emitAddTrajectory, this, &ControllerCommands::emitAddTrajectory); - QObject::connect(addCmd, &AddTrackCommand::emitValidateTrajectory, this, &ControllerCommands::emitValidateTrajectory); - QObject::connect(addCmd, &AddTrackCommand::emitRemoveTrajectoryId, this, &ControllerCommands::emitRemoveTrajectoryId); - - _undoStack->push(addCmd); -} - -void ControllerCommands::receiveRemoveTrackCommand(IModelTrackedTrajectory * traj) -{ - RemoveTrackCommand* rmtCmd = new RemoveTrackCommand(traj); - QObject::connect(rmtCmd, &RemoveTrackCommand::emitValidateTrajectory, this, &ControllerCommands::emitValidateTrajectory); - QObject::connect(rmtCmd, &RemoveTrackCommand::emitRemoveTrajectory, this, &ControllerCommands::emitRemoveTrajectory); - - _undoStack->push(rmtCmd); -} - -void ControllerCommands::receiveRemoveTrackEntityCommand(IModelTrackedTrajectory * traj, uint frameNumber) -{ - RemoveElementCommand* rmeCmd = new RemoveElementCommand(traj, frameNumber); - QObject::connect(rmeCmd, &RemoveElementCommand::emitValidateEntity, this, &ControllerCommands::emitValidateEntity); - QObject::connect(rmeCmd, &RemoveElementCommand::emitRemoveElement, this, &ControllerCommands::emitRemoveTrackEntity); - - _undoStack->push(rmeCmd); -} - -void ControllerCommands::receiveMoveElementCommand(IModelTrackedTrajectory* traj, QPoint oldPos, QPoint newPos, uint frameNumber, int toMove) -{ - MoveElementCommand* mvCmd = new MoveElementCommand(traj, frameNumber, oldPos, newPos, toMove); - QObject::connect(mvCmd, &MoveElementCommand::emitMoveElement, this, &ControllerCommands::emitMoveElement); - - _undoStack->push(mvCmd); -} - -void ControllerCommands::receiveSwapIdCommand(IModelTrackedTrajectory * traj0, IModelTrackedTrajectory * traj1) -{ - SwapTrackIdCommand* swapCmd = new SwapTrackIdCommand(traj0, traj1); - QObject::connect(swapCmd, &SwapTrackIdCommand::emitSwapIds, this, &ControllerCommands::emitSwapIds); - - _undoStack->push(swapCmd); -} - -void ControllerCommands::receiveFixTrackCommand(IModelTrackedTrajectory * traj, bool toggle) -{ - FixTrackCommand* fixCmd = new FixTrackCommand(traj, toggle); - QObject::connect(fixCmd, &FixTrackCommand::emitFixTrack, this, &ControllerCommands::emitToggleFixTrack); - - _undoStack->push(fixCmd); -} - -void ControllerCommands::receiveEntityRotation(IModelTrackedTrajectory * traj,double oldAngleDeg, double newAngleDeg, uint frameNumber) -{ - RotateEntityCommand* rotCmd = new RotateEntityCommand(traj, oldAngleDeg, newAngleDeg, frameNumber); - QObject::connect(rotCmd, &RotateEntityCommand::emitEntityRotation, this, &ControllerCommands::emitEntityRotation); - - _undoStack->push(rotCmd); -} - -void ControllerCommands::receiveUndo() -{ - if (_undoStack->canUndo()) { - _undoStack->undo(); - } - else { - qDebug() << "CORE: Cannot undo the last command!"; - } -} - -void ControllerCommands::receiveRedo() -{ - if (_undoStack->canRedo()) { - _undoStack->redo(); - } - else { - qDebug() << "CORE: Csannot redo the next command!"; - } -} - -void ControllerCommands::receiveClear() -{ - _undoStack->clear(); -} - -void ControllerCommands::receiveShowActionList() -{ - _undoView->show(); -} - -void ControllerCommands::connectControllerToController() -{ - -} - -void ControllerCommands::createModel() -{ - _undoStack = new QUndoStack(this); -} - -void ControllerCommands::createView() -{ - _undoView = new QUndoView(_undoStack); - _undoView->setWindowTitle("Command List"); - _undoView->setAttribute(Qt::WA_QuitOnClose, false); -} - -void ControllerCommands::connectModelToController() -{ -} diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerCommands.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerCommands.h deleted file mode 100644 index 65c0ea77..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerCommands.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef CONTROLLERCOMMANDS_H -#define CONTROLLERCOMMANDS_H - -#pragma once -#include "Interfaces/IController/IController.h" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "Model/UndoCommands/TrackCommands.h" -#include "QUndoStack" -#include "QUndoView" - -/** -* This class inherits from IController. -* http://doc.qt.io/qt-5/qundo.html -* The commands component controls the commands on an undo/redo stack (model) and the undo view -*/ -class ControllerCommands : public IController { - Q_OBJECT -public: - ControllerCommands(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - virtual ~ControllerCommands(); - -signals: - // signal to ctrPlugin to remove trajectory - void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); - - void emitRemoveTrajectoryId(int id); - - // signal to ctrPlugin to remove track entity - void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - - // signal to ctrPlugin to add trajectory - void emitAddTrajectory(QPoint pos); - - void emitValidateTrajectory(int id); - - void emitValidateEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - - void emitMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint pos, int toMove); - - void emitSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - - void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - - void emitEntityRotation(IModelTrackedTrajectory* trajectory, double angleDeg, uint frameNumber); - - - public slots: - void receiveAddTrackCommand(QPoint pos, int id); - void receiveRemoveTrackCommand(IModelTrackedTrajectory* traj); - void receiveRemoveTrackEntityCommand(IModelTrackedTrajectory* traj, uint frameNumber); - void receiveMoveElementCommand(IModelTrackedTrajectory* traj, QPoint oldPos, QPoint newPos, uint frameNumber, int toMove); - void receiveSwapIdCommand(IModelTrackedTrajectory* traj0, IModelTrackedTrajectory* traj1); - void receiveFixTrackCommand(IModelTrackedTrajectory* traj, bool toggle); - void receiveEntityRotation(IModelTrackedTrajectory* traj, double oldAngleDeg, double newAngleDeg, uint frameNumber); - - void receiveUndo(); - void receiveRedo(); - void receiveClear(); - void receiveShowActionList(); - - // IController interface -public: - void connectControllerToController() override; - -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - //member -private: - QUndoStack* _undoStack; - QUndoView* _undoView; -}; - -#endif // CONTROLLERCOMMANDS_H \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerCoreParameter.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerCoreParameter.cpp deleted file mode 100644 index cc1ba3cd..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerCoreParameter.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "ControllerCoreParameter.h" -#include "ControllerTrackedComponentCore.h" -#include "ControllerAreaDescriptor.h" -#include "ControllerDataExporter.h" -#include "ControllerGraphicScene.h" -#include "ControllerPlayer.h" -#include "ControllerMainWindow.h" -#include "ControllerAnnotations.h" -#include "View/CoreParameterView.h" -#include "View/TrackedComponentView.h" -#include "Model/CoreParameter.h" - -ControllerCoreParameter::ControllerCoreParameter(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - -} - -void ControllerCoreParameter::createView() -{ - assert(m_Model); - m_View = new CoreParameterView(0, this, m_Model); -} - -void ControllerCoreParameter::connectModelToController() -{ - -} - -void ControllerCoreParameter::connectControllerToController() -{ - CoreParameterView* view = static_cast(m_View);view->triggerUpdate(); - //Connections to the trackedComponentCore - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - ControllerTrackedComponentCore *tccController = dynamic_cast(ctr); - IView* vv = tccController->getView(); - TrackedComponentView* tcview = static_cast(vv); - - IController* ctr2 = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - ControllerGraphicScene* ctrGrphScn = dynamic_cast(ctr2); - - - QObject::connect(view, &CoreParameterView::emitViewSwitch, tcview, &TrackedComponentView::receiveViewSwitch, Qt::DirectConnection); - //Tracks - //QObject::connect(view, &CoreParameterView::emitSelectAll, tcview, &TrackedComponentView::receiveSelectAll, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitAddTrack, tcview, &TrackedComponentView::addTrajectory, Qt::DirectConnection); - - //Track dimensions - QObject::connect(view, &CoreParameterView::emitTrackOrientationLine, tcview, &TrackedComponentView::receiveTrackOrientationLine, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrackShowId, tcview, &TrackedComponentView::receiveTrackShowId, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrackDimensionsAll, tcview, &TrackedComponentView::receiveTrackDimensionsAll, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrackDimensionsSelected, tcview, &TrackedComponentView::receiveTrackDimensionsSelected, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrackDimensionsSetDefault, tcview, &TrackedComponentView::receiveTrackDimensionsSetDefault, Qt::DirectConnection); - - //Track ignore zoom - QObject::connect(view, &CoreParameterView::emitIgnoreZoom, tcview, &TrackedComponentView::receiveIgnoreZoom, Qt::DirectConnection); - - //Track color - QObject::connect(view, &CoreParameterView::emitColorChangeBorderAll, tcview, &TrackedComponentView::receiveColorChangeBorderAll, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitColorChangeBorderSelected, tcview, &TrackedComponentView::receiveColorChangeBorderSelected, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitColorChangeBrushAll, tcview, &TrackedComponentView::receiveColorChangeBrushAll, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitColorChangeBrushSelected, tcview, &TrackedComponentView::receiveColorChangeBrushSelected, Qt::DirectConnection); - //Tracing - QObject::connect(view, &CoreParameterView::emitTracingHistoryLength, tcview, &TrackedComponentView::receiveTracingHistoryLength, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTracingStyle, tcview, &TrackedComponentView::receiveTracingStyle, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTracingSteps, tcview, &TrackedComponentView::receiveTracingSteps, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTracingTimeDegradation, tcview, &TrackedComponentView::receiveTracingTimeDegradation, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTracerFrameNumber, tcview, &TrackedComponentView::receiveTracerFrameNumber, Qt::DirectConnection); - //Tracing dimensions - QObject::connect(view, &CoreParameterView::emitTracerProportions, tcview, &TrackedComponentView::receiveTracerProportions, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTracerOrientationLine, tcview, &TrackedComponentView::receiveTracerOrientationLine, Qt::DirectConnection); - //Misc - QObject::connect(view, &CoreParameterView::emitToggleAntialiasingEntities, tcview, &TrackedComponentView::receiveToggleAntialiasingEntities, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitToggleAntialiasingFull, ctrGrphScn, &ControllerGraphicScene::receiveToggleAntialiasingFull, Qt::DirectConnection); - - } - //Connections to the AreaDescriptor - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); - ControllerAreaDescriptor *adController = static_cast(ctr); - QObject::connect(view, &CoreParameterView::emitRectDimensions, adController, &ControllerAreaDescriptor::setRectificationDimensions, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitDisplayTrackingArea, adController, &ControllerAreaDescriptor::setDisplayTrackingAreaDefinition, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitDisplayRectification, adController, &ControllerAreaDescriptor::setDisplayRectificationDefinition, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrackingAreaAsEllipse, adController, &ControllerAreaDescriptor::setTrackingAreaAsEllipse, Qt::DirectConnection); - } - - //Connections to the Annotations - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::ANNOTATIONS); - ControllerAnnotations *annoController = static_cast(ctr); - QObject::connect(view, &CoreParameterView::emitSetAnnoColor, annoController, &ControllerAnnotations::receiveSetAnnoColor, Qt::DirectConnection); - } - - //Connections to the DataExporter - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - ControllerDataExporter *deController = static_cast(ctr); - QObject::connect(view, &CoreParameterView::emitFinalizeExperiment, deController, &ControllerDataExporter::receiveFinalizeExperiment, Qt::DirectConnection); - QObject::connect(view, &CoreParameterView::emitTrialStarted, deController, &ControllerDataExporter::receiveTrialStarted, Qt::DirectConnection); - - - } - //Media Player - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - ControllerPlayer *mpc = static_cast(ctr); - MediaPlayer* mp = static_cast(mpc->getModel()); - QObject::connect(mp, &MediaPlayer::fwdPlayerParameters, view, &CoreParameterView::rcvPlayerParameters); - QObject::connect(view, &CoreParameterView::emitStartPlayback, mpc, &ControllerPlayer::play); - QObject::connect(view, &CoreParameterView::emitStopPlayback, mpc, &ControllerPlayer::stop); - QObject::connect(view, &CoreParameterView::emitPausePlayback, mpc, &ControllerPlayer::pause); - } - //Main Window - { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - ControllerMainWindow *mwc = static_cast(ctr); - QObject::connect(view, &CoreParameterView::emitEnableTracking, mwc, &ControllerMainWindow::activeTracking); - QObject::connect(view, &CoreParameterView::emitDisableTracking, mwc, &ControllerMainWindow::deactiveTrackring); - QObject::connect(view, &CoreParameterView::emitActivateTrackingSwitch, mwc, &ControllerMainWindow::activeTrackingCheckBox); - QObject::connect(view, &CoreParameterView::emitDeactivateTrackingSwitch, mwc, &ControllerMainWindow::deactiveTrackingCheckBox); - QObject::connect(view, &CoreParameterView::emitSaveDataToFile, mwc, &ControllerMainWindow::receiveSaveTrajData); - } - - view->triggerUpdate(); -} - -void ControllerCoreParameter::changeAreaDescriptorType(QString type) { - if (dynamic_cast(m_View)) - dynamic_cast(m_View)->areaDescriptorTypeChanged(type); -} - -void ControllerCoreParameter::receiveResetTrial() -{ - CoreParameterView* view = static_cast(m_View); - view->resetTrial(); -} - -void ControllerCoreParameter::triggerUpdate() { - - CoreParameterView* view = static_cast(m_View); - view->triggerUpdate(); -} - -void ControllerCoreParameter::receiveTrackNumber(int number) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - if (coreParams) { - coreParams->setTrackNumber(number); - } -} - -void ControllerCoreParameter::createModel() -{ - - m_Model = new CoreParameter(this); -} - -void ControllerCoreParameter::updateView() -{ -} - -void ControllerCoreParameter::setCorePermission(std::pair permission) -{ - if (dynamic_cast(m_View)) { - dynamic_cast(m_View)->setPermission(permission); - } - else { - //qDebug() << "no view yet"; - //This should never happen, actually - assert(false); - } -} - -int ControllerCoreParameter::getTrialNumber() { - return (static_cast(m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT)))->getNumber(true); -} - diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerCoreParameter.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerCoreParameter.h deleted file mode 100644 index a1627b13..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerCoreParameter.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "Interfaces/IController/IController.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include -#include - -class ControllerCoreParameter : public IController -{ - Q_OBJECT -public: - ControllerCoreParameter(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COREPARAMETER); - - //Triggers the view to re-send gui parameters - void triggerUpdate(); - -signals: - //... - - private slots: - //... - void updateView(); - //update track number - void receiveTrackNumber(int number); - - public slots: - void setCorePermission(std::pair permission); - void changeAreaDescriptorType(QString type); - void receiveResetTrial(); - - //Forwarded from data exporter - int getTrialNumber(); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; -private: - //... - -}; diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerDataExporter.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerDataExporter.cpp deleted file mode 100644 index c4436669..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerDataExporter.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "ControllerDataExporter.h" -#include "Controller/ControllerCommands.h" -#include "Controller/ControllerTrackedComponentCore.h" -#include "Controller/ControllerPlayer.h" -#include "Model/DataExporters/DataExporterCSV.h" -#include "Model/DataExporters/DataExporterSerialize.h" -#include "Model/DataExporters/DataExporterJson.h" -#include "settings/Settings.h" -#include "util/types.h" -#include -#include "QDesktopServices" - - -ControllerDataExporter::ControllerDataExporter(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ -} - -ControllerDataExporter::~ControllerDataExporter() -{ -} - -void ControllerDataExporter::cleanup() { - if (m_Model) - qobject_cast(m_Model)->finalize(); -} - -void ControllerDataExporter::connectControllerToController() { - //connect to controller commands - IController* ictrcmd = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMMANDS); - ControllerCommands *ctrcmd = static_cast(ictrcmd); - - QObject::connect(this, &ControllerDataExporter::emitResetUndoStack, ctrcmd, &ControllerCommands::receiveClear, Qt::DirectConnection); - - //connect to view controller - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - ControllerTrackedComponentCore *tccController = dynamic_cast(ctr); - - QObject::connect(this, &ControllerDataExporter::emitViewUpdate, tccController, &ControllerTrackedComponentCore::receiveUpdateView, Qt::DirectConnection); - - - ControllerPlayer* cPl = dynamic_cast(m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER)); - QObject::connect(cPl, &ControllerPlayer::emitNextMediaInBatch, this, &ControllerDataExporter::receiveReset, Qt::DirectConnection); -} - -void ControllerDataExporter::createModel() { - m_Model = nullptr; -} - -SourceVideoMetadata ControllerDataExporter::getSourceMetadata() { - IController* ctrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - MediaPlayer* mplay = dynamic_cast(ctrM->getModel()); - SourceVideoMetadata d; - d.name = mplay->getCurrentFileName().toStdString(); - d.fps = std::to_string(mplay->getFpsOfSourceFile()); - d.fps = d.fps.erase(d.fps.find_last_not_of('0') + 1, std::string::npos); - return d; -} - -void ControllerDataExporter::loadFile(std::string file) { - if (_factory) { - qobject_cast(m_Model)->loadFile(file); - } - else { - std::cout << "Can not load tracks for this plugin as it does not provide a factory." << std::endl; - } -} - -void ControllerDataExporter::saveFile(std::string file) { - if (_factory) { - qobject_cast(m_Model)->writeAll(file); - } - else { - std::cout << "Can not save tracks for this plugin as it does not provide a factory." << std::endl; - } -} - -void ControllerDataExporter::createView() { - - m_View = 0; -} - -void ControllerDataExporter::setDataStructure(IModel* exp) { - if (getModel()) - delete getModel(); - - //Grab the codec from config file - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - std::string exporter = exporterList[set->getValueOrDefault(CFG_EXPORTER, 0)]; - if (exporter == "CSV") - m_Model = new DataExporterCSV(this); - else if (exporter == "Serialize") - m_Model = new DataExporterSerialize(this); - else if (exporter == "Json") - m_Model = new DataExporterJson(this); - else - m_Model = nullptr; - - qobject_cast(m_Model)->open(static_cast(exp)); - - IModelDataExporter* model; - if ((model = dynamic_cast(getModel())) != nullptr) { - QObject::connect(model, &IModelDataExporter::fileWritten, this, &ControllerDataExporter::receiveFileWritten); - } - -} - -void ControllerDataExporter::setComponentFactory(IModelTrackedComponentFactory* exp) { - _factory = exp; -} - -void ControllerDataExporter::receiveTrackingDone(uint frame) { - if (getModel()) { - dynamic_cast(getModel())->write(frame); - } -} - -void ControllerDataExporter::receiveFinalizeExperiment() { - if (getModel()) { - emitResetUndoStack(); - dynamic_cast(getModel())->finalizeAndReInit(); - emitViewUpdate(); - } -} - -void ControllerDataExporter::receiveReset() { - if (getModel()) { - emitResetUndoStack(); - dynamic_cast(getModel())->finalizeAndReInit(); - dynamic_cast(getModel())->close(); - emitViewUpdate(); - } - - createModel(); -} - -void ControllerDataExporter::connectModelToController() { - IController* ctrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - MediaPlayer* mplay = dynamic_cast(ctrM->getModel()); - - QObject::connect(mplay, &MediaPlayer::fwdPlayerParameters, this, &ControllerDataExporter::rcvPlayerParameters); -} - -void ControllerDataExporter::rcvPlayerParameters(playerParameters* parameters) { - if (qobject_cast(m_Model) != nullptr) { - qobject_cast(m_Model)->setFps(parameters->m_fpsSourceVideo); - qobject_cast(m_Model)->setTitle(parameters->m_CurrentTitle); - } -} - -int ControllerDataExporter::getNumber(bool trial) { - //Get all existing files of trial or track directory and parse highest export number - QString basePath = trial ? CFG_DIR_TRIALS : CFG_DIR_TRACKS; - QStringList allFiles = QDir(basePath).entryList(QDir::NoDotAndDotDot | QDir::Files); - - int maxVal = 0; - foreach(QString s, allFiles) { - int val; - if (sscanf(s.toStdString().c_str(), "Export_%d_*", &val) != EOF) { - maxVal = std::max(maxVal, val); - } - } - return maxVal; -} - -QString ControllerDataExporter::generateBasename(bool temporaryFile) { - - QString resultPath = (_trialStarted ? CFG_DIR_TRIALS : CFG_DIR_TRACKS); - - QString path = (temporaryFile ? CFG_DIR_TEMP : resultPath); - int maxVal = getNumber(_trialStarted ? true : false); - std::string current = "Export_"+std::to_string(maxVal+1)+"_"; - - return QString(getTimeAndDate(path.toStdString() + current, "").c_str()); -} - -void ControllerDataExporter::receiveFileWritten(QFileInfo fname) { - - QString str = "Exported file:\n"; - str += fname.absoluteFilePath(); - -// int ret = QMessageBox::information(nullptr, QString("Trajectory Exporting"), -// str, -// QMessageBox::Ok); - QMessageBox msgBox; - msgBox.setText("File saved!"); - msgBox.setInformativeText(str); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - QPushButton *goToFileDirButton = msgBox.addButton(tr("Show in folder"), QMessageBox::ActionRole); - QPushButton *openFileButton = msgBox.addButton(tr("Open file"), QMessageBox::ActionRole); - - msgBox.setIcon(QMessageBox::Information); - msgBox.exec(); - - if (msgBox.clickedButton() == goToFileDirButton) { - QUrl fileDirUrl = QUrl::fromLocalFile(fname.absolutePath()); - QDesktopServices::openUrl(fileDirUrl); - } - else if (msgBox.clickedButton() == openFileButton){ - QUrl fileUrl = QUrl::fromLocalFile(fname.absoluteFilePath()); - QDesktopServices::openUrl(fileUrl); - } - -} - -void ControllerDataExporter::receiveTrialStarted(bool started) -{ - _trialStarted = started; -} - diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerDataExporter.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerDataExporter.h deleted file mode 100644 index ea71cb3c..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerDataExporter.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "Interfaces/IController/IController.h" -#include "Interfaces/IBioTrackerPlugin.h" -#include "Interfaces/IModel/IModelTrackedComponentFactory.h" -#include "QPointer" -#include "QThread" -#include "Model/MediaPlayer.h" - -//POD class to bundle some infos -struct SourceVideoMetadata { - std::string name; - std::string fps; -}; - -class ControllerDataExporter : public IController { - Q_OBJECT -public: - ControllerDataExporter(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - ~ControllerDataExporter(); - void cleanup(); - - // IController interface -public: - void connectControllerToController() override; - void setDataStructure(IModel* exp); - void setComponentFactory(IModelTrackedComponentFactory* exp); - IModelTrackedComponentFactory* getComponentFactory() { return _factory; }; - SourceVideoMetadata getSourceMetadata(); - int getNumber(bool trial); - QString generateBasename(bool temporaryFile); - - void loadFile(std::string file); - void saveFile(std::string file); - -Q_SIGNALS: - void emitResetUndoStack(); - void emitViewUpdate(); - - public Q_SLOTS: - void receiveReset(); - void receiveTrackingDone(uint frame); - void receiveFinalizeExperiment(); - void receiveFileWritten(QFileInfo fname); - void receiveTrialStarted(bool started); - -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - -private Q_SLOTS: - void rcvPlayerParameters(playerParameters* parameters); - -private: - IModelTrackedComponentFactory* _factory; - bool _trialStarted = false; -}; - diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerGraphicScene.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerGraphicScene.cpp deleted file mode 100644 index 24ac9fb8..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerGraphicScene.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "ControllerGraphicScene.h" -//#include "Model/TrackedComponents/TrackedElement.h" -#include "View/GraphicsView.h" -#include "Model/null_Model.h" -#include "View/MainWindow.h" - -ControllerGraphicScene::ControllerGraphicScene(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - m_Element = NULL; - m_GraphicsView = NULL; -} - -void ControllerGraphicScene::addGraphicsItem(QGraphicsItem *item) -{ - GraphicsView *gview = dynamic_cast (m_View); - gview->addGraphicsItem(item); -} - -void ControllerGraphicScene::addTextureObject(QGraphicsItem *item) -{ - GraphicsView *gview = dynamic_cast (m_View); - gview->addPixmapItem(item); -} - -void ControllerGraphicScene::createModel() -{ - m_NullModel = new null_Model(); -} - -void ControllerGraphicScene::createView() -{ - m_View = new GraphicsView(0, this, m_NullModel); -} - -void ControllerGraphicScene::connectModelToController() -{ - QObject::connect(this, &ControllerGraphicScene::signalToggleAntialiasingFull, dynamic_cast(m_View), &GraphicsView::receiveToggleAntialiasingFull); -} - -void ControllerGraphicScene::connectControllerToController() -{ - IController * ctrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< MainWindow > mainWin = dynamic_cast(ctrM->getView()); - mainWin->addVideoView(m_View); -} - -void ControllerGraphicScene::receiveToggleAntialiasingFull(bool toggle) { - signalToggleAntialiasingFull(toggle); -} \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerGraphicScene.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerGraphicScene.h deleted file mode 100644 index 84972cd1..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerGraphicScene.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef CONTROLLERGRAPHICSCENE_H -#define CONTROLLERGRAPHICSCENE_H - -#include "Interfaces/IController/IController.h" -#include "QGraphicsObject" -#include "QPointer" - -/** - * The ControllerGraphicScene class controlls the component for rendering TextureObjects and TrackedComponents on a GraphhicsView. - * Each PixmapItem represents a cv::Mat. The cv::Mat comes from the TextureObjects-Component of BioTracker. - * The GraphicsItem represents the compositum structure of IViewTrackedComponent classes. These structure comes from the ControllerTrackedComponentCore or the Plugin and handed over by the PluginController of the MainApplication. - * - */ -class ControllerGraphicScene : public IController { - Q_OBJECT - public: - ControllerGraphicScene(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - /** - * This methode add a the root node of the compositum structure of IViewTrackedComponent classes to the GraphicsView canvas. - * All child nodes will be rendered on a GraphicsView canvas as well. - */ - void addGraphicsItem(QGraphicsItem* item); - /** - * This methode adds a IViewGraphicsPixmapItem to the GraphicsView canvas for rendering. - */ - void addTextureObject(QGraphicsItem* item); - - signals: - void signalToggleAntialiasingFull(bool toggle); - - public slots: - void receiveToggleAntialiasingFull(bool toggle); - - // IController interface - protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - - private: - - IView* m_GraphicsView; - - IModel* m_Element; - QPointer< IModel > m_NullModel; -}; - -#endif // CONTROLLERGRAPHICSCENE_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerMainWindow.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerMainWindow.cpp deleted file mode 100644 index 225dbbd8..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerMainWindow.cpp +++ /dev/null @@ -1,255 +0,0 @@ -#include "ControllerMainWindow.h" -#include "View/MainWindow.h" -#include "View/GraphicsView.h" -#include "Model/null_Model.h" -#include "Model/Annotations.h" - -#include "Controller/ControllerPlayer.h" -#include "Controller/ControllerPlugin.h" -#include "Controller/ControllerAnnotations.h" -#include "Controller/ControllerDataExporter.h" -#include "Controller/ControllerTrackedComponentCore.h" -#include "Controller/ControllerCommands.h" -#include "Controller/ControllerGraphicScene.h" -#include "Controller/ControllerCoreParameter.h" -#include "GuiContext.h" - -#include "QPluginLoader" -#include "util/types.h" - -#include -#include - - -ControllerMainWindow::ControllerMainWindow(QObject* parent, IBioTrackerContext* context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) { - -} - -void ControllerMainWindow::loadVideo(std::vector files) { - - Q_EMIT emitOnLoadMedia(files.front().string()); - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - qobject_cast(ctr)->loadVideoStream(files); - Q_EMIT emitMediaLoaded(files.front().string()); - - dynamic_cast(m_View)->checkMediaGroupBox(); -} - -void ControllerMainWindow::loadTracker(QString plugin) { - Q_EMIT emitOnLoadPlugin(plugin.toStdString()); - dynamic_cast(m_View)->resetTrackerViews(); - qobject_cast(m_BioTrackerContext)->loadBioTrackerPlugin(plugin); - dynamic_cast(m_View)->checkTrackerGroupBox(); - activeTrackingCheckBox(); - Q_EMIT emitPluginLoaded(plugin.toStdString()); -} - -void ControllerMainWindow::loadPictures(std::vector files) { - std::string str = files.empty() ? "" : files.front().string(); - - Q_EMIT emitOnLoadMedia(str); - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - qobject_cast(ctr)->loadPictures(files); - Q_EMIT emitMediaLoaded(str); - - dynamic_cast(m_View)->checkMediaGroupBox(); -} - -void ControllerMainWindow::loadCameraDevice(CameraConfiguration conf) { - Q_EMIT emitOnLoadMedia("::Camera"); - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - qobject_cast(ctr)->loadCameraDevice(conf); - Q_EMIT emitMediaLoaded("::Camera"); - - dynamic_cast(m_View)->checkMediaGroupBox(); -} - -void ControllerMainWindow::activeTracking() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - qobject_cast(ctr)->setTrackingActivated(); - dynamic_cast(m_View)->activateTracking(); -} - -void ControllerMainWindow::deactiveTrackring() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - qobject_cast(ctr)->setTrackingDeactivated(); - dynamic_cast(m_View)->deactivateTracking(); -} - -void ControllerMainWindow::setTrackerList(QStringListModel* trackerList, QString current) { - dynamic_cast(m_View)->setTrackerList(trackerList, current); -} - -void ControllerMainWindow::setTrackerParamterWidget(IView* widget) { - dynamic_cast(m_View)->addTrackerParameterView(widget); -} - -void ControllerMainWindow::setTrackerElementsWidget(IView *widget) -{ - dynamic_cast(m_View)->addTrackerElementsView(widget); -} - -void ControllerMainWindow::setCoreElementsWidget(IView * widget) -{ - dynamic_cast(m_View)->addCoreElementsView(widget); -} - -void ControllerMainWindow::setNotificationBrowserWidget(IView* widget) -{ - dynamic_cast(m_View)->addNotificationBrowser(widget); -} - - -void ControllerMainWindow::loadTrajectoryFile(std::string file) { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - static_cast(ctr)->loadFile(file); - Q_EMIT emitTrackLoaded(file); -} - -void ControllerMainWindow::saveTrajectoryFile(std::string file) { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - static_cast(ctr)->saveFile(file); -} - -void ControllerMainWindow::deactiveTrackingCheckBox() { - dynamic_cast(m_View)->deactivateTrackingCheckBox(); -} - -void ControllerMainWindow::activeTrackingCheckBox() { - dynamic_cast(m_View)->activeTrackingCheckBox(); -} - -void ControllerMainWindow::receiveSaveTrajData(){ - dynamic_cast(m_View)->saveDataToFile(); -} - -void ControllerMainWindow::createModel() -{ - // no model for MainWindow - m_Model = new null_Model(); -} - -void ControllerMainWindow::createView() { - m_View = dynamic_cast (new MainWindow(0, this, m_Model)); - static_cast(m_View)->show(); -} - -void ControllerMainWindow::connectModelToController() { - - MainWindow *mw = dynamic_cast (m_View); - QObject::connect(mw, &MainWindow::selectPlugin, this, &ControllerMainWindow::rcvSelectPlugin); - - // Prepare annotations and serialize existing ones. - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::ANNOTATIONS); - ControllerAnnotations *annotationController = static_cast(ctr); - QObject::connect(this, &ControllerMainWindow::emitMediaLoaded, annotationController, &ControllerAnnotations::reset, Qt::DirectConnection); - - // Write previously written data structure and reset it - IController* ctr2 = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - ControllerDataExporter *contrl = static_cast(ctr2); - QObject::connect(this, &ControllerMainWindow::emitOnLoadMedia, contrl, &ControllerDataExporter::receiveFinalizeExperiment, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitOnLoadPlugin, contrl, &ControllerDataExporter::receiveReset, Qt::DirectConnection); - -} - -void ControllerMainWindow::connectControllerToController() { - // - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - IView* v = ctr->getView(); - dynamic_cast(m_View)->addCoreParameterView(v); - - //connect to controller commands - IController* ictrcmd = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMMANDS); - ControllerCommands *ctrcmd = static_cast(ictrcmd); - - QObject::connect(this, &ControllerMainWindow::emitUndoCommand, ctrcmd, &ControllerCommands::receiveUndo, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitRedoCommand, ctrcmd, &ControllerCommands::receiveRedo, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitOnLoadMedia, ctrcmd, &ControllerCommands::receiveClear, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitOnLoadPlugin, ctrcmd, &ControllerCommands::receiveClear, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitShowActionListCommand, ctrcmd, &ControllerCommands::receiveShowActionList, Qt::DirectConnection); - - //connect to ControllerGraphicScene - IController* ictrgrv = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - ControllerGraphicScene *ctrgrv = static_cast(ictrgrv); - GraphicsView* grv = static_cast(ctrgrv->getView()); - - QObject::connect(grv, &GraphicsView::emitCursorPosition, this, &ControllerMainWindow::receiveCursorPosition, Qt::QueuedConnection); - - //connect to ControllerTrackedComponentCore - IController* ictrtrcc = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - ControllerTrackedComponentCore *ctrtrcc = static_cast(ictrtrcc); - - QObject::connect(this, &ControllerMainWindow::emitAddTrack, ctrtrcc, &ControllerTrackedComponentCore::emitAddTrack, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitDeleteSelectedTracks, ctrtrcc, &ControllerTrackedComponentCore::emitDeleteSelectedTracks, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitSelectAll, ctrtrcc, &ControllerTrackedComponentCore::emitSelectAll, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitSwapIds, ctrtrcc, &ControllerTrackedComponentCore::emitSwapIdsToView, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitChangeColorBorder, ctrtrcc, &ControllerTrackedComponentCore::emitChangeColorBorder, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitChangeColorFill, ctrtrcc, &ControllerTrackedComponentCore::emitChangeColorFill, Qt::DirectConnection); - - //connect to ControllerAnnotations - IController* ictrann = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::ANNOTATIONS); - ControllerAnnotations *ctrann = static_cast(ictrann); - - QObject::connect(this, &ControllerMainWindow::emitAddLabelAnno, ctrann, &ControllerAnnotations::receiveAddLabelAnno, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitAddRectAnno, ctrann, &ControllerAnnotations::receiveAddRectAnno, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitAddArrAnno, ctrann, &ControllerAnnotations::receiveAddArrAnno, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitAddEllAnno, ctrann, &ControllerAnnotations::receiveAddEllAnno, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitDelSelAnno, ctrann, &ControllerAnnotations::receiveDelSelAnno, Qt::DirectConnection); - - //connect to ControllerDataExporter - IController* ictrde = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - ControllerDataExporter *deController = static_cast(ictrde); - QObject::connect(this, &ControllerMainWindow::emitFinalizeExperiment, deController, &ControllerDataExporter::receiveFinalizeExperiment, Qt::DirectConnection); - - // reset trials - IController* ictrcpv = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - ControllerCoreParameter *ctrcpv = static_cast(ictrcpv); - QObject::connect(this, &ControllerMainWindow::emitOnLoadMedia, ctrcpv, &ControllerCoreParameter::receiveResetTrial, Qt::DirectConnection); - QObject::connect(this, &ControllerMainWindow::emitOnLoadPlugin, ctrcpv, &ControllerCoreParameter::receiveResetTrial, Qt::DirectConnection); - - // - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - std::string *video = (std::string*)(set->readValue("video")); - if (video) - loadVideo({ video->c_str() }); - -} - -void ControllerMainWindow::receiveCursorPosition(QPoint pos) -{ - //qDebug() << pos; - dynamic_cast(m_View)->setCursorPositionLabel(pos); -} - -void ControllerMainWindow::setCorePermission(std::pair permission){ - if( dynamic_cast(m_View)){ - dynamic_cast(m_View)->setCorePermission(permission); - } - else{ - assert(false); - } -} - -void ControllerMainWindow::rcvSelectPlugin(QString plugin) { - Q_EMIT emitOnLoadPlugin(plugin.toStdString()); - dynamic_cast(m_View)->resetTrackerViews(); - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLUGIN); - qobject_cast(ctr)->selectPlugin(plugin); - //dynamic_cast(m_View)->activeTrackingCheckBox(); - activeTrackingCheckBox(); - Q_EMIT emitPluginLoaded(plugin.toStdString()); -} - -void ControllerMainWindow::onNewMediumLoaded(const std::string path) -{ - Q_EMIT emitMediaLoaded(path); -} - -void ControllerMainWindow::exit() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - ControllerPlayer *pc = static_cast(ctr); - pc->stop(); - delete m_BioTrackerContext; -} - diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerMainWindow.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerMainWindow.h deleted file mode 100644 index 548cedc6..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerMainWindow.h +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef CONTROLLERMAINWINDOW_H -#define CONTROLLERMAINWINDOW_H - -#include "Interfaces/IController/IController.h" -#include "QPointer" -#include "QStringListModel" -#include "boost/filesystem.hpp" -#include -#include "util/types.h" - - /** - * The ControllerMainWindow class controlls the IView class MainWindow. - * All user interactions done through the MainWindow class are delegated to the controllers of the component that concerns them. - * Other components can place their IView Widgets on the MainWindow. - */ -class ControllerMainWindow : public IController { - Q_OBJECT -public: - ControllerMainWindow(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - /** - * Receives the a string containing the video file path from the MainWindow class. The string is then given to the ControllerPlayer class of the MediaPlayer-Component. - */ - void loadVideo(std::vector files); - /** - * Receives the a string containing the Plugin file path from the MainWindow class. The string is then given to the BioTrackerContext class which will hand it over to the ControllerPlugin class. - */ - void loadTracker(QString str); - /** - * Receives the a string containing the pictures file path from the MainWindow class. The string is then given to the ControllerPlayer class of the MediaPlayer-Component. - */ - void loadPictures(std::vector files); - /** - * Receives the a string containing the camera device number from the MainWindow class. The string is then given to the ControllerPlayer class of the MediaPlayer-Component. - */ - void loadCameraDevice(CameraConfiguration conf); - /** - * Receives a QStringListModel with the names of all currently loades BioTracker Plugins from the ControllerPlugin class. - */ - void setTrackerList(QStringListModel* trackerList, QString current); - /** - * Embeds the Parameter Widget devined in the BioTracker Plugins into the MainWindow Widget. - */ - void setTrackerParamterWidget(IView* widget); - /** - * Embeds the view for visualization of tracking data devined in the BioTracker Plugins into the MainWindow Widget. - */ - void setTrackerElementsWidget(IView *widget); - /** - * Embeds the view for visualization of tracking data from the core app into the MainWindow Widget. - */ - void setCoreElementsWidget(IView* widget); - /** - * Embeds the the notification view of the core app into the MainWindow Widget. - */ - void setNotificationBrowserWidget(IView * widget); - - void loadTrajectoryFile(std::string file); - void saveTrajectoryFile(std::string file); - - void deactiveTrackingCheckBox(); - void activeTrackingCheckBox(); - - //Passes exit command to the GUI context - void exit(); - -public: - signals : - void emitFinalizeExperiment(); - - void emitOnLoadPlugin(const std::string path); - void emitOnLoadMedia(const std::string path); - - void emitPluginLoaded(const std::string path); - void emitMediaLoaded(const std::string path); - void emitTrackLoaded(const std::string path); - - void emitUndoCommand(); - void emitRedoCommand(); - void emitClearUndoStack(); - void emitShowActionListCommand(); - - //view toolbar actions - void emitAddTrack(); - void emitDeleteSelectedTracks(); - void emitSwapIds(); - void emitSelectAll(); - void emitChangeColorBorder(); - void emitChangeColorFill(); - void emitAddLabelAnno(); - void emitAddRectAnno(); - void emitAddArrAnno(); - void emitAddEllAnno(); - void emitDelSelAnno(); - - public slots: - void setCorePermission(std::pair permission); - /** - * Receives the command for activating the Tracking in a BioTracker Plugin from the MainWindow class. This command is given to the ControllerPlayer class of the MediaPlayer-component. - */ - void activeTracking(); - /** - * Receives the command for deactivating the Tracking in a BioTracker Plugin from the MainWindow class. This command is given to the ControllerPlayer class of the MediaPlayer-component. - */ - void deactiveTrackring(); - - void receiveSaveTrajData(); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - - private slots: - void rcvSelectPlugin(QString plugin); - void receiveCursorPosition(QPoint pos); - -private: - // Internal cleanup callback when a new video or imagestream is loaded. - void onNewMediumLoaded(const std::string path = ""); -}; - -#endif // CONTROLLERMAINWINDOW_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerNotifications.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerNotifications.cpp deleted file mode 100644 index cdb59a49..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerNotifications.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "ControllerNotifications.h" -#include "View/NotificationLogBrowser.h" -#include "ControllerMainWindow.h" -#include "qdebug.h" - -IView* view; - -ControllerNotifications::ControllerNotifications(QObject* parent, IBioTrackerContext* context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) { - -} - -ControllerNotifications::~ControllerNotifications() { - qInstallMessageHandler(0); -} - -void ControllerNotifications::cleanup() { - qInstallMessageHandler(0); -} - -void ControllerNotifications::createModel() -{ -} - -void ControllerNotifications::createView() -{ - m_View = new NotificationLogBrowser(); - view = m_View; - qInstallMessageHandler(messageHandler); - -} - -void ControllerNotifications::connectModelToController() -{ -} - -void ControllerNotifications::connectControllerToController() -{ - // Add notification browser to Main Window - IController* ctrA = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctrA); - - ctrMainWindow->setNotificationBrowserWidget(m_View); -} - - - -void messageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg) -{ - NotificationLogBrowser* log = dynamic_cast(view); - if (log) { - log->outputMessage(type, msg); - } -} diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerNotifications.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerNotifications.h deleted file mode 100644 index b5533d53..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerNotifications.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#ifndef CONTROLLERNOTIFICATIONS_H -#define CONTROLLERNOTIFICATIONS_H - -#include "Interfaces/IController/IController.h" - -/** -* This class inherits from IController. -* The notifications component includes the notifications view. -* This controller uses qInstallMessageHandler(messageHandler) to -* intercept all qDebug messages and display them in a text browser (the view). -* This text browser is displayed in the 'Notifications' tab in the GUI. -* QDebug reference: http://doc.qt.io/qt-5/qdebug.html -*/ -class ControllerNotifications : public IController { - Q_OBJECT -public: - ControllerNotifications(QObject* parent = 0, IBioTrackerContext* context = 0, - ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - ~ControllerNotifications(); - void cleanup() override; - -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - -}; - -void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); - -#endif // CONTROLLERNOTIFICATIONS_H \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlayer.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerPlayer.cpp deleted file mode 100644 index 2a8191a1..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlayer.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "ControllerPlayer.h" -#include "View/VideoControllWidget.h" -#include "View/MainWindow.h" -#include "Controller/ControllerTextureObject.h" -#include "Controller/ControllerPlugin.h" -#include "Controller/ControllerGraphicScene.h" -#include "Controller/ControllerTrackedComponentCore.h" -#include "Controller/ControllerCoreParameter.h" - -#include -#include - -ControllerPlayer::ControllerPlayer(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ -} - -ControllerPlayer::~ControllerPlayer() -{ -} - -void ControllerPlayer::loadVideoStream(std::vector files) { - qobject_cast(m_Model)->loadVideoStream(files); - emitPauseState(true); -} - -void ControllerPlayer::loadPictures(std::vector files) { - qobject_cast(m_Model)->loadPictures(files); - emitPauseState(true); -} - -void ControllerPlayer::loadCameraDevice(CameraConfiguration conf) { - qobject_cast(m_Model)->loadCameraDevice(conf); - emitPauseState(true); -} - -void ControllerPlayer::nextFrame() { - qobject_cast(m_Model)->nextFrameCommand(); -} - -void ControllerPlayer::prevFrame() { - qobject_cast(m_Model)->prevFrameCommand(); -} - -void ControllerPlayer::play() { - qobject_cast(m_Model)->playCommand(); - emitPauseState(false); -} - -void ControllerPlayer::stop() { - qobject_cast(m_Model)->stopCommand(); - emitPauseState(true); -} - -void ControllerPlayer::pause() { - qobject_cast(m_Model)->pauseCommand(); - emitPauseState(true); -} - -void ControllerPlayer::setGoToFrame(int frame) { - qobject_cast(m_Model)->goToFrame(frame); -} - -void ControllerPlayer::receiveRenderImage(std::shared_ptr mat, QString name) { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); - QPointer< ControllerTextureObject > ctrTextureObject = qobject_cast(ctr); - - ctrTextureObject->receiveCvMat(mat, name); -} - -void ControllerPlayer::receiveImageToTracker(std::shared_ptr mat, uint number) { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLUGIN); - QPointer< ControllerPlugin > ctrPlugin = qobject_cast(ctr); - - ctrPlugin->sendCurrentFrameToPlugin(mat, number); -} - -void ControllerPlayer::changeImageView(QString str) { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); - QPointer< ControllerTextureObject > ctrTextureObject = qobject_cast(ctr); - - ctrTextureObject->changeTextureModel(str); -} - -int ControllerPlayer::recordOutput() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - QPointer< ControllerGraphicScene > ctrTextureObject = qobject_cast(ctr); - - return qobject_cast(m_Model)->toggleRecordGraphicsScenes(dynamic_cast (ctrTextureObject->getView())); -} - -int ControllerPlayer::recordInput() { - return qobject_cast(m_Model)->toggleRecordImageStream(); -} - -void ControllerPlayer::setTargetFps(double fps) { - return qobject_cast(m_Model)->setTargetFPS(fps); -} - -QString ControllerPlayer::takeScreenshot() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - QPointer< ControllerGraphicScene > ctrTextureObject = qobject_cast(ctr); - return qobject_cast(m_Model)->takeScreenshot(dynamic_cast(ctrTextureObject->getView())); -} - -void ControllerPlayer::setTrackingActivated() { - qobject_cast(m_Model)->setTrackingActive(); -} - -void ControllerPlayer::setTrackingDeactivated() { - qobject_cast(m_Model)->setTrackingDeactive(); -} - -void ControllerPlayer::connectControllerToController() { - //connect to mainwindow - IController* ctrM = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< MainWindow > mainWin = dynamic_cast(ctrM->getView()); - mainWin->addVideoControllWidget(m_View); - VideoControllWidget* vControl = static_cast(m_View); - vControl->setupVideoToolbar(); - - ////connect to coreparameterview - //IController* ictrCpv = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - //QPointer< ControllerCoreParameter > ctrCpv = dynamic_cast(ictrCpv); - - //QObject::connect(this, &ControllerPlayer::emitPauseState, ctrCpv, &ControllercoreParameter) -} - -void ControllerPlayer::createModel() { - m_Model = new MediaPlayer(this); -} - -void ControllerPlayer::createView() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< MainWindow > mainWindow = dynamic_cast(ctr->getView()); - - m_View = new VideoControllWidget(mainWindow, this, m_Model); -} - -void ControllerPlayer::connectModelToController() { - - QObject::connect(qobject_cast(m_Model), &MediaPlayer::renderCurrentImage, this, &ControllerPlayer::receiveRenderImage); - QObject::connect(qobject_cast(m_Model), &MediaPlayer::trackCurrentImage, this, &ControllerPlayer::receiveImageToTracker); - QObject::connect(this, &ControllerPlayer::emitPauseState, qobject_cast(m_Model), &MediaPlayer::rcvPauseState); - QObject::connect(qobject_cast(m_Model), &MediaPlayer::signalVisualizeCurrentModel, this, &ControllerPlayer::receiveVisualizeCurrentModel); - QObject::connect(qobject_cast(m_Model), &MediaPlayer::signalCurrentFrameNumberToPlugin, this, &ControllerPlayer::receiveCurrentFrameNumberToPlugin); - QObject::connect(qobject_cast(m_Model), &MediaPlayer::emitNextMediaInBatch, this, &ControllerPlayer::emitNextMediaInBatch); - -} - -void ControllerPlayer::receiveVisualizeCurrentModel(uint frameNumber) -{ - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - QPointer< ControllerTrackedComponentCore > ctrTrCompCore = qobject_cast(ctr); - - ctrTrCompCore->receiveVisualizeTrackingModel(frameNumber); -} - -void ControllerPlayer::receiveChangeDisplayImage(QString str) { - - VideoControllWidget *w = dynamic_cast(m_View); - w->setSelectedView(str); -} - -void ControllerPlayer::receiveCurrentFrameNumberToPlugin(uint frameNumber) -{ - Q_EMIT signalCurrentFrameNumberToPlugin(frameNumber); -} diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlayer.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerPlayer.h deleted file mode 100644 index b139a531..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlayer.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ -#ifndef CONTROLLERPLAYER_H -#define CONTROLLERPLAYER_H - -#include "Interfaces/IController/IController.h" -#include "Model/MediaPlayer.h" -#include "QPointer" -#include "util/types.h" - -/** - * The ControllerPlayer class it the controller of the MediaPlayer-Component. This controller creates and controlls the IModel class MediaPlayer and the IView class VideoControllWidget. - */ -class ControllerPlayer : public IController { - Q_OBJECT - public: - ControllerPlayer(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - ~ControllerPlayer(); - - /** - * Hands over the file path of a video to the IModel class MediaPlayer. - */ - void loadVideoStream(std::vector files); - /** - * Hands over the file path of pictures to the IModel class MediaPlayer. - */ - void loadPictures(std::vector files); - /** - * Hands over the camera device number to the IModel class MediaPlayer. - */ - void loadCameraDevice(CameraConfiguration conf); - - /** - * Tells the MediaPlayer-Component to hand over the current cv::Mat and the current frame number to the BioTracker Plugin. - */ - void setTrackingActivated(); - /** - * Tells the MediaPlayer-Component not to hand over the current cv::Mat and the current frame number to the BioTracker Plugin. - */ - void setTrackingDeactivated(); - - /** - * Tells the IModel class MediaPlayer to display the next image frame of the ImageStream. - */ - void nextFrame(); - /** - * Tells the IModel class MediaPlayer to display the previous image frame of the ImageStream. - */ - void prevFrame(); - /** - * Tells the IModel class MediaPlayer to start playing the ImageStream. - */ - void play(); - /** - * Tells the IModel class MediaPlayer to stop playing the ImageStream. - */ - void stop(); - /** - * Tells the IModel class MediaPlayer to pause playing the ImageStream. - */ - void pause(); - /** - * If the user changes the ImageView in the comboBox represented in the VideoControllWidget it passes the selected ImageView name to the ControllerTextureObject class of the TextureObject-Component. - */ - void changeImageView(QString str); - - /** - * User clicked record -> record "what the user sees" - */ - int recordOutput(); - - int recordInput(); - - void setTargetFps(double fps); - - QString takeScreenshot(); - - // IController interface - public: - void connectControllerToController() override; - - signals: - void emitPauseState(bool state); - void signalCurrentFrameNumberToPlugin(uint frameNumber); - void emitNextMediaInBatch(); - - public Q_SLOTS: - /** - * This SLOT receives a cv::Mat and a name for the cv::Mat from the MediaPlayer class and hands it over to the ControllerTextureObject for rendering. - */ - void receiveRenderImage(std::shared_ptr mat, QString name); - /** - * This SLOT receives a cv::Mat and its frame number and hands it over to the ControllerPlugin for Tracking in the BioTracker Plugin. - */ - void receiveImageToTracker(std::shared_ptr mat, uint number); - /** - * This SLOT receives a framenumber and hands it over to the ControllerTrackedComponentCore for visualizing in the main app. - */ - void receiveVisualizeCurrentModel(uint frameNumber); - - void receiveChangeDisplayImage(QString str); - - void receiveCurrentFrameNumberToPlugin(uint frameNumber); - /** - * Tells the IModel class MediaPlayer to jump directly to the specified image frame by the parameter frame. - */ - void setGoToFrame(int frame); - - protected: - void createModel() override; - void createView() override; - void connectModelToController() override; -}; - -#endif // CONTROLLERPLAYER_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlugin.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerPlugin.cpp deleted file mode 100644 index b776af30..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlugin.cpp +++ /dev/null @@ -1,497 +0,0 @@ -#include "ControllerPlugin.h" - -#include "Controller/ControllerPlayer.h" -#include "Controller/ControllerTextureObject.h" -#include "Controller/ControllerTrackedComponentCore.h" -#include "ControllerMainWindow.h" -#include "QDebug" -#include "Model/PluginLoader.h" -#include "settings/Settings.h" -#include "util/types.h" -#include "ControllerDataExporter.h" -#include "ControllerAreaDescriptor.h" -#include "Controller/ControllerCoreParameter.h" -#include "Controller/ControllerCommands.h" - - -ControllerPlugin::ControllerPlugin(QObject* parent, IBioTrackerContext* context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) { - m_BioTrackerPlugin = NULL; - - m_TrackingThread = new QThread(this); - m_TrackingThread->start(); -} - -ControllerPlugin::~ControllerPlugin() { - m_TrackingThread->quit(); - m_TrackingThread->wait(); - -} - -void ControllerPlugin::addToPluginList(QString str) { - - PluginLoader* loader = qobject_cast(m_Model); - loader->addToPluginList(str); - - // Add Plugin name to Main Window - IController* ctrA = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctrA); - - ctrMainWindow->setTrackerList(qobject_cast(m_Model)->getPluginMetaData(), - qobject_cast(m_Model)->getCurrentPluginName()); -} - -void ControllerPlugin::loadPluginFromFileName(QString str) { - PluginLoader* loader = qobject_cast(m_Model); - - if (loader->loadPluginFromFilename(str)) { - - createPlugin(); - - // Add Plugin name to Main Window - IController* ctrA = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctrA); - - ctrMainWindow->setTrackerList(qobject_cast(m_Model)->getPluginMetaData(), - qobject_cast(m_Model)->getCurrentPluginName()); - - //Add Tracker Parameter to Main Window - IView *parms = m_BioTrackerPlugin->getTrackerParameterWidget(); - ctrMainWindow->setTrackerParamterWidget(parms); - - //Add Tracker tracked components (Elements) to Main Window - IView *elems = m_BioTrackerPlugin->getTrackerElementsWidget(); - ctrMainWindow->setTrackerElementsWidget(elems); - - IController* ctrB = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - QPointer< ControllerTrackedComponentCore > ctrTrackedComponentCore = qobject_cast(ctrB); - - //Add Tracker tracked components model to ControllerTrackedComponentCore - ctrTrackedComponentCore->addModel(m_BioTrackerPlugin->getTrackerComponentModel()); - //Add tracked component view to main window - ctrMainWindow->setCoreElementsWidget(ctrTrackedComponentCore->getTrackingElementsWidgetCore()); - - IController* ctrDE = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - QPointer< ControllerDataExporter > ctrDataExp = qobject_cast(ctrDE); - ctrDataExp->setDataStructure(m_BioTrackerPlugin->getTrackerComponentModel()); - ctrDataExp->setComponentFactory(m_BioTrackerPlugin->getComponentFactory()); - - m_BioTrackerPlugin->sendCorePermissions(); - - } -} - -void ControllerPlugin::selectPlugin(QString str) { - if (str.isEmpty()) - return; - PluginLoader* loader = qobject_cast(m_Model); - - if (loader->getCurrentPluginName() != str) - loadPluginFromFileName(loader->getPluginMap().find(str)->second); -} - -void ControllerPlugin::createModel() { - m_Model = new PluginLoader(this); -} - -void ControllerPlugin::createView() { -} - -void ControllerPlugin::connectModelToController() { -} - -void ControllerPlugin::loadPluginsFromPluginSubfolder() { - - ////////////// - QDir d(CFG_DIR_PLUGINS); - d.setFilter(QDir::Filter::Files); - QStringList nameFilter; - QFileInfoList fl = d.entryInfoList(nameFilter, QDir::Filter::Files); - foreach(QFileInfo fi, fl) { - QString s = fi.absoluteFilePath(); - std::string asdf = s.toStdString(); - addToPluginList(s); - } - - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - std::string *usePlugins = (std::string*)(set->readValue("usePlugins")); - if (usePlugins) { - addToPluginList(usePlugins->c_str()); - } - -} - -void ControllerPlugin::connectControllerToController() { - - // Add Plugin name to Main Window - IController* ctrA = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctrA); - - ctrMainWindow->deactiveTrackingCheckBox(); - - loadPluginsFromPluginSubfolder(); - - // connect ControllerTrackedComponentView - IController* ctrB = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - QPointer< ControllerTrackedComponentCore > ctrTrackedComponentCore = qobject_cast(ctrB); - - QObject::connect(this, SIGNAL(emitUpdateView()), ctrTrackedComponentCore, - SLOT(receiveUpdateView())); - - // connect ControllerCommands - IController* ctrD = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMMANDS); - QPointer< ControllerCommands > ctrCommands = qobject_cast(ctrD); - - QObject::connect(ctrCommands, SIGNAL(emitAddTrajectory(QPoint)), this, - SLOT(receiveAddTrajectory(QPoint)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), this, - SLOT(receiveRemoveTrajectory(IModelTrackedTrajectory*)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitRemoveTrajectoryId(int)), this, - SLOT(receiveRemoveTrajectoryId(int)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), this, - SLOT(receiveRemoveTrackEntity(IModelTrackedTrajectory*, uint)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitValidateTrajectory(int)), this, - SLOT(receiveValidateTrajectory(int)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), this, - SLOT(receiveValidateEntity(IModelTrackedTrajectory*, uint)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint, int)), this, - SLOT(receiveMoveElement(IModelTrackedTrajectory*, uint, QPoint, int)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), this, - SLOT(receiveSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), this, - SLOT(receiveToggleFixTrack(IModelTrackedTrajectory*, bool)), Qt::DirectConnection); - QObject::connect(ctrCommands, SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), this, - SLOT(receiveEntityRotation(IModelTrackedTrajectory*, double, uint)), Qt::DirectConnection); - - - // connect ControllerPlayer - IController* ctrC = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - QPointer< ControllerPlayer > ctrPlayer = qobject_cast(ctrC); - QObject::connect(ctrPlayer, SIGNAL(emitPauseState(bool)), this, - SLOT(receivePauseState(bool)), Qt::DirectConnection); - - QObject::connect(ctrPlayer, SIGNAL(signalCurrentFrameNumberToPlugin(uint)), - this, SLOT(receiveCurrentFrameNumberToPlugin(uint)), Qt::DirectConnection); - -} - -void ControllerPlugin::createPlugin() { - m_BioTrackerPlugin = qobject_cast(m_Model)->getPluginInstance(); - m_BioTrackerPlugin->createPlugin(); - - m_BioTrackerPlugin->moveToThread(m_TrackingThread); - - connectPlugin(); - - IController* ctrAreaDesc = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); - ControllerAreaDescriptor* ctAreaDesc = qobject_cast(ctrAreaDesc); - ctAreaDesc->triggerUpdateAreaDescriptor(); - - Q_EMIT signalCurrentFrameNumberToPlugin(m_currentFrameNumber); - -} - -void ControllerPlugin::connectPlugin() { - IController* ctrA = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - QPointer< ControllerPlayer > ctrPlayer = qobject_cast(ctrA); - - IModel* model = ctrPlayer->getModel(); - - IController* ctrB = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); - ControllerTextureObject* ctrTexture = qobject_cast(ctrB); - - IController* ctrAreaDesc = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); - ControllerAreaDescriptor* ctAreaDesc = qobject_cast(ctrAreaDesc); - - - IController* ctrData = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::DATAEXPORT); - ControllerDataExporter* ctDataEx = qobject_cast(ctrData); - - IController* ctrC = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - ControllerTrackedComponentCore* ctrCompView = qobject_cast(ctrC); - - IController* ctrD = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - ControllerCoreParameter* ctrCoreParam = qobject_cast(ctrD); - - IController* ctrE = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctrE); - - QObject* obj = dynamic_cast(m_BioTrackerPlugin); - - QObject::connect(obj, SIGNAL(emitTrackingDone(uint)), ctDataEx, SLOT(receiveTrackingDone(uint))); - - QObject::connect(obj, SIGNAL(emitCvMat(std::shared_ptr, QString)), - ctrTexture, SLOT(receiveCvMat(std::shared_ptr, QString))); - - //TODO whyy do this two times?? - QObject::connect(obj, SIGNAL(emitTrackingDone(uint)), model, SLOT(receiveTrackingOperationDone())); - - QObject::connect(obj, SIGNAL(emitTrackingDone(uint)), ctrCompView, SLOT(receiveVisualizeTrackingModel(uint))); - - QObject::connect(obj, SIGNAL(emitChangeDisplayImage(QString)), ctrPlayer, SLOT(receiveChangeDisplayImage(QString))); - - QObject::connect(ctAreaDesc, SIGNAL(updateAreaDescriptor(IModelAreaDescriptor*)), obj, SLOT(receiveAreaDescriptor(IModelAreaDescriptor*))); - - QObject::connect(obj, SIGNAL(emitCorePermission(std::pair)), ctrCompView, - SLOT(setCorePermission(std::pair))); - - QObject::connect(obj, SIGNAL(emitCorePermission(std::pair)), ctrCoreParam, - SLOT(setCorePermission(std::pair))); - - QObject::connect(obj, SIGNAL(emitCorePermission(std::pair)), ctrMainWindow, - SLOT(setCorePermission(std::pair))); - - QObject::connect(obj, SIGNAL(emitDimensionUpdate(int, int)), ctrCompView, SIGNAL(emitDimensionUpdate(int, int))); - - - // data model actions - QObject::connect(this, SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), obj, - SLOT(receiveRemoveTrajectory(IModelTrackedTrajectory*)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), obj, - SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitAddTrajectory(QPoint)), obj, - SLOT(receiveAddTrajectory(QPoint)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint)), obj, - SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), obj, - SLOT(receiveSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), obj, - SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), Qt::DirectConnection); - - QObject::connect(this, SIGNAL(emitRemoveTrajectoryId(int)), obj, - SIGNAL(emitRemoveTrajectoryId(int)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitValidateTrajectory(int)), obj, - SIGNAL(emitValidateTrajectory(int)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), obj, - SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), Qt::DirectConnection); - QObject::connect(this, SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), obj, - SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), Qt::DirectConnection); - - QObject::connect(this, SIGNAL(signalCurrentFrameNumberToPlugin(uint)), obj, - SLOT(receiveCurrentFrameNumberFromMainApp(uint)), Qt::DirectConnection); -} - -void ControllerPlugin::disconnectPlugin() { - -} - -//first send all the commands currently in the command queue then the next image can be sent -void ControllerPlugin::sendCurrentFrameToPlugin(std::shared_ptr mat, uint number) { - m_currentFrameNumber = number; - - //Prevent calling the plugin if none is loaded - if (m_BioTrackerPlugin) { - while (!m_editQueue.isEmpty()) { - queueElement edit = m_editQueue.dequeue(); - - switch (edit.type) - { - case EDIT::REMOVE_TRACK: - emitRemoveTrajectory(edit.trajectory0); - break; - case EDIT::REMOVE_TRACK_ID: - emitRemoveTrajectoryId(edit.id); - break; - case EDIT::REMOVE_ENTITY: - emitRemoveTrackEntity(edit.trajectory0, edit.frameNumber); - break; - case EDIT::ADD: - emitAddTrajectory(edit.pos); - break; - case EDIT::MOVE: - emitMoveElement(edit.trajectory0, edit.frameNumber, edit.pos); - break; - case EDIT::SWAP: - emitSwapIds(edit.trajectory0, edit.trajectory1); - break; - case EDIT::FIX: - emitToggleFixTrack(edit.trajectory0, edit.toggle); - break; - case EDIT::VALIDATE: - emitValidateTrajectory(edit.id); - break; - case EDIT::VALIDATE_ENTITY: - emitValidateEntity(edit.trajectory0, edit.frameNumber); - break; - case EDIT::ROTATE_ENTITY: - emitEntityRotation(edit.trajectory0, edit.angle, edit.frameNumber); - break; - } - } - m_BioTrackerPlugin->receiveCurrentFrameFromMainApp(mat, number); - } -} - - - -//############################SLOTS################################################## - -// receivers of commands - -void ControllerPlugin::receiveRemoveTrajectory(IModelTrackedTrajectory * trajectory) -{ - if (m_paused) { - emitRemoveTrajectory(trajectory); - emitUpdateView(); - } - else { - queueElement removeTrackEdit; - removeTrackEdit.type = EDIT::REMOVE_TRACK; - removeTrackEdit.trajectory0 = trajectory; - m_editQueue.enqueue(removeTrackEdit); - } -} - -void ControllerPlugin::receiveRemoveTrajectoryId(int id) -{ - if (m_paused) { - emitRemoveTrajectoryId(id); - emitUpdateView(); - } - else { - queueElement removeTrackEdit; - removeTrackEdit.type = EDIT::REMOVE_TRACK_ID; - removeTrackEdit.id = id; - m_editQueue.enqueue(removeTrackEdit); - } -} - -void ControllerPlugin::receiveRemoveTrackEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) -{ - if (m_paused) { - emitRemoveTrackEntity(trajectory, frameNumber); - emitUpdateView(); - } - else { - queueElement removeEntityEdit; - removeEntityEdit.type = EDIT::REMOVE_ENTITY; - removeEntityEdit.trajectory0 = trajectory; - removeEntityEdit.frameNumber = frameNumber; - m_editQueue.enqueue(removeEntityEdit); - } -} - -void ControllerPlugin::receiveAddTrajectory(QPoint pos) -{ - if (m_paused) { - emitAddTrajectory(pos); - emitUpdateView(); - } - else { - queueElement addEdit; - addEdit.type = EDIT::ADD; - addEdit.pos = pos; - m_editQueue.enqueue(addEdit); - } -} - -void ControllerPlugin::receiveMoveElement(IModelTrackedTrajectory * trajectory, uint frameNumber, QPoint pos, int toMove) -{ - if (m_paused) { - emitMoveElement(trajectory, frameNumber, pos); - //only emit the update after the last move is processed - if (toMove == 1) { - emitUpdateView(); - } - } - else { - queueElement moveEdit; - moveEdit.type = EDIT::MOVE; - moveEdit.trajectory0 = trajectory; - moveEdit.pos = pos; - moveEdit.frameNumber = frameNumber; - m_editQueue.enqueue(moveEdit); - } -} - -void ControllerPlugin::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) -{ - if (m_paused) { - emitSwapIds(trajectory0, trajectory1); - emitUpdateView(); - } - else { - queueElement swapEdit; - swapEdit.type = EDIT::SWAP; - swapEdit.trajectory0 = trajectory0; - swapEdit.trajectory1 = trajectory1; - m_editQueue.enqueue(swapEdit); - } -} - -void ControllerPlugin::receiveValidateTrajectory(int id) -{ - if (m_paused) { - emitValidateTrajectory(id); - emitUpdateView(); - } - else { - queueElement validateEdit; - validateEdit.type = EDIT::VALIDATE; - validateEdit.id = id; - m_editQueue.enqueue(validateEdit); - } -} - -void ControllerPlugin::receiveValidateEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) -{ - if (m_paused) { - emitValidateEntity(trajectory, frameNumber); - emitUpdateView(); - } - else { - queueElement validateEntityEdit; - validateEntityEdit.type = EDIT::VALIDATE_ENTITY; - validateEntityEdit.trajectory0 = trajectory; - validateEntityEdit.frameNumber = frameNumber; - m_editQueue.enqueue(validateEntityEdit); - } -} - -void ControllerPlugin::receiveToggleFixTrack(IModelTrackedTrajectory * trajectory, bool toggle) -{ - if (m_paused) { - emitToggleFixTrack(trajectory, toggle); - emitUpdateView(); - } - else { - queueElement fixEdit; - fixEdit.type = EDIT::FIX; - fixEdit.trajectory0 = trajectory; - fixEdit.toggle = toggle; - m_editQueue.enqueue(fixEdit); - } -} - -void ControllerPlugin::receiveEntityRotation(IModelTrackedTrajectory * trajectory, double angle, uint frameNumber) -{ - if (m_paused) { - emitEntityRotation(trajectory, angle, frameNumber); - emitUpdateView(); - } - else { - queueElement rotEdit; - rotEdit.type = EDIT::ROTATE_ENTITY; - rotEdit.trajectory0 = trajectory; - rotEdit.angle = angle; - rotEdit.frameNumber = frameNumber; - m_editQueue.enqueue(rotEdit); - } -} - -//********************************************************************* - -void ControllerPlugin::receivePauseState(bool state) -{ - m_paused = state; -} - -void ControllerPlugin::receiveCurrentFrameNumberToPlugin(uint frameNumber) -{ - m_currentFrameNumber = frameNumber; - Q_EMIT signalCurrentFrameNumberToPlugin(frameNumber); -} - -void ControllerPlugin::receiveTrackingDone() { - -} diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlugin.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerPlugin.h deleted file mode 100644 index ea0028e1..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerPlugin.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** edited by Jonas Piotrowski - ** - ****************************************************************************/ - -#ifndef CONTROLLERPLUGIN_H -#define CONTROLLERPLUGIN_H - -#include "Interfaces/IController/IController.h" -#include "Interfaces/IBioTrackerPlugin.h" -#include "QThread" -#include "QQueue" -#include "QPoint" - - /// ENUM for the command queue in the controllerplugin -enum EDIT { REMOVE_TRACK, REMOVE_TRACK_ID, REMOVE_ENTITY, ADD, MOVE, SWAP, FIX, VALIDATE, VALIDATE_ENTITY, ROTATE_ENTITY }; - -/// struct for the command queue in the controllerplugin -struct queueElement { - EDIT type; - QPoint pos; - IModelTrackedTrajectory* trajectory0; - IModelTrackedTrajectory* trajectory1; - IModelTrackedComponent* element; - bool toggle; - int id; - double angle; - uint frameNumber; -}; - -/** - * This is the controller class of the Plugin Loader Component. This component is responsible for loading and managing BioTracker Plugins - * The ControllerPlugin class is responsible for loading and connecting to BioTracker Plugins. - * It also manages tracking data modification commands. It queues up the commands and forwards them to the trakcing plugin if - * either the tracking is paused or the tracker is done with tracking the previous frame. The plgin then sends the commands first and afterward - * the next image to track. This avoids a race condition. - */ -class ControllerPlugin : public IController { - Q_OBJECT -public: - ControllerPlugin(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - ~ControllerPlugin(); - - void addToPluginList(QString str); - - /** - * (This function - * This function delivers a file path of a Plugin to the IModel class PluginLoader. If the Plugin could be loaded, - * the functions additionally requests the name of the Plugin and sets it as an entry into an IView widget in the MainWindow. - */ - void loadPluginFromFileName(QString str); - - /** - * This function hands the received cv::Mat pointer and the current frame number to the PluginLoader. - */ - void sendCurrentFrameToPlugin(std::shared_ptr mat, uint number); - - void selectPlugin(QString str); - -signals: - void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); - void emitRemoveTrajectoryId(int id); - void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void emitValidateTrajectory(int id); - void emitValidateEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void emitAddTrajectory(QPoint pos); - void emitMoveElement(IModelTrackedTrajectory* element, uint frameNumber, QPoint pos); - void emitSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - void emitToggleFixTrack(IModelTrackedTrajectory* trajectory0, bool toggle); - void emitEntityRotation(IModelTrackedTrajectory* trajectory0, double angle, uint frameNumber); - - void emitUpdateView(); - void signalCurrentFrameNumberToPlugin(uint frameNumber); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - - void createPlugin(); - - void connectPlugin(); - void disconnectPlugin(); - - private Q_SLOTS: - /** - * - * If Tracking is active and the tracking process was finished, the Plugin is able to emit a Signal that triggers this SLOT. - */ - void receiveTrackingDone(); - /** - * - * Receive command to remove a trajectory and put it in edit queue - */ - void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); - /** - * - * Receive command to remove a trajectory by id and put it in edit queue - */ - void receiveRemoveTrajectoryId(int id); - /** - * - * Receive command to remove a track entity and put it in edit queue - */ - void receiveRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - /** - * - * Receive command to add a trajectory and put it in edit queue - */ - void receiveAddTrajectory(QPoint pos); - /** - * - * Receive command to move a element in a trajectory and put it in edit queue - */ - void receiveMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint pos, int toMove); - /** - * - * Receive command to swap two ID's and put it in edit queue - */ - void receiveSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - /** - * - * Receive command to revalidate a traj by id - */ - void receiveValidateTrajectory(int id); - /** - * - * Receive command to revalidate a entity - */ - void receiveValidateEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - /** - * - * Receive command to fix a traj, so the tracker should not change it's data - */ - void receiveToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - /** - * - * Receive command to rotate an entity - */ - void receiveEntityRotation(IModelTrackedTrajectory* trajectory, double angle, uint frameNumber); - /** - * - * Receive current state of medium (pause or play) - */ - void receivePauseState(bool state); - /** - * - * Receive current frame from media play to send it to the plugin - */ - void receiveCurrentFrameNumberToPlugin(uint frameNumber); - - - -private: - void loadPluginsFromPluginSubfolder(); - - IBioTrackerPlugin* m_BioTrackerPlugin; - - QQueue m_editQueue; - - QPointer< QThread > m_TrackingThread; - - bool m_paused = true; - - uint m_currentFrameNumber = 0; - - - -}; - -#endif // CONTROLLERPLUGIN_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerTextureObject.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerTextureObject.cpp deleted file mode 100644 index 13cd5869..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerTextureObject.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "ControllerTextureObject.h" -#include "View/GLVideoView.h" -#include "View/MainWindow.h" -#include "Controller/ControllerGraphicScene.h" -#include "Controller/ControllerPlayer.h" -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -#include "View/TextureObjectView.h" - -ControllerTextureObject::ControllerTextureObject(QObject* parent, IBioTrackerContext* context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) { - m_TextureViewNamesModel = new QStringListModel(); - m_TextureViewNamesModel->setStringList(m_TextureViewNames); -} - -void ControllerTextureObject::changeTextureModel(QString name) { - if(name == QString("") ) - name = m_DefaultTextureName; - - checkIfTextureModelExists(name); - m_Model = m_TextureObjects.value(name); - - changeTextureView(m_Model); -} - -void ControllerTextureObject::connectControllerToController() { - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - QPointer< ControllerPlayer > ctrPlayer = qobject_cast(ctr); - - QPointer< VideoControllWidget > videoView = dynamic_cast (ctrPlayer->getView()); - videoView->setVideoViewComboboxModel(m_TextureViewNamesModel); - - - IController* ctrG = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - QPointer< ControllerGraphicScene > ctrGraphics = qobject_cast(ctrG); - QGraphicsPixmapItem* item = dynamic_cast(m_View); - - ctrGraphics->addTextureObject(item); -} - -void ControllerTextureObject::receiveCvMat(std::shared_ptr mat, QString name) { - checkIfTextureModelExists(name); - - m_TextureObjects.value(name)->set(*mat); - -} - -void ControllerTextureObject::createModel() { - createNewTextureObjectModel(m_DefaultTextureName); - - m_Model = m_TextureObjects.value(m_DefaultTextureName); -} - -void ControllerTextureObject::createView() { - m_View = new TextureObjectView(this, this, m_Model); -} - -void ControllerTextureObject::connectModelToController() { - -} - -void ControllerTextureObject::checkIfTextureModelExists(QString name) { - if(name == QString("") ) - name = m_DefaultTextureName; - - - bool itemIsInList = false; - for (int i = 0 ; i < m_TextureViewNames.size(); ++i) { - - if (m_TextureViewNames.at(i) == name) { - itemIsInList = true; - } - } - - if (!itemIsInList) { - createNewTextureObjectModel(name); - } -} - -void ControllerTextureObject::createNewTextureObjectModel(QString name) { - TextureObject* newTextureModel = new TextureObject(this, name); - m_TextureObjects.insert(name, newTextureModel); - m_TextureViewNames.append(name); - m_TextureViewNamesModel->setStringList(m_TextureViewNames); - -} - -void ControllerTextureObject::changeTextureView(IModel* model) { - m_View->setNewModel(model); - -} diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerTextureObject.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerTextureObject.h deleted file mode 100644 index ca1c80f3..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerTextureObject.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - - -#ifndef CONTROLLERTEXTUREOBJECT_H -#define CONTROLLERTEXTUREOBJECT_H - -#include "Interfaces/IController/IController.h" -#include "opencv2/core/core.hpp" -#include "QString" -#include "Model/TextureObject.h" - -#include "QStringList" -#include "QStringListModel" -#include "QPointer" - -/** - * This is the Controller class of the software component TextureObject. This component is responsible for rendering cv::Mats on a disply canvas. Other components can trigger the SLOT - * receiveCvMat(std::shard_ptr mat, QString name) in order to render their images. Usually this would be the component MediaPlayer which will send the original cv::Mat from - * an ImageStream to controller class ControllerTextureObject. An other component is the BioTracker Plugin. If a cv::Mat is manipulated by a Tracking Algorithm the Plugin is able to - * send that cv::Mat to this component. The Parameter name will be listed in the combobox widget on the MainWindow widget. - * The ControllerTextureObject class controlls the of the TrextureObject Component. - */ -class ControllerTextureObject : public IController { - Q_OBJECT - public: - ControllerTextureObject(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - /** - * If the user changes the combobox widget for the rendered cv::Mat in the MainWindow this methode will change the corresponding IModel class TextureObject. - */ - void changeTextureModel(QString name); - - // IController interface - public: - void connectControllerToController() override; - - public Q_SLOTS: - /** - * This SLOT can be triggered by any component that wants to render a cv::Mat. - */ - void receiveCvMat(std::shared_ptr mat, QString name); - - protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - - private: - void checkIfTextureModelExists(QString name); - void createNewTextureObjectModel(QString name); - void changeTextureView(IModel* model); - - private: - QMap > m_TextureObjects; - - QString m_DefaultTextureName = "Original"; - - QStringList m_TextureViewNames; - QPointer< QStringListModel > m_TextureViewNamesModel; - -}; - -#endif // CONTROLLERTEXTUREOBJECT_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerTrackedComponentCore.cpp b/BioTracker/CoreApp/BioTracker/Controller/ControllerTrackedComponentCore.cpp deleted file mode 100644 index 6bca699c..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerTrackedComponentCore.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "ControllerTrackedComponentCore.h" -#include "ControllerMainWindow.h" -#include "ControllerCoreParameter.h" -#include "ControllerPlayer.h" -#include "Model/null_Model.h" -#include "Model/CoreParameter.h" -#include "View/TrackedComponentView.h" -#include "View/CoreParameterView.h" -#include "settings/Settings.h" -#include "util/types.h" -#include "qdebug.h" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "Interfaces/IView/IViewTrackedComponent.h" -#include "Controller/ControllerCommands.h" - - -ControllerTrackedComponentCore::ControllerTrackedComponentCore(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - m_View = nullptr; - m_Model = nullptr; -} - -void ControllerTrackedComponentCore::createView() -{ - //This occurs when there has been a previous plugin to visualize - if (m_View != nullptr) - delete m_View; - - m_View = new TrackedComponentView(0, this, m_Model); -} - -void ControllerTrackedComponentCore::connectModelToController() -{ - -} - -void ControllerTrackedComponentCore::connectControllerToController() -{ - IController * ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< ControllerMainWindow > ctrMainWindow = qobject_cast(ctr); - - //connect to view - TrackedComponentView* view = static_cast(m_View); - QObject::connect(view, SIGNAL(emitAddTrajectory(QPoint, int)), this, SIGNAL(emitAddTrajectory(QPoint, int))); - QObject::connect(view, SIGNAL(emitSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), this, SIGNAL(emitSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*))); - QObject::connect(this, SIGNAL(emitDimensionUpdate(int, int)), view, SLOT(rcvDimensionUpdate(int, int))); - - QObject::connect(this, SIGNAL(emitAddTrack()), view, SLOT(addTrajectory())); - QObject::connect(this, SIGNAL(emitDeleteSelectedTracks()), view, SLOT(removeTrajectories())); - QObject::connect(this, SIGNAL(emitSelectAll()), view, SLOT(receiveSelectAll())); - QObject::connect(this, SIGNAL(emitSwapIdsToView()), view, SLOT(swapIds())); - QObject::connect(this, SIGNAL(emitChangeColorBorder()), view, SLOT(receiveColorChangeBorderSelected())); - QObject::connect(this, SIGNAL(emitChangeColorFill()), view, SLOT(receiveColorChangeBrushSelected())); - - - //connect to update track number in core params - IController * ctrICP = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - QPointer< ControllerCoreParameter > ctrCP = qobject_cast(ctrICP); - QObject::connect(this, SIGNAL(emitTrackNumber(int)), ctrCP, SLOT(receiveTrackNumber(int))); - - //connect to commandcontroller - IController * ctrICC = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMMANDS); - QPointer< ControllerCommands > ctrCC = qobject_cast(ctrICC); - QObject::connect(this, SIGNAL(emitAddTrajectory(QPoint, int)), ctrCC, SLOT(receiveAddTrackCommand(QPoint, int))); - QObject::connect(this, SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), ctrCC, SLOT(receiveRemoveTrackCommand(IModelTrackedTrajectory*))); - QObject::connect(this, SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), ctrCC, SLOT(receiveRemoveTrackEntityCommand(IModelTrackedTrajectory*, uint))); - QObject::connect(this, SIGNAL(emitMoveElement(IModelTrackedTrajectory*, QPoint, QPoint, uint, int)), ctrCC, SLOT(receiveMoveElementCommand(IModelTrackedTrajectory*, QPoint, QPoint, uint, int))); - QObject::connect(this, SIGNAL(emitSwapIds(IModelTrackedTrajectory*, IModelTrackedTrajectory*)), ctrCC, SLOT(receiveSwapIdCommand(IModelTrackedTrajectory*, IModelTrackedTrajectory*))); - QObject::connect(this, SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), ctrCC, SLOT(receiveFixTrackCommand(IModelTrackedTrajectory*, bool))); - QObject::connect(this, SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, double, uint)), ctrCC, SLOT(receiveEntityRotation(IModelTrackedTrajectory*, double, double, uint))); - - //connect to controllerPlayer - IController * ctrIP = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER); - QPointer< ControllerPlayer > ctrP = qobject_cast(ctrIP); - QObject::connect(this, &ControllerTrackedComponentCore::emitGoToFrame, ctrP, &ControllerPlayer::setGoToFrame); - - - // Tell the Visualization to reset upon loading a new plugin - QObject::connect(ctrMainWindow, &ControllerMainWindow::emitTrackLoaded, this, &ControllerTrackedComponentCore::receiveOnPluginLoaded); - -} - -void ControllerTrackedComponentCore::receiveOnPluginLoaded() { - receiveUpdateView(); -} - -void ControllerTrackedComponentCore::setCorePermission(std::pair permission) -{ - if (dynamic_cast(m_View)) { - dynamic_cast(m_View)->setPermission(permission); - } - else { - //qDebug() << "no view yet"; - //This should never happen, actually - assert(false); - } -} - -void ControllerTrackedComponentCore::receiveUpdateView() -{ - TrackedComponentView* compView = dynamic_cast(m_View); - compView->getNotified(); - //signal the core parameter controller to update the track number - IModelTrackedTrajectory *model = dynamic_cast(getModel()); - int trackNumber = model->validCount(); - emitTrackNumber(trackNumber); -} - -void ControllerTrackedComponentCore::createModel() -{ - // This controller gets his model (via addModel()) from the corresponding tracked-component-controller when a plugin is loaded - m_Model = new null_Model(); -} - -IView *ControllerTrackedComponentCore::getTrackingElementsWidgetCore() -{ - return m_View; -} - -IModel* ControllerTrackedComponentCore::getCoreParameter() -{ - IController * ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); - QPointer< ControllerCoreParameter > ctrCP = qobject_cast(ctr); - return ctrCP->getModel(); -} - -void ControllerTrackedComponentCore::addModel(IModel* model) -{ - m_Model = model; - m_View->setNewModel(m_Model); - - TrackedComponentView* view = dynamic_cast(m_View); - - //signal initial track number to core params - IModelTrackedTrajectory *iModel = dynamic_cast(getModel()); - if (iModel) { - int trackNumber = iModel->validCount(); - emitTrackNumber(trackNumber); - } -} - -void ControllerTrackedComponentCore::receiveVisualizeTrackingModel(uint framenumber) -{ - //signal the view to update track entities - TrackedComponentView* compView = dynamic_cast(m_View); - compView->updateShapes(framenumber); - //signal the core parameter controller to update the track number - IModelTrackedTrajectory *model = dynamic_cast(getModel()); - if (model) { - int trackNumber = model->validCount(); - emitTrackNumber(trackNumber); - } -} diff --git a/BioTracker/CoreApp/BioTracker/Controller/ControllerTrackedComponentCore.h b/BioTracker/CoreApp/BioTracker/Controller/ControllerTrackedComponentCore.h deleted file mode 100644 index 3cb7b758..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/ControllerTrackedComponentCore.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef CONTROLLERTRACKEDCOMPONENTCORE_H -#define CONTROLLERTRACKEDCOMPONENTCORE_H - -#include "Interfaces/IController/IController.h" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" - - -/** -* The ControllerTrackedComponentCore class controls the component for visualizing TrackedComponents. -* It is basically a forwarder for permissions, user interaction signals (including tracking data manipulation). -*/ - -class ControllerTrackedComponentCore : public IController -{ - Q_OBJECT -public: - ControllerTrackedComponentCore(QObject *parent = 0, IBioTrackerContext *context = 0, - ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - - /** - * Hook for the view to put in in the mainwindow's media panel each time a plugin is loaded - */ - IView *getTrackingElementsWidgetCore(); - - /** - * The model is actually the tracking data from the tracking plugin. This component only reads this data. - * Is called when a new tracking plugin is loaded. - */ - void addModel(IModel* model); - - /** - * Hook for the view to get the core parameters to set up new componentshapes with default settings - */ - IModel* getCoreParameter(); - - /* - * SIGNALS - */ -signals: - /// signal to ctrcommands to remove trajectory - void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); - - /// signal to ctrcommands to remove entity - void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - - /// signal to ctrcommands to add trajectory - void emitAddTrajectory(QPoint pos, int id); - - /// signal to ctrcommands to move entity - void emitMoveElement(IModelTrackedTrajectory* trajectory, QPoint oldPos, QPoint newPos, uint frameNumber, int toMove); - - /// signal to ctrcommands to swap track id's - void emitSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - - /// signal to ctrcommands fix or unfix a traj - void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - - /// signal to ctrcommands rotate entity - void emitEntityRotation(IModelTrackedTrajectory*, double oldAngleDeg, double newAngleDeg, uint frameNumber); - - /// signal to ctrCoreParameter to show number of valid trrajectories - - void emitTrackNumber(int number); - - /// signal to view to update its dimensions - void emitDimensionUpdate(int x, int y); - - //forward left-toolbar actions to view - void emitAddTrack(); - void emitDeleteSelectedTracks(); - void emitSwapIdsToView(); - void emitSelectAll(); - void emitChangeColorBorder(); - void emitChangeColorFill(); - void emitGoToFrame(int frame); - - - /* - * SLOTS - */ - public Q_SLOTS: - - /// A (different) plugin has been loaded. Here, the controller needs to inform the view - void receiveOnPluginLoaded(); - - /// this slot gets triggered when the core-view needs to update with the current frame - void receiveVisualizeTrackingModel(uint framenumber); - - /// gets triggered when plugin sends permissions and forwards it to the view - void setCorePermission(std::pair permission); - - /// gets triggered when a the view needs an update - void receiveUpdateView(); - - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - - //IView* m_parameterView; - //IModel* m_coreParameterModel; -}; - -#endif // CONTROLLERTRACKEDCOMPONENTCORE_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/null_Controller.h b/BioTracker/CoreApp/BioTracker/Controller/null_Controller.h deleted file mode 100644 index 9fdba1b3..00000000 --- a/BioTracker/CoreApp/BioTracker/Controller/null_Controller.h +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef NULL_CONTROLLER_H -#define NULL_CONTROLLER_H - -#include "Interfaces/IController/IController.h" - -/** - * The null_Controller class is for initialisation of IController classes instead of using Null Pointers. - */ -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/BioTracker/CoreApp/BioTracker/Debug/BiotrackerCore.ini b/BioTracker/CoreApp/BioTracker/Debug/BiotrackerCore.ini deleted file mode 100644 index 7aac3255..00000000 --- a/BioTracker/CoreApp/BioTracker/Debug/BiotrackerCore.ini +++ /dev/null @@ -1,8 +0,0 @@ -{ - "BiotrackerCore\/DataExporter": "0", - "BiotrackerCore\/FrameStride": "1", - "BiotrackerCore\/CodecUsed": "0", - "BiotrackerCore\/DropFrames": "false", - "BiotrackerCore\/RecordScaledOutput": "false", - "BiotrackerCore\/GPU_QP": "15" -} diff --git a/BioTracker/CoreApp/BioTracker/GuiContext.cpp b/BioTracker/CoreApp/BioTracker/GuiContext.cpp deleted file mode 100644 index 3c1fbd4b..00000000 --- a/BioTracker/CoreApp/BioTracker/GuiContext.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "GuiContext.h" -#include "Controller/ControllerMainWindow.h" -#include "Controller/ControllerPlayer.h" -#include "Controller/ControllerTextureObject.h" -#include "Controller/ControllerPlugin.h" -#include "Controller/ControllerAnnotations.h" -#include "Controller/ControllerTrackedComponentCore.h" -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -#include "Model/TextureObject.h" -#include "Controller/ControllerGraphicScene.h" -#include "Controller/ControllerDataExporter.h" -#include "Controller/ControllerAreaDescriptor.h" -#include "Controller/ControllerCoreParameter.h" -#include "Controller/ControllerCommands.h" -#include "Controller/ControllerNotifications.h" -#include "QPointer" - -#include "QDebug" - - -GuiContext::GuiContext(QObject *parent) : - IBioTrackerContext(parent) -{ - QPointer< IController > MainWindowController = new ControllerMainWindow(this, this, ENUMS::CONTROLLERTYPE::MAINWINDOW); - QPointer< IController > PlayerController = new ControllerPlayer(this, this, ENUMS::CONTROLLERTYPE::PLAYER); - QPointer< IController > TextureObjectController = new ControllerTextureObject(this, this, ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); - QPointer< IController > GraphicsViewController = new ControllerGraphicScene(this, this, ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); - QPointer< IController > TrackedComponentCoreController = new ControllerTrackedComponentCore(this, this, ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); - QPointer< IController > DataExportController = new ControllerDataExporter(this, this, ENUMS::CONTROLLERTYPE::DATAEXPORT); - QPointer< IController > PluginController = new ControllerPlugin(this, this, ENUMS::CONTROLLERTYPE::PLUGIN); - QPointer< IController > AnnotationsController = new ControllerAnnotations(this, this, ENUMS::CONTROLLERTYPE::ANNOTATIONS); - QPointer< IController > AreaDescriptorController = new ControllerAreaDescriptor(this, this, ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); - QPointer< IController > CoreParameterController = new ControllerCoreParameter(this, this, ENUMS::CONTROLLERTYPE::COREPARAMETER); - QPointer< IController > CommandsController = new ControllerCommands(this, this, ENUMS::CONTROLLERTYPE::COMMANDS); - QPointer< IController > NotificationController = new ControllerNotifications(this, this, ENUMS::CONTROLLERTYPE::NOTIFICATION); - - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::MAINWINDOW, MainWindowController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::PLAYER, PlayerController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TEXTUREOBJECT, TextureObjectController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW, GraphicsViewController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE, TrackedComponentCoreController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::DATAEXPORT, DataExportController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::PLUGIN, PluginController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::ANNOTATIONS, AnnotationsController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::AREADESCRIPTOR, AreaDescriptorController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COREPARAMETER, CoreParameterController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMMANDS, CommandsController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::NOTIFICATION, NotificationController); - - -} - -void GuiContext::loadBioTrackerPlugin(QString str) -{ - qobject_cast (m_ControllersMap.value(ENUMS::CONTROLLERTYPE::PLUGIN))->loadPluginFromFileName(str); -} - -void GuiContext::createAppController() -{ - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->createComponents(); - } -} - -void GuiContext::connectController() -{ - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->connectComponents(); - } -} - -void GuiContext::exit() { - - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->cleanup(); - } - - //for (auto&& i : m_ControllersMap) - //{ - // delete i; - //} - - qApp->exit(); - std::exit(0); -} diff --git a/BioTracker/CoreApp/BioTracker/IStates/IPlayerState.cpp b/BioTracker/CoreApp/BioTracker/IStates/IPlayerState.cpp deleted file mode 100644 index 760f9f45..00000000 --- a/BioTracker/CoreApp/BioTracker/IStates/IPlayerState.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "IPlayerState.h" - -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" - -#include "opencv2/core/core.hpp" - -IPlayerState::IPlayerState(MediaPlayerStateMachine* player, std::shared_ptr imageStream) : - m_Player(player), - m_ImageStream(imageStream) { - m_FrameNumber = 0; -} - -std::shared_ptr IPlayerState::getCurrentFrame() { - return m_Mat; -} - -size_t IPlayerState::getCurrentFrameNumber() { - return m_FrameNumber; -} - -void IPlayerState::changeImageStream(std::shared_ptr imageStream) { - m_ImageStream.reset(); - m_ImageStream = imageStream; -} - -stateParameters IPlayerState::getStateParameters() { - return m_StateParameters; -} - -QString IPlayerState::getCurrentFileName() { - return QString::fromStdString( m_ImageStream->currentFilename() ); -} diff --git a/BioTracker/CoreApp/BioTracker/IStates/IPlayerState.h b/BioTracker/CoreApp/BioTracker/IStates/IPlayerState.h deleted file mode 100644 index eab5a681..00000000 --- a/BioTracker/CoreApp/BioTracker/IStates/IPlayerState.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - - -#ifndef IPLAYERSTATE_H -#define IPLAYERSTATE_H - -#include -#include "QPointer" - -#include "Interfaces/IModel/IModel.h" - -#include "Model/ImageStream.h" -#include "Model/TextureObject.h" - -/** - * The stateParameters struct represents the possible stats for the VideoControll buttons in the MainWindow widget. - * If a value is true, the button will be available to the user. If a value is false, the button is deactivated in the MainWindow. - */ -struct stateParameters { - bool m_Play; - bool m_Forw; - bool m_Back; - bool m_Stop; - bool m_Paus; - bool m_RecI; - bool m_RecO; -}; - -class MediaPlayerStateMachine; -/** - * The IPlayerState class is the interface for all states of the MediaPlayerStateMachine. - * This class is responsible for manipulating ImageStreams with its method operate(). - * If new states are required simply create them and add a name for the state to the - * ENUMERATION PLAYER_STATES. - * - * Any State class is able to set its following state in the MediaPlayerStateMachine. - * - */ -class IPlayerState : public IModel { - Q_OBJECT - public: - explicit IPlayerState(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - enum PLAYER_STATES {STATE_INITIAL, STATE_INITIAL_STREAM, STATE_PLAY, STATE_STEP_FORW, - STATE_STEP_BACK, STATE_PAUSE, STATE_WAIT, STATE_GOTOFRAME - }; - Q_ENUM(PLAYER_STATES) - - - public: - /** - * If the user changes the Image Source all states will be informed throught this method. - */ - void changeImageStream(std::shared_ptr imageStream); - - /** - * Must be implemented by any state. Implement here the ImageStream manipulation. - */ - virtual void operate() = 0; - - /** - * Returns the State Parameters for the ImageStream controlls in the VideoViewWidget. - */ - stateParameters getStateParameters(); - /** - * Returns the current filename of the ImageStream. - */ - QString getCurrentFileName(); - /** - * Returns the current title of the ImageStream. - */ - std::string getCurrentTitle() { return m_ImageStream->getTitle(); }; - /** - * Returns the current cv::Mat of the ImageStream. - */ - std::shared_ptr getCurrentFrame(); - /** - * Returns the current frame number of the ImageStream. - */ - size_t getCurrentFrameNumber(); - - //TODO: The Media player does not hold a valid imagestream. Hence use the current state's stream to grab details - std::shared_ptr m_ImageStream; - - protected: - MediaPlayerStateMachine* m_Player; - - stateParameters m_StateParameters; - - std::shared_ptr m_Mat; - size_t m_FrameNumber; - std::fstream fs; - - QString m_currentFileName; -}; - -#endif // IPLAYERSTATE_H diff --git a/BioTracker/CoreApp/BioTracker/Model/Annotations.cpp b/BioTracker/CoreApp/BioTracker/Model/Annotations.cpp deleted file mode 100644 index 6cdcc890..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/Annotations.cpp +++ /dev/null @@ -1,449 +0,0 @@ -#include "Annotations.h" - -#include -#include - -#include -#include - -Annotations::~Annotations() -{ - serialize(); -} - -std::string Annotations::getFilename() const -{ - return filepath + ".annotations.csv"; -} - -void Annotations::serialize() const -{ - if (!dirty || filepath.empty()) return; - - std::ofstream outfile(getFilename(), std::ios_base::out | std::ios_base::trunc); - if (!outfile.good()) return; - - if (!annotations.empty()) { - for (auto & annotation : annotations) - { - outfile << annotation.get() << std::endl; - } - } - - dirty = !outfile.good(); -} - -void Annotations::deserialize() -{ - if (filepath.empty()) return; - std::ifstream infile(getFilename(), std::ios_base::in); - if (!infile.good()) return; - annotations.clear(); - // Implements a simple CSV-reader. - // Could be replaced by library functionality. - std::string line; - while (std::getline(infile, line)) - { - try - { - std::string::size_type begin = 0; - std::queue args; - do - { - switch (line[begin]) - { - case '"': - { - const auto end = line.find('"', begin + 1); - if (end == std::string::npos) throw("parse error"); - args.push(line.substr(begin + 1, end - begin - 1)); - begin = end + 1; - break; - } - case ',': - ++begin; - break; - default: - { - auto end = line.find('"', begin + 1); - if (end == std::string::npos) - end = line.size(); - args.push(line.substr(begin + 1, end - begin - 1)); - begin = end + 1; - break; - } - } - } while (begin < line.size()); - - if (!args.empty()) - { - const std::string type = args.front(); - args.pop(); - std::shared_ptr annotation; - if (type == "arrow") - annotation = std::make_shared(); - else if (type == "label") - annotation = std::make_shared(); - else if (type == "rect") - annotation = std::make_shared(); - else if (type == "ellipse") - annotation = std::make_shared(); - if (annotation) - { - annotation->deserializeFrom(args); - annotations.push_back(annotation); - } - } - } - catch (...) {} - } -} - -std::ostream& operator<<(std::ostream& stream, const Annotations::Annotation *annotation) -{ - const std::vector serialized = annotation->serializeToVector(); - for (auto &str : serialized) - stream << "\"" << str << "\","; - return stream; -} - -void Annotations::Annotation::drawHandleLocation(QPainter *painter, QPoint pos, QString text) -{ - QPen original{ painter->pen() }; - QPen dotted{ original }; - dotted.setStyle(Qt::PenStyle::DotLine); - dotted.setWidthF(dotted.widthF() / 2.0); - painter->setPen(dotted); - const int radius = 20; - painter->drawEllipse(pos, radius, radius); - - //text slighy other color --> hue + 20 - //so text can be read when annotation is also contrasting with the background - QPen textPen{ original }; - QColor textColor{ dotted.color() }; - textColor.setHsv(textColor.hsvHue() + 20, textColor.hsvSaturation(), textColor.value()); - textPen.setColor(textColor); - painter->setPen(textPen); - - //font - QFont font= painter->font(); - font.setPointSize(15); - painter->setFont(font); - - //calculate text width to position variably - QFontMetrics fm(font); - int width = fm.width(text); - int height = fm.height(); - - //text position under origin handle - QPoint textPos = pos + QPoint(-width / 2, 20 + height); - - //draw text - painter->drawText(textPos, text); - - painter->setPen(original); -} - -bool Annotations::Annotation::isHandleAtPosition(const QPoint &handle, const QPoint &pos) -{ - QPoint diff = handle - pos; - const float euclidian = std::sqrt((diff.x() * diff.x()) + (diff.y() * diff.y())); - return euclidian <= 20.0; -} - -void Annotations::Annotation::deserializeFrom(std::queue &args) -{ - if (args.size() < 4) return; - startFrame = std::stoi(args.front()); args.pop(); - text = QString::fromStdString(args.front()); args.pop(); - const int x = std::stoi(args.front()); args.pop(); - const int y = std::stoi(args.front()); args.pop(); - origin = QPoint(x, y); - -} - -std::vector Annotations::Annotation::serializeToVector() const -{ - return { name(), std::to_string(startFrame), text.toStdString(), std::to_string(origin.x()), std::to_string(origin.y()) }; -} - -void Annotations::AnnotationLabel::deserializeFrom(std::queue &args) -{ - Annotation::deserializeFrom(args); - if (args.size() < 0) { - return; - } -} - -std::vector Annotations::AnnotationLabel::serializeToVector() const -{ - auto base = Annotations::Annotation::serializeToVector(); - return base; -} - -void Annotations::AnnotationLabel::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const -{ - QPen original{ painter->pen() }; - QPen thin{ original }; - thin.setWidthF(1.0); - painter->setPen(thin); - const int len = 20; - painter->drawLine(this->origin + QPoint(-len, -len), this->origin + QPoint(+len, +len)); - painter->drawLine(this->origin + QPoint(-len, len), this->origin + QPoint(+len, -len)); - - painter->setPen(original); - - Annotation::drawHandleLocation(painter, origin, text); -} - -void Annotations::AnnotationArrow::deserializeFrom(std::queue &args) -{ - Annotation::deserializeFrom(args); - if (args.size() < 2) return; - const int x = std::stoi(args.front()); args.pop(); - const int y = std::stoi(args.front()); args.pop(); - arrowHead = QPoint(x, y); -} - -std::vector Annotations::AnnotationArrow::serializeToVector() const -{ - auto base = Annotations::Annotation::serializeToVector(); - decltype(base) suffix { std::to_string(arrowHead.x()), std::to_string(arrowHead.y()) }; - base.insert(base.end(), suffix.begin(), suffix.end()); - return base; -} - -void Annotations::AnnotationArrow::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const -{ - painter->drawLine(this->origin, this->arrowHead); - // Draw the origin slightly bigger. - { - painter->save(); - QPen thick{ painter->pen() }; - thick.setWidthF(thick.widthF()* 2.5f); - painter->setPen(thick); - painter->drawPoint(this->origin); - painter->restore(); - } - // Draw the arrowhead slightly thinner. - { - painter->save(); - QPen thin{ painter->pen() }; - thin.setWidthF(thin.widthF()* 0.5f); - painter->setPen(thin); - painter->drawPoint(this->arrowHead); - painter->restore(); - } - Annotation::drawHandleLocation(painter, origin, text ); - Annotation::drawHandleLocation(painter, arrowHead, ""); -} - -QPoint *Annotations::AnnotationArrow::getHandleForPosition(const QPoint &pos) -{ - if (isHandleAtPosition(arrowHead, pos)) return &arrowHead; - return Annotation::getHandleForPosition(pos); -} - -void Annotations::AnnotationRect::deserializeFrom(std::queue& args) -{ - Annotation::deserializeFrom(args); - if (args.size() < 2) return; - const int x = std::stoi(args.front()); args.pop(); - const int y = std::stoi(args.front()); args.pop(); - bottomRight = QPoint(x, y); -} - -std::vector Annotations::AnnotationRect::serializeToVector() const -{ - auto base = Annotations::Annotation::serializeToVector(); - decltype(base) suffix{ std::to_string(bottomRight.x()), std::to_string(bottomRight.y()) }; - base.insert(base.end(), suffix.begin(), suffix.end()); - return base; -} - -void Annotations::AnnotationRect::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const -{ - QRect rect{ origin, bottomRight }; - painter->drawRect(rect); - // Draw the origin slightly bigger. - { - painter->save(); - QPen thick{ painter->pen() }; - thick.setWidthF(thick.widthF()* 2.5f); - painter->setPen(thick); - painter->drawPoint(this->origin); - painter->restore(); - } - // Draw the bottom right point slightly thinner. - { - painter->save(); - QPen thin{ painter->pen() }; - thin.setWidthF(thin.widthF()* 0.5f); - painter->setPen(thin); - painter->drawPoint(this->bottomRight); - painter->restore(); - } - Annotation::drawHandleLocation(painter, origin, text); - Annotation::drawHandleLocation(painter, bottomRight, ""); -} - -QPoint * Annotations::AnnotationRect::getHandleForPosition(const QPoint & pos) -{ - if (isHandleAtPosition(bottomRight, pos)) return &bottomRight; - return Annotation::getHandleForPosition(pos); -} - -void Annotations::AnnotationEllipse::deserializeFrom(std::queue& args) -{ - Annotation::deserializeFrom(args); - if (args.size() < 2) return; - const int x = std::stoi(args.front()); args.pop(); - const int y = std::stoi(args.front()); args.pop(); - bottomRight = QPoint(x, y); -} - -std::vector Annotations::AnnotationEllipse::serializeToVector() const -{ - auto base = Annotations::Annotation::serializeToVector(); - decltype(base) suffix{ std::to_string(bottomRight.x()), std::to_string(bottomRight.y()) }; - base.insert(base.end(), suffix.begin(), suffix.end()); - return base; -} - -void Annotations::AnnotationEllipse::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const -{ - QRect rect{ origin, bottomRight }; - painter->drawEllipse(rect); - // Draw the origin slightly bigger. - { - painter->save(); - QPen thick{ painter->pen() }; - thick.setWidthF(thick.widthF()* 2.5f); - painter->setPen(thick); - painter->drawPoint(this->origin); - painter->restore(); - } - // Draw the bottom right point slightly thinner. - { - painter->save(); - QPen thin{ painter->pen() }; - thin.setWidthF(thin.widthF()* 0.5f); - painter->setPen(thin); - painter->drawPoint(this->bottomRight); - painter->restore(); - } - Annotation::drawHandleLocation(painter, origin, text); - Annotation::drawHandleLocation(painter, bottomRight, ""); -} - -QPoint * Annotations::AnnotationEllipse::getHandleForPosition(const QPoint & pos) -{ - if (isHandleAtPosition(bottomRight, pos)) return &bottomRight; - return Annotation::getHandleForPosition(pos); -} - - -void Annotations::startArrow(QPoint origin, size_t currentFrame) -{ - currentAnnotation = std::make_shared(origin, currentFrame); -} - -void Annotations::startLabel(QPoint origin, size_t currentFrame) -{ - currentAnnotation = std::make_shared(origin, currentFrame); -} - -void Annotations::startRect(QPoint origin, size_t currentFrame) -{ - currentAnnotation = std::make_shared(origin, currentFrame); -} - -void Annotations::startEllipse(QPoint origin, size_t currentFrame) -{ - currentAnnotation = std::make_shared(origin, currentFrame); -} - -bool Annotations::updateAnnotation(QPoint cursor) -{ - if (currentAnnotation) - { - currentAnnotation->onEndAnnotation(cursor); - dirty = true; - return true; - } - if (selection) - { - *selection.handle = cursor; - dirty = true; - return true; - } - return false; -} - -bool Annotations::tryStartDragging(QPoint cursor) -{ - selection.reset(); - for (auto &annotation : annotations) - { - if (!(selection.handle = annotation->getHandleForPosition(cursor))) { - continue; - } - selection.annotation = annotation; - return true; - } - return false; -} - -bool Annotations::trySetText(QPoint cursor) { - selection.reset(); - for (auto &annotation : annotations) - { - if (!(selection.handle = annotation->getHandleForPosition(cursor))) { - continue; - } - selection.annotation = annotation; - - bool ok; - QString annoText = QInputDialog::getText(Q_NULLPTR, tr("Set annotation text"), - tr("Annotation text:"), QLineEdit::Normal, annotation->getText(), &ok); - if (ok) { - annotation->setText(annoText); - dirty = true; - } - return true; - } - return false; -} - -bool Annotations::endAnnotation(QPoint cursor) -{ - if (currentAnnotation) - { - const bool isValid = currentAnnotation->onEndAnnotation(cursor); - if (!isValid) return false; - - annotations.push_back(currentAnnotation); - currentAnnotation.reset(); - dirty = true; - return true; - } - - return false; -} - -bool Annotations::removeSelection() -{ - if (!selection) return false; - Annotation *selectedAnnotation{ selection.annotation.lock().get() }; - - for (auto iter = annotations.begin(); iter != annotations.end();) - { - const auto annotation = *iter; - if (annotation.get() == selectedAnnotation){ - iter = annotations.erase(iter); - dirty = true; - } - else - ++iter; - } -} diff --git a/BioTracker/CoreApp/BioTracker/Model/Annotations.h b/BioTracker/CoreApp/BioTracker/Model/Annotations.h deleted file mode 100644 index 78b4046c..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/Annotations.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg and BioTracker in version 2. - ** - ** - ****************************************************************************/ - - -#pragma once - -#include "Interfaces/IModel/IModel.h" - -#include "QString" -#include -#include -#include - -#include -#include -#include -#include - - /** - * Model to handle annotations, including serialization. - * Annotations will be drawn on top of the video. Their position is defined in image coordinates. - * Here the annotations are actually created, serialized and deserialized. - */ -class Annotations : public IModel { - Q_OBJECT -public: - Annotations(std::string filepath = "") : filepath(filepath) { deserialize(); } - virtual ~Annotations(); - - /* - Base annotation class. - Children must at least support serialization and drawing. - */ - struct Annotation - { - Annotation(QPoint origin = { 0,0 }, size_t startFrame = 0) : origin(origin), startFrame(startFrame) {} - virtual ~Annotation() = default; - /// Position in pixels. - QPoint origin{ 0, 0 }; - size_t startFrame{ 0 }; - /// Possible text for each annotation - QString text{ "" }; - /// Name that identifies this type of annotation and is used for serialization. - virtual std::string name() const = 0; - virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const = 0; - /// Saving requires writing properties to vector of strings. - virtual std::vector serializeToVector() const; - virtual void deserializeFrom(std::queue &args); - /// Set text. Called when right clicking. - virtual void setText(QString newText) { text = newText; }; - /// Get text.Called when right clicking. - virtual QString getText() { return text; }; - // Called either during dragging or when the mouse is released. - //Needs to update positional data. - virtual bool onEndAnnotation(QPoint currentPosition) { origin = currentPosition; return true; }; - virtual QRectF boundingRect() const { return QRect(origin, origin).marginsAdded({ 20, 20, 20, 20 }); } - // Used for mouse-click events. - // Returns the handle that has been clicked. - virtual QPoint *getHandleForPosition(const QPoint &pos) - { - if (isHandleAtPosition(origin, pos)) return &origin; - return nullptr; - } - // Static, so that the view can use it to draw special handles. - static void drawHandleLocation(QPainter *painter, QPoint pos, QString text); - protected: - bool isHandleAtPosition(const QPoint &handle, const QPoint &pos); - }; - - /// A label marks a position. - struct AnnotationLabel : public Annotation - { - using Annotation::Annotation; - virtual ~AnnotationLabel() = default; - - virtual std::string name() const override { return "label"; } - virtual void deserializeFrom(std::queue &args); - virtual std::vector serializeToVector() const; - virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const override; - }; - - /// An arrow defines a vector between two positions. - struct AnnotationArrow : public Annotation - { - using Annotation::Annotation; - virtual ~AnnotationArrow() = default; - - virtual std::string name() const override { return "arrow"; } - virtual void deserializeFrom(std::queue &args); - virtual std::vector serializeToVector() const; - virtual bool onEndAnnotation(QPoint currentPosition) override { arrowHead = currentPosition; return true; }; - virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const override; - virtual QRectF boundingRect() const { return QRect(origin, arrowHead).marginsAdded({ 20, 20, 20, 20 }); } - virtual QPoint *getHandleForPosition(const QPoint &pos) override; - - QPoint arrowHead; - }; - - /// A rectangle defined by two points (top-left and bottom-right) - struct AnnotationRect : public Annotation - { - using Annotation::Annotation; - virtual ~AnnotationRect() = default; - - virtual std::string name() const override { return "rect"; } - virtual void deserializeFrom(std::queue &args); - virtual std::vector serializeToVector() const; - virtual bool onEndAnnotation(QPoint currentPosition) override { bottomRight = currentPosition; return true; }; - virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const override; - virtual QRectF boundingRect() const { return QRect(origin, bottomRight).marginsAdded({ 20, 20, 20, 20 }); } - virtual QPoint *getHandleForPosition(const QPoint &pos) override; - - QPoint bottomRight; - }; - /// An ellipse defined by two points (top-left and bottom-right) - struct AnnotationEllipse : public Annotation - { - using Annotation::Annotation; - virtual ~AnnotationEllipse() = default; - - virtual std::string name() const override { return "ellipse"; } - virtual void deserializeFrom(std::queue &args); - virtual std::vector serializeToVector() const; - virtual bool onEndAnnotation(QPoint currentPosition) override { bottomRight = currentPosition; return true; }; - virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) const override; - virtual QRectF boundingRect() const { return QRect(origin, bottomRight).marginsAdded({ 20, 20, 20, 20 }); } - virtual QPoint *getHandleForPosition(const QPoint &pos) override; - - QPoint bottomRight; - }; - - - void serialize() const; - void deserialize(); - /// Called by the controller to begin a new annotation. - void startArrow(QPoint origin, size_t currentFrame); - void startLabel(QPoint origin, size_t currentFrame); - void startRect(QPoint origin, size_t currentFrame); - void startEllipse(QPoint origin, size_t currentFrame); - /// Called by the controller on left mouse-clicks. - bool tryStartDragging(QPoint cursor); - /// Called by the controller on left mouse-clicks. - bool trySetText(QPoint cursor); - /// Called by the controller during mouse-drags to update the current annotation. - bool updateAnnotation(QPoint cursor); - /// Called on mouse-release. - bool endAnnotation(QPoint cursor); - /// Removes the currently selected (through tryStartDragging) annotation. - bool removeSelection(); - /// The current frame is required for the view to highlight annotations. - void setCurrentFrame(size_t currentFrame) { this->currentFrame = currentFrame; } - size_t getCurrentFrame() const { return currentFrame; } -private: - size_t currentFrame{ 0 }; /**< The current frame is required by the view. */ - - std::string filepath; /**< filepath of the original source image. */ - - std::string getFilename() const; /**< The resulting filename will add a suffix to the original source path. */ - - mutable bool dirty{ false }; /**< Whether the annotations need to be serialized on exit. */ - - std::vector> annotations;/**< vector of all annotations */ - - std::shared_ptr currentAnnotation; /**< Held temporarily during events - not yet 'created'. */ - - /// Valid during drag & drop or after mouse selection. - struct SelectionData - { - // Annotation from the annotations vector above. Defines validity of the whole struct. - std::weak_ptr annotation; - QPoint *handle{ nullptr }; - explicit operator bool() const { return !annotation.expired(); } - // This is likely not thread-safe. - Annotation *operator->() { return annotation.lock().get(); } - void reset() { return annotation.reset(); } - } selection; - - friend class AnnotationsView; -}; - -std::ostream& operator<<(std::ostream& stream, const Annotations::Annotation *annotation); diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfo.cpp b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfo.cpp deleted file mode 100644 index 3b13cbe1..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfo.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "AreaInfo.h" - -#include "Rectification.h" - -#include "settings/Settings.h" -#include "util/misc.h" -#include -#include "AreaMemory.h" - -using namespace AreaMemory; - -AreaInfo::AreaInfo(QObject *parent) : - IModelAreaDescriptor(parent) -{ - _parms = nullptr; - _rect = std::make_shared(); - _rect->setShowNumbers(true); - _rect->setAreaType(BiotrackerTypes::AreaType::RECT); - _apperture = std::make_shared(); - _apperture->setAreaType(BiotrackerTypes::AreaType::APPERTURE); - loadAreas(); - -} - -QString AreaInfo::myType(){ - if (_apperture != nullptr) { - return QString::number(_apperture->getType()); - } - return "0"; -} - -void AreaInfo::reset(int w, int h) { - _useEntireScreen = true; - _rectInitialized = false; - _vdimX = w; - _vdimY = h; - - - QVector vertices = _parms != nullptr ? getVertices(_parms->m_CurrentFilename) : QVector(); - - if ( vertices == DEFAULT_PAIR //couldn't find entry - || vertices.empty()) //biotracker just started - { - std::vector v{ - cv::Point(0,0), - cv::Point(0,_vdimY), - cv::Point(_vdimX,_vdimY), - cv::Point(_vdimX,0) - }; - _apperture->setVertices(v); - _rect->setVertices(v); - } - else - { - std::vector pts = toQPointVector(vertices[0]); - std::vector pts2 = toQPointVector(vertices[1]); - _apperture->setVertices(QVecToCvVec(pts2)); - _rect->setVertices(QVecToCvVec(pts)); - } -} - -void AreaInfo::loadAreas() { - - QVector pair = getVertices(_parms ? _parms->m_CurrentFilename : "", true); - - if (pair[1] == QString(DEFAULT_RECT)) { - if (_parms) { - std::shared_ptr m = _parms->m_CurrentFrame; - reset(m->size().width, m->size().height); - } - else { - reset(100, 100); - } - } - - - std::vector p = stringToCVPointVec(pair[0].toStdString()); - _rect->setVertices(p); - - p = stringToCVPointVec(pair[1].toStdString());; - _apperture->setVertices(p); -} - -void AreaInfo::rcvPlayerParameters(playerParameters* parameters) -{ - if (_parms == nullptr || _parms->m_CurrentFilename != parameters->m_CurrentFilename) { - _rectInitialized = false; - } - if (parameters->m_CurrentFrame == nullptr) { - return; - } - - _parms = parameters; - std::shared_ptr m = parameters->m_CurrentFrame; - if ((m->size().width != _vdimX || m->size().height != _vdimY) && - _useEntireScreen) { - reset(m->size().width, m->size().height); - loadAreas(); - updateRectification(); - } -} - -void AreaInfo::updateRectification() { - if (_parms) { - if (!_rectInitialized) { - QVector vertices = getVertices(_parms->m_CurrentFilename); - std::vector pts = toQPointVector(vertices[0]); - Rectification::instance().setArea(pts); - Rectification::instance().setupRecitification(100, 100, _vdimX, _vdimY); - _rectInitialized = true; - } - else { - QVector vertices = getVertices(_parms->m_CurrentFilename); - Rectification::instance().setArea(_rect->getQVertices()); - Rectification::instance().setupRecitification(100, 100, _vdimX, _vdimY); - - setVertices(_parms->m_CurrentFilename, - QVector{ - cvPointsToString(_rect->getVertices()).c_str(), - cvPointsToString(_apperture->getVertices()).c_str(), - QString(myType()), QString(vertices[3]) }); - - setVertices("Last", - QVector{ - cvPointsToString(_rect->getVertices()).c_str(), - cvPointsToString(_apperture->getVertices()).c_str(), - QString(myType()), QString(vertices[3]) }); - } - } - else { - //TODO: What's to do here? - } -} - -void AreaInfo::setRectificationDimensions(double w, double h) { - Rectification::instance().setDimension(w,h); -} - -void AreaInfo::updateApperture() { - - if (_parms && _rectInitialized) { - QVector vertices = getVertices(_parms->m_CurrentFilename); - std::vector p = _apperture->getVertices(); - - setVertices(_parms->m_CurrentFilename, - QVector{ - cvPointsToString(_rect->getVertices()).c_str(), - cvPointsToString(p).c_str(), - QString(myType()), QString(vertices[3]) }); //TODO - - } -} - -bool AreaInfo::inTrackingArea(cv::Point2f point_cm) { - return _apperture->insideElement(point_cm); -} - -cv::Point2f AreaInfo::pxToCm(cv::Point point_px) { - return Rectification::instance().pxToCm(point_px); -} - -cv::Point2f AreaInfo::cmToPx(cv::Point2f point_cm) { - return Rectification::instance().cmToPx(point_cm); -} diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfo.h b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfo.h deleted file mode 100644 index ee3881de..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfo.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include "Interfaces/IModel/IModel.h" -#include "AreaInfoElement.h" -#include "util/types.h" -#include "Model/MediaPlayerStateMachine/PlayerParameters.h" - -class AreaInfo : public IModelAreaDescriptor -{ - Q_OBJECT -public: - AreaInfo() = delete; - AreaInfo(QObject *parent = 0); - - //TODO PORT - bool inTrackingArea(cv::Point2f point_cm) override; - - /** - * Transform the provided pixel coordinates into world coordinates and return world coordinates. - * @param: pixelCoords, a list of points. - * @return: world coordinates in as a list. - */ - cv::Point2f pxToCm(cv::Point point_px) override; - - /** - * Transform the provided pixel point into world coordinates and return world point. - * @param: point, a pixel point, used opencv point - * @return: world point. - */ - cv::Point2f cmToPx(cv::Point2f point_cm) override; - - void updateApperture(); - - void updateRectification(); - - void setRectificationDimensions(double w, double h); - - void reset(int w, int h); - void loadAreas(); - void setUseEntireScreen(bool b) { _useEntireScreen = b; }; - bool getUseEntireScreen() { return _useEntireScreen; }; - - std::shared_ptr _rect; - std::shared_ptr _apperture; - -private: - - //If the user never changed the area, use the whole screen. Indicate by this switch - bool _useEntireScreen = false; - int _vdimX = 1; - int _vdimY = 1; - playerParameters* _parms; - bool _rectInitialized = false; - -public Q_SLOTS: - void rcvPlayerParameters(playerParameters* parameters); - -private: - QString myType(); -}; - diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfoElement.cpp b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfoElement.cpp deleted file mode 100644 index 995eb4d6..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfoElement.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "AreaInfoElement.h" - -#include -#include "opencv2/imgproc/imgproc.hpp" - -AreaInfoElement::AreaInfoElement(int type) : - _areaType(BiotrackerTypes::AreaType::NONE), - _type(type), - _showNumbers(false) -{ -} - - -AreaInfoElement::~AreaInfoElement() -{ -} - - -bool AreaInfoElement::insideElement(cv::Point p) { - - if (_type == 0) { - - return cv::pointPolygonTest(_v, p, true) > 0; - } - else if (_type == 1) { - float rx = std::abs(_v[1].x - _v[0].x) / 2; - float ry = std::abs(_v[1].y - _v[0].y) / 2; - float h = _v[0].x + rx; - float k = _v[0].y + ry; - float x = p.x; - float y = p.y; - - float xh = std::pow(x - h, 2); - float yk = std::pow(y - k, 2); - float val = (xh / (rx*rx)) + (yk / (ry*ry)); - bool inShape = val <= 1; - - return inShape; - } - return false; -} - -int AreaInfoElement::getVerticeAtLocation(const QPoint &pos) { - if (_type == 0) { - for (int i = 0; i < 4; i++) { - if (isHandleAtPosition(_v[i], pos)) - return i; - } - } - else if (_type == 1) { - for (int i = 0; i < 2; i++) { - if (isHandleAtPosition(_v[i], pos)) - return i; - } - } - - return -1; -} - -void AreaInfoElement::setVerticeAtLocation(const QPoint &pos, int vertice) { - if (_type == 0 && vertice >= 0 && vertice <4) { - _v[vertice] = cv::Point2f(pos.x(), pos.y()); - } - else if (_type > 0 && vertice >= 0 && vertice < 2) { - _v[vertice] = cv::Point2f(pos.x(), pos.y()); - } - - Q_EMIT updatedVertices(); - -} - -bool AreaInfoElement::isHandleAtPosition(const cv::Point2f &handle, const QPoint &pos) { - return isHandleAtPosition(QPoint(handle.x, handle.y), pos); -} -bool AreaInfoElement::isHandleAtPosition(const QPoint &handle, const QPoint &pos) -{ - QPoint diff = handle - pos; - const float euclidian = std::sqrt((diff.x() * diff.x()) + (diff.y() * diff.y())); - return euclidian <= 20.0; -} diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfoElement.h b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfoElement.h deleted file mode 100644 index 6653d6c0..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaInfoElement.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#include "Interfaces/IModel/IModel.h" -#include -#include -#include "util/types.h" - -class AreaInfoElement : public IModel -{ - Q_OBJECT - -public: - AreaInfoElement(int type = 0); - ~AreaInfoElement(); - - bool insideElement(cv::Point p); - - void setVertices(std::vector p) { - _v = p; - Q_EMIT updatedVertices(); - }; - - std::vector _v; - - std::vector getVertices() { return _v; }; - - //TODO: change everything to QPoints? - std::vector getQVertices() { - std::vector v; - for (int i = 0; i < _v.size(); i++) { - v.push_back(QPoint(_v[i].x, _v[i].y)); - } - return v; - }; - - int getType() { return _type; }; - void setType(int t) { _type = t; }; - - void setVerticeAtLocation(const QPoint &pos, int vertice); - int getVerticeAtLocation(const QPoint &pos); - - virtual QPoint *getHandleForPosition(const QPoint &pos) - { - if (isHandleAtPosition(_origin, pos)) return &_origin; - return nullptr; - } - - void setShowNumbers(bool b) { - _showNumbers = b; - } - - bool getShowNumbers() { - return _showNumbers; - } - - BiotrackerTypes::AreaType getAreaType() { return _areaType; } - void setAreaType(BiotrackerTypes::AreaType t) { _areaType = t; } - -protected: - bool isHandleAtPosition(const cv::Point2f &handle, const QPoint &pos); - bool isHandleAtPosition(const QPoint &handle, const QPoint &pos); - -signals: - void updatedVertices(); - -private: - // Position in pixels. - QPoint _origin{ 0, 0 }; - - bool _showNumbers; - - //Rect or Ellipse? - int _type; - - //Rectification, tracking area or both? - BiotrackerTypes::AreaType _areaType; -}; - diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaMemory.h b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaMemory.h deleted file mode 100644 index 8e791132..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaMemory.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include "Interfaces/IModel/IModel.h" -#include "AreaInfoElement.h" -#include "util/types.h" -#include "Model/MediaPlayerStateMachine/PlayerParameters.h" - -namespace AreaMemory -{ -#define DEFAULT_RECT "15,15;15,105;105,105;105,15" -#define DEFAULT_AREA "10,10;10,100;100,100;100,10" -#define DEFAULT_PAIR QVector{DEFAULT_AREA, DEFAULT_RECT, "0", "0"} - - QVector getVertices(QString file, bool useLast = false); - void setVertices(QString file, QVector values); - std::vector toQPointVector(QString vertices); -}; - diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/Rectification.cpp b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/Rectification.cpp deleted file mode 100644 index ceba5dc5..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/Rectification.cpp +++ /dev/null @@ -1,349 +0,0 @@ -#include "Rectification.h" -#include -#include - -#include -#include "settings/Settings.h" -#include "util/misc.h" -#include "util/types.h" - -Rectification::Rectification() { - - BioTracker::Core::Settings *_settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - double w = std::max(_settings->getValueOrDefault(AREADESCRIPTOR::RECT_W, AREADESCRIPTOR::RECT_W_DEFAULT), std::numeric_limits::epsilon()); - double h = std::max(_settings->getValueOrDefault(AREADESCRIPTOR::RECT_H, AREADESCRIPTOR::RECT_H_DEFAULT), std::numeric_limits::epsilon()); - initRecitification(w,h); - setupRecitification(0,0,0,0); -} - -void Rectification::init(double areaHeight_cm, double areaWidth_cm, - std::vector areaCoordinates, int camCaptureWidth_px, - int camCaptureHeight_px, int frameDisplayWidthPx, int frameDisplayHeightPx) -{ - _q = cv::Mat(3, 1, CV_32F); - _camCaptureWidth_px = camCaptureWidth_px; - _camCaptureHeight_px = camCaptureHeight_px; - _areaHeight_cm = areaHeight_cm; - _areaWidth_cm = areaWidth_cm; - _areaCoordinates = areaCoordinates; - _frameDisplayWidthPx = frameDisplayWidthPx; - _frameDisplayHeightPx = frameDisplayHeightPx; - - setupRecitification(frameDisplayWidthPx, frameDisplayHeightPx, camCaptureWidth_px, camCaptureHeight_px); -} - -void Rectification::initRecitification(double areaHeight_cm, double areaWidth_cm) -{ - setArea(); - setDimension(areaWidth_cm, areaHeight_cm); -} - - -void Rectification::setArea(std::vector areaCoordinates) { - _areaCoordinates = areaCoordinates; - //BioTracker::Core::Settings *_settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - //_settings->setParam(AREADESCRIPTOR::CN_ARENA, cvPointsToString(areaCoordinates).c_str()); -} - -void Rectification::setArea(std::vector areaCoordinates) { - std::vector cvAreaCoordinates; - for (int i = 0; i < areaCoordinates.size(); i++) { - cvAreaCoordinates.push_back(cv::Point(areaCoordinates[i].x(), areaCoordinates[i].y())); - } - setArea(cvAreaCoordinates); -} - -std::vector Rectification::getDefaultArena() { - BioTracker::Core::Settings *_settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - std::string arena = _settings->getValueOrDefault(AREADESCRIPTOR::CN_ARENA, "10,10;10,100;100,100;100,10"); - return stringToCVPointVec(arena); -} - -void Rectification::setArea() -{ - setArea(getDefaultArena()); -} - -void Rectification::setDimension(double areaWidth_cm, double areaHeight_cm) { - _areaWidth_cm = areaWidth_cm; - _areaHeight_cm = areaHeight_cm; - setupRecitification(_frameDisplayWidthPx, _frameDisplayHeightPx, _camCaptureWidth_px, _camCaptureHeight_px); -} - -void Rectification::setupRecitification(int frameDisplayWidthPx, int frameDisplayHeightPx, int camImageWidth, int camImageHeight) -{ - _frameDisplayWidthPx = frameDisplayWidthPx; - _frameDisplayHeightPx = frameDisplayHeightPx; - - _camCaptureWidth_px = camImageWidth; - _camCaptureHeight_px = camImageHeight; - - if (_rectifiedAreaCoordinates.size() > 0) { - _rectifiedAreaCoordinates.clear(); - } - - _rectifiedAreaCoordinates.push_back(cv::Point2f(0.0, 0.0)); // Top left - _rectifiedAreaCoordinates.push_back(cv::Point2f(0.0, _areaHeight_cm)); // botton left - _rectifiedAreaCoordinates.push_back(cv::Point2f(_areaWidth_cm, _areaHeight_cm)); // bottom right - _rectifiedAreaCoordinates.push_back(cv::Point2f(_areaWidth_cm, 0.0)); // top right - - std::vector areaCoordinates_2f; - - assert(_areaCoordinates.size() == 4); - - cv::Mat coordinateMatrix(getSortedPoints()); - - if (cv::sum(coordinateMatrix)[0] > 0.0f) - coordinateMatrix.copyTo(areaCoordinates_2f); - else - areaCoordinates_2f = _rectifiedAreaCoordinates; - - _H = cv::findHomography(areaCoordinates_2f, _rectifiedAreaCoordinates); - _H_inv = _H.inv(); - _isSetup = true; -} - -void Rectification::resetAreaCoordinates() -{ - std::vector areaCoordinates; - - double rationHeight = double(_frameDisplayHeightPx) / double(_camCaptureHeight_px); - double rationWidth = double(_frameDisplayWidthPx) / double(_camCaptureWidth_px); - - for (cv::Point p : _areaCoordinates) { - - - int newP_x = p.x / rationWidth; - int newP_y = p.y / rationHeight; - - areaCoordinates.push_back(cv::Point(newP_x, newP_y)); - } - - if (checkValidCoordinates(areaCoordinates, _camCaptureHeight_px, _camCaptureWidth_px)) - { - _areaCoordinates.clear(); - _areaCoordinates = areaCoordinates; - - setupRecitification(_frameDisplayWidthPx, _frameDisplayHeightPx, _camCaptureWidth_px, _camCaptureHeight_px); - } -} - -bool Rectification::checkValidCoordinates(std::vector areaCoordinates, int camCaptureHeight_px, int camCaptureWidth_px) -{ - for (cv::Point p : areaCoordinates) { - if (p.y > camCaptureHeight_px) return false; - if (p.x > camCaptureWidth_px) return false; - } - - return true; -} - -cv::Point2f Rectification::pxToCm(cv::Point point_px) const -{ - cv::Mat_ v = (cv::Mat_(3,1) << point_px.x, point_px.y, 1); - cv::gemm(_H, v, 1, 0, 0, _q); - double* qx = _q.ptr(0); - double* qy = _q.ptr(1); - double* qz = _q.ptr(2); - - cv::Point2f cm((*qx / *qz), (*qy / *qz)); - return cm; -} - -cv::Point2f Rectification::pxToCm(QPoint point_px) const -{ - return pxToCm(cv::Point(point_px.x(), point_px.y())); -} - -cv::Point2f Rectification::cmToPx(cv::Point2f point_cm) const -{ - cv::Mat_ v = (cv::Mat_(3, 1) << point_cm.x, point_cm.y, 1); - cv::gemm(_H_inv, v, 1, 0, 0, _q); - double *qx = _q.ptr(0); - double *qy = _q.ptr(1); - double *qz = _q.ptr(2); - - return cv::Point2f((*qx / *qz), (*qy / *qz)); -} - -bool Rectification::inArea(cv::Point2f point_cm) const -{ - bool flag = (point_cm.x >= 0 && point_cm.y >= 0 && point_cm.x <= _areaWidth_cm && point_cm.y <= _areaHeight_cm); - return flag; -} - - -int Rectification::minXPx() -{ - int minX = _camCaptureWidth_px; - for (int i = 0; i < _areaCoordinates.size(); i++) - { - if(_areaCoordinates.at(i).x < minX) - minX = _areaCoordinates.at(i).x; - } - return minX; -} - -int Rectification::maxXPx() -{ - int maxX = -1; - for (int i = 0; i < _areaCoordinates.size(); i++) - { - if(_areaCoordinates.at(i).x > maxX) - maxX = _areaCoordinates.at(i).x; - } - return maxX; -} - -int Rectification::minYPx() -{ - int minY = _camCaptureHeight_px; - for (int i = 0; i < _areaCoordinates.size(); i++) - { - if(_areaCoordinates.at(i).y < minY) - minY = _areaCoordinates.at(i).y; - } - return minY; -} - -int Rectification::maxYPx() -{ - int maxY = -1; - for (int i = 0; i < _areaCoordinates.size(); i++) - { - if(_areaCoordinates.at(i).y > maxY) - maxY = _areaCoordinates.at(i).y; - } - return maxY; -} - -cv::Point Rectification::getTopLeft() -{ - assert(_areaCoordinates.size() == 4); - - std::vector ac(_areaCoordinates); - - std::sort(ac.begin(), ac.end(), - [](const cv::Point & a, const cv::Point & b) -> bool - { - return (a.x <= b.x) && (a.y <= b.y); - } - ); - - return ac[0]; -} - -cv::Point Rectification::getBottomLeft() -{ - assert(_areaCoordinates.size() == 4); - - std::vector ac(_areaCoordinates); - - std::sort(ac.begin(), ac.end(), - [](const cv::Point & a, const cv::Point & b) -> bool - { - return (a.x <= b.x) && (a.y >= b.y); - } - ); - - return ac[0]; -} - -cv::Point Rectification::getBottomRight() -{ - assert(_areaCoordinates.size() == 4); - - std::vector ac(_areaCoordinates); - - std::sort(ac.begin(), ac.end(), - [](const cv::Point & a, const cv::Point & b) -> bool - { - return (a.x >= b.x) && (a.y >= b.y); - } - ); - - - return ac[0]; -} - -cv::Point Rectification::getTopRight() -{ - assert(_areaCoordinates.size() == 4); - - - std::vector ac(_areaCoordinates); - - std::sort(ac.begin(), ac.end(), - [](const cv::Point & a, const cv::Point & b) -> bool - { - return (a.x >= b.x) && (a.y <= b.y); - } - ); - - return ac[0]; -} - -cv::Mat Rectification::getSortedPoints() -{ - assert(_areaCoordinates.size() == 4); - return cv::Mat(_areaCoordinates); -} - -cv::Point Rectification::getCorrectedResolutionPoint(QPoint pos) -{ - return getCorrectedResolutionPoint(cv::Point(pos.x(),pos.y())); -} - -cv::Point Rectification::getCorrectedResolutionPoint(cv::Point pos) -{ - - int heightScaled = _frameDisplayHeightPx; - int widthScaled = _frameDisplayWidthPx; - - float scaleFactor = 1.0f; - - if (_camCaptureWidth_px > _frameDisplayWidthPx || _camCaptureHeight_px > _frameDisplayHeightPx) - { - scaleFactor = float(_camCaptureWidth_px) / float(_frameDisplayWidthPx); - - heightScaled = _camCaptureHeight_px / scaleFactor; - - if (_camCaptureWidth_px == _camCaptureHeight_px) - { - if (heightScaled > _frameDisplayHeightPx) - { - scaleFactor = float(_camCaptureHeight_px) / float(_frameDisplayHeightPx); - - widthScaled = _camCaptureWidth_px / scaleFactor; - - assert(widthScaled <= _frameDisplayWidthPx); - } - else - { - if (heightScaled > _frameDisplayWidthPx) - { - scaleFactor = float(_camCaptureHeight_px) / float(_frameDisplayWidthPx); - - widthScaled = _camCaptureWidth_px / scaleFactor; - - assert(widthScaled <= _frameDisplayWidthPx); - } - } - } - else - { - if (heightScaled > _frameDisplayWidthPx) - { - scaleFactor = float(_camCaptureHeight_px) / float(_frameDisplayWidthPx); - - widthScaled = _camCaptureWidth_px / scaleFactor; - - assert(widthScaled <= _frameDisplayWidthPx); - } - } - - - } - - return cv::Point(int(float(pos.x) * scaleFactor), int(float(pos.y) * scaleFactor)); -} \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/Rectification.h b/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/Rectification.h deleted file mode 100644 index dce3a190..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/Rectification.h +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -#include -#include -#include - -/** - * Rectification class normalizing the tracking image - */ -class Rectification -{ -public: - - static Rectification& instance() - { - static Rectification _instance; // Guaranteed to be destroyed. - // Instantiated on first use. - return _instance; - } - - ~Rectification() {} - -private: - - /** - * The standard constructor. - */ - Rectification(); - - Rectification(const Rectification&); /* verhindert, dass eine weitere Instanz via - Kopier-Konstruktor erstellt werden kann */ - - Rectification & operator = (const Rectification &); //Verhindert weitere Instanz durch Kopie - -public: - - void init(double areaHeight_cm, double areaWidth_cm, - std::vector areaCoordinates, int camCaptureWidth_px, - int camCaptureHeight_px, int frameDisplayWidthPx, int frameDisplayHeightPx); - - bool isSetup() { return _isSetup; }; - - double areaWidth_cm() const { return _areaWidth_cm; } - double areaHeight_cm() const { return _areaHeight_cm; } - int captureWidth_px() const { return _camCaptureWidth_px; } - int captureHeight_px() const { return _camCaptureHeight_px; } - - bool inArea(cv::Point2f point_cm) const; - - /** - * Transform the provided pixel coordinates into world coordinates and return world coordinates. - * @param: pixelCoords, a list of points. - * @return: world coordinates in as a list. - */ - cv::Point2f pxToCm(cv::Point point_px) const; - cv::Point2f pxToCm(QPoint point_px) const; - - /** - * Transform the provided pixel point into world coordinates and return world point. - * @param: point, a pixel point, used opencv point - * @return: world point. - */ - cv::Point2f cmToPx(cv::Point2f point_cm) const; - - /** - * Sets the tank coordinates. - * @param: areaCoordinates, the coordinate list of the considered area. - * @return: void. - */ - void setArea(std::vector areaCoordinates); - void setArea(std::vector areaCoordinates); - - //infers the area coordinates from the data model - void setArea(); - std::vector getDefaultArena(); - void resetAreaCoordinates(); - - /** - * Sets the real world dimension the tank. - * @param: areaWidth_cm, width of the tank in cm, - * @param: areaHeight_cm, height of the tank in cm, - * @return: void. - */ - void setDimension(double areaWidth_cm, double areaHeight_cm); - - void setCamImageSize(cv::Size size) { _camCaptureWidth_px = size.width; _camCaptureHeight_px = size.height; } - - void initRecitification(double areaHeight_cm, double areaWidth_cm); - void setupRecitification(int frameDisplayWidthPx, int frameDisplayHeightPx, int camImageWidth, int camImageHeight); - - std::vector area() const { return _areaCoordinates; } - - int minXPx(); - int maxXPx(); - int minYPx(); - int maxYPx(); - - cv::Point getTopLeft(); - cv::Point getBottomLeft(); - cv::Point getBottomRight(); - cv::Point getTopRight(); - cv::Point getCorrectedResolutionPoint(QPoint pos); - cv::Point getCorrectedResolutionPoint(cv::Point pos); - cv::Mat getSortedPoints(); - -private: - std::vector _areaCoordinates; - std::vector _rectifiedAreaCoordinates; - - //Homography - cv::Mat_ _H; - cv::Mat_ _H_inv; - //some vector 3x1. Might be zero? TODO - mutable cv::Mat_ _q; - - int _camCaptureWidth_px; - int _camCaptureHeight_px; - - int _frameDisplayWidthPx; - int _frameDisplayHeightPx; - - double _areaWidth_cm; - double _areaHeight_cm; - - bool _isSetup; - - bool checkValidCoordinates(std::vector areaCoordinates, int camCaptureHeight_px, int camCaptureWidth_px); - -}; diff --git a/BioTracker/CoreApp/BioTracker/Model/CoreParameter.cpp b/BioTracker/CoreApp/BioTracker/Model/CoreParameter.cpp deleted file mode 100644 index 9f0df116..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/CoreParameter.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "CoreParameter.h" -#include "util/singleton.h" - -CoreParameter::CoreParameter(QObject *parent) : - IModel(parent) -{ - //_settings = BioTracker::Util::TypedSingleton::getInstance(CONFIGPARAM::CONFIG_INI_FILE); - //_settings = new BioTracker::Core::Settings(CONFIGPARAM::CONFIG_INI_FILE); - - Q_EMIT notifyView(); -} - -void CoreParameter::setTrackNumber(int number) -{ - m_trackNumber = number; - notifyView(); -} diff --git a/BioTracker/CoreApp/BioTracker/Model/CoreParameter.h b/BioTracker/CoreApp/BioTracker/Model/CoreParameter.h deleted file mode 100644 index ef0db4e1..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/CoreParameter.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef COREPARAMETER_H -#define COREPARAMETER_H - - -#include "Interfaces/IModel/IModel.h" -#include "qcolor.h" - -/** -* This model includes the default visualization options the TrackedcomponentView -* uses to create its ComponentsShapes. -* Other shared paramters can also be added. -* It is a runtime shared storage. -*/ -class CoreParameter : public IModel -{ - Q_OBJECT -public: - CoreParameter(QObject *parent = 0); - - //void setAll( - // bool viewSwitch, - // QString tracingStyle, - // int tracingHistory, - // int tracingSteps, - // QColor* colorBorder, - // QColor* colorBrush) - //{ - // m_viewSwitch = viewSwitch; - // m_tracingStyle = tracingStyle; - // m_tracingHistory = tracingHistory; - // m_tracingSteps = tracingSteps; - // m_colorBorder = colorBorder; - // m_colorBrush = colorBrush; - - // Q_EMIT notifyView(); - //}; - void setTrackNumber(int number); - - - -public: - bool m_viewSwitch = true; - bool m_antialiasingEntities = false; - bool m_antialiasingFull = false; - - //Tracing - QString m_tracingStyle = "No tracing"; - int m_tracingHistory = 20; - int m_tracingSteps = 1; - QString m_tracingTimeDegradation = "None"; - double m_tracerProportions = 0.5; - bool m_tracerOrientationLine = false; - bool m_tracerFrameNumber = false; - //Track dimensions - int m_trackWidth = 30; - int m_trackHeight = 20; - //Track misc - bool m_trackOrientationLine = true; - bool m_trackShowId = false; - //Track color - QColor* m_colorBorder = new QColor(Qt::black); - QColor* m_colorBrush = new QColor(Qt::green); - //Track count - int m_trackNumber = 0; - //Ignore zooming - bool m_ignoreZoom = false; - - -}; - -#endif // COREPARAMETER_H diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterCSV.h b/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterCSV.h deleted file mode 100644 index d771d703..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterCSV.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#include "DataExporterGeneric.h" - -class DataExporterCSV : public DataExporterGeneric -{ - Q_OBJECT -public: - DataExporterCSV(QObject *parent = 0); - ~DataExporterCSV(); - - /** - * Add a single frame index to the output file - * @param Index to write or -1 for latest - */ - void write(int idx = -1) override; - - /** - * Re-Serialize the entire structure in a clean fashion - */ - void writeAll(std::string f = "") override; - - /** - * Close the file - */ - void close() override; - - void loadFile(std::string file) override; - - /** - * Effectively a writeAll, close and open. - */ - void finalizeAndReInit() override; - - QString getSuffix() { return ".csv"; }; - -private: - - /** - * helper function to generate a part of an output line - */ - std::string writeTrackpoint(IModelTrackedPoint *e, int trajNumber); - - std::string _separator; - - - /* finding the number of occurrences of a string in another strin - * - * https://codereview.stackexchange.com/questions/29611/finding-the-number-of-occurrences-of-a-string-in-another-string - */ - int key_search(const std::string& s, const std::string& key); - - /* Get's the names of all stored properties. - * - * Useful for corresponding them with CSV headers. order relevant. - * returns Individual1 - */ - std::vector getHeaderElements(IModelTrackedComponent *comp); - - /* Get's the header as one connected string - * - * Similar getHeaderElements, but for all components and having all elements of the return vector concatenated - * returns GlobalHeaders,Individual1,Indiviual2,... - */ - std::string getHeader(IModelTrackedComponent *comp, int cnt); - - /* Sets sets a property to a components. - */ - void setProperty(IModelTrackedComponent* comp, std::string key, std::string val); - - /* Writes a tracked component to string - */ - std::string writeComponentCSV(IModelTrackedComponent* comp, int tid); - - - void addChildOfChild(IModelTrackedTrajectory *root, IModelTrackedComponent* child, IModelTrackedComponentFactory* factory, int idx); -}; - diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterGeneric.cpp b/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterGeneric.cpp deleted file mode 100644 index 42faffa8..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterGeneric.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "DataExporterGeneric.h" -#include "Controller/ControllerDataExporter.h" -#include "util/types.h" -#include "util/misc.h" -#include -#include -#include - -DataExporterGeneric::DataExporterGeneric(QObject *parent) : - IModelDataExporter(parent) -{ - _parent = parent; -} - -void DataExporterGeneric::open(IModelTrackedTrajectory *root) { - _root = root; - - _tmpFile = dynamic_cast(_parent)->generateBasename(true).toStdString() + ".tmp" + getSuffix().toStdString(); - _finalFile = dynamic_cast(_parent)->generateBasename(false).toStdString() + getSuffix().toStdString(); - _ofs.open(_tmpFile, std::ofstream::out); -} - -int DataExporterGeneric::getMaxLinecount() -{ - int max = 0; - for (int i = 0; i < _root->size(); i++) { - IModelTrackedTrajectory *t = dynamic_cast(_root->getChild(i)); - if (t) max = std::max(t->size(), max); - } - - return max; -} - -void DataExporterGeneric::cleanup() -{ - int s = _root->size(); - - //Erase all tracking data from the tracking structure! - _root->clear(); - - //Remove temporary file - QFile file(_tmpFile.c_str()); - file.remove(); - - if (s > 0) { - //Tell the controller about the written file - QFileInfo fi(_finalFile.c_str()); - fileWritten(fi); - } - return; -} - -void DataExporterGeneric::finalize() -{ - close(); - writeAll(""); - cleanup(); -}; diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterJson.h b/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterJson.h deleted file mode 100644 index d7827bcc..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterJson.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "DataExporterGeneric.h" - -class DataExporterJson : public DataExporterGeneric -{ - Q_OBJECT -public: - DataExporterJson(QObject *parent = 0); - ~DataExporterJson(); - - /** - * Add a single frame index to the output file - * @param Index to write or -1 for latest - */ - void write(int idx = -1) override; - - /** - * Re-Serialize the entire structure in a clean fashion - */ - void writeAll(std::string f = "") override; - - /** - * Close the file - */ - void close() override; - - void loadFile(std::string file) override; - - /** - * Effectively a writeAll, close and open. - */ - void finalizeAndReInit() override; - - QString getSuffix() { return ".json"; }; - -private: - - /** - * helper function to generate a part of an output line - */ - std::string writeTrackpoint(IModelTrackedPoint *e, int trajNumber); -}; - diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterSerialize.cpp b/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterSerialize.cpp deleted file mode 100644 index 9f74d0f9..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterSerialize.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "DataExporterSerialize.h" -#include "util/types.h" -#include "util/misc.h" -#include -#include - -#include -#include -#include -#include - -#include "Controller/ControllerDataExporter.h" - -DataExporterSerialize::DataExporterSerialize(QObject *parent) : - DataExporterGeneric(parent) -{ - _root = 0; -} - - -DataExporterSerialize::~DataExporterSerialize() -{ -} - -std::string DataExporterSerialize::writeTrackpoint(IModelTrackedPoint *e, int trajNumber) { - std::stringstream ss; - - - return ss.str(); -} - -void DataExporterSerialize::write(int idx) { - if (!_root) { - qDebug() << "CORE: No output opened!"; - return; - } - - _ofs << std::endl; -} - -void DataExporterSerialize::finalizeAndReInit() { - close(); //Not needed, but... - writeAll(); - cleanup(); - open(_root); -} - -extern IModelTrackedComponentFactory* factory; - -void DataExporterSerialize::loadFile(std::string file){ - - ControllerDataExporter *ctr = dynamic_cast(_parent); - factory = ctr ? ctr->getComponentFactory() : nullptr; - if (!factory) { - return; - } - - QFile f(file.c_str()); - f.open(QIODevice::ReadOnly); - QDataStream in(&f); - - IModelTrackedTrajectory *root = _root; - in >> *root; - int children = -1; - in >> children; - - std::vector childids; - for (int i = 0; i < children; i++) { - IModelTrackedTrajectory *child = static_cast(factory->getNewTrackedTrajectory("0")); - in >> *child; - childids.push_back(child->getId()); - root->add(child, child->getId()); - } - - //i is the track number - for (int i = 0; i < childids.size(); i++) { - IModelTrackedTrajectory* curTraj = static_cast(root->getChild(childids[i])); - int trajSize = -1; - in >> trajSize; - //idx is the frame number - for (int idx = 0; idx < trajSize; idx++) { - IModelTrackedComponent *e = factory->getNewTrackedElement("0"); - int cid = 0; - in >> cid; - in >> *e; - curTraj->add(e, cid); - } - } -}; - -void DataExporterSerialize::writeAll(std::string f) { - //Sanity - if (!_root) { - qDebug() << "CORE: No output opened!"; - return; - } - if (_ofs.is_open()) { - _ofs.close(); - } - - if (getMaxLinecount() <= 1) { - cleanup(); - return; - } - - std::string target = f; - if (target.size() <= 1) { - target = _finalFile; - } - if (target.substr(target.size() - 4) != ".dat") - target += ".dat"; - - //Create final file - QFile file(target.c_str()); - file.open(QIODevice::WriteOnly); - QDataStream out(&file); - - //serialize tree nodes (!= leafs) - out << *_root; - out << _root->size(); - for (int i = 0; i < _root->size(); i++) { - IModelTrackedTrajectory *t = dynamic_cast(_root->getChild(i)); - out << *t; - } - - - //i is the track number - for (int i = 0; i < _root->size(); i++) { - IModelTrackedTrajectory *t = dynamic_cast(_root->getChild(i)); - - int cnt = 0; - for (int idx = 0; idx < t->size(); idx++) { - if (t) { - IModelTrackedComponent *e = dynamic_cast(t->getChild(idx)); - if (e) { - cnt++; - } - } - } - out << cnt; - - //idx is the frame number - for (int idx = 0; idx < t->size(); idx++) { - if (t) { - IModelTrackedComponent *e = dynamic_cast(t->getChild(idx)); - if (e) { - out << idx; - out << *e; - } - } - } - } -} - -void DataExporterSerialize::close() { - _ofs.close(); - - if ((!_root || _root->size() == 0) && _tmpFile!="" ) { - //Remove temporary file - QFile file(_tmpFile.c_str()); - file.remove(); - } -} diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterSerialize.h b/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterSerialize.h deleted file mode 100644 index 93c868d6..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterSerialize.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "DataExporterGeneric.h" - -class DataExporterSerialize : public DataExporterGeneric -{ - Q_OBJECT -public: - DataExporterSerialize(QObject *parent = 0); - ~DataExporterSerialize(); - - /** - * Add a single frame index to the output file - * @param Index to write or -1 for latest - */ - void write(int idx = -1) override; - - /** - * Re-Serialize the entire structure in a clean fashion - */ - void writeAll(std::string f = "") override; - - /** - * Close the file - */ - void close() override; - - void loadFile(std::string file) override; - - /** - * Effectively a writeAll, close and open. - */ - void finalizeAndReInit() override; - - QString getSuffix() { return ".dat"; }; - -private: - - /** - * helper function to generate a part of an output line - */ - std::string writeTrackpoint(IModelTrackedPoint *e, int trajNumber); -}; - diff --git a/BioTracker/CoreApp/BioTracker/Model/ImageStream.cpp b/BioTracker/CoreApp/BioTracker/Model/ImageStream.cpp deleted file mode 100644 index a6bee67e..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/ImageStream.cpp +++ /dev/null @@ -1,476 +0,0 @@ -#include "ImageStream.h" - -#include "util/stdext.h" -#include // assert -#include // std::invalid_argument -#include -#include - -#include "util/Exceptions.h" -#include "QSharedPointer" -#include "settings/Settings.h" -#include "util/misc.h" - -#include "View/CameraDevice.h" -#include "util/types.h" -#include "util/singleton.h" -#include "settings/Settings.h" -#include "util/VideoCoder.h" - -namespace BioTracker { - namespace Core { - - ImageStream::ImageStream(QObject *parent) : QObject(parent), - m_current_frame(new cv::Mat(cv::Size(0, 0), CV_8UC3)), - m_current_frame_number(0), - m_frame_stride(BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION)-> - getValueOrDefault(CFG_INPUT_FRAME_STRIDE, CFG_INPUT_FRAME_STRIDE_VAL)) { - } - - size_t ImageStream::currentFrameNumber() const { - return m_current_frame_number; - } - - std::shared_ptr ImageStream::currentFrame() const { - return m_current_frame; - } - - bool ImageStream::setFrameNumber(size_t frame_number) { - // valid new frame number - if (frame_number < this->numFrames()) { - // skip update if frame number doesn't change - if (frame_number == this->currentFrameNumber()) { - return true; - } - else { - const bool success = this->setFrameNumber_impl(frame_number); - m_current_frame_number = frame_number; - return success; - } - } - // invalid new frame number - else { - this->clearImage(); - return false; - } - } - - bool ImageStream::lastFrame() const { - return this->currentFrameNumber() + 1 == this->numFrames(); - } - - bool ImageStream::end() const { - return (this->currentFrameNumber() >= this->numFrames() && this->numFrames() >= 0); - } - - bool ImageStream::currentFrameIsEmpty() const { - return this->currentFrame()->empty(); - } - - bool ImageStream::nextFrame() { - const size_t new_frame_number = this->currentFrameNumber() + m_frame_stride; - if (new_frame_number < this->numFrames()) { - const bool success = this->nextFrame_impl(); - m_current_frame_number = new_frame_number; - return success; - } - else { - this->clearImage(); - return false; - } - } - - bool ImageStream::previousFrame() { - if (this->currentFrameNumber() > 0) { - const size_t new_frame_numer = this->currentFrameNumber() - 1; - const bool success = this->previousFrame_impl(); - m_current_frame_number = new_frame_numer; - return success; - } - else { - this->clearImage(); - return false; - } - } - - void ImageStream::set_current_frame(std::shared_ptr img) { - m_current_frame.swap(img); - } - - void ImageStream::clearImage() { - m_current_frame.reset(); - m_current_frame_number = this->numFrames(); - } - - bool ImageStream::nextFrame_impl() { - assert(this->currentFrameNumber() + 1 < this->numFrames()); - const size_t new_frame_number = this->currentFrameNumber() + 1; - return this->setFrameNumber_impl(new_frame_number); - } - - bool ImageStream::previousFrame_impl() { - assert(this->currentFrameNumber() > 0); - const size_t new_frame_number = this->currentFrameNumber() - 1; - return this->setFrameNumber_impl(new_frame_number); - } - - ImageStream::~ImageStream() = default; - - - /*********************************************************/ - - - class ImageStream3NoMedia : public ImageStream { - public: - explicit ImageStream3NoMedia() = default; - virtual GuiParam::MediaType type() const override { - return GuiParam::MediaType::NoMedia; - } - virtual size_t numFrames() const override { - return 0; - } - virtual bool toggleRecord() override { - return false; - } - virtual double fps() const override { - return 1.0; - } - virtual std::string currentFilename() const override { - return "No Media"; // TODO make this nicer.. - } - - private: - virtual bool setFrameNumber_impl(size_t) override { - return false; - } - }; - - - /*********************************************************/ - - - class ImageStream3Pictures : public ImageStream { - public: - explicit ImageStream3Pictures(std::vector picture_files) - : m_picture_files(std::move(picture_files)), m_currentFrame(0) { - - //Grab the codec from config file - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - double fps = set->getValueOrDefault(CFG_RECORD_FPS, CFG_RECORD_FPS_VAL); - if (fps > 0) { - m_fps = fps; - } - else - { - m_fps = 1; - } - - // load first image - if (this->numFrames() > 0) { - this->setFrameNumber_impl(0); - std::string filename = m_picture_files[0].string(); - std::shared_ptr new_frame = std::make_shared(cv::imread(filename)); - m_w = new_frame->size().width; - m_h = new_frame->size().height; - m_recording = false; - vCoder = std::make_shared(); - } - - } - virtual GuiParam::MediaType type() const override { - return GuiParam::MediaType::Images; - } - virtual size_t numFrames() const override { - return m_picture_files.size(); - } - virtual bool toggleRecord() override { - if (this->numFrames() <= 0) { - return false; - } - m_recording = vCoder->toggle(m_w, m_h, m_fps); - - return m_recording; - } - virtual double fps() const override { - return m_fps; - } - virtual std::string currentFilename() const override { - assert(currentFrameNumber() < m_picture_files.size()); - return m_picture_files[currentFrameNumber()].string(); - } - - private: - virtual bool nextFrame_impl() override { - m_currentFrame += m_frame_stride; - if (this->numFrames() > m_currentFrame) { - - const std::string &filename = m_picture_files[m_currentFrame].string(); - std::shared_ptr new_frame = std::make_shared(cv::imread(filename)); - this->set_current_frame(new_frame); - if (m_recording) { - if (vCoder) vCoder->add(new_frame); - } - return true; - } - return false; - } - - virtual bool setFrameNumber_impl(size_t frame_number) override { - const std::string &filename = m_picture_files[frame_number].string(); - std::shared_ptr new_frame = std::make_shared(cv::imread(filename)); - this->set_current_frame(new_frame); - m_currentFrame = frame_number; - if (m_recording) { - if (vCoder) vCoder->add(new_frame); - } - return !new_frame->empty(); - } - std::vector m_picture_files; - std::shared_ptr vCoder; - double m_w; - double m_h; - bool m_recording; - int m_currentFrame; - double m_fps; - }; - - - /*********************************************************/ - - - class ImageStream3Video : public ImageStream { - public: - /** - * @throw file_not_found when the file does not exists - * @throw video_open_error when there is an error with the video - * @brief ImageStreamVideo - * @param filename path to the file - */ - explicit ImageStream3Video(const std::vector &files) - : m_capture(files.front().string()) - , m_num_frames(static_cast(m_capture.get(CV_CAP_PROP_FRAME_COUNT))) - , m_fps(m_capture.get(CV_CAP_PROP_FPS)) - , m_fileName(files.front().string()) { - - if (!boost::filesystem::exists(files.front())) { - throw file_not_found("Could not find file " + files.front().string()); - } - if (!m_capture.isOpened()) { - throw video_open_error(":("); - } - - m_batch = files; - m_batch.erase(m_batch.begin(), m_batch.begin()+1); - - //Grab the fps from config file - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - double fps = set->getValueOrDefault(CFG_RECORD_FPS, CFG_RECORD_FPS_VAL); - if (fps != -1) { - m_fps = fps; - } - - m_w = m_capture.get(CV_CAP_PROP_FRAME_WIDTH); - m_h = m_capture.get(CV_CAP_PROP_FRAME_HEIGHT); - m_recording = false; - vCoder = std::make_shared(); - - // load first image - if (this->numFrames() > 0) { - this->nextFrame_impl(); - } - } - virtual GuiParam::MediaType type() const override { - return GuiParam::MediaType::Video; - } - virtual size_t numFrames() const override { - return m_num_frames; - } - virtual bool toggleRecord() override { - if (!m_capture.isOpened()) { - return false; - } - m_recording = vCoder->toggle(m_w, m_h, m_fps); - - return m_recording; - } - virtual double fps() const override { - return m_fps; - } - virtual std::string currentFilename() const override { - return m_fileName; - } - - private: - virtual bool nextFrame_impl() override { - cv::Mat new_frame; - for (int i = 0; i> new_frame; - std::shared_ptr mat(new cv::Mat(new_frame)); - this->set_current_frame(mat); - if (m_recording) { - if (vCoder) vCoder->add(mat); - } - return !new_frame.empty(); - } - - virtual bool setFrameNumber_impl(size_t frame_number) override { - // new frame is next frame --> use next frame function - if (this->currentFrameNumber() + 1 == frame_number) { - return this->nextFrame_impl(); - } - else { - // adjust frame position ("0-based index of the frame to be decoded/captured next.") - m_capture.set(CV_CAP_PROP_POS_FRAMES, static_cast(frame_number)); - return this->nextFrame_impl(); - } - } - - cv::VideoCapture m_capture; - const size_t m_num_frames; - const std::string m_fileName; - std::shared_ptr vCoder; - std::vector m_batch; - double m_fps; - double m_w; - double m_h; - bool m_recording; - }; - - - /*********************************************************/ -#include - class ImageStream3Camera : public ImageStream { - public: - /** - * @throw file_not_found when device does not exists - * @throw device_open_error when there is an error with the device - * @brief ImageStreamCamera - * @param device_id according to the VideoCapture class of OpenCV - */ - explicit ImageStream3Camera(CameraConfiguration conf) - : m_capture(conf._id) - , m_fps(m_capture.get(CV_CAP_PROP_FPS)) { - // Give the camera some extra time to get ready: - // Somehow opening it on first try sometimes does not succeed. - // Workaround: http://stackoverflow.com/questions/22019064/unable-to-read-frames-from-videocapture-from-secondary-webcam-with-opencv?rq=1 - // So, stubbornly try it a few times until it works. - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - - Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - - std::cout << "\nStarting to record on camera no. " << conf._id << std::endl; - m_w = conf._width == -1 ? set->getValueOrDefault(CFG_CAMERA_DEFAULT_W, CFG_CAMERA_DEFAULT_W_VAL) : conf._width; - m_h = conf._height == -1 ? set->getValueOrDefault(CFG_CAMERA_DEFAULT_H, CFG_CAMERA_DEFAULT_H_VAL) : conf._height; - m_fps = conf._fps == -1 ? set->getValueOrDefault(CFG_RECORD_FPS, CFG_RECORD_FPS_VAL) : conf._fps; - m_recording = false; - vCoder = std::make_shared(m_fps); - - int fails = 0; - while (!m_capture.isOpened() && fails < 5) { - m_capture.open(conf._id); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - fails++; - } - - if (!m_capture.isOpened()) { - std::cout << "Unable to open camera!" << std::endl; - throw device_open_error(":("); - } - - if (m_w != -1) m_capture.set(CV_CAP_PROP_FRAME_WIDTH, m_w); - if (m_h != -1) m_capture.set(CV_CAP_PROP_FRAME_HEIGHT, m_h); - if (m_fps != -1) m_capture.set(CV_CAP_PROP_FPS, m_fps); - - m_w = m_capture.get(CV_CAP_PROP_FRAME_WIDTH); - m_h = m_capture.get(CV_CAP_PROP_FRAME_HEIGHT); - m_fps = m_capture.get(CV_CAP_PROP_FPS); - std::cout << "Cam open: " << m_capture.isOpened() << " w/h:" << m_w << "/" << m_h << " fps:" << m_fps << std::endl; - // load first image - if (this->numFrames() > 0) { - this->nextFrame_impl(); - } - } - virtual GuiParam::MediaType type() const override { - return GuiParam::MediaType::Camera; - } - virtual size_t numFrames() const override { - return -1; //TODO - } - virtual bool toggleRecord() override { - if (!m_capture.isOpened()) { - return false; - } - m_recording = vCoder->toggle(m_w, m_h, m_fps); - - return m_recording; - } - virtual double fps() const override { - return m_fps; - } - virtual std::string currentFilename() const override { - return "Camera"; // TODO be more specific! - } - - private: - - virtual bool nextFrame_impl() override { - cv::Mat new_frame; - - for (int i = 0; i < m_frame_stride; i++) { - m_capture >> new_frame; - } - - std::shared_ptr mat(new cv::Mat(new_frame)); - this->set_current_frame(mat); - if (m_recording) { - if (vCoder) vCoder->add(mat); - } - return !mat->empty(); - } - - virtual bool setFrameNumber_impl(size_t) override { - // throw std::runtime_error("setFrameNumber not available for ImageStreamCamera"); - this->nextFrame_impl(); - return true; - } - - std::shared_ptr vCoder; - cv::VideoCapture m_capture; - double m_fps; - double m_w; - double m_h; - bool m_recording; - }; - - /*********************************************************/ - - - std::shared_ptr make_ImageStream3NoMedia() { - return std::make_shared(); - } - - std::shared_ptr make_ImageStream3Pictures( - std::vector filenames) { - return std::make_shared(std::move(filenames)); - } - - std::shared_ptr make_ImageStream3Video(const std::vector &files) { - try { - return std::make_shared(files); - } - catch (const video_open_error &) { - return make_ImageStream3NoMedia(); - } - } - - std::shared_ptr make_ImageStream3Camera(CameraConfiguration conf) { - try { - return std::make_shared(conf); - } - catch (const device_open_error &) { - return make_ImageStream3NoMedia(); - } - } - - } -} diff --git a/BioTracker/CoreApp/BioTracker/Model/ImageStream.h b/BioTracker/CoreApp/BioTracker/Model/ImageStream.h deleted file mode 100644 index 1d40cea0..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/ImageStream.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** Origin of this class is BioTracker in version 2. - ** - ****************************************************************************/ - -#ifndef BIOTRACKER3IMAGESTREAM_H -#define BIOTRACKER3IMAGESTREAM_H - -#include // std::unique_ptr -#include // cv::Mat -#include // std::vector -#include // std::string -#include -#include -#include "QSharedPointer" - -#include "settings/ParamNames.h" // GUIPARAM::MediaType -#include "util/types.h" - -namespace BioTracker { -namespace Core { - -/** - * The ImageStream class was part of BioTracker version 2. It is responsible for generation ImageStreams from files or camera devices. - */ -class ImageStream : public QObject { - Q_OBJECT - public: - explicit ImageStream(QObject* parent = 0); - - /** - * @return the stream's MediaType i.e. "Video", "Images", "NoMedia" - */ - virtual GuiParam::MediaType type() const = 0; - - /** - * @return the total number of frames - */ - virtual size_t numFrames() const = 0; - - virtual bool toggleRecord() = 0; - - /** - * @return the current frame number - */ - size_t currentFrameNumber() const; - - /** - * @return true, if the current frame is the last frame - */ - bool lastFrame() const; - - /** - * @return true, if the stream's end is reached; i.e. current frame points behind it's last frame - */ - bool end() const; - - /** - * @return true, if currentFrame().empty(); - */ - bool currentFrameIsEmpty() const; - - /** - * @return the media's fps rate - */ - virtual double fps() const = 0; - - /** - * @return the filename of the current file defined through the frameNumber - */ - virtual std::string currentFilename() const = 0; - - /** - * returns the current frame. - * - if the current frame position is invalid or an error occurred, an empty image is returned. - */ - std::shared_ptr currentFrame() const; - - /** - * sets the current frame number and updates the current frame. - * - if frame_number is invalid, the current frame is invalidated. - * @return true if the operation was successful, i.e. the frame number is valid and no error occurred. - */ - bool setFrameNumber(size_t frame_number); - - /** - * advances the current frame frame. - * - if this function is called on the media's last frame, the current frame is invalidated. - * @return true if the operation was successful, i.e. the current frame isn't the last frame and no error occurred. - */ - bool nextFrame(); - - /** - * sets the current frame position to the previous frame. - * - if this function is called on the media's first frame, the current frame is invalidated. - * @return true if the operation was successful, i.e. the current frame isn't the first one and no error occurred. - */ - bool previousFrame(); - - /** - * Gets the title of the current image stream. - * A title should represent the identity of a source stream as a string. - * E.g. a video "MyTracking.mkv" should yield a name like "MyTracking". - * Streams from Camera No. 1 should yiel "Camera_1" or the like. - * Naming conventions are up to the stream implementations. - */ - std::string getTitle(); - - virtual ~ImageStream(); - - protected: - /** - * sets the image returned by this->currentFrame(); - */ - void set_current_frame(std::shared_ptr img); - - /** - * Sets the title of the current image stream. - * A title should represent the identity of a source stream as a string. - * E.g. a video "MyTracking.mkv" should yield a name like "MyTracking". - * Streams from Camera No. 1 should yiel "Camera_1" or the like. - * Naming conventions are up to the stream implementations. - * The title is set by the stream itself and may not be modified from the outside. - */ - void setTitle(std::string title); - - /** - * The stride of the image stream. Think of it as "use only every n'th frame". - */ - const size_t m_frame_stride; - - private: - /** - * empties m_current_frame & sets m_current_frame_number to this->numFrames(); - */ - void clearImage(); - /** - * - called by ImageStreamImpl::setFrameNumber - * if frame_number < numFrames() && frame_number != this->currentFrameNumber(); - * - m_current_frame_number is updated afterwards - */ - virtual bool setFrameNumber_impl(size_t frame_number) = 0; - /** - * - called by ImageStreamImpl::nextFrame() - * if currentFrameNumber() + 1 < numFrames(); - * - m_current_frame_number is updated afterwards - */ - virtual bool nextFrame_impl(); - /** - * - called by ImageStreamImpl::previousFrame() - * if currentFrameNumber() > 0; - * - m_current_frame_number is updated afterwards - */ - virtual bool previousFrame_impl(); - - std::shared_ptr m_current_frame; - size_t m_current_frame_number; - std::string m_title; -}; - -std::shared_ptr make_ImageStream3NoMedia(); - -std::shared_ptr make_ImageStream3Pictures( - std::vector filenames); - -std::shared_ptr make_ImageStream3Video(const std::vector - &filename); - -std::shared_ptr make_ImageStream3Camera(CameraConfiguration conf); - -} -} - -#endif // BIOTRACKER3IMAGESTREAM_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayer.cpp b/BioTracker/CoreApp/BioTracker/Model/MediaPlayer.cpp deleted file mode 100644 index 6985a67e..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayer.cpp +++ /dev/null @@ -1,336 +0,0 @@ -#include "MediaPlayer.h" -#include "util/misc.h" - - -//Settings related -#include "util/types.h" -#include "util/singleton.h" -#include "settings/Settings.h" - -MediaPlayer::MediaPlayer(QObject* parent) : - IModel(parent) { - m_trackingDone = true; - m_currentFPS = 0; - m_fpsOfSourceFile = 0; - _imagew = 0; - _imageh = 0; - m_useCuda = false; - m_RecI = false; - m_RecO = false; - m_videoc = std::make_shared(); - m_NameOfCvMat = "Original"; - - m_TrackingIsActive = false; - m_recd = false; - m_recordScaled = false; - // Initialize PlayerStateMachine and a Thread for the Player - // // Do not set a Parent for MediaPlayerStateMachine in order to run the Player in the QThread! - - m_PlayerThread = new QThread(this); - m_Player = new MediaPlayerStateMachine(); - - // Connect MediaPlayer with PlayerStateMachine - - // Load ImageStreams in StateMachine - QObject::connect(this, &MediaPlayer::loadVideoStream, m_Player, &MediaPlayerStateMachine::receiveLoadVideoCommand); - QObject::connect(this, &MediaPlayer::loadCameraDevice, m_Player, &MediaPlayerStateMachine::receiveLoadCameraDevice); - QObject::connect(this, &MediaPlayer::loadPictures, m_Player, &MediaPlayerStateMachine::receiveLoadPictures); - - // Controll the Player - QObject::connect(this, &MediaPlayer::nextFrameCommand, m_Player, &MediaPlayerStateMachine::receiveNextFramCommand); - QObject::connect(this, &MediaPlayer::pauseCommand, m_Player, &MediaPlayerStateMachine::receivePauseCommand); - QObject::connect(this, &MediaPlayer::playCommand, m_Player, &MediaPlayerStateMachine::receivePlayCommand); - QObject::connect(this, &MediaPlayer::prevFrameCommand, m_Player, &MediaPlayerStateMachine::receivePrevFrameCommand); - QObject::connect(this, &MediaPlayer::stopCommand, m_Player, &MediaPlayerStateMachine::receiveStopCommand); - QObject::connect(this, &MediaPlayer::goToFrame, m_Player, &MediaPlayerStateMachine::receiveGoToFrame); - - QObject::connect(this, &MediaPlayer::pauseCommand, this, &MediaPlayer::receiveTrackingPaused); - QObject::connect(this, &MediaPlayer::stopCommand, this, &MediaPlayer::receiveTrackingPaused); - - QObject::connect(this, &MediaPlayer::toggleRecordImageStreamCommand, m_Player, &MediaPlayerStateMachine::receivetoggleRecordImageStream); - - // Handel PlayerStateMachine results - QObject::connect(m_Player, &MediaPlayerStateMachine::emitPlayerParameters, this, &MediaPlayer::receivePlayerParameters, Qt::BlockingQueuedConnection); - QObject::connect(m_Player, &MediaPlayerStateMachine::emitPlayerParameters, this, &MediaPlayer::fwdPlayerParameters); - - // Handle next state operation - QObject::connect(m_Player, &MediaPlayerStateMachine::emitPlayerOperationDone, this, &MediaPlayer::receivePlayerOperationDone); - QObject::connect(this, &MediaPlayer::runPlayerOperation, m_Player, &MediaPlayerStateMachine::receiveRunPlayerOperation); - - // Move the PlayerStateMachine to the Thread - m_Player->moveToThread(m_PlayerThread); - - // Start the Thread - m_PlayerThread->start(); -} - -MediaPlayer::~MediaPlayer() { - stopCommand(); - m_PlayerThread->quit(); - if (!m_PlayerThread->wait(2000)) - { - m_PlayerThread->terminate(); - m_PlayerThread->wait(); - } -} - -void MediaPlayer::setTrackingActive() { - m_TrackingIsActive = true; -} - -void MediaPlayer::setTrackingDeactive() { - m_TrackingIsActive = false; -} - -bool MediaPlayer::getPlayState() { - return m_Play; -} - -bool MediaPlayer::getForwardState() { - return m_Forw; -} - -bool MediaPlayer::getBackwardState() { - return m_Back; -} - -bool MediaPlayer::getStopState() { - return m_Stop; -} - -bool MediaPlayer::getPauseState() { - return m_Paus; -} - -bool MediaPlayer::getRecIState() { - return m_RecI; -} - -bool MediaPlayer::getRecOState() { - return m_RecO; -} - -bool MediaPlayer::getTrackingState() { - return m_TrackingIsActive; -} - -size_t MediaPlayer::getTotalNumberOfFrames() { - return m_TotalNumbFrames; -} - -size_t MediaPlayer::getCurrentFrameNumber() { - return m_CurrentFrameNumber; -} - -double MediaPlayer::getFpsOfSourceFile() { - return m_fpsOfSourceFile; -} - -double MediaPlayer::getCurrentFPS() { - return m_currentFPS; -} - -double MediaPlayer::getTargetFPS() { - return m_targetFPS; -} -void MediaPlayer::setTargetFPS(double fps) { - m_targetFPS = fps; - m_Player->receiveTargetFps(fps); -} - -QString MediaPlayer::getCurrentFileName() { - return m_CurrentFilename; -} - -std::shared_ptr MediaPlayer::getCurrentFrame() { - return m_CurrentFrame; -} - -int MediaPlayer::reopenVideoWriter() { - QRectF r = m_gv->sceneRect(); - - if (_imagew != r.width() || _imageh != r.height() || !m_recd) { - - if (m_useCuda) { -#ifdef WITH_CUDA - - _imagew = r.width(); - _imageh = r.height(); - m_videoc = std::make_shared(); - EncodeConfig *cfg = m_videoc->m_nvEncoder->getEncodeConfig(); - cfg->width = _imagew; - cfg->height = _imageh; - cfg->fps = 30; - cfg->codec = NV_ENC_H264; - cfg->inputFormat = NV_ENC_BUFFER_FORMAT_NV12;//NV_ENC_BUFFER_FORMAT_YUV444 //NV_ENC_BUFFER_FORMAT_NV12 - const std::string f = getTimeAndDate("ViewCapture", ".avi"); - char* chr = strdup(f.c_str()); - m_videoc->start(); - free(chr); - m_recd = true; -#else - std::cout << "Error on recording: Asked to use cudacodec although build is not cuda-enabled. Not recording." << std::endl; -#endif - - } - else { - if (m_videoWriter && m_videoWriter->isOpened()) - m_videoWriter->release(); - _imagew = r.width(); - _imageh = r.height(); - - int codec = CV_FOURCC('X', '2', '6', '4'); - m_videoWriter = std::make_shared(getTimeAndDate("./ViewCapture", ".avi"), codec, 30, CvSize(r.width(), r.height()), 1); - m_recd = m_videoWriter->isOpened(); - } - } - return m_recd; -} - -QString MediaPlayer::takeScreenshot(GraphicsView *gv) { - //TODO duplicated code - QRectF rscene = gv->sceneRect(); //0us - QRectF rview = gv->rect(); //0us - QPixmap *pix; - if (!m_recordScaled) - pix = new QPixmap(rscene.size().toSize()); //17us - else - pix = new QPixmap(rview.size().toSize()); //17us - - QPainter *paint = new QPainter(pix); //21us - - if (!m_recordScaled) - gv->scene()->render(paint); //8544us - else - gv->render(paint); - - QImage image = pix->toImage(); //8724us - - QString filePath = getTimeAndDate(CFG_DIR_SCREENSHOTS+std::string("/Screenshot"), ".png").c_str(); - - image.save(filePath); - - return filePath; -} - -void MediaPlayer::receiveTrackingPaused() { - m_trackingDone = true; -} - -void MediaPlayer::receivePlayerParameters(playerParameters* param) { - - m_Back = param->m_Back; - m_Paus = param->m_Paus; - m_Play = param->m_Play; - m_Stop = param->m_Stop; - m_Forw = param->m_Forw; - m_RecI = param->m_RecI; - m_RecO = param->m_RecO; - - m_CurrentFilename = param->m_CurrentFilename; - m_CurrentFrame = param->m_CurrentFrame; - m_CurrentFrameNumber = param->m_CurrentFrameNumber; - m_fpsOfSourceFile = param->m_fpsSourceVideo; - m_TotalNumbFrames = param->m_TotalNumbFrames; - - m_CurrentFrame = param->m_CurrentFrame; - - Q_EMIT renderCurrentImage(m_CurrentFrame, m_NameOfCvMat); - - if (m_TrackingIsActive) { - m_trackingDone = false; - Q_EMIT trackCurrentImage(m_CurrentFrame, m_CurrentFrameNumber); - } - else { - Q_EMIT signalVisualizeCurrentModel(m_CurrentFrameNumber); - Q_EMIT signalCurrentFrameNumberToPlugin(m_CurrentFrameNumber); - } - - if (m_recd) { - //reopenVideoWriter(); //4us - QRectF rscene = m_gv->sceneRect(); //0us - QRectF rview = m_gv->rect(); //0us - QPixmap *pix; - if (!m_recordScaled) - pix = new QPixmap(rscene.size().toSize()); //17us - else - pix = new QPixmap(rview.size().toSize()); //17us - - QPainter *paint = new QPainter(pix); //21us - - if(!m_recordScaled) - m_gv->scene()->render(paint); //8544us - else - m_gv->render(paint);// , m_gv->scene()->sceneRect(), QRect());// , Qt::AspectRatioMode::IgnoreAspectRatio); - - QImage image = pix->toImage(); //8724us - int x = image.format(); //0us - std::shared_ptr mat = std::make_shared(image.height(), image.width(), CV_8UC(image.depth()/8), (uchar*)image.bits(), image.bytesPerLine()); //1us - - cv::cvtColor(*mat, *mat, CV_BGR2RGB); //16898 us - cv::cvtColor(*mat, *mat, CV_BGR2RGB); - m_videoc->add(mat,1); - - } - - Q_EMIT notifyView(); -} - - -void MediaPlayer::rcvPauseState(bool state) { - _paused = state; - - if (!state) { - m_currentFPS = 0; - } -} - -void MediaPlayer::receivePlayerOperationDone() { - // Only emit this SIGNAL when tracking is not active - end = std::chrono::system_clock::now(); - long s = std::chrono::duration_cast(end - start).count(); - if (!_paused) { - m_currentFPS = floor(1.0 / (double(s) / 1000.0)); - } - else { - m_currentFPS = 0; - } - - if(m_trackingDone == true || !m_TrackingIsActive) - Q_EMIT runPlayerOperation(); - - - start = std::chrono::system_clock::now(); -} - -void MediaPlayer::receiveTrackingOperationDone() { - // Only emit this SIGNAL when tracking is active - if (m_TrackingIsActive) { - m_trackingDone = true; - } -} - -void MediaPlayer::receiveChangeDisplayImage(QString str) { - int x = 0; -} - -int MediaPlayer::toggleRecordImageStream() { - Q_EMIT toggleRecordImageStreamCommand(); - return 0; -} - -int MediaPlayer::toggleRecordGraphicsScenes(GraphicsView *gv) { - - m_gv = gv; - QRectF rscene = m_gv->sceneRect(); //0us - QRectF rview = m_gv->rect(); //0us - QSize s1 = rscene.size().toSize(); //0us - QSize s2 = rview.size().toSize(); //0us - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - m_recordScaled = set->getValueOrDefault(CFG_RECORDSCALEDOUT, false); - if (!m_recordScaled) - m_recd = m_videoc->toggle(s1.width(), s1.height(), 30); - else - m_recd = m_videoc->toggle(s2.width(), s2.height(), 30); - return m_recd; -} diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayer.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayer.h deleted file mode 100644 index f95803a0..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayer.h +++ /dev/null @@ -1,213 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - - -#ifndef MEDIAPLAYER_H -#define MEDIAPLAYER_H - -#include "Interfaces/IModel/IModel.h" -#include "QThread" -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -#include "View/GraphicsView.h" - -#include -#include -#include "util/types.h" -#include "util/VideoCoder.h" - -/** - * The MediaPlayer class is an IModel class an part of the MediaPlayer component. This class creats a MediaPlayerStateMachine object and moves it to a QThread. - * The MediaPlayer class controlls and represents the results of the MediaPlayerStateMachine. The communication between a MediaPlayer object and a MediaPlayerStateMachine object is done by - * Qts SIGNALS and SLOTS. This is due to the fact that SIGNALS and SLTOS are thread safe. A disadvantage is that SIGNALS and SLOTS are slower then normal function calls. - * - * The constructor of this class is responsible for connecting to the MediaPlayerStateMachine. - */ -class MediaPlayer : public IModel { - Q_OBJECT - public: - MediaPlayer(QObject* parent = 0); - ~MediaPlayer(); - - Q_SIGNALS: - /** - * Emit the path to a video stream. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void loadVideoStream(std::vector files); - /** - * Emit the path to pictures. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void loadPictures(std::vector files); - /** - * Emit the camera device number. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void loadCameraDevice(CameraConfiguration conf); - - /** - * Emit a frame number. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void goToFrame(int frame); - /** - * Emit the next frame command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void nextFrameCommand(); - /** - * Emit previous frame command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void prevFrameCommand(); - /** - * Emit the play command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void playCommand(); - /** - * Emit stop command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void stopCommand(); - /** - * Emit the pause command. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void pauseCommand(); - - /** - * This SIGNAL will be emmited if a state operation should be executed. This signal will be received by the MediaPlayerStateMachine which runns in a separate Thread. - */ - void runPlayerOperation(); - - /** - * This SIGNAL will send a cv::Mat and a name to the MediaPlayer controller class. This controller will give the data to the TextureObject component. - */ - void renderCurrentImage(std::shared_ptr mat, QString name); - /** - * This SIGNAL is only emmited if Tracking Is Active. The PluginLoader component will receive the cv::Mat and the current frame number. - */ - void trackCurrentImage(std::shared_ptr mat, uint number); - /** - * This SIGNAL is only emmited if Tracking Is inactive. The core visualization controller will receive the framenumber and will try to visualize the tracking model. - */ - void signalVisualizeCurrentModel(uint frameNumber); - - void signalCurrentFrameNumberToPlugin(uint frameNumber); - - void toggleRecordImageStreamCommand(); - - void fwdPlayerParameters(playerParameters* parameters); - - void emitNextMediaInBatch(); - - public: - void setTrackingActive(); - void setTrackingDeactive(); - void setTargetFPS(double fps); - - bool getPlayState(); - bool getForwardState(); - bool getBackwardState(); - bool getStopState(); - bool getPauseState(); - bool getRecIState(); - bool getRecOState(); - - bool getTrackingState(); - - int toggleRecordGraphicsScenes(GraphicsView * gv); - int toggleRecordImageStream(); - - size_t getTotalNumberOfFrames(); - size_t getCurrentFrameNumber(); - double getFpsOfSourceFile(); - double getCurrentFPS(); - double getTargetFPS(); - QString getCurrentFileName(); - std::shared_ptr getCurrentFrame(); - - QString takeScreenshot(GraphicsView *gv); - - public Q_SLOTS: - /** - * MediaPlayer will receive the current playerParameters from the MediaPlayerStateMachine. - */ - void receivePlayerParameters(playerParameters* param); - - /** - * If the MediaPlayerStateMachine is finished with executing the current state it will trigger this SLOT. - */ - void receivePlayerOperationDone(); - - /** - * If a BioTracker Plugin is done with executing its tracking algorithm this SLOT will be triggerd. As soon as this SLOT is triggered, the MediaPlayerStateMachine will be - * advised to execute the next state. - */ - void receiveTrackingOperationDone(); - - /** - * - */ - void receiveTrackingPaused(); - - /** - * Catches the pause state from the controller. - * This will automatically wrap all cases of "stop" semantics. - * We do this although the info is basically passed implicitly via other commands, because it's easier - */ - void rcvPauseState(bool state); - - void receiveChangeDisplayImage(QString str); - - - private: - //TODO Refactor members to _ instead of m_ - - /** - * helper function which opens a video. If video size has changed, a new video is opened. - */ - int reopenVideoWriter(); - int _imagew; - int _imageh; - - QPointer< QThread > m_PlayerThread; - QPointer< MediaPlayerStateMachine > m_Player; - - //IPlayerState* m_CurrentPlayerState; - //IPlayerState* m_NextPlayerState; - - QMap m_States; - - size_t m_TotalNumbFrames; - size_t m_CurrentFrameNumber; - double m_fpsOfSourceFile; - double m_currentFPS; - double m_targetFPS; - QString m_CurrentFilename; - std::shared_ptr m_CurrentFrame; - - bool m_Play; - bool m_Forw; - bool m_Back; - bool m_Stop; - bool m_Paus; - bool m_RecI; - bool m_RecO; - - - bool m_recd; - bool m_recordScaled; - bool m_trackingDone; - bool _paused = true; - - bool m_useCuda; - GraphicsView *m_gv; - std::shared_ptr m_videoWriter; - std::shared_ptr m_videoc; - - bool m_TrackingIsActive; - QString m_NameOfCvMat = "Original"; - - - std::chrono::system_clock::time_point start; - std::chrono::system_clock::time_point end; -}; - -#endif // MEDIAPLAYER_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp deleted file mode 100644 index c9442785..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "MediaPlayerStateMachine.h" - -#include "PlayerStates/PStatePlay.h" -#include "PlayerStates/PStateInitialStream.h" -#include "PlayerStates/PStateStepForw.h" -#include "PlayerStates/PStateInitial.h" -#include "PlayerStates/PStatePause.h" -#include "PlayerStates/PStateStepBack.h" -#include "PlayerStates/PStateWait.h" -#include "PlayerStates/PStateGoToFrame.h" - -#include "util/types.h" - -MediaPlayerStateMachine::MediaPlayerStateMachine(QObject* parent) : - IModel(parent), - m_ImageStream(BioTracker::Core::make_ImageStream3NoMedia()) { - - m_PlayerParameters = new playerParameters(); - - m_States.insert(IPlayerState::PLAYER_STATES::STATE_INITIAL, (new PStateInitial(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_INITIAL_STREAM, (new PStateInitialStream(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_STEP_FORW, (new PStateStepForw(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_PLAY, (new PStatePlay(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_PAUSE, (new PStatePause(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_STEP_BACK, (new PStateStepBack(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_WAIT, (new PStateWait(this, m_ImageStream))); - m_States.insert(IPlayerState::PLAYER_STATES::STATE_GOTOFRAME, (new PStateGoToFrame(this, m_ImageStream))); - - setNextState(IPlayerState::PLAYER_STATES::STATE_INITIAL); -} - -int x = 0; -void MediaPlayerStateMachine::receiveRunPlayerOperation() { - - if (m_NextPlayerState != m_States.value(IPlayerState::PLAYER_STATES::STATE_WAIT)) { - - m_CurrentPlayerState = m_NextPlayerState; - - x++; - if (x % 100 == 0) { - emitNextMediaInBatch(); - } - - m_CurrentPlayerState->operate(); - updatePlayerParameter(); - emitSignals(); - } - -} - -void MediaPlayerStateMachine::receiveLoadVideoCommand(std::vector files) { - - m_stream = BioTracker::Core::make_ImageStream3Video(files); - - m_PlayerParameters->m_TotalNumbFrames = m_stream->numFrames(); - - QMap::iterator i; - for (i = m_States.begin(); i != m_States.end(); i++) { - i.value()->changeImageStream(m_stream); - } - - setNextState(IPlayerState::STATE_INITIAL_STREAM); - -} - -void MediaPlayerStateMachine::receiveLoadPictures(std::vector files) { - m_stream = BioTracker::Core::make_ImageStream3Pictures(files); - - m_PlayerParameters->m_TotalNumbFrames = m_stream->numFrames(); - - QMap::iterator i; - for (i = m_States.begin(); i != m_States.end(); i++) { - i.value()->changeImageStream(m_stream); - } - - setNextState(IPlayerState::STATE_INITIAL_STREAM); - -} - -void MediaPlayerStateMachine::receiveLoadCameraDevice(CameraConfiguration conf) { - m_stream = BioTracker::Core::make_ImageStream3Camera(conf); - - m_PlayerParameters->m_TotalNumbFrames = m_stream->numFrames(); - - QMap::iterator i; - for (i = m_States.begin(); i != m_States.end(); i++) { - i.value()->changeImageStream(m_stream); - } - - setNextState(IPlayerState::STATE_INITIAL_STREAM); -} - -void MediaPlayerStateMachine::receivePrevFrameCommand() { - setNextState(IPlayerState::STATE_STEP_BACK); -} - -void MediaPlayerStateMachine::receiveNextFramCommand() { - setNextState(IPlayerState::STATE_STEP_FORW); -} - -void MediaPlayerStateMachine::receivePauseCommand() { - setNextState(IPlayerState::STATE_PAUSE); -} - -void MediaPlayerStateMachine::receiveStopCommand() { - setNextState(IPlayerState::STATE_INITIAL_STREAM); -} - -void MediaPlayerStateMachine::receivePlayCommand() { - setNextState(IPlayerState::STATE_PLAY); -} - -void MediaPlayerStateMachine::receiveGoToFrame(int frame) { - PStateGoToFrame* state = dynamic_cast (m_States.value(IPlayerState::PLAYER_STATES::STATE_GOTOFRAME)); - state->setFrameNumber(frame); - setNextState(IPlayerState::STATE_GOTOFRAME); -} - -void MediaPlayerStateMachine::receiveTargetFps(double fps) { - m_PlayerParameters->m_fpsTarget = fps; - static_cast(m_States.value(IPlayerState::STATE_PLAY))->setFps(fps); -} - -void MediaPlayerStateMachine::receivetoggleRecordImageStream() { - if (m_stream) - m_PlayerParameters->m_RecI = m_stream->toggleRecord(); - else - m_PlayerParameters->m_RecI = false; - emitSignals(); - return; -} - -void MediaPlayerStateMachine::updatePlayerParameter() { - - stateParameters stateParam = m_CurrentPlayerState->getStateParameters(); - - m_PlayerParameters->m_Back = stateParam.m_Back; - m_PlayerParameters->m_Forw = stateParam.m_Forw; - m_PlayerParameters->m_Paus = stateParam.m_Paus; - m_PlayerParameters->m_Play = stateParam.m_Play; - m_PlayerParameters->m_Stop = stateParam.m_Stop; - - m_PlayerParameters->m_CurrentFilename = m_CurrentPlayerState->getCurrentFileName(); - - m_PlayerParameters->m_CurrentFrame = m_CurrentPlayerState->getCurrentFrame(); - m_PlayerParameters->m_CurrentFrameNumber = m_CurrentPlayerState->getCurrentFrameNumber(); - m_PlayerParameters->m_fpsSourceVideo = m_CurrentPlayerState->m_ImageStream->fps(); -} - -void MediaPlayerStateMachine::emitSignals() { - - Q_EMIT emitPlayerParameters(m_PlayerParameters); -} - -void MediaPlayerStateMachine::setNextState(IPlayerState::PLAYER_STATES state) { - m_NextPlayerState = m_States.value(state); - - Q_EMIT emitPlayerOperationDone(); - -} - - diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerParameters.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerParameters.h deleted file mode 100644 index 3904819c..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerParameters.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PLAYERPARAMETERS_H -#define PLAYERPARAMETERS_H - -/** - * The playerParameters struct holds all data types of the current MediaPlayer state. - */ -struct playerParameters { - - // PlayerStates - bool m_Play; - bool m_Forw; - bool m_Back; - bool m_Stop; - bool m_Paus; - bool m_RecI; - bool m_RecO; - - // The other information - size_t m_TotalNumbFrames; - QString m_CurrentFilename; - std::string m_CurrentTitle; - size_t m_CurrentFrameNumber; - std::shared_ptr m_CurrentFrame; - double m_fpsSourceVideo; - double m_fpsTarget; -}; - -#endif // PLAYERPARAMETERS_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h deleted file mode 100644 index 5237479e..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - - -#ifndef PSTATEGOTOFRAME_H -#define PSTATEGOTOFRAME_H - -#include "IStates/IPlayerState.h" - -/** - * This State is responsible for jumping to a spezific frame number in the ImageStream. The following state will be STATE_WAIT - */ -class PStateGoToFrame : public IPlayerState { - public: - PStateGoToFrame(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; - - public: - /** - * This function sets the next frame number. - */ - void setFrameNumber(int frame); - - private: - int m_GoToFrameNumber; -}; - -#endif // PSTATEGOTOFRAME_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h deleted file mode 100644 index 03340ccb..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h +++ /dev/null @@ -1,25 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PSTATEINITIAL_H -#define PSTATEINITIAL_H - -#include "IStates/IPlayerState.h" - -/** - * This State is the first state when running BioTracker. It sets all parameters to false and sets as next state STATE_WAIT - */ -class PStateInitial : public IPlayerState { - public: - PStateInitial(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; -}; - -#endif // PSTATEINITIAL_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h deleted file mode 100644 index 1b6e1249..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h +++ /dev/null @@ -1,25 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PSTATEINITIALSTREAM_H -#define PSTATEINITIALSTREAM_H - -#include "IStates/IPlayerState.h" - -/** - * This State is active when a video or camera device was selected by the user. It sets as following state STATE_WAIT. - */ -class PStateInitialStream : public IPlayerState { - public: - PStateInitialStream(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; -}; - -#endif // INITIALVIDEOSTATE_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h deleted file mode 100644 index f2d3a06d..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PSTATEPAUSE_H -#define PSTATEPAUSE_H - -#include "IStates/IPlayerState.h" - -/** - * This state is active when the user clicks on the Pause button in the GUI. The next state will be STATE_WAIT. - */ -class PStatePause : public IPlayerState { - public: - PStatePause(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; - -}; - -#endif // PSTATEPAUSE_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp deleted file mode 100644 index 269721cf..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "PStatePlay.h" -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -#include "QTimer" - -#include -using namespace std::chrono; - -PStatePlay::PStatePlay(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { - - m_StateParameters.m_Back = false; - m_StateParameters.m_Forw = false; - m_StateParameters.m_Paus = false; - m_StateParameters.m_Play = false; - m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; - - m_FrameNumber = 0; - - -} - -void PStatePlay::operate() { - - m_StateParameters.m_Play = true; - m_StateParameters.m_Forw = false; - m_StateParameters.m_Back = false; - m_StateParameters.m_Stop = true; - m_StateParameters.m_Paus = true; - - - bool isLastFrame = m_ImageStream->lastFrame(); - IPlayerState::PLAYER_STATES nextState = IPlayerState::STATE_INITIAL; - - if (!isLastFrame) { - m_ImageStream->nextFrame(); - m_Mat = m_ImageStream->currentFrame(); - m_FrameNumber = m_ImageStream->currentFrameNumber(); - nextState = IPlayerState::STATE_PLAY; - } else { - nextState = IPlayerState::STATE_INITIAL_STREAM; - } - - //If fps is limited, wait the neccessary time - end = std::chrono::system_clock::now(); - if (_targetFps > 0) { - long long dt = std::chrono::duration_cast(end - start).count(); - long long targetFps = (1. / _targetFps) * 1000.; - - if (dt < targetFps) { - std::this_thread::sleep_for(std::chrono::milliseconds(targetFps - dt)); - } - } - start = std::chrono::system_clock::now(); - - - m_Player->setNextState(nextState); - -} diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h deleted file mode 100644 index 056959b9..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PSTATEPLAY_H -#define PSTATEPLAY_H - -#include "IStates/IPlayerState.h" -#include - -/** - * This Stat is active when a video fiel is playing or a camera device is streaming. If the current frame is the last in the ImageStream this state will set STATE_INITIAL as next state. - * If the current frame is not the last frame in the ImageStream, the next state will be STATE_PLAY. - */ -class PStatePlay : public IPlayerState { - public: - PStatePlay(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - void setFps(double fps) { - _targetFps = fps; - } - - // IPlayerState interface - public Q_SLOTS: - void operate() override; - -private: - std::chrono::system_clock::time_point end, start; - double _targetFps = 0; -}; - -#endif // PSTATEPLAY_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h deleted file mode 100644 index 5a805aed..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h +++ /dev/null @@ -1,25 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PSTATESTEPBACK_H -#define PSTATESTEPBACK_H - -#include "IStates/IPlayerState.h" - -/** - * This state will active if the user clicks on the Back button in the GUI. The following state will be STATE_WAIT. - */ -class PStateStepBack : public IPlayerState { - public: - PStateStepBack(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; -}; - -#endif // PSTATESTEPBACK_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h deleted file mode 100644 index 44b67703..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h +++ /dev/null @@ -1,25 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PSTATESTEPFORW_H -#define PSTATESTEPFORW_H - -#include "IStates/IPlayerState.h" - -/** - * This State is active if the user clicks the Forward button in the GUI. The next state will be STATE_WAIT. - */ -class PStateStepForw : public IPlayerState { - public: - PStateStepForw(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; -}; - -#endif // PSTATESTEPFORW_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h b/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h deleted file mode 100644 index 65927b72..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - - -#ifndef PSTATEWAIT_H -#define PSTATEWAIT_H - -#include "IStates/IPlayerState.h" - -/** - * This state dose nothing. There is also no next state set by this state. - */ -class PStateWait : public IPlayerState { - public: - PStateWait(MediaPlayerStateMachine* player, std::shared_ptr imageStream); - - // IPlayerState interface - public Q_SLOTS: - void operate() override; -}; - -#endif // PSTATEWAIT_H diff --git a/BioTracker/CoreApp/BioTracker/Model/PluginLoader.cpp b/BioTracker/CoreApp/BioTracker/Model/PluginLoader.cpp deleted file mode 100644 index 9d5fa933..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/PluginLoader.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "PluginLoader.h" -#include "QDebug" -#include - -PluginLoader::PluginLoader(QObject* parent) : - IModel(parent) { - - m_isPluginLoaded = false; - m_currentPluginName = ""; - m_PluginLoader = new QPluginLoader(this); - - m_PluginListModel = new QStringListModel(); - m_PluginListModel->setStringList(m_PluginList); -} - -void PluginLoader::addToPluginList(QString filename) { - - bool isLib = QLibrary::isLibrary(filename); - - if (isLib) { - - QPluginLoader loader; - loader.setFileName(filename); - QJsonValue pluginMeda(loader.metaData().value("MetaData")); - QJsonObject metaObj = pluginMeda.toObject(); - QString mstring = metaObj.value("name").toString(); - if (!m_PluginList.contains(mstring)) - m_PluginList.append(mstring); - m_PluginListModel->setStringList(m_PluginList); - m_PluginMap.insert(std::pair(mstring, filename)); - } - else { - std::cout << "Error reading plugin: " << filename.toStdString() << std::endl; - } -} - -bool PluginLoader::loadPluginFromFilename(QString filename) { - bool retval = false; - - if (m_PluginLoader->isLoaded()) { - m_PluginLoader->unload(); - } - - bool isLib = QLibrary::isLibrary(filename); - - if (isLib) { - - m_PluginLoader->setFileName(filename); - QString name = readMetaDataFromPlugin(); - m_currentPluginName = name; - m_PluginMap.insert(std::pair(name, filename)); - retval = true; - } - else { - retval = false; - } - - qDebug() << "CORE: Plugin loaded: " << m_PluginLoader->fileName(); - - m_isPluginLoaded = retval; - - return retval; -} - -bool PluginLoader::loadPluginFromName(QString name) { - QString filename = m_PluginMap.find(name)->second; - return loadPluginFromFilename(filename); -} - -IBioTrackerPlugin* PluginLoader::getPluginInstance() { - return qobject_cast(m_PluginLoader->instance()); -} - -QStringListModel* PluginLoader::getPluginMetaData() { - return m_PluginListModel; -} - -bool PluginLoader::getIsPluginLoaded() { - return m_isPluginLoaded; -} - -QString PluginLoader::getCurrentPluginName() { - return m_currentPluginName; -} - -const std::map &PluginLoader::getPluginMap() const -{ - return m_PluginMap; -} - -QString PluginLoader::readMetaDataFromPlugin() { - QJsonValue pluginMeda(m_PluginLoader->metaData().value("MetaData")); - QJsonObject metaObj = pluginMeda.toObject(); - QString mstring = metaObj.value("name").toString(); - - if (!m_PluginList.contains(mstring)) - m_PluginList.append(mstring); - m_PluginListModel->setStringList(m_PluginList); - return mstring; -} - diff --git a/BioTracker/CoreApp/BioTracker/Model/PluginLoader.h b/BioTracker/CoreApp/BioTracker/Model/PluginLoader.h deleted file mode 100644 index f7e91037..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/PluginLoader.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - -#ifndef PLUGINLOADER_H -#define PLUGINLOADER_H - -#include "Interfaces/IModel/IModel.h" -#include "QPluginLoader" -#include "QStringListModel" -#include "Interfaces/IBioTrackerPlugin.h" -#include "QPointer" - -/** - * The PluginLoader class is a IModel class. It is responsible for managing BioTracker Plugins. - * It can load them and it sends a list of all loaded Plugin names to the a selection box in the MainWindow. - */ -class PluginLoader : public IModel { - Q_OBJECT - public: - explicit PluginLoader(QObject* parent = 0); - - /** - * Loads a file as a QT plugin and reads it's name from the metadata. - * It will then be added to the stringlist and is selectable via "loadPluginFromName". - * This function does not actually set the plugin instance. - */ - void addToPluginList(QString p); - - /** - * Loads a BioTracker Plugin from a filpaht. It returns true if the Plugin could be loaded, otherwise false. - */ - bool loadPluginFromFilename(QString filename); - - /** - * Loads a plugin from it's name (given in the metadata) instead of the filename. - * Only works if it is already known to the pluginloader, i.e. was loaded manually or automatically before or - * or has been added to the pluginlist via "addToPluginList" - */ - bool loadPluginFromName(QString name); - - /** - * Returns the Instance of the BioTracker Plugin. - */ - IBioTrackerPlugin* getPluginInstance(); - - /** - * Returns a QStrinListModel with the names of all loaded Plugins. - */ - QStringListModel* getPluginMetaData(); - - // Is a plugin loaded or not? - bool getIsPluginLoaded(); - - // Gets the name of the currently loaded plugin - QString getCurrentPluginName(); - - /** - * Returns a map containing the mapping "plugin name -> filename" - */ - std::map const& getPluginMap() const; - -private: - - //a map containing the mapping "plugin name -> filename" - std::map m_PluginMap; - - //nomen est omen - bool m_isPluginLoaded; - - //Name of the currently loaded plugin - QString m_currentPluginName; - - /** - * Gets the metadata from the currently loaded plugin. - * Currently this is nothing but the advertised name of the plugin - */ - QString readMetaDataFromPlugin(); - - // The QT object to actually load the plugins - QPluginLoader* m_PluginLoader; - - // List of all available plugins - QStringList m_PluginList; - - // Entire ListModel of the metadata (actually containing all metadata, not only name) - QStringListModel* m_PluginListModel; - - -}; - -#endif // PLUGINLOADER_H diff --git a/BioTracker/CoreApp/BioTracker/Model/UndoCommands/TrackCommands.cpp b/BioTracker/CoreApp/BioTracker/Model/UndoCommands/TrackCommands.cpp deleted file mode 100644 index 8e3f6f8f..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/UndoCommands/TrackCommands.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "TrackCommands.h" - -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "QUndoCommand" -#include "QPoint" -#include "QDebug" - -AddTrackCommand::AddTrackCommand(int id, QPoint pos, QUndoCommand *parent) - :QUndoCommand(parent), _id(id), _pos(pos) -{ - _added = false; - setText(QString("Add trajectory ") + QString::number(id)); -} - -void AddTrackCommand::undo() -{ - emitRemoveTrajectoryId(_id); -} - -void AddTrackCommand::redo() -{ - if (!_added) { - Q_EMIT emitAddTrajectory(_pos); - _added = true; - } - else { - emitValidateTrajectory(_id); - } -} - -RemoveTrackCommand::RemoveTrackCommand(IModelTrackedTrajectory* traj, QUndoCommand *parent) - :QUndoCommand(parent), _traj(traj) -{ - setText(QString("Remove trajectory ") + QString::number(traj->getId())); -} - -void RemoveTrackCommand::undo() -{ - emitValidateTrajectory(_traj->getId()); -} - -void RemoveTrackCommand::redo() -{ - emitRemoveTrajectory(_traj); -} - -RemoveElementCommand::RemoveElementCommand(IModelTrackedTrajectory* traj, uint frameNumber, QUndoCommand *parent) - :QUndoCommand(parent), _traj(traj), _frameNumber(frameNumber) -{ - - - setText("Remove entity " + QString::number(_frameNumber) + " of trajectory " + QString::number(traj->getId())); -} - -void RemoveElementCommand::undo() -{ - emitValidateEntity(_traj, _frameNumber); -} - -void RemoveElementCommand::redo() -{ - emitRemoveElement(_traj, _frameNumber); -} - -MoveElementCommand::MoveElementCommand(IModelTrackedTrajectory* traj, uint frameNumber, QPoint oldPos, QPoint newPos, int toMove, QUndoCommand *parent) - :QUndoCommand(parent), _traj(traj), _frameNumber(frameNumber), _oldPos(oldPos), _newPos(newPos), _toMove(toMove) -{ - setText("Move entity " + QString::number(_frameNumber) + " of trajectory " + QString::number(traj->getId()) + " to " + QString::number(_newPos.x()) + ", " + QString::number(_newPos.y())); -} - -void MoveElementCommand::undo() -{ - emitMoveElement(_traj, _frameNumber, _oldPos, _toMove); -} - -void MoveElementCommand::redo() -{ - emitMoveElement(_traj, _frameNumber, _newPos, _toMove); - _toMove = 1; -} - -/*bool MoveElementCommand::mergeWith(const QUndoCommand * command) -//{ -// const MoveElementCommand *moveCommandToMerge = static_cast(command); -// IModelTrackedTrajectory* trajToMerge = moveCommandToMerge->_traj; -// uint frameNumberToMerge = moveCommandToMerge->_frameNumber; -// -// if ((_traj != trajToMerge) || (frameNumberToMerge != _frameNumber)) { -// return false; -// } -// -// _oldPos -// -}*/ - -SwapTrackIdCommand::SwapTrackIdCommand(IModelTrackedTrajectory* traj0, IModelTrackedTrajectory* traj1, QUndoCommand *parent) - :QUndoCommand(parent), _traj0(traj0), _traj1(traj1) -{ - setText("Swap id's of " + QString::number(_traj0->getId()) + " and " + QString::number(_traj1->getId())); -} - -void SwapTrackIdCommand::undo() -{ - emitSwapIds(_traj1, _traj0); -} - -void SwapTrackIdCommand::redo() -{ - emitSwapIds(_traj0, _traj1); -} - -FixTrackCommand::FixTrackCommand(IModelTrackedTrajectory* traj, bool isFixed, QUndoCommand *parent) - :QUndoCommand(parent), _traj(traj), _isFixed(isFixed) -{ - if (_isFixed) { - setText("Fix tracking data of trajectory " + QString::number(_traj->getId())); - } - else { - setText("Unfix tracking data of trajectory " + QString::number(_traj->getId())); - - } -} - -void FixTrackCommand::undo() -{ - emitFixTrack(_traj, !_isFixed); -} - -void FixTrackCommand::redo() -{ - emitFixTrack(_traj, _isFixed); -} - -RotateEntityCommand::RotateEntityCommand(IModelTrackedTrajectory* traj, double oldAngle, double angle, uint frameNumber, QUndoCommand *parent) - :QUndoCommand(parent), _traj(traj), _newAngle(angle), _oldAngle(oldAngle), _frameNumber(frameNumber) -{ - setText("Rotate entity "+ QString::number(_frameNumber) + " of trajectory " + QString::number(_traj->getId()) + " to " + QString::number(_newAngle)); -} - -void RotateEntityCommand::undo() -{ - emitEntityRotation(_traj, _oldAngle, _frameNumber); -} - -void RotateEntityCommand::redo() -{ - emitEntityRotation(_traj, _newAngle, _frameNumber); -} \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/Model/UndoCommands/TrackCommands.h b/BioTracker/CoreApp/BioTracker/Model/UndoCommands/TrackCommands.h deleted file mode 100644 index 7bce9de6..00000000 --- a/BioTracker/CoreApp/BioTracker/Model/UndoCommands/TrackCommands.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef TRACKCOMMANDS_H -#define TRACKCOMMANDS_H - -#pragma once - -#include "QUndoCommand" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "QPoint" - -// http://doc.qt.io/qt-5/qundo.html - -/** -* Add track command with data to do and undo: -* position, id, traj, added -*/ -class AddTrackCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - AddTrackCommand(int id, QPoint pos, - QUndoCommand *parent = 0); - void undo() override; - void redo() override; -signals: - void emitAddTrajectory(QPoint pos); - void emitValidateTrajectory(int id); - void emitRemoveTrajectoryId(int id); - -private: - IModelTrackedTrajectory* _traj; - int _id; - QPoint _pos; - bool _added; -}; - -/** -* Remove Track command with data to do and undo: -* traj -*/ -class RemoveTrackCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - RemoveTrackCommand(IModelTrackedTrajectory* traj, - QUndoCommand *parent = 0); - - void undo() override; - void redo() override; -signals: - void emitValidateTrajectory(int id); - void emitRemoveTrajectory(IModelTrackedTrajectory* traj); - -private: - IModelTrackedTrajectory* _traj; -}; - -/** -* Remove Entity command with data to do and undo: -* traj, framenumber -*/ -class RemoveElementCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - RemoveElementCommand(IModelTrackedTrajectory* traj, uint frameNumber, - QUndoCommand *parent = 0); - - void undo() override; - void redo() override; -signals: - void emitValidateEntity(IModelTrackedTrajectory* traj, uint frameNumber); - void emitRemoveElement(IModelTrackedTrajectory* traj, uint frameNumber); - -private: - IModelTrackedTrajectory* _traj; - uint _frameNumber; -}; - -/** -* Move Entity command with data to do and undo: -* traj, oldPos, newPos, hwo many left to move (for a multimove), framenuber -*/ -class MoveElementCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - MoveElementCommand(IModelTrackedTrajectory* traj, uint frameNumber, QPoint oldPos, QPoint newPos, int toMove, - QUndoCommand *parent = 0); - - void undo() override; - void redo() override; - //bool mergeWith(const QUndoCommand *command) override; -signals: - void emitMoveElement(IModelTrackedTrajectory* traj, uint _frameNumber, QPoint pos, int toMove); - -private: - IModelTrackedTrajectory* _traj; - uint _frameNumber; - QPoint _oldPos; - QPoint _newPos; - int _toMove; -}; - -/** -* Swap Track Id command with data to do and undo: -* traj 0 and traj 1 -*/ -class SwapTrackIdCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - SwapTrackIdCommand(IModelTrackedTrajectory* traj0, IModelTrackedTrajectory* traj1, - QUndoCommand *parent = 0); - - void undo() override; - void redo() override; - -signals: - void emitSwapIds(IModelTrackedTrajectory* traj0, IModelTrackedTrajectory* traj1); - -private: - IModelTrackedTrajectory* _traj0; - IModelTrackedTrajectory* _traj1; -}; - -/** -* Fix Track command with data to do and undo: -* fix toggle and traj -*/ -class FixTrackCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - FixTrackCommand(IModelTrackedTrajectory* traj, bool isFixed, - QUndoCommand *parent = 0); - - void undo() override; - void redo() override; -signals: - void emitFixTrack(IModelTrackedTrajectory* traj, bool toggle); - -private: - IModelTrackedTrajectory* _traj; - bool _isFixed; -}; - -/** -* Rotate Entity command with data to do and undo: -* traj, old angle, new angle, fraemenumber -*/ -class RotateEntityCommand : public QObject, public QUndoCommand -{ - Q_OBJECT -public: - RotateEntityCommand(IModelTrackedTrajectory* traj, double oldAngleDeg, double newAngleDeg, uint frameNumber, - QUndoCommand *parent = 0); - - void undo() override; - void redo() override; -signals: - void emitEntityRotation(IModelTrackedTrajectory* traj, double angle, uint frameNumber); - -private: - IModelTrackedTrajectory* _traj; - double _oldAngle; - double _newAngle; - uint _frameNumber; -}; - -#endif //TRACKCOMMANDS_H diff --git a/BioTracker/CoreApp/BioTracker/View/AnnotationsView.cpp b/BioTracker/CoreApp/BioTracker/View/AnnotationsView.cpp deleted file mode 100644 index d1f26480..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AnnotationsView.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "AnnotationsView.h" - -#include -#include -#include - -#include "Interfaces/IController/IController.h" - -#include "Model/TextureObject.h" -#include "Model/Annotations.h" -#include "View/GraphicsView.h" - -AnnotationsView::~AnnotationsView() -{ -} - -void AnnotationsView::prepareUpdate() -{ - prepareGeometryChange(); -} - -void AnnotationsView::setColor(QColor color) -{ - _annoColor = color; -} - -QRectF AnnotationsView::boundingRect() const -{ - auto model = static_cast(getModel()); - - QRectF rect{}; - for (auto &annotation : model->annotations) - { - rect = rect.united(annotation->boundingRect()); - } - - if (model->currentAnnotation) - rect = rect.united(model->currentAnnotation->boundingRect()); - return rect; -} - - -void AnnotationsView::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) -{ - setZValue(-1); - auto model = static_cast(getModel()); - for (auto &annotation : model->annotations) - { - if (model->getCurrentFrame() == annotation->startFrame) - painter->setPen(QPen(_annoColor, 6, Qt::SolidLine, Qt::RoundCap)); - else - { - QColor transparentGray = Qt::gray; - transparentGray.setAlphaF(0.25); - painter->setPen(QPen(transparentGray, 6, Qt::SolidLine, Qt::RoundCap)); - } - annotation->paint(painter, option, widget); - } - - if (model->currentAnnotation) - { - QColor transparentYellow = _annoColor; - transparentYellow.setAlphaF(0.5); - painter->setPen(QPen(transparentYellow, 6, Qt::SolidLine, Qt::RoundCap)); - model->currentAnnotation->paint(painter, option, widget); - } - if (model->selection) - { - painter->setPen(QPen(Qt::red, 6, Qt::SolidLine, Qt::RoundCap)); - Annotations::Annotation::drawHandleLocation(painter, *model->selection.handle, ""); - } -} diff --git a/BioTracker/CoreApp/BioTracker/View/AnnotationsView.h b/BioTracker/CoreApp/BioTracker/View/AnnotationsView.h deleted file mode 100644 index f54a9af6..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AnnotationsView.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "Interfaces/IView/IView.h" - -#include -#include -#include - -class GraphicsView; - -/** -* This view inherits from IView and QGraphicsItem. -* It is responsible for drawing the annotations. -* It is shown on to of the media panel. -*/ -class AnnotationsView : public IView, public QGraphicsItem -{ -public: - using IView::IView; - AnnotationsView() = delete; - virtual ~AnnotationsView(); - -public: - void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) override; - void prepareUpdate(); - void setColor(QColor color); -protected: - QRectF boundingRect() const; - - // IView interface -public: - void setNewModel(IModel *model) override { setModel(model); }; -protected: - void connectModelView() override {}; - - //members - QColor _annoColor = QColor(Qt::yellow); /**< color of all annotations */ -}; - diff --git a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/AreaDescriptor.cpp b/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/AreaDescriptor.cpp deleted file mode 100644 index 1fa1420a..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/AreaDescriptor.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "AreaDescriptor.h" - - - -AreaDescriptor::~AreaDescriptor() -{ -} diff --git a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/AreaDescriptor.h b/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/AreaDescriptor.h deleted file mode 100644 index 05ca62dd..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/AreaDescriptor.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "Interfaces/IView/IViewTrackedComponent.h" -#include - -class AreaDescriptor : public QObject, public IView, public QGraphicsItem -{ - Q_OBJECT -public: - AreaDescriptor(IController *controller, IModel *model) : - IView(controller, model) {}; - ~AreaDescriptor(); - - virtual void setBrush(QBrush brush) = 0; - virtual void setRect(std::vector rect) = 0; - virtual std::vector getRect() = 0; - virtual void updateRect() = 0; - - void setDimensions(int x, int y) { - _vdimX = x; - _vdimY = y; - } -protected: - - int _vdimX = 1; - int _vdimY = 1; -}; - diff --git a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/EllipseDescriptor.cpp b/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/EllipseDescriptor.cpp deleted file mode 100644 index 7540be26..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/EllipseDescriptor.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "EllipseDescriptor.h" -#include "Model/AreaDescriptor/AreaInfoElement.h" -#include "util/misc.h" - -#include "QBrush" -#include "QPainter" -#include -#include - -EllipseDescriptor::EllipseDescriptor(IController *controller, IModel *model) : - AreaDescriptor(controller, model) -{ - setAcceptHoverEvents(true); - setAcceptedMouseButtons(Qt::MouseButtons::enum_type::LeftButton); - - _brush = QBrush(Qt::blue); - - - _v = (dynamic_cast(getModel()))->getVertices(); - for (int i = 0; i < 4; i++) { - std::shared_ptr ri = std::make_shared(QRect(_v[i].x - 10, _v[i].y - 10, 20, 20), this); - ri->setBrush(_brush); - } - - updateEllipse(); - - _isInit = false; -} - -void EllipseDescriptor::init() { - _rectificationMarkerOrig->setBrush(_brush); - _rectificationMarkerEnd->setBrush(_brush); -} - -void EllipseDescriptor::updateEllipse() { - - _v = (dynamic_cast(getModel()))->getVertices(); - _rectification = std::make_shared(QRect(_v[0].x, _v[0].y, _v[1].x-_v[0].x, _v[1].y- _v[0].y), this); - _rectificationMarkerOrig = std::make_shared(QRect(_v[0].x, _v[0].y, 10, 10), this); - _rectificationMarkerEnd = std::make_shared(QRect(_v[1].x, _v[1].y, 10, 10), this); - _rectificationMarkerOrig->setBrush(_brush); - _rectificationMarkerEnd->setBrush(_brush); -} - -EllipseDescriptor::~EllipseDescriptor() -{ -} - -void EllipseDescriptor::setBrush(QBrush brush) { - _brush = brush; - _rectificationMarkerOrig->setBrush(_brush); - _rectificationMarkerEnd->setBrush(_brush); -} - -void EllipseDescriptor::updateRect() { - setRect(getRect()); -} - -void EllipseDescriptor::setRect(std::vector rect) { - if(rect.size() >= 2){ - _v = (dynamic_cast(getModel()))->getVertices(); - updateEllipse(); - } -} - -void EllipseDescriptor::receiveDragUpdate(BiotrackerTypes::AreaType vectorType, int id, double x, double y) { - int atype = (dynamic_cast(getModel()))->getAreaType(); - if (atype == vectorType) { - _dragVectorId = id; - _drag = QPoint(x, y); - } - else { - _dragVectorId = -1; - } - update(); -} - -std::vector EllipseDescriptor::getRect() { - return (dynamic_cast(getModel()))->getVertices(); -} - - -void EllipseDescriptor::getNotified() { - -} - -QRectF EllipseDescriptor::boundingRect() const -{ - return QRect(10, 10, 10, 10); -} - -bool isInverted(int x1, int y1, int x2, int y2) { - if ((x1 > x2 && y1 < y2) || (x1 < x2 && y1 > y2)) { - return true; - } - return false; -} - -void EllipseDescriptor::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (!_isInit) - init(); - - //TODO remove hardcoding and code duplication - if (_dragVectorId >= 0) { - QColor transparentGray = Qt::gray; - transparentGray.setAlphaF(0.75); - painter->setPen(QPen(transparentGray, 1, Qt::SolidLine)); - painter->drawRect(_drag.x(), _drag.y(), 10, 10); - - auto fst = _dragVectorId != 0 ? _rectificationMarkerOrig : _rectificationMarkerEnd; - bool inv = isInverted(fst->rect().x(), fst->rect().y(), _drag.x(), _drag.y()); - int x = fst->rect().x() + (_drag.x() - fst->rect().x()) / 2.0; - int y = fst->rect().y() + (_drag.y() - fst->rect().y()) / 2.0; - - - if (inv) { - //Create a canvas to draw on - QImage image(_vdimX, _vdimY, QImage::Format_ARGB32_Premultiplied); - image.fill(Qt::transparent); - QPainter p(&image); - - //Create dark rect which spans the screen - p.setCompositionMode(QPainter::CompositionMode_SourceOver); - QRectF r(0,0, _vdimX, _vdimY); - QColor b; - b.setRgb(0,0,0, 200); - QBrush brush(b); - p.fillRect(r, brush); - p.drawRect(r); - - //Cut out the rectangle - p.setCompositionMode(QPainter::CompositionMode_DestinationOut); - b.setNamedColor("white"); - b.setAlpha(125); - QBrush bbb(b); - p.setBrush(bbb); - p.drawEllipse(QRect(fst->rect().x(), fst->rect().y(), _drag.x() - fst->rect().x(), _drag.y() - fst->rect().y())); - - //Draw canvas onto the actual image - painter->setOpacity(0.5); //mixed with the previous alphas! - painter->drawImage(0,0, image); - } - else - { - //This part is way simpler, as we only need to draw a somewhat transparent & filled ellipse - QColor b; - b.setNamedColor("black"); - b.setAlpha(125); - QBrush brush(b); - painter->setBrush(brush); - painter->setOpacity(0.5); - painter->drawEllipse(QRect(fst->rect().x(), fst->rect().y(), _drag.x() - fst->rect().x(), _drag.y() - fst->rect().y())); - } - } -} - -bool EllipseDescriptor::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { - return 1; -} diff --git a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/EllipseDescriptor.h b/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/EllipseDescriptor.h deleted file mode 100644 index 27011fc7..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/EllipseDescriptor.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "AreaDescriptor.h" -#include -#include "util/types.h" - -class EllipseDescriptor : public AreaDescriptor -{ - Q_OBJECT -public: - EllipseDescriptor(IController *controller = 0, IModel *model = 0); - ~EllipseDescriptor(); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - - QRectF boundingRect() const override; - void setBrush(QBrush brush) override; - - - void setRect(std::vector rect) override; - std::vector getRect() override; - - void updateRect() override; - - // IViewTrackedComponent interface - public Q_SLOTS: - void getNotified(); - void receiveDragUpdate(BiotrackerTypes::AreaType vectorType, int id, double x, double y); - -protected: - bool sceneEventFilter(QGraphicsItem * watched, QEvent * event) override; - -private: - void init(); - void updateEllipse(); - bool _isInit; - - std::vector _v; - //float _ellipseRotation; - - QGraphicsItem *_watchingDrag; - QBrush _brush; - - //Rects - std::shared_ptr _rectification; - std::shared_ptr _rectificationMarkerOrig; - std::shared_ptr _rectificationMarkerEnd; - - int _dragVectorId; - QPoint _drag; - - // IView interface -public: - void setNewModel(IModel *model) override { setModel(model); }; -protected: - void connectModelView() override {}; -}; - diff --git a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/RectDescriptor.cpp b/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/RectDescriptor.cpp deleted file mode 100644 index a2b79385..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/RectDescriptor.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "RectDescriptor.h" - -#include "QBrush" -#include "QPainter" -#include - -#include "util/misc.h" -#include "Model/AreaDescriptor/AreaInfoElement.h" -#include "Model/AreaDescriptor/AreaInfo.h" -#include -#include "settings/Settings.h" - -double orientation(cv::Point2f p1, cv::Point2f p2) -{ - cv::Point2f diff = p1 - p2; - // need to check the origin of coorindiates - return std::atan2(p1.y - p2.y, p1.x - p2.x); -} - -RectDescriptor::RectDescriptor(IController *controller, IModel *model) : - AreaDescriptor(controller, model) -{ - BioTracker::Core::Settings *settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - _dragVectorId = -1; - _dragType = BiotrackerTypes::AreaType::NONE; - setAcceptHoverEvents(true); - - _brush = QBrush(Qt::blue); - - _v = (dynamic_cast(getModel()))->getVertices(); - setRect(_v); - - _isInit = false; -} - -void RectDescriptor::init() { - for (int i = 0; i < 4; i++) { - _rectification[i]->setAcceptHoverEvents(true); - _rectification[i]->installSceneEventFilter(this); - } -} - -void RectDescriptor::setBrush(QBrush brush) { - for (int i = 0; i < 4; i++) { - _rectification[i]->setBrush(brush); - } - _brush = brush; -} - -bool RectDescriptor::inShape(QPoint p) { - return false; -} - -void RectDescriptor::updateRect() { - setRect(getRect()); -} - -void RectDescriptor::setRect(std::vector rect) { - std::vector> rectification; - std::vector> rectificationLines; - std::vector> rectificationNumbers; - - BioTracker::Core::Settings *settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - - _v = (dynamic_cast(getModel()))->getVertices(); - - for (int i = 0; i < 4; i++) { - std::shared_ptr ri = std::make_shared(QRect(rect[i].x - 10, rect[i].y - 10, 20, 20), this); - ri->setBrush(_brush); - rectification.push_back(ri); - //Numbers at corners - if ((dynamic_cast(getModel()))->getShowNumbers()) { - std::shared_ptr ti = std::make_shared(QString::number(i), this); - ti->setPos(_v[i].x + 10, _v[i].y + 10); - ti->setFont(QFont("Arial", 20)); - rectificationNumbers.push_back(ti); - } - } - - for (int i = 0; i < 4; i++) { - - auto fst = rectification[i]; - auto snd = rectification[(i + 1) % 4]; - - std::shared_ptr ri = std::make_shared( - QLine(fst->rect().x() + 10, fst->rect().y() + 10, snd->rect().x() + 10, snd->rect().y() + 10), this); - - rectificationLines.push_back(ri); - if ((dynamic_cast(getModel()))->getShowNumbers()) { - std::string label = "???"; - if (i % 2 == 0) { - label = std::to_string(settings->getValueOrDefault(AREADESCRIPTOR::RECT_H, AREADESCRIPTOR::RECT_H_DEFAULT)); - label.erase(label.find_last_not_of('0') + 1, std::string::npos); - } - else { - label = std::to_string(settings->getValueOrDefault(AREADESCRIPTOR::RECT_W, AREADESCRIPTOR::RECT_W_DEFAULT)); - label.erase(label.find_last_not_of('0') + 1, std::string::npos); - } - std::shared_ptr ti = std::make_shared(label.c_str(), this); - cv::Point2f a(fst->rect().x() + 10, fst->rect().y() + 10); - cv::Point2f b(snd->rect().x() + 10, snd->rect().y() + 10); - double alpha = orientation(a, b) * 180 / CV_PI; - //Fix upside down text - alpha = alpha > 0 ? 180 - alpha : alpha; - cv::Point2f c = a + (b - a) * 0.5; - ti->setPos(c.x, c.y); - ti->setFont(QFont("Arial", 20)); - ti->setRotation(-1*alpha); - rectificationNumbers.push_back(ti); - } - } - _rectification = rectification; - _rectificationLines = rectificationLines; - _rectificationNumbers = rectificationNumbers; -} - -std::vector RectDescriptor::getRect() { - return (dynamic_cast(getModel()))->getVertices(); -} - -void RectDescriptor::receiveDragUpdate(BiotrackerTypes::AreaType vectorType, int id, double x, double y) { - _dragType = (dynamic_cast(getModel()))->getAreaType(); - if (_dragType == vectorType) { - _dragVectorId = id; - _drag = QPoint(x,y); - } - else { - _dragVectorId = -1; - } - update(); -} - -RectDescriptor::~RectDescriptor() -{ -} - -void RectDescriptor::getNotified() { - -} - -QRectF RectDescriptor::boundingRect() const -{ - return QRect(10,10,10,10); -} - -void RectDescriptor::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - if (!_isInit) - init(); - - //We want smooth lines! - painter->setRenderHint(QPainter::Antialiasing); - - //TODO remove hardcoding and code duplication - if (_dragVectorId >= 0 && _dragType != BiotrackerTypes::AreaType::NONE) { - QColor transparentGray = Qt::gray; - transparentGray.setAlphaF(0.75); - painter->setPen(QPen(transparentGray, 1, Qt::SolidLine)); - painter->drawRect(_drag.x()-10, _drag.y()-10, 20, 20); - int fstId = (_dragVectorId - 1) % 4; - fstId = (fstId == -1 ? 3 : fstId); - auto fst = _rectification[fstId]; - auto snd = _rectification[(_dragVectorId + 1) % 4]; - painter->drawLine(QLine(fst->rect().x() + 10, fst->rect().y() + 10, _drag.x(), _drag.y())); - painter->drawLine(QLine(snd->rect().x() + 10, snd->rect().y() + 10, _drag.x(), _drag.y())); - } -} - -void RectDescriptor::updateLinePositions() { - - for (int i = 0; i < 4; i++) { - - auto fst = _rectification[i]; - auto snd = _rectification[(i + 1) % 4]; - auto ln = _rectificationLines[i]; - ln->setLine(QLine(fst->rect().x() + 10, fst->rect().y() + 10, snd->rect().x() + 10, snd->rect().y() + 10)); - } - -} - -bool RectDescriptor::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { - - return 0; -} diff --git a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/RectDescriptor.h b/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/RectDescriptor.h deleted file mode 100644 index b11e876a..00000000 --- a/BioTracker/CoreApp/BioTracker/View/AreaDesciptor/RectDescriptor.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "AreaDescriptor.h" -#include "cv.h" -#include -#include "util/types.h" -#include - -class RectDescriptor : public AreaDescriptor -{ - Q_OBJECT -public: - RectDescriptor(IController *controller = 0, IModel *model = 0); - ~RectDescriptor(); - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - - QRectF boundingRect() const override; - - bool inShape(QPoint p); - - void setBrush(QBrush brush) override; - void setRect(std::vector rect) override; - std::vector getRect() override; - - void updateRect() override; - - // IViewTrackedComponent interface -public Q_SLOTS: - void getNotified(); - void receiveDragUpdate(BiotrackerTypes::AreaType vectorType, int id, double x, double y); - -protected: - bool sceneEventFilter(QGraphicsItem * watched, QEvent * event) override; - void updateLinePositions(); - -private: - void init(); - bool _isInit; - - QGraphicsItem *_watchingDrag; - int _dragX; - int _dragY; - - std::vector _v; - - //Rects - std::vector> _rectification; - std::vector> _rectificationLines; - std::vector> _rectificationNumbers; - - QBrush _brush; - - BiotrackerTypes::AreaType _dragType; - int _dragVectorId; - QPoint _drag; - - // IView interface -public: - void setNewModel(IModel *model) override { setModel(model); }; -protected: - void connectModelView() override {}; -}; - diff --git a/BioTracker/CoreApp/BioTracker/View/CameraDevice.cpp b/BioTracker/CoreApp/BioTracker/View/CameraDevice.cpp deleted file mode 100644 index e30ca38d..00000000 --- a/BioTracker/CoreApp/BioTracker/View/CameraDevice.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "CameraDevice.h" -#include "ui_CameraDevice.h" - -#include "QCameraInfo" -#include "util/types.h" -#include -#include -#include "opencv2/highgui/highgui.hpp" - -CameraDevice::CameraDevice(QWidget *parent) : - QWidget(parent), - ui(new Ui::CameraDevice) -{ - ui->setupUi(this); - m_ximeaId = -1; - - this->setAttribute(Qt::WA_DeleteOnClose); - - - listAllCameras(); -} - -CameraDevice::~CameraDevice() -{ - delete ui; -} - -CameraConfiguration CameraDevice::grabUICameraConfiguration() { - int id = ui->comboBox->currentIndex(); - if (m_ximeaId == id) - id = CV_CAP_XIAPI; - - std::string sx = ui->lineEdit->text().toStdString(); - std::string sy = ui->lineEdit_2->text().toStdString(); - std::string sf = ui->lineEdit_3->text().toStdString(); - int x, y, f; - x = (sx == "Default" ? -1 : std::stoi(sx)); - y = (sx == "Default" ? -1 : std::stoi(sy)); - f = (sf == "Default" ? -1 : std::stoi(sf)); - - CameraConfiguration conf(id, x, y, f, false, ""); - return conf; -} - -void CameraDevice::on_buttonBox_accepted() -{ - CameraConfiguration conf = grabUICameraConfiguration(); - Q_EMIT emitSelectedCameraDevice(conf); - - this->close(); -} - -void CameraDevice::on_pushButton_clicked() -{ - int id = ui->comboBox->currentIndex(); - if (m_ximeaId != id) - { - m_capture.open(id); - } - else - { - id = CV_CAP_XIAPI; - m_capture.open(id); - } - CameraConfiguration conf = grabUICameraConfiguration(); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - int fails = 0; - - while (!m_capture.isOpened() && fails < 5) { - m_capture.open(id); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - fails++; - } - - if (conf._width != -1) m_capture.set(CV_CAP_PROP_FRAME_WIDTH, conf._width); - if (conf._height != -1) m_capture.set(CV_CAP_PROP_FRAME_HEIGHT, conf._height); - if (conf._fps != -1) m_capture.set(CV_CAP_PROP_FPS, conf._fps); - - if (!m_capture.isOpened()) { - //throw device_open_error(":("); - ui->label_NoImage->setText("Error loading camera"); - } - else - { - cv::Mat mat; - for (int i = 0; i < 10; i++) { - m_capture.grab(); - m_capture.retrieve(mat); - } - cv::Mat destination; - cv::resize(mat, destination, cv::Size(240, 180)); - QPixmap image = QPixmap::fromImage(QImage((unsigned char*)destination.data, destination.cols, destination.rows, QImage::Format_RGB888)); - ui->label_NoImage->setPixmap(image); - m_capture.release(); - } - -} - -void CameraDevice::on_comboBox_currentIndexChanged(int index) -{ -} - - -void CameraDevice::listAllCameras() -{ - cameras = QCameraInfo::availableCameras(); - foreach (const QCameraInfo &cameraInfo, cameras) { - ui->comboBox->addItem(cameraInfo.description()); - } - - //Try to find ximea cameras - cv::VideoCapture cap(CV_CAP_XIAPI); - if (cap.isOpened()) { - ui->comboBox->addItem("XIMEA default"); - m_ximeaId = cameras.size(); - std::cout << "XIMEA props: " << cap.get(CV_CAP_PROP_FRAME_WIDTH) << " " << cap.get(CV_CAP_PROP_FRAME_HEIGHT) << endl; - } -} - -void CameraDevice::on_buttonBox_rejected() -{ - this->close(); -} diff --git a/BioTracker/CoreApp/BioTracker/View/CameraDevice.ui b/BioTracker/CoreApp/BioTracker/View/CameraDevice.ui deleted file mode 100644 index 71397814..00000000 --- a/BioTracker/CoreApp/BioTracker/View/CameraDevice.ui +++ /dev/null @@ -1,187 +0,0 @@ - - - CameraDevice - - - - 0 - 0 - 489 - 329 - - - - Form - - - - - 10 - 250 - 471 - 31 - - - - - - - Select Camera Device - - - - - - - - - - Preview - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - 10 - 9 - 471 - 231 - - - - - - 0 - 0 - 471 - 231 - - - - - - - <No Image> - - - - - - - - - - 10 - 290 - 471 - 31 - - - - - - - - 0 - 0 - - - - Resolution: - - - - - - - - 0 - 0 - - - - - 100 - 16777215 - - - - Default - - - - - - - - 0 - 0 - - - - x - - - - - - - - 100 - 16777215 - - - - Default - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - FPS: - - - - - - - Default - - - - - - - - - diff --git a/BioTracker/CoreApp/BioTracker/View/ComponentShape.cpp b/BioTracker/CoreApp/BioTracker/View/ComponentShape.cpp deleted file mode 100644 index abc84a67..00000000 --- a/BioTracker/CoreApp/BioTracker/View/ComponentShape.cpp +++ /dev/null @@ -1,1368 +0,0 @@ -#include "ComponentShape.h" -#include - -#include "View/Utility/Tracer.h" - -#include "QBrush" -#include "QPainter" -#include "QMenu" -#include "QAction" -#include "QGraphicsScene" -#include "QGraphicsSceneContextMenuEvent" -#include "QDebug" -#include "QColorDialog" -#include "qwidgetaction.h" -#include "qlabel.h" -#include "assert.h" -#include "QTime" -#include "qlistwidget.h" -#include "QGraphicsProxyWidget" -#include "QVBoxLayout" -#include "QSlider" -#include "QLineEdit" -#include "QAbstractSlider" -#include "QComboBox" -#include "QSpinBox" -#include "QDoubleSpinBox" -#include -#include -#include -#include -#include - - -/* -* This is the cpp file of the ComponentShape class -* Collapse/Fold all methods to have a better overview. -*/ - -ComponentShape::ComponentShape(QGraphicsObject* parent, - IModelTrackedTrajectory* trajectory, int id) : - QGraphicsObject(parent), m_trajectory(trajectory), m_id(id), m_parent(parent) -{ - setData(0, m_id); - setData(1, "point"); - - m_polygons = QList(); - m_useDefaultDimensions = true; - m_penWidth = 2; - m_transparency = 255; - m_penStyle = Qt::SolidLine; - m_penStylePrev = Qt::SolidLine; - m_marked = false; - - //set default permissions - m_pMovable = true; - m_pRemovable = true; - m_pSwappable = true; - m_pRotatable = true; - - m_fixed = false; - m_currentFramenumber = 0; - m_rotation = 0; - //m_trajectoryWasActiveOnce = false; - - //create tracing layer - m_tracingLayer = new QGraphicsRectItem(); - m_tracingLayer->setZValue(3); - this->scene()->addItem(m_tracingLayer); - - //create orientation line - m_rotationLine = QLineF(); - - //set flags - setFlag(ItemIsMovable); - setFlag(ItemIsSelectable); - setAcceptedMouseButtons(Qt::LeftButton); - - setVisible(true); -} - -ComponentShape::~ComponentShape() { - delete m_tracingLayer; -} - -//*****************************QGraphicsItem interface*************************************** - -QRectF ComponentShape::boundingRect() const -{ - if (this->data(1) == "ellipse" || this->data(1) == "point" || this->data(1) == "rectangle") { - return QRectF(0, 0, m_w, m_h); - } - else if (this->data(1) == "polygon") { - //outer polygon bounding rect - return m_polygons[0].boundingRect(); - } - else { - //Note: This log might not appear (on console) as the application dies of assert before the buffer is served - qDebug() << "Could not create a bounding rect for current track " << m_id; - assert(0); - } - -} - -QPainterPath ComponentShape::shape() const -{ - QPainterPath path; - if (this->data(1) == "ellipse") { - path.addEllipse(0, 0, m_w, m_h); - } - else if (this->data(1) == "point") { - int dim = m_w <= m_h ? m_w : m_h; - // path.addEllipse(0, 0, dim , dim); - QRectF ellipse; - //ellipse = QRectF(0, m_h - m_w , m_w, m_w); - qreal origin_x = m_rotationLine.p1().x() - dim / 2; - qreal origin_y = m_rotationLine.p1().y() - dim / 2; - ellipse = QRectF(origin_x, origin_y, dim, dim); - - path.addEllipse(ellipse); - - } - else if (this->data(1) == "rectangle") { - path.addRect(0, 0, m_w, m_h); - } - else if (this->data(1) == "polygon") { - //outer polygon - path.addPolygon(m_polygons[0]); - } - else { - qDebug() << "Could not create a interaction area for trajectory " << m_id; - assert(0); - } - return path; -} - -void ComponentShape::paint(QPainter * painter, - const QStyleOptionGraphicsItem * option, QWidget * widget) -{ - Q_UNUSED(option); - Q_UNUSED(widget); - - - if (m_currentFramenumber < 0) - return; - //Antialiasing - if (m_antialiasing) { - painter->setRenderHint(QPainter::Antialiasing); - } - - //check if scene is set - if (!(this->scene())) { - qDebug() << "componentscene is null\n"; - } - - QPen pen = QPen(m_penColor, m_penWidth, m_penStyle); - QBrush brush = QBrush(m_brushColor); - painter->setPen(pen); - painter->setBrush(brush); - - // draw orientation line - if (m_orientationLine && !m_rotationLine.isNull()) { - painter->drawLine(m_rotationLine); - } - - //TODO enums for types? - - //draw ellipse - if (this->data(1) == "ellipse") { - QRectF ellipse = QRectF(0, 0, m_w, m_h); - painter->drawEllipse(ellipse); - } - - //draw rectangle - if (this->data(1) == "rectangle") { - QRect rectangle = QRect(0, 0, m_w, m_h); - painter->drawRect(rectangle); - } - - //draw point - //take the smaller of width and height - //a point should always have the same height and width - if (this->data(1) == "point") { - QRectF ellipse; - if (m_w <= m_h) { - //ellipse = QRectF(0, m_h - m_w , m_w, m_w); - qreal origin_x = m_rotationLine.p1().x() - m_w / 2; - qreal origin_y = m_rotationLine.p1().y() - m_w / 2; - ellipse = QRectF(origin_x, origin_y, m_w, m_w); - } - else { - qreal origin_x = m_rotationLine.p1().x() - m_h / 2; - qreal origin_y = m_rotationLine.p1().y() - m_h / 2; - ellipse = QRectF(origin_x, origin_y, m_h, m_h); - } - painter->drawEllipse(ellipse); - } - - //draw polygon - if (this->data(1) == "polygon") { - foreach(QPolygonF polygonF, m_polygons) { - painter->drawPolygon(polygonF); - } - } - - // draw id in center - if (m_showId) { - painter->drawText(this->boundingRect(), Qt::AlignCenter, QString::number(m_id)); - } -} - -bool ComponentShape::advance() -{ - return false; -} - -void ComponentShape::mousePressEvent(QGraphicsSceneMouseEvent * event) -{ - m_mousePressTime = QTime::currentTime(); - m_mousePressTime.start(); - m_mousePressPos = pos().toPoint(); - - if (event->button() == Qt::LeftButton) { - // handle left mouse button here - setCursor(Qt::ClosedHandCursor); - update(); - } - //pass on - QGraphicsItem::mousePressEvent(event); -} - -void ComponentShape::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) -{ - if (event->button() == Qt::LeftButton) { - setCursor(Qt::ArrowCursor); - - QPoint currentPos = this->pos().toPoint(); - int manhattanLength = (currentPos - m_mousePressPos).manhattanLength(); - int moveTime = m_mousePressTime.elapsed(); - if (manhattanLength > 5 || moveTime > 200) { - m_dragged = true; - } - - - if (m_dragged) { - - //broadcast move so other selected elements get moved too - //maybe unconventional and slow but couldn't find another way; Dropevents in view and dropevents in shape didn't seem to work - broadcastMove(); - } - else { - this->setPos(m_mousePressPos); - this->update(); - } - m_dragged = false; - - update(); - } - //pass on - QGraphicsItem::mouseReleaseEvent(event); - -} - -void ComponentShape::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { - //pass on - QGraphicsItem::mouseMoveEvent(event); -} - -QVariant ComponentShape::itemChange(GraphicsItemChange change, - const QVariant &value) -{ - if (change == ItemSelectedHasChanged && scene()) { - if (this->isSelected()) { - m_penColorLast = m_penColor; - m_penColor = Qt::red; - m_penStylePrev = m_penStyle; - if (m_fixed) { - m_penStyle = Qt::DashDotLine; - } - else { - m_penStyle = Qt::DashLine; - } - this->setZValue(2); - trace(); - update(); - } - else { - m_penColor = m_penColorLast; - m_penStyle = m_penStylePrev; - this->setZValue(0); - trace(); - update(); - - } - } - return QGraphicsItem::itemChange(change, value); -} - -void ComponentShape::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) -{ - QMenu menu; - - /* - create the info box - */ - QWidgetAction* infoBox = new QWidgetAction(this); - - QString info = QString("ID: "); - info.append(QString::number(m_id)); - QLabel* infoLabel = new QLabel(info); - infoLabel->setWordWrap(true); - infoLabel->setStyleSheet("QLabel {font-weight: bold; text-align: center}"); - infoLabel->setAlignment(Qt::AlignCenter); - infoBox->setDefaultWidget(infoLabel); - menu.addAction(infoBox); - - // - menu.addSeparator(); - - /* - create set object name - line edit - */ - QWidgetAction* objectNameAction = new QWidgetAction(this); - QLineEdit* objectEdit = new QLineEdit(); - - if (objectName() == "") { - objectEdit->setPlaceholderText("no object name set"); - } - else { - objectEdit->setText(objectName()); - } - objectEdit->setAlignment(Qt::AlignHCenter); - objectEdit->setFrame(false); - objectEdit->setToolTip("Change the trajectory's name. This will not be saved in the data output (yet)!"); - - QObject::connect(objectEdit, &QLineEdit::textEdited, this, &ComponentShape::setObjectNameContext); - - objectNameAction->setDefaultWidget(objectEdit); - menu.addAction(objectNameAction); - - /* - show info window for current frame - */ - menu.addSeparator(); - QAction *showInfoAction = menu.addAction("Show full info", dynamic_cast(this), SLOT(createInfoWindow())); - menu.addSeparator(); - - /* - coloring - */ - QAction *changeBrushColorAction = menu.addAction("Change fill color", dynamic_cast(this), SLOT(changeBrushColor())); - QAction *changePenColorAction = menu.addAction("Change border color", dynamic_cast(this), SLOT(changePenColor())); - - /* - transparency slider - */ - QMenu* transparencyMenu = new QMenu("Transparency"); - QWidgetAction* sliderBox = new QWidgetAction(this); - QSlider* transparencySlider = new QSlider(Qt::Horizontal); - - transparencySlider->setMinimum(0); - transparencySlider->setMaximum(255); - transparencySlider->setSingleStep(1); - transparencySlider->setTickPosition(QSlider::TicksBothSides); - transparencySlider->setTickInterval(64); - transparencySlider->setValue(m_transparency); - - QObject::connect(transparencySlider, &QSlider::sliderMoved, this, &ComponentShape::receiveTransparency); - - sliderBox->setDefaultWidget(transparencySlider); - transparencyMenu->addAction(sliderBox); - - menu.addMenu(transparencyMenu); - - // - menu.addSeparator(); - /* - dimension menu - */ - QMenu* dimensionMenu = new QMenu("Dimensions"); - - //Width - QWidgetAction* widthBox = new QWidgetAction(this); - QSpinBox* widthSpin = new QSpinBox; - widthSpin->setPrefix("Width: "); - widthSpin->setMinimum(1); - widthSpin->setMaximum(100000); - widthSpin->setValue(m_w); - QObject::connect(widthSpin, QOverload::of(&QSpinBox::valueChanged), this, &ComponentShape::receiveWidth); - widthBox->setDefaultWidget(widthSpin); - dimensionMenu->addAction(widthBox); - - //Height - QWidgetAction* heightBox = new QWidgetAction(this); - QSpinBox* heightSpin = new QSpinBox; - heightSpin->setPrefix("Height: "); - heightSpin->setMinimum(1); - heightSpin->setMaximum(100000); - heightSpin->setValue(m_h); - QObject::connect(heightSpin, QOverload::of(&QSpinBox::valueChanged), this, &ComponentShape::receiveHeight); - heightBox->setDefaultWidget(heightSpin); - dimensionMenu->addAction(heightBox); - - // - menu.addMenu(dimensionMenu); - - /* - toggle orientation line - */ - - QAction *showOrientationAction = menu.addAction("Show orientation line", dynamic_cast(this), SLOT(receiveToggleOrientationLine(bool))); - showOrientationAction->setCheckable(true); - showOrientationAction->setChecked(m_orientationLine); - - /* - toggle id - */ - - QAction *showIDAction = menu.addAction("Show ID", dynamic_cast(this), SLOT(receiveShowId(bool))); - showIDAction->setCheckable(true); - showIDAction->setChecked(m_showId); - - - /* - tracing menu - */ - QMenu* tracingMenu = new QMenu("Tracing"); - //tracing type - QWidgetAction* typeBox = new QWidgetAction(this); - QComboBox* typeCombo = new QComboBox; - QStringList types; - types << "No tracing" << "Shape" << "Path" << "Arrow Path"; - typeCombo->addItems(types); - typeCombo->setCurrentText(m_tracingStyle); - QObject::connect(typeCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &ComponentShape::receiveTracingStyle); - typeBox->setDefaultWidget(typeCombo); - QMenu* tracingTypeMenu = new QMenu("Type"); - tracingTypeMenu->addAction(typeBox); - tracingMenu->addMenu(tracingTypeMenu); - - //tracingHistory - QWidgetAction* historyBox = new QWidgetAction(this); - QSpinBox* historySpinBox = new QSpinBox; - historySpinBox->setPrefix("History: "); - historySpinBox->setMinimum(1); - historySpinBox->setMaximum(100000); - historySpinBox->setValue(m_tracingLength); - QObject::connect(historySpinBox, QOverload::of(&QSpinBox::valueChanged), this, &ComponentShape::receiveTracingLength); - historyBox->setDefaultWidget(historySpinBox); - tracingMenu->addAction(historyBox); - - //tracingSteps - QWidgetAction* stepsBox = new QWidgetAction(this); - QSpinBox* stepsSpinBox = new QSpinBox; - stepsSpinBox->setPrefix("Steps: "); - stepsSpinBox->setMinimum(1); - stepsSpinBox->setMaximum(100000); - stepsSpinBox->setValue(m_tracingSteps); - QObject::connect(stepsSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &ComponentShape::receiveTracingSteps); - stepsBox->setDefaultWidget(stepsSpinBox); - tracingMenu->addAction(stepsBox); - - //tracingDegradation - QWidgetAction* degrBox = new QWidgetAction(this); - QComboBox* degrCombo = new QComboBox; - QStringList degrTypes; - degrTypes << "None" << "Transparency" << "False color"; - degrCombo->addItems(degrTypes); - degrCombo->setCurrentText(m_tracingTimeDegradation); - QObject::connect(degrCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &ComponentShape::receiveTracingTimeDegradation); - degrBox->setDefaultWidget(degrCombo); - QMenu* tracingTimeDegrMenu = new QMenu("Time degradation"); - tracingTimeDegrMenu->addAction(degrBox); - tracingMenu->addMenu(tracingTimeDegrMenu); - - //toggle orientation line - - QAction *showTrOrientationAction = tracingMenu->addAction("Show tracer orientation line", dynamic_cast(this), SLOT(receiveTracerOrientationLine(bool))); - showTrOrientationAction->setCheckable(true); - showTrOrientationAction->setChecked(m_tracingOrientationLine); - - //tracer number - QAction *showTrNumberAction = tracingMenu->addAction("Show framenumber on tracers", dynamic_cast(this), SLOT(receiveTracerFrameNumber(bool))); - showTrNumberAction->setCheckable(true); - showTrNumberAction->setChecked(m_tracerFrameNumber); - - //tracer proportions - QWidgetAction* propBox = new QWidgetAction(this); - QDoubleSpinBox* propSpinBox = new QDoubleSpinBox; - propSpinBox->setPrefix("Proportions: "); - propSpinBox->setDecimals(2); - propSpinBox->setSingleStep(0.001f); - propSpinBox->setMinimum(0.01f); - propSpinBox->setMaximum(99.99f); - propSpinBox->setValue(m_tracerProportions); - QObject::connect(propSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &ComponentShape::receiveTracerProportions); - propBox->setDefaultWidget(propSpinBox); - tracingMenu->addAction(propBox); - - - menu.addMenu(tracingMenu); - - // - menu.addSeparator(); - - /* - removing - */ - QAction *removeTrackAction = menu.addAction("Remove track", dynamic_cast(this), SLOT(removeTrack())); - QAction *removeTrackEntityAction = menu.addAction("Remove track entity", dynamic_cast(this), SLOT(removeTrackEntity())); - if (!m_pRemovable) { - removeTrackAction->setEnabled(false); - removeTrackEntityAction->setEnabled(false); - } - - /* - fixing - */ - QString fixText = m_fixed ? "Unfix track" : "Fix Track"; - QAction *fixTrackAction = menu.addAction(fixText, dynamic_cast(this), SLOT(toggleFixTrack())); - - /* - marking - */ - QString markText = m_marked ? "Unmark" : "Mark"; - QAction *markAction = menu.addAction(markText, dynamic_cast(this), SLOT(markShape())); - QAction *unmarkAction = menu.addAction(markText, dynamic_cast(this), SLOT(unmarkShape())); - markAction->setVisible(!m_marked); - unmarkAction->setVisible(m_marked); - - // - menu.addSeparator(); - - /* - morphing - */ - QMenu* morphMenu = new QMenu("Morph into..."); - if (data(1) == "rectangle" || data(1) == "ellipse" || data(1) == "point" || data(1) == "polygon") { - QAction* morphPoint = morphMenu->addAction("Point", dynamic_cast(this), SLOT(morphIntoPoint())); - QAction* morphEllipse = morphMenu->addAction("Ellipse", dynamic_cast(this), SLOT(morphIntoEllipse())); - QAction* morphRect = morphMenu->addAction("Rectangle", dynamic_cast(this), SLOT(morphIntoRect())); - QAction* morphPoylgon = morphMenu->addAction("Polygon", dynamic_cast(this), SLOT(morphIntoPolygon())); - } - else { - morphMenu->setEnabled(false); - } - menu.addMenu(morphMenu); - - // - QAction *selectedAction = menu.exec(event->screenPos()); -} - - -//************************************************************************* - -/// updates this with data from new current entity -bool ComponentShape::updateAttributes(uint frameNumber) -{ - m_currentFramenumber = frameNumber; - - // if trajectory does not exist anymore, delete the shape - if (!m_trajectory) { - this->hide(); - m_tracingLayer->hide(); - this->deleteLater(); - return false; - } - - // check if trajectory is valid and current entity exists - if (m_trajectory->size() != 0 && m_trajectory->getValid() && m_trajectory->getChild(frameNumber)) { - m_id = m_trajectory->getId(); - //update m_fixed - m_fixed = m_trajectory->getFixed(); - if (!m_fixed) - { - if (this->isSelected()) { m_penStyle = Qt::DashLine; } - else { m_penStyle = Qt::SolidLine; } - } - else { - if (this->isSelected()) { m_penStyle = Qt::DashDotLine; } - else { m_penStyle = Qt::DotLine; } - } - - //update dimensions - prepareGeometryChange(); - - //type checker - bool hasType = false; - - //if point, ellipse, rectangle and valid - IModelTrackedPoint* pointLike = dynamic_cast(m_trajectory->getChild(m_currentFramenumber)); - if (pointLike && (pointLike->getValid())) { - hasType = true; - //update width and height or use defaults - if (m_useDefaultDimensions) { - if (pointLike->hasW()) { m_w = pointLike->getW(); } - else { m_w = m_wDefault; } - if (pointLike->hasH()) { m_h = pointLike->getH(); } - else { m_h = m_hDefault; } - } - //update rotation - if (pointLike->hasDeg()) { - this->setTransformOriginPoint(m_w / 2, m_h / 2); - if (m_h > m_w || data(1) == "polygon") { - m_rotation = -90 - pointLike->getDeg(); - this->setRotation(m_rotation); - } - else { - m_rotation = -pointLike->getDeg(); - this->setRotation(m_rotation); - } - - //update rotation line - m_rotationLine.setP1(QPointF(m_w / 2, m_h / 2)); - if (m_h > m_w || data(1) == "polygon") { - m_rotationLine.setAngle(-90); - } - else { - m_rotationLine.setAngle(0); - } - qreal length = (m_w + m_h) / 2 * 3; - m_rotationLine.setLength(length); - - //update rotation handle - m_rotationHandleLayer->setTransformOriginPoint(m_w / 2, m_h / 2); - m_rotationHandleLayer->setRotation(0); - m_rotationHandle->setPos(m_rotationLine.p2()); - } - else { - m_rotationLine = QLineF(); - } - - //update Position - this->setPos(pointLike->getXpx() - m_w / 2, pointLike->getYpx() - m_h / 2); - m_oldPos = this->pos().toPoint(); - - - /* - -when morphing into polygon: - -construct polygon from pos and width,height - -pentagon - - x / \ - / \ - | | - \_ _/ - - */ - m_polygons = QList(); - - QPolygonF polygon; - QPointF startPoint = QPointF(m_w / 2, 0); - polygon << startPoint; - polygon << QPointF(m_w, m_h / 2); - polygon << QPointF(3 * m_w / 4, m_h); - polygon << QPointF(m_w / 4, m_h); - polygon << QPointF(0, m_h / 2); - polygon << startPoint; - - if (polygon.isClosed()) { - m_polygons.append(polygon); - } - - //create tracers - trace(); - - this->show(); - update(); - - return true; - } - else { - this->hide(); - return true; - } - // if polygon - IModelTrackedPolygon* polygons = dynamic_cast(m_trajectory->getChild(frameNumber)); - if (polygons && (polygons->getValid() || m_currentFramenumber == 0)) { - hasType = true; - //update polygon - if (polygons->hasPolygon()) { - m_polygons = polygons->getPolygon(); - } - //also update position - this->setPos(polygons->getXpx() - m_w / 2, polygons->getYpx() - m_h / 2); - m_oldPos = this->pos().toPoint(); - - //update width and height or use defaults --> for morphing - if (m_useDefaultDimensions) { - m_w = m_polygons[0].boundingRect().width(); - m_h = m_polygons[0].boundingRect().height(); - } - - //create tracers - trace(); - - this->show(); - update(); - - return true; - } - //has no type - if (!hasType) { - qDebug() << "The current entity has no known type"; - - } - } - else { - //trajectory is empty or null or invald or current entity is null - this->hide(); - m_tracingLayer->hide(); - //delete this; - return false; - } -} - -/// attemps to draw tracers, if _tracingStyle is set tracers are drawn -void ComponentShape::trace() -{ - //TRACING - - IModelTrackedPoint* currentChild = dynamic_cast - (m_trajectory->getChild(m_currentFramenumber)); - //return if current entity is not existant - if (!currentChild) - return; - - QPointF currentPoint = QPointF(currentChild->getXpx(), currentChild->getYpx()); - - //update the tracing layer - m_tracingLayer->setPos(this->pos()); - m_tracingLayer->setFlag(QGraphicsItem::ItemHasNoContents); - m_tracingLayer->show(); - - // really unefficient to flush each time - //flush tracing shape history, open up the memory --> thats slow - QList tracers = m_tracingLayer->childItems(); - foreach(QGraphicsItem * tracer, tracers) - { - delete tracer; - } - - //return if tracing disabled - if (m_trajectory->size() == 0 || m_tracingLength <= 0 || m_tracingStyle == "No tracing") { - return; - } - - QPointF lastPointDifference = QPointF(0, 0);// + QPointF(m_h / 2, m_w / 2); - - //create each n'th (m_tracingSteps) tracer of tracing history (m_tracingLength) - for (int i = 1; i <= m_tracingLength && i <= m_currentFramenumber; i += m_tracingSteps) { - - IModelTrackedPoint* historyChild = dynamic_cast - (m_trajectory->getChild(m_currentFramenumber - i)); - if (historyChild && historyChild->getValid()) { - - //positioning - QPointF historyPoint = QPointF(historyChild->getXpx(), historyChild->getYpx()); - QPointF historyPointDifference = historyPoint - currentPoint; - QPointF adjustedHistoryPointDifference = historyPointDifference; - - //time degradation colors - QPen timeDegradationPen = QPen(m_penColor, m_penWidth, m_penStyle); - QBrush timeDegradationBrush = QBrush(m_brushColor); - QColor timeDegradationBrushColor; - QColor timeDegradationPenColor; - - if (m_tracingTimeDegradation == "Transparency") { - - float tr = (float)m_transparency; - float trForThis = tr != 0 ? tr - (tr / (float)m_tracingLength) * (i - 1) : 0.0f; - - timeDegradationPenColor = QColor(m_penColor.red(), - m_penColor.green(), m_penColor.blue(), trForThis); - timeDegradationPen = QPen(timeDegradationPenColor, m_penWidth, Qt::SolidLine); - - timeDegradationBrushColor = QColor(m_brushColor.red(), - m_brushColor.green(), m_brushColor.blue(), trForThis); - timeDegradationBrush = QBrush(timeDegradationBrushColor); - - } - else if (m_tracingTimeDegradation == "False color") { - float hue = (240.0f - ((240.0f / (float)m_tracingLength) * i)); - timeDegradationPenColor = QColor::fromHsv((int)hue, 255.0f, 255.0f); - timeDegradationPenColor.setAlpha(m_transparency); - timeDegradationBrushColor = QColor::fromHsv((int)hue, 255.0f, 255.0f); - timeDegradationBrushColor.setAlpha(m_transparency); - timeDegradationPen = QPen(m_penColor, m_penWidth, m_penStyle); - timeDegradationBrush = QBrush(timeDegradationBrushColor); - } - - // check tracing type - - //SHAPE - if (m_tracingStyle == "Shape") { - - //orientation line - if (m_tracingOrientationLine) { - QLineF orientationLine = QLineF(); - orientationLine.setP1(adjustedHistoryPointDifference); - orientationLine.setAngle(historyChild->getDeg()); - qreal length = (m_w + m_h) / 2 / m_tracerProportions * 3; - orientationLine.setLength(15); - - QGraphicsLineItem* orientationItem = new QGraphicsLineItem(orientationLine, - m_tracingLayer); - } - - float tracerDeg = historyChild->hasDeg() ? historyChild->getDeg() : 0.0; - float tracerW = m_w * m_tracerProportions; - float tracerH = m_h * m_tracerProportions; - int tracerNumber = m_currentFramenumber - i; - - Tracer* tracer = new Tracer(this->data(1), tracerNumber, tracerDeg, - adjustedHistoryPointDifference, tracerW, tracerH, - timeDegradationPen, timeDegradationBrush, m_tracingLayer); - - QObject::connect(tracer, &Tracer::emitGoToFrame, - this, &ComponentShape::emitGoToFrame); - } - - //PATH - else if (m_tracingStyle == "Path") { - - if (lastPointDifference != adjustedHistoryPointDifference) { - - QLineF base = QLineF(lastPointDifference, adjustedHistoryPointDifference); - QGraphicsLineItem* lineItem = new QGraphicsLineItem(base, m_tracingLayer); - lineItem->setPen(QPen(timeDegradationPenColor, m_penWidth, m_penStyle)); - - lastPointDifference = adjustedHistoryPointDifference; - } - } - - //ARROWPATH - else if (m_tracingStyle == "Arrow path") { - - if (lastPointDifference != adjustedHistoryPointDifference) { - - QLineF base = QLineF(lastPointDifference, adjustedHistoryPointDifference); - - int armLength = std::floor(base.length() / 9) + 2; - - QLineF arm0 = base.normalVector(); - arm0.setLength(armLength); - arm0.setAngle(base.angle() + 20); - - QLineF arm1 = base.normalVector(); - arm1.setLength(armLength); - arm1.setAngle(base.angle() - 20); - - QGraphicsLineItem* baseItem = new QGraphicsLineItem(base, m_tracingLayer); - baseItem->setPen(QPen(timeDegradationBrushColor, m_penWidth, m_penStyle)); - QGraphicsLineItem* arm0Item = new QGraphicsLineItem(arm0, m_tracingLayer); - arm0Item->setPen(timeDegradationPen); - QGraphicsLineItem* arm1Item = new QGraphicsLineItem(arm1, m_tracingLayer); - arm1Item->setPen(timeDegradationPen); - - lastPointDifference = adjustedHistoryPointDifference; - - } - } - - //add framenumber to each tracer - if (m_tracerFrameNumber) { - uint tracerNumber = m_currentFramenumber - i; - QFont font = QFont(); - int fontPixelSize = (int)((m_w + m_h) / 5) * m_tracerProportions; - font.setPixelSize(fontPixelSize); - //font.setBold(true); - QGraphicsSimpleTextItem* tracerNumberText = - new QGraphicsSimpleTextItem(QString::number(tracerNumber), m_tracingLayer); - tracerNumberText->setFont(font); - tracerNumberText->setBrush(QBrush(Qt::white)); //sloooow - QPen pen = QPen(Qt::black); - pen.setWidth(0); - tracerNumberText->setPen(pen); //sloooow - tracerNumberText->setPos(adjustedHistoryPointDifference + - QPointF(-m_w * m_tracerProportions / 2.0f, -m_h * m_tracerProportions / 5)); - } - } - } -} - -IModelTrackedTrajectory * ComponentShape::getTrajectory() -{ - return m_trajectory; -} - -void ComponentShape::setPermission(std::pair permission) -{ - m_permissions.insert(permission); - - - switch (permission.first) - { - case ENUMS::COREPERMISSIONS::COMPONENTMOVE: - m_pMovable = permission.second; - this->setFlag(ItemIsMovable, permission.second); - break; - case ENUMS::COREPERMISSIONS::COMPONENTREMOVE: - m_pRemovable = permission.second; - break; - case ENUMS::COREPERMISSIONS::COMPONENTSWAP: - m_pSwappable = permission.second; - break; - case ENUMS::COREPERMISSIONS::COMPONENTROTATE: - m_pRotatable = permission.second; - - if (m_pRotatable) { - m_rotationHandleLayer->setVisible(m_orientationLine); - m_rotationHandle->setVisible(m_orientationLine); - } - else { - m_rotationHandleLayer->hide(); - m_rotationHandle->hide(); - } - break; - } -} - -int ComponentShape::getId() -{ - return m_id; -} - -bool ComponentShape::isSwappable() -{ - return m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP]; -} - -bool ComponentShape::isRemovable() -{ - return m_pRemovable; -} - -bool ComponentShape::isRotatable() -{ - return m_pRotatable; -} - -QPoint ComponentShape::getOldPos() -{ - return m_oldPos; -} - -//set default members from core params -void ComponentShape::setMembers(CoreParameter* coreParams) -{ - //from coreParams - m_antialiasing = coreParams->m_antialiasingEntities; - - - m_tracingStyle = coreParams->m_tracingStyle; - m_tracingTimeDegradation = coreParams->m_tracingTimeDegradation; - m_tracingLength = coreParams->m_tracingHistory; - m_tracingSteps = coreParams->m_tracingSteps; - m_tracerProportions = coreParams->m_tracerProportions; - m_tracingOrientationLine = coreParams->m_tracerOrientationLine; - m_tracerFrameNumber = coreParams->m_tracerFrameNumber; - - m_orientationLine = coreParams->m_trackOrientationLine; - m_showId = coreParams->m_trackShowId; - - m_brushColor = *(coreParams->m_colorBrush); - m_penColor = *(coreParams->m_colorBorder); - - m_dragged = false; - setFlag(QGraphicsItem::ItemIgnoresTransformations, coreParams->m_ignoreZoom); - - // set dimensions and default dimensions - if (coreParams->m_trackWidth > 0) { - m_w = coreParams->m_trackWidth; - m_wDefault = coreParams->m_trackWidth; - } - if (coreParams->m_trackHeight > 0) { - m_h = coreParams->m_trackHeight; - m_hDefault = coreParams->m_trackHeight; - } - - //initialize helpers - m_rotationHandleLayer = new QGraphicsRectItem(this); - m_rotationHandleLayer->setPos(0, 0); - m_rotationHandleLayer->setFlag(QGraphicsItem::ItemHasNoContents); - - m_rotationHandle = new RotationHandle(QPoint(m_w / 2, m_h / 2), m_rotationHandleLayer); - m_rotationHandle->setAntialiasing(m_antialiasing); - QObject::connect(m_rotationHandle, &RotationHandle::emitShapeRotation, this, &ComponentShape::receiveShapeRotation); - - if (m_pRotatable) { - m_rotationHandleLayer->setVisible(m_orientationLine); - m_rotationHandle->setVisible(m_orientationLine); - } - - update(); -} - -double ComponentShape::constrainAngle(double x) { - x = fmod(x, 360); - if (x < 0) - x += 360; - return x; -} - - -//################################SLOTS############################# - -//**************************context menu actions******************** - -void ComponentShape::changeBrushColor() -{ - - this->m_brushColor = QColorDialog::getColor(m_brushColor, nullptr, QString("Choose fill color"), QColorDialog::ShowAlphaChannel); - //m_transparency = m_brushColor.alpha(); - trace(); - update(); -} - -void ComponentShape::changePenColor() -{ - QColor newColor = QColorDialog::getColor(m_penColor, nullptr, QString("Choose border color"), QColorDialog::ShowAlphaChannel); - //m_transparency = newColor.alpha(); - - if (!isSelected()) { - m_penColorLast = m_penColor; - m_penColor = newColor; - - trace(); - update(); - } - else { - m_penColorLast = newColor; - } - -} - -void ComponentShape::changeBrushColor(QColor color) -{ - m_brushColor = color; - - trace(); - update(); -} - -void ComponentShape::changePenColor(QColor color) -{ - if (!isSelected()) { - m_penColorLast = m_penColor; - m_penColor = color; - trace(); - update(); - } - else { - m_penColorLast = color; - } -} - -bool ComponentShape::removeTrack() -{ - if (m_pRemovable) { - qDebug() << "Removing track..."; - - //emit to set trajectory invalid - Q_EMIT emitRemoveTrajectory(m_trajectory); - - } - else { - qDebug() << "Track is not removable"; - } - return m_pRemovable; -} - -bool ComponentShape::removeTrackEntity() -{ - if (m_pRemovable) { - qDebug() << "Removing track entity..."; - - //emit to set trajectory invalid - Q_EMIT emitRemoveTrackEntity(m_trajectory, m_currentFramenumber); - } - else { - qDebug() << "track entity is not removable"; - } - return m_pRemovable; -} - -void ComponentShape::markShape(int penwidth) -{ - if (!m_marked) { - m_penWidth = 3; - } - else { - m_penWidth = penwidth; - } - m_marked = true; - trace(); - update(); -} - -void ComponentShape::unmarkShape() -{ - m_marked = false; - m_penWidth = 2; - - trace(); - update(); -} - -void ComponentShape::toggleFixTrack() -{ - //if traj is currently fixed-> emit flase, else emit true - bool fixToggle = m_fixed ? false : true; - Q_EMIT emitToggleFixTrack(m_trajectory, fixToggle); - update(); - trace(); -} - -//TODO create ui file for this and do this there -void ComponentShape::createInfoWindow() -{ - QTableWidget* infoTable = new QTableWidget(); - - infoTable->setRowCount(0); - infoTable->setColumnCount(2); - - infoTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Property")); - infoTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); - infoTable->verticalHeader()->hide(); - - QLinkedList> infoList; - infoList.append(QPair("ID", QString::number(m_id))); - infoList.append(QPair("Framenumber", QString::number(m_currentFramenumber))); - infoList.append(QPair("Seen for frames", QString::number(m_trajectory->validCount()))); - infoList.append(QPair("Width", QString::number(m_w))); - infoList.append(QPair("Height", QString::number(m_h))); - infoList.append(QPair("Orientation (in Degrees)", QString::number(m_rotation))); - infoList.append(QPair("Fixed", QString::number(m_fixed))); - - QLinkedList>::const_iterator info; - for (info = infoList.constBegin(); info != infoList.constEnd(); ++info) { - infoTable->insertRow(infoTable->rowCount()); - - - QTableWidgetItem* infoKey = new QTableWidgetItem(info->first); - QTableWidgetItem* infoKeyInfo = new QTableWidgetItem(info->second); - infoKey->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - infoKeyInfo->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - - infoTable->setItem(infoTable->rowCount() - 1, 0, infoKey); - infoTable->setItem(infoTable->rowCount() - 1, 1, infoKeyInfo); - - } - - //infoTable->horizontalHeader()->setStretchLastSection( true ); - infoTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - - QWidget* infoWidget = new QWidget(); - const QString title = QString("Information for track %1 on frame %2").arg(QString::number(m_id), QString::number(m_currentFramenumber)); - infoWidget->setWindowTitle(title); - QVBoxLayout* vLayout = new QVBoxLayout(); - - - infoWidget->resize(infoTable->size()); - vLayout->addWidget(infoTable); - infoWidget->setLayout(vLayout); - - infoWidget->show(); - - -} - -// this is only visual, the object name is not set in the exported file -void ComponentShape::setObjectNameContext(QString name) { - setObjectName(name); - m_trajectory->setObjectName(name); -} - -void ComponentShape::morphIntoRect() { - setData(1, "rectangle"); - updateAttributes(m_currentFramenumber); - trace(); -} -void ComponentShape::morphIntoEllipse() { - setData(1, "ellipse"); - updateAttributes(m_currentFramenumber); - trace(); -} -void ComponentShape::morphIntoPoint() { - setData(1, "point"); - updateAttributes(m_currentFramenumber); - trace(); -} -void ComponentShape::morphIntoPolygon() -{ - setData(1, "polygon"); - - updateAttributes(m_currentFramenumber); - trace(); -} - -//************************************************************************ - -//*************************** SLOTS to set members***************************** -void ComponentShape::receiveTracingLength(int tracingLength) -{ - m_tracingLength = tracingLength; - trace(); - update(); -} - -void ComponentShape::receiveTracingStyle(QString style) -{ - m_tracingStyle = style; - trace(); - update(); -} - -void ComponentShape::receiveTracingSteps(int steps) -{ - m_tracingSteps = steps; - trace(); - update(); -} - -void ComponentShape::receiveTracingTimeDegradation(QString timeDegradation) -{ - m_tracingTimeDegradation = timeDegradation; - trace(); - update(); -} - -void ComponentShape::receiveTracerProportions(float proportion) -{ - m_tracerProportions = proportion; - trace(); - update(); -} - -void ComponentShape::receiveTracerOrientationLine(bool toggle) -{ - m_tracingOrientationLine = toggle; - trace(); - update(); -} - -void ComponentShape::receiveTracerFrameNumber(bool toggle) -{ - m_tracerFrameNumber = toggle; - trace(); - update(); -} - -void ComponentShape::receiveAntialiasing(bool toggle) -{ - m_antialiasing = toggle; - m_rotationHandle->setAntialiasing(toggle); - trace(); - update(); -} - -void ComponentShape::receiveDimensions(int width, int height) -{ - m_useDefaultDimensions = false; - m_w = width; - m_h = height; - updateAttributes(m_currentFramenumber); - trace(); - update(); -} - -void ComponentShape::receiveHeight(int height) { - m_useDefaultDimensions = false; - m_h = height; - updateAttributes(m_currentFramenumber); - trace(); - update(); -} - -void ComponentShape::receiveWidth(int width) { - m_useDefaultDimensions = false; - m_w = width; - updateAttributes(m_currentFramenumber); - trace(); - update(); -} - -void ComponentShape::setDimensionsToDefault() -{ - m_useDefaultDimensions = true; - m_w = m_wDefault; - m_h = m_hDefault; - updateAttributes(m_currentFramenumber); - trace(); - update(); -} - -void ComponentShape::receiveToggleOrientationLine(bool toggle) -{ - m_orientationLine = toggle; - if (m_pRotatable) { - m_rotationHandleLayer->setVisible(toggle); - m_rotationHandle->setVisible(toggle); - } - trace(); - update(); -} - -void ComponentShape::receiveShowId(bool toggle) -{ - m_showId = toggle; - trace(); - update(); -} - -void ComponentShape::receiveShapeRotation(double angle, bool rotateEntity) -{ - m_rotationHandleLayer->setTransformOriginPoint(m_w / 2, m_h / 2); - //m_rotationHandleLayer->setRotation(-angle); - - this->setTransformOriginPoint(m_w / 2, m_h / 2); - if (m_h > m_w || data(1) == "polygon") { - m_rotationHandleLayer->setRotation(-angle + 90); - this->setRotation(m_rotation + angle - 90); - } - else { - m_rotationHandleLayer->setRotation(-angle); - this->setRotation(m_rotation + angle); - } - - if (rotateEntity) { - - this->pos(); - - double toAngle = -angle - m_rotation; - double oldAngle = -m_rotation; - - double toAngleNorm = constrainAngle(toAngle); - double oldAngleNorm = constrainAngle(oldAngle); - Q_EMIT emitEntityRotation(m_trajectory, oldAngleNorm, toAngleNorm, m_currentFramenumber); - } - - update(); -} - -//currently disabled -void ComponentShape::receiveIgnoreZoom(bool toggle) -{ - setFlag(QGraphicsItem::ItemIgnoresTransformations, toggle); - trace(); - update(); -} - -void ComponentShape::receiveTransparency(int alpha) { - m_transparency = alpha; - m_brushColor.setAlpha(alpha); - m_penColor.setAlpha(alpha); - - QColor penColorHandle = m_rotationHandle->pen().color(); - penColorHandle.setAlpha(alpha); - m_rotationHandle->setPen(QPen(penColorHandle)); - - QColor brushColorHandle = m_rotationHandle->brush().color(); - brushColorHandle.setAlpha(alpha); - m_rotationHandle->setBrush(QBrush(brushColorHandle)); - - trace(); - update(); - -} diff --git a/BioTracker/CoreApp/BioTracker/View/ComponentShape.h b/BioTracker/CoreApp/BioTracker/View/ComponentShape.h deleted file mode 100644 index 12490040..00000000 --- a/BioTracker/CoreApp/BioTracker/View/ComponentShape.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef COMPONENTSHAPE_H -#define COMPONENTSHAPE_H - -#include "QGraphicsObject" -#include "Interfaces/IView/IViewTrackedComponent.h" -#include "Interfaces/IModel/IModelTrackedComponent.h" -#include "qpainter.h" -#include "qgraphicsitem.h" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "Model/CoreParameter.h" -#include "QTime" -#include "View/Utility/RotationHandle.h" - - -/** -* This class inherits QGraphicsObject. -* It is a child of the TrackedComponentView and is generated by it for -* each trajectory in the tracking data. It visualizes the corresponding entity of the -* trajectory in the current frame of the medium. If there is no tracking data for that frame, -* this shape is hidden. It deletes itself when the trajectory is a nullpointer. -* It contains user interaction functionality to move, remove and rotate the -* corresponding entity or trajectory. -* The form/type is set when created (from entity: ellipse, point, rectangle, polygon) -* It can be changed by the user via the context menu -*/ -class ComponentShape : public QGraphicsObject -{ - Q_OBJECT - -public: - //Constructor - ComponentShape(QGraphicsObject* parent = 0, IModelTrackedTrajectory* trajectory = 0, int id = -1); - ~ComponentShape(); - - //QGraphicsItem interface - QRectF boundingRect() const override; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - QPainterPath shape() const override; - bool advance(); - //////////////////////////////// - - - /** - * called by view when tracking data was modified - * updates this with data from new current entity - * --> rotation, position, etc.... - */ - bool updateAttributes(uint framenumber); - - /// returns the corresponding traj - IModelTrackedTrajectory* getTrajectory(); - - /// set permission to enable/disable certain user interactions - void setPermission(std::pair permission); - - /// returns ID of corresponding trajectory - int getId(); - - /// returns swappable permission - bool isSwappable(); - /// returns removeable permission - bool isRemovable(); - /// returns rotatable permission - bool isRotatable(); - - /// helper function - QPoint getOldPos(); - - /// attemps to draw tracers, if _tracingStyle is set tracers are drawn - void trace(); - - /// called in constructor to setup the members with default vlaues from coreparameter component - void setMembers(CoreParameter* coreParams); - - //public members - int m_currentFramenumber; /**< current visualized framenumber --> entity */ - //to fix a bug when moving; TODO better - int m_w; /**< width of this; if polygon width of bounding rect of polygon */ - int m_h; /**< height of this; if polygon height of bounding rect of polygon */ - - QGraphicsRectItem* m_tracingLayer; /**< the layer with all tracers; is counter-rotated if component shape is rotated */ - - -signals: - - /* - * These are the signals sent to the command component. - * They are all modifiying the trakcing data. - * They contain all the data to reverse them (in the commands component). - */ - void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); - void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void emitMoveElement(IModelTrackedTrajectory* trajectory, QPoint oldPos, QPoint newPos, uint frameNumber, int sizeOfStackToMove); - void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - void emitEntityRotation(IModelTrackedTrajectory* trajectory, double oldAngleDeg, double newAngleDeg, uint frameNumber); - ///////////////////////////////////////////// - - void emitGoToFrame(int frame); - /// each user movement gets broadcasted to other shapes - void broadcastMove(); - - public Q_SLOTS: - //context menu actions - //(actions only give trigger signals and therefore can only connect to parameterless slots) - void changeBrushColor(); - void changePenColor(); - void changeBrushColor(QColor color); - void changePenColor(QColor color); - bool removeTrack(); - bool removeTrackEntity(); - void markShape(int penwidth = 0); - void unmarkShape(); - void toggleFixTrack(); - void createInfoWindow(); - void setObjectNameContext(QString name); - void morphIntoRect(); - void morphIntoEllipse(); - void morphIntoPoint(); - void morphIntoPolygon(); - ////////////////////////////////////////////// - - - //Tracing - void receiveTracingLength(int tracingLength); - void receiveTracingStyle(QString style); - void receiveTracingSteps(int steps); - void receiveTracingTimeDegradation(QString timeDegradation); - void receiveTracerProportions(float proportion); - void receiveTracerOrientationLine(bool toggle); - void receiveTracerFrameNumber(bool toggle); - //Visual - void receiveAntialiasing(bool toggle); - void receiveTransparency(int alpha); - //Dimensions - void receiveDimensions(int width, int height); - void receiveHeight(int height); - void receiveWidth(int width); - void setDimensionsToDefault(); - void receiveToggleOrientationLine(bool toggle); - void receiveShowId(bool toggle); - void receiveShapeRotation(double angle, bool rotateEntity); - //Ignore zoom (disabled) - void receiveIgnoreZoom(bool toggle); - - -protected: - //QGraphicsItem interface - QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; - void mousePressEvent(QGraphicsSceneMouseEvent *event) override; - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; - void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; - //////////////////////////////// - - //constrains angles under 0 or over 360 degrees to [0, 360] - double constrainAngle(double x); - -private: - - /* - * MEMBERS - */ - - QGraphicsObject *m_parent; - - //permissions - std::map m_permissions; /**< list of permissions */ - bool m_pMovable; /**< permission to move the component shape */ - bool m_pRemovable; /**< permission to remove the component shape */ - bool m_pSwappable; /**< permission to move the component shape */ - bool m_pRotatable; /**< permission to move the component shape */ - - //dimensions - - //int m_z; - int m_wDefault = 20; /**< default width, will be set by entity */ - int m_hDefault = 20; /**< default height, will be set by entity */ - bool m_useDefaultDimensions; /**< true, if dimensions were changed by user, they will stay */ - - // appearance - QColor m_penColor; /**< border color */ - QColor m_penColorLast; /**< last border color */ - QColor m_brushColor; /**< fill color */ - int m_transparency; /**< transparency of this */ - bool m_marked; /**< if marked, border is thick */ - int m_penWidth; /**< border_thickness */ - Qt::PenStyle m_penStyle; /**< style of border */ - Qt::PenStyle m_penStylePrev; /**< last stlye of border */ - bool m_antialiasing; /**< if true, antialiasing in enabled */ - - // tracing - QString m_tracingStyle; /**< tracing style (none, path, arrow, shape) */ - int m_tracingLength; /**< sets how many tracers are drawn (history) */ - int m_tracingSteps; /**< sets each x'th tracer is drawn */ - QString m_tracingTimeDegradation; /**< sets tracer color style (default, transparency, false color) */ - float m_tracerProportions; /**< set the tracers proportion relative to component shape */ - bool m_tracingOrientationLine; /**< toggles if orientation line is shwon for tracers */ - bool m_tracerFrameNumber; /**< toggles if tracer's framenumber is shown (very slow) */ - - // rotation - float m_rotation; /**< the current rotation of the compontent shape and entity */ - QLineF m_rotationLine; /**< the orientation line */ - RotationHandle* m_rotationHandle; /**< the handle with wich the user can change the rotation */ - QGraphicsRectItem* m_rotationHandleLayer;/**< help layer for rotation handle */ - bool m_orientationLine; /**< toggles if _rotationLine is shown */ - - // misc - int m_id; /**< the traj's ID */ - bool m_showId; /**< toggles if id is shown in center */ - IModelTrackedTrajectory* m_trajectory; /**< the corresponding traj */ - QList m_polygons; /**< list of polygons to draw (if entity inherited from polygon) */ - bool m_fixed; /**< if fixed, border is dotted and tracker cannot change traj data */ - //bool m_trajectoryWasActiveOnce; /**< unused */ - QPoint m_oldPos; /**< position before moving by hand */ - - // dragging - bool m_dragged; /**< true if currently dragged */ - QTime m_mousePressTime; /**< helper for dragging */ - QPoint m_mousePressPos; /**< helper for dragging */ -}; - - -#endif // COMPONENTSHAPE_H diff --git a/BioTracker/CoreApp/BioTracker/View/CoreParameterView.cpp b/BioTracker/CoreApp/BioTracker/View/CoreParameterView.cpp deleted file mode 100644 index 8813a8f7..00000000 --- a/BioTracker/CoreApp/BioTracker/View/CoreParameterView.cpp +++ /dev/null @@ -1,552 +0,0 @@ -#include "CoreParameterView.h" -#include "ui_CoreParameterView.h" -#include "qdebug.h" -#include "Model/CoreParameter.h" - -#include -#include "settings/Settings.h" -#include "util/types.h" -#include -#include "Controller/ControllerCoreParameter.h" -#include -#include - -CoreParameterView::CoreParameterView(QWidget *parent, IController *controller, IModel *model) : - IViewWidget(parent, controller, model), - ui(new Ui::CoreParameterView) -{ - ui->setupUi(this); - - ui->lineEditRectWidth->setValidator(new QDoubleValidator(this)); - ui->lineEditRectHeight->setValidator(new QDoubleValidator(this)); - - BioTracker::Core::Settings *settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - double asdf = settings->getValueOrDefault(AREADESCRIPTOR::RECT_H, AREADESCRIPTOR::RECT_H_DEFAULT); //TODO1111 - double h = std::max(settings->getValueOrDefault(AREADESCRIPTOR::RECT_H, AREADESCRIPTOR::RECT_H_DEFAULT), std::numeric_limits::epsilon()); - double w = std::max(settings->getValueOrDefault(AREADESCRIPTOR::RECT_W, AREADESCRIPTOR::RECT_W_DEFAULT), std::numeric_limits::epsilon()); - std::string sw = std::to_string(w); - std::string sh = std::to_string(h); - sh.erase(sh.find_last_not_of('0') + 1, std::string::npos); - sw.erase(sw.find_last_not_of('0') + 1, std::string::npos); - ui->lineEditRectWidth->setText(sw.c_str()); - ui->lineEditRectHeight->setText(sh.c_str()); - - //TODO implement it correctly before enabling again - ui->checkBoxIgnoreZoom->hide(); - - CoreParameter* coreParams = dynamic_cast(model); - - int trial = dynamic_cast(controller)->getTrialNumber(); - ui->label_ExpTrialNo->setText(std::to_string(trial).c_str()); - - fillUI(); - setStyle(); - - getNotified(); -} - -CoreParameterView::~CoreParameterView() -{ - delete ui; -} - -QWidget * CoreParameterView::getTrackerHook() -{ - //return ui->tabWidgetParameters; - //dead code - return nullptr; -} - -void CoreParameterView::setPermission(std::pair permission) -{ - - //first check if permission is for view, if not pass permission to shapes -> view has all permissions, shapes only certain ones - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTVIEW && permission.second == false) { - //disable everything but the area descriptor groupbox - ui->checkBoxEnableCoreView->setEnabled(false); - ui->groupBoxTracks->setEnabled(false); - ui->groupBoxTracing->setEnabled(false); - ui->groupBoxMiscellaneous->setEnabled(false); - ui->groupBoxAnno->setEnabled(false); - ui->groupBoxRectificationParm->setEnabled(true); - _expertSwitch->setEnabled(false); - return; - } - //does not need to be propagated to shapes; only handled by view - //TODO: move this to controller - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTADD && permission.second == false) { - this->ui->pushButton_addTraj->setDisabled(true); - return; - } - - -} - -void CoreParameterView::triggerUpdate() { - on_checkBoxDisplayTrackingArea_stateChanged(0); - on_checkBoxDisplayRectification_stateChanged(0); - on_checkboxTrackingAreaAsEllipse_stateChanged(0); -} - -void CoreParameterView::areaDescriptorTypeChanged(QString type) { - if (type != "0") { - ui->checkboxTrackingAreaAsEllipse->setChecked(true); - } - else { - ui->checkboxTrackingAreaAsEllipse->setChecked(false); - } -} - -void CoreParameterView::on_checkBoxEnableCoreView_stateChanged(int v) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - //disable - if (ui->checkBoxEnableCoreView->checkState() == Qt::Unchecked) { - //disable all groupboxes but the area descriptor one - ui->groupBoxTracks->setEnabled(false); - ui->groupBoxTracing->setEnabled(false); - ui->groupBoxMiscellaneous->setEnabled(false); - ui->groupBoxAnno->setEnabled(false); - ui->groupBoxRectificationParm->setEnabled(true); - _expertSwitch->setEnabled(false); - - - emitViewSwitch(false); - coreParams->m_viewSwitch = false; - } - //enable - else if (ui->checkBoxEnableCoreView->checkState() == Qt::Checked){ - //enable all groupboxes - ui->groupBoxTracks->setEnabled(true); - ui->groupBoxTracing->setEnabled(true); - ui->groupBoxMiscellaneous->setEnabled(true); - ui->groupBoxAnno->setEnabled(true); - ui->groupBoxRectificationParm->setEnabled(true); - _expertSwitch->setEnabled(true); - - emitViewSwitch(true); - coreParams->m_viewSwitch = true; - } -} - -void CoreParameterView::on_comboBoxTracingStyle_currentIndexChanged(const QString & text) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_tracingStyle = text; - emitTracingStyle(text); -} - -void CoreParameterView::on_spinBoxTracingHistoryLength_valueChanged(int i) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - //int value = ui->spinBoxTracingHistoryLength->value(); - coreParams->m_tracingHistory = i; - emitTracingHistoryLength(i); -} - -void CoreParameterView::on_spinBoxTracingSteps_valueChanged(int i) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - //int value = ui->spinBoxTracingSteps->value(); - coreParams->m_tracingSteps = i; - emitTracingSteps(i); -} - -void CoreParameterView::on_comboBoxTracingTimeDegradation_currentIndexChanged(const QString & text) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_tracingTimeDegradation = text; - emitTracingTimeDegradation(text); -} - -void CoreParameterView::on_checkBoxTracerFrameNumber_stateChanged(int toggle) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_tracerFrameNumber = toggle; - emitTracerFrameNumber(toggle); -} - -void CoreParameterView::on_spinBoxTracerProportions_valueChanged(double d) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - //float value = (float)ui->spinBoxTracerProportions->value(); - coreParams->m_tracerProportions = d; - emitTracerProportions(d); -} - -void CoreParameterView::on_checkBoxTracerOrientationLine_stateChanged(int toggle) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_tracerOrientationLine = toggle; - emitTracerOrientationLine(toggle); -} - -// void CoreParameterView::on_pushButtonSelectAll_clicked() -// { -// emitSelectAll(); -// } - -// void CoreParameterView::on_pushButtonAddTrack_clicked() -// { -// emitAddTrack(); -// } - -void CoreParameterView::on_checkBoxIgnoreZoom_stateChanged(int v) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_ignoreZoom = v; - emitIgnoreZoom(v); -} -//TODO show current color -void CoreParameterView::on_pushButtonColorChangeBorder_clicked() -{ - emitColorChangeBorderAll(); -} - -void CoreParameterView::on_pushButtonColorChangeBorderSelected_clicked() -{ - emitColorChangeBorderSelected(); -} -//TODO show current color -void CoreParameterView::on_pushButtonColorChangeBrush_clicked() -{ - emitColorChangeBrushAll(); -} - -void CoreParameterView::on_pushButtonColorchangeBrushSelected_clicked() -{ - emitColorChangeBrushSelected(); -} - -void CoreParameterView::on_checkBoxTrackOrientationLine_stateChanged(int v) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_trackOrientationLine = v; - emitTrackOrientationLine(v); -} - -void CoreParameterView::on_checkBoxShowId_stateChanged(int v) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_trackShowId = v; - emitTrackShowId(v); -} - -// if dimensions are set for all tracks they are going to be set for new tracks aswell -void CoreParameterView::on_pushButtonTrackDimensionSetterAll_clicked() -{ - int width = ui->spinboxTrackWidth->value(); - int height = ui->spinBoxTrackHeight->value(); - - CoreParameter* coreParams = dynamic_cast(getModel()); - if (coreParams) { - coreParams->m_trackWidth = width; - coreParams->m_trackHeight = height; - - emitTrackDimensionsAll(width, height); - } -} - -void CoreParameterView::on_pushButtonTrackDimensionSetterSelected_clicked() -{ - int width = ui->spinboxTrackWidth->value(); - int height = ui->spinBoxTrackHeight->value(); - emitTrackDimensionsSelected(width, height); -} - -void CoreParameterView::on_pushButtonDefaultDimensions_clicked() -{ - emitTrackDimensionsSetDefault(); -} - -void CoreParameterView::on_lineEditRectWidth_textChanged(QString s) { - double w = std::max(::atof(ui->lineEditRectWidth->text().toStdString().c_str()), std::numeric_limits::epsilon()); - double h = std::max(::atof(ui->lineEditRectHeight->text().toStdString().c_str()), std::numeric_limits::epsilon()); - Q_EMIT emitRectDimensions(w,h); -} - -void CoreParameterView::on_lineEditRectHeight_textChanged(QString s) { - double w = std::max(::atof(ui->lineEditRectWidth->text().toStdString().c_str()), std::numeric_limits::epsilon()); - double h = std::max(::atof(ui->lineEditRectHeight->text().toStdString().c_str()), std::numeric_limits::epsilon()); - Q_EMIT emitRectDimensions(w, h); -} - -void CoreParameterView::on_checkBoxDisplayTrackingArea_stateChanged(int v) { - Q_EMIT emitDisplayTrackingArea(ui->checkBoxDisplayTrackingArea->isChecked()); -} - -void CoreParameterView::on_checkBoxDisplayRectification_stateChanged(int v) { - Q_EMIT emitDisplayRectification(ui->checkBoxDisplayRectification->isChecked()); -} - -void CoreParameterView::on_checkboxTrackingAreaAsEllipse_stateChanged(int v) { - Q_EMIT emitTrackingAreaAsEllipse(ui->checkboxTrackingAreaAsEllipse->isChecked()); -} - -void CoreParameterView::on_pushButtonAnnoColor_clicked() -{ - QPalette pal = ui->pushButtonAnnoColor->palette(); - QColor oldColor = pal.color(QPalette::Button); - QColor newAnnoColor = QColorDialog::getColor(oldColor, Q_NULLPTR ,"Set new annotation color", QColorDialog::ShowAlphaChannel); - - if (newAnnoColor.isValid()) { - QPalette pal = ui->pushButtonAnnoColor->palette(); - pal.setColor(QPalette::Button, newAnnoColor); - ui->pushButtonAnnoColor->setAutoFillBackground(true); - ui->pushButtonAnnoColor->setPalette(pal); - ui->pushButtonAnnoColor->update(); - ui->pushButtonAnnoColor->setAutoFillBackground(true); - ui->pushButtonAnnoColor->setFlat(true); - - Q_EMIT emitSetAnnoColor(newAnnoColor); - } - - -} - -void CoreParameterView::toggleExpertOptions(bool toggle){ - ui->groupBoxTracerDimensions->setVisible(toggle); - ui->groupBoxMiscellaneous->setVisible(toggle); - ui->groupBoxTrackDimensions->setVisible(toggle); - ui->groupBoxTracerDimensions->setVisible(toggle); - ui->groupBoxAnno->setVisible(toggle); - - ui->checkBoxTracerFrameNumber->setVisible(toggle); - ui->checkBoxShowId->setVisible(toggle); -} - -void CoreParameterView::on_checkBoxAntialiasingEntities_toggled(bool toggle) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_antialiasingEntities = toggle; - emitToggleAntialiasingEntities(toggle); -} - -void CoreParameterView::on_checkBoxAntialiasingFull_toggled(bool toggle) -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - coreParams->m_antialiasingFull = toggle; - emitToggleAntialiasingFull(toggle); -} - -void CoreParameterView::fillUI() -{ - //add switchbutton for expert options - _expertSwitch = new SwitchButton("not advanced", "advanced"); - ui->widgetParameterLayout->addWidget(_expertSwitch); - QObject::connect(_expertSwitch , &SwitchButton::emitSetEnabled, this, &CoreParameterView::toggleExpertOptions, Qt::DirectConnection); - - //setup ui from params - CoreParameter* coreParams = dynamic_cast(getModel()); - - //view toggle - ui->checkBoxEnableCoreView->setChecked(coreParams->m_viewSwitch); - //track ignore zoom - ui->checkBoxIgnoreZoom->setChecked(coreParams->m_ignoreZoom); - //track orientation line - ui->checkBoxTrackOrientationLine->setChecked(coreParams->m_trackOrientationLine); - //track show id - ui->checkBoxShowId->setChecked(coreParams->m_trackShowId); - //tracer proportions - ui->spinBoxTracerProportions->setValue(coreParams->m_tracerProportions); - //tracer orientation line - ui->checkBoxTracerOrientationLine->setChecked(coreParams->m_tracerOrientationLine); - //tracing style - if (coreParams->m_tracingStyle == "No tracing") { ui->comboBoxTracingStyle->setCurrentIndex(0); } - //tracing time degradation - if (coreParams->m_tracingTimeDegradation == "None") { ui->comboBoxTracingTimeDegradation->setCurrentIndex(0); } - //tracing history - if (coreParams->m_tracingHistory) { ui->spinBoxTracingHistoryLength->setValue(coreParams->m_tracingHistory); } - //tracing steps - if (coreParams->m_tracingSteps) { ui->spinBoxTracingSteps->setValue(coreParams->m_tracingSteps); } - //tracer frame number - ui->checkBoxTracerFrameNumber->setChecked(coreParams->m_tracerFrameNumber); - //antialiasing - ui->checkBoxAntialiasingEntities->setChecked(coreParams->m_antialiasingEntities); - ui->checkBoxAntialiasingFull->setChecked(coreParams->m_antialiasingFull); - //track width - if (coreParams->m_trackWidth) { ui->spinboxTrackWidth->setValue(coreParams->m_trackWidth); } - //track height - if (coreParams->m_trackHeight) { ui->spinBoxTrackHeight->setValue(coreParams->m_trackHeight); } - - //annotation color button - QPalette pal = ui->pushButtonAnnoColor->palette(); - pal.setColor(QPalette::Button, Qt::yellow); - ui->pushButtonAnnoColor->setAutoFillBackground(true); - ui->pushButtonAnnoColor->setPalette(pal); - ui->pushButtonAnnoColor->setFlat(true); - ui->pushButtonAnnoColor->update(); - - //enable/disable widgets - - //expert options - if (_expertSwitch->state()) { - ui->groupBoxTracerDimensions->show(); - ui->groupBoxMiscellaneous->show(); - ui->groupBoxTrackDimensions->show(); - ui->groupBoxAnno->show(); - ui->checkBoxTracerFrameNumber->show(); - ui->checkBoxShowId->show(); - } - else { - ui->groupBoxTracerDimensions->hide(); - ui->groupBoxMiscellaneous->hide(); - ui->groupBoxTrackDimensions->hide(); - ui->groupBoxAnno->hide(); - ui->checkBoxTracerFrameNumber->hide(); - ui->checkBoxShowId->hide(); - - } -} - -void CoreParameterView::setStyle() -{ - //main groupboxes - ui->groupBoxTracks->setStyleSheet("QGroupBox { background-color: #bbdefb;}"); - ui->groupBoxRectificationParm->setStyleSheet("QGroupBox { background-color: #d1c4e9; }"); - ui->groupBoxTracing->setStyleSheet("QGroupBox { background-color: #c8e6c9; }"); - ui->groupBoxMiscellaneous->setStyleSheet("QGroupBox { background-color: #ffecb3; }"); - ui->groupBoxAnno->setStyleSheet("QGroupBox { background-color: #fad8ba; }"); - - //expert options are slightly darker - ui->groupBoxTrackDimensions->setStyleSheet("QGroupBox { background-color: #90caf9;}"); - ui->groupBoxTracerDimensions->setStyleSheet("QGroupBox { background-color: #a5d6a7;}"); - - //default groupbox style - ui->widgetParameter->setStyleSheet("QGroupBox" - " {border: 1px solid #e5e5e5; border-radius: 5px; margin-top: 1ex; /* leave space at the top for the title */}" - "QGroupBox::title {subcontrol-origin: margin; padding: -1px 3px; background-color: #e5e5e5; }"); -} - -void CoreParameterView::resetTrial() -{ - _trialActive = false; - _trialStarted = false; - Q_EMIT emitTrialStarted(false); - ui->pushButton_startExp->setText("Start a new Trial"); - -} - -void CoreParameterView::getNotified() -{ - CoreParameter* coreParams = dynamic_cast(getModel()); - ui->labelNumberOfTracks->setText(QString::number(coreParams->m_trackNumber)); - ui->label_ExpObjCnt->setText(QString::number(coreParams->m_trackNumber)); - - int trial = dynamic_cast(getController())->getTrialNumber() + 1; - ui->label_ExpTrialNo->setText(std::to_string(trial).c_str()); -} - -/************EXPERIMENT TAB*******************/ - -void CoreParameterView::on_pushButton_startExp_clicked() { - if (!_trialActive) { - - if (_currentFile == "No Media"){ - int ret = QMessageBox::information(this, tr("BioTracker"), - tr("Please select a source video first. \nYou can do so in the \"File\" menu."), - QMessageBox::Ok); - } - else { - if (!_trialStarted) { - QMessageBox::StandardButton reply; - reply = QMessageBox::question(this, "Confirmation", "Are you sure you want to start a new trial?" - "\nThis will reset the previous tracking data!", - QMessageBox::Yes|QMessageBox::No); - if (reply == QMessageBox::No) { - qDebug() << "CORE: New trial aborted"; - return; - } - - _trialStarted = true; - emitTrialStarted(true); - emitFinalizeExperiment(); - emitPausePlayback(); - QMessageBox::information(0, "New trial", "You started a new trial! Previous data was saved and reset.\n\nGo to the timespot in the video you want to track at." - "\n\nPlease add the number of objects you want to track as trajectories.\nResume the video." ); - } - else { - emitStartPlayback(); - } - emitDeactivateTrackingSwitch(); - emitEnableTracking(); - ui->pushButton_startExp->setText("Pause Trial"); - ui->label_ExpSt->setText("Active - tracking"); - _trialActive = true; - } - } - else { - - emitDisableTracking(); - emitPausePlayback(); - ui->pushButton_startExp->setText("Resume Trial"); - ui->label_ExpSt->setText("Paused - not tracking"); - _trialActive = false; - } -} - -void CoreParameterView::on_pushButton_finalizeExp_clicked() { - QMessageBox::StandardButton reply; - reply = QMessageBox::question(this, "Confirmation", "Are you sure you want to finalize the trial?" - "\nThis will save the current trial tracking" - " data in a new file in the 'Trials' directory" - " and reset it afterwards!", - QMessageBox::Yes|QMessageBox::No); - if (reply == QMessageBox::No) { - qDebug() << "CORE: Finalize trial aborted!"; - return; - } - - Q_EMIT emitStopPlayback(); - Q_EMIT emitActivateTrackingSwitch(); - Q_EMIT emitDisableTracking(); - _trialActive = false; - _trialStarted = false; - ui->pushButton_startExp->setText("Start a new Trial"); - ui->label_ExpSt->setText("No Trial started!"); - Q_EMIT emitTrialStarted(false); - Q_EMIT emitFinalizeExperiment(); -} - -void CoreParameterView::on_label_ExpSrcCnt_clicked() { - //Event does not exist -} - -void CoreParameterView::on_trialHelpButton_clicked() -{ - QMessageBox::information(0, "Trials", "'Start a new Trial' will cause all the previous data to be saved and then reset.\n\n" - "Go to the time spot you want to track and create a trajectory for each object you want to track.\n" - "Resume the video and the tracker will track your objects.\n\n" - "If you want to pause the tracking you can just pause the video. Resuming the video will continue the tracking.\n" - "If you want to pause the video and resume without tracking you will have to click 'Pause Trial' causing the tracking to be disabled.\n" - "You can now watch the video without tracking.\n\n" - "'Resume trial' will cause the tracking to be activated AND the video to be resumed"); -} - -void CoreParameterView::on_pushButton_saveData_clicked(){ - emitSaveDataToFile(); -} - -void CoreParameterView::on_pushButton_resetData_clicked(){ - QMessageBox::StandardButton reply; - reply = QMessageBox::question(this, "Confirmation", "Are you sure you want to reset the current tracking data?" - "This will firstly save the data and then reset it!", - QMessageBox::Yes|QMessageBox::No); - if (reply == QMessageBox::No) { - qDebug() << "CORE: Data reset aborted"; - return; - } - Q_EMIT emitFinalizeExperiment(); -} - - -void CoreParameterView::on_pushButton_addTraj_clicked(){ - emitAddTrack(); -} - -void CoreParameterView::rcvPlayerParameters(playerParameters* parameters) { - QFileInfo f(parameters->m_CurrentFilename); - _currentFile = f.baseName(); - ui->label_ExpSrcCnt->setText(_currentFile); -} - diff --git a/BioTracker/CoreApp/BioTracker/View/CoreParameterView.h b/BioTracker/CoreApp/BioTracker/View/CoreParameterView.h deleted file mode 100644 index b34d7473..00000000 --- a/BioTracker/CoreApp/BioTracker/View/CoreParameterView.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef COREPARAMETERVIEW_H -#define COREPARAMETERVIEW_H - -#include "Interfaces/IView/IViewWidget.h" -#include "View/Utility/SwitchButton.h" -//TODO add default parameters accesible via config -//#include "Model/CoreViewParameter.h" -#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" - -namespace Ui { - class CoreParameterView; -} - -/** -* This class contains the 'Experiment' tab and the 'Visualisation options' tab in the GUI -* It basically displays the current set parameters -* The -*/ - -class CoreParameterView : public IViewWidget -{ - Q_OBJECT - -public: - explicit CoreParameterView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - ~CoreParameterView(); - - QWidget* getTrackerHook(); - void setPermission(std::pair permission); - - // Triggers re-sending essential signals - void triggerUpdate(); - - void areaDescriptorTypeChanged(QString type); - - private slots: - - /* - VIEW TAB - */ - //Enable view - void on_checkBoxEnableCoreView_stateChanged(int v); - //Tracing - void on_comboBoxTracingStyle_currentIndexChanged(const QString & text); - void on_spinBoxTracingHistoryLength_valueChanged(int i); - void on_spinBoxTracingSteps_valueChanged(int i); - void on_comboBoxTracingTimeDegradation_currentIndexChanged(const QString & text); - void on_checkBoxTracerFrameNumber_stateChanged(int toggle); - - void on_spinBoxTracerProportions_valueChanged(double d); - void on_checkBoxTracerOrientationLine_stateChanged(int toggle); - - //Track - //void on_pushButtonSelectAll_clicked(); - //void on_pushButtonAddTrack_clicked(); - - void on_checkBoxIgnoreZoom_stateChanged(int v); - - //Track color - void on_pushButtonColorChangeBorder_clicked(); - void on_pushButtonColorChangeBorderSelected_clicked(); - void on_pushButtonColorChangeBrush_clicked(); - void on_pushButtonColorchangeBrushSelected_clicked(); - - //Track dimensions - void on_checkBoxTrackOrientationLine_stateChanged(int v); - void on_checkBoxShowId_stateChanged(int v); - - - void on_pushButtonTrackDimensionSetterAll_clicked(); - void on_pushButtonTrackDimensionSetterSelected_clicked(); - void on_pushButtonDefaultDimensions_clicked(); - - //Area descriptor - void on_lineEditRectWidth_textChanged(QString s); - void on_lineEditRectHeight_textChanged(QString s); - void on_checkBoxDisplayTrackingArea_stateChanged(int v); - void on_checkBoxDisplayRectification_stateChanged(int v); - void on_checkboxTrackingAreaAsEllipse_stateChanged(int v); - - //Annotations - void on_pushButtonAnnoColor_clicked(); - - //Finalize experiment - //void on_pushButtonFinalizeExperiment_clicked(); - - //Misc - //void on_checkBoxExpertOptions_stateChanged(int v); - void toggleExpertOptions(bool toggle); - void on_checkBoxAntialiasingEntities_toggled(bool toggle); - void on_checkBoxAntialiasingFull_toggled(bool toggle); - - /* - EXPERIMENT TAB - */ - - //label_ExpTrialNo - //label_ExpSrcCnt - //label_ExpObjCnt - //pushButton_startExp - //pushButton_finalizeExp - void on_pushButton_startExp_clicked(); - void on_pushButton_finalizeExp_clicked(); - void on_label_ExpSrcCnt_clicked(); - void on_trialHelpButton_clicked(); - void on_pushButton_saveData_clicked(); - void on_pushButton_resetData_clicked(); - void on_pushButton_addTraj_clicked(); - public slots: - void rcvPlayerParameters(playerParameters* parameters); - - -public: - signals : - - /* - EXPERIMENT TAB - */ - void emitEnableTracking(); - void emitDisableTracking(); - void emitActivateTrackingSwitch(); - void emitDeactivateTrackingSwitch(); - void emitStartPlayback(); - void emitStopPlayback(); - void emitPausePlayback(); - void emitTrialStarted(bool started); - void emitSaveDataToFile(); - - - //Enable view - void emitViewSwitch(bool lever); - //Select all tracks - //void emitSelectAll(); - //Add tracks - void emitAddTrack(); - //Ignore zoom - void emitIgnoreZoom(bool toggle); - //Track color - void emitColorChangeBorderAll(); - void emitColorChangeBorderSelected(); - void emitColorChangeBrushAll(); - void emitColorChangeBrushSelected(); - //Track dimensions - void emitTrackOrientationLine(bool toggle); - void emitTrackShowId(bool toggle); - void emitTrackDimensionsAll(int width, int height); - void emitTrackDimensionsSelected(int width, int height); - void emitTrackDimensionsSetDefault(); - //Tracing - void emitTracingHistoryLength(int history); - void emitTracingStyle(QString style); - void emitTracingSteps(int steps); - void emitTracingTimeDegradation(QString degradation); - void emitTracerFrameNumber(bool toggle); - //Tracing dimensions - void emitTracerProportions(float proportion); - void emitTracerOrientationLine(bool toggle); - - //Area descriptor - void emitRectDimensions(double w, double h); - void emitDisplayTrackingArea(bool b); - void emitDisplayRectification(bool b); - void emitTrackingAreaAsEllipse(bool b); - - //Annotations - void emitSetAnnoColor(QColor color); - - //Finalize Experiment - void emitFinalizeExperiment(); - - //Misc - void emitToggleAntialiasingEntities(bool toggle); - void emitToggleAntialiasingFull(bool toggle); - -private: - Ui::CoreParameterView *ui; /**< processed ui file */ - - bool m_viewSwitch; /**< switch to enable/disable visualization options tab */ - SwitchButton* _expertSwitch; /**< switch to expand visualization options tab */ - bool _trialActive = false; /**< currently trial active? */ - bool _trialStarted = false; /**< was trial started? */ - QString _currentFile = "No Media"; /**< show media name in experiment tab */ - - // IViewWidget interface - public slots: - - void getNotified(); - - /// fills the ui elements with the current default parameters - void fillUI(); - - /// styles the "visualisation options" tab - void setStyle(); - void resetTrial(); - -}; - -#endif // COREPARAMETERVIEW_H diff --git a/BioTracker/CoreApp/BioTracker/View/GLVideoView.cpp b/BioTracker/CoreApp/BioTracker/View/GLVideoView.cpp deleted file mode 100644 index 888ae1df..00000000 --- a/BioTracker/CoreApp/BioTracker/View/GLVideoView.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "GLVideoView.h" - -#include -#include "Interfaces/IController/IController.h" - -#include "Model/TextureObject.h" - - -GLVideoView::GLVideoView(QWidget *parent, IController *controller, IModel *model): - IViewOpenGLWidget(parent, controller, model) -{ -} - -GLVideoView::~GLVideoView() -{ - -} - -void GLVideoView::paintGL() -{ - TextureObject *textureObject = dynamic_cast(getModel()); - QImage img = textureObject->get(); - - - QPainter painter(this); - - painter.setBrush(QColor(0, 0, 0)); - painter.drawRect(QRect(0, 0, this->width(), this->height())); - painter.setBrush(QColor(0, 0, 0, 0)); - - QRect window; - QRect viewport; - const float viewport_skew = BioTracker::Core::ScreenHelper::calculate_viewport( - textureObject->width(), - textureObject->height(), - this->width(), - this->height(), - window, - viewport - ); - - painter.setWindow(window); - painter.setViewport(viewport); - - QRectF target(0, 0 , textureObject->width(), textureObject->height()); - QRectF source(0, 0, textureObject->width(), textureObject->height()); - - - - painter.drawImage(target, img, source); - QPainter p(this); - -} - -void GLVideoView::getNotified() -{ - this->update(); -} diff --git a/BioTracker/CoreApp/BioTracker/View/GraphicsScene.cpp b/BioTracker/CoreApp/BioTracker/View/GraphicsScene.cpp deleted file mode 100644 index 4584e2e3..00000000 --- a/BioTracker/CoreApp/BioTracker/View/GraphicsScene.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "GraphicsScene.h" - -GraphicsScene::GraphicsScene(QObject *parent, IController *controller, IModel *model) : - IViewGraphicsScene(parent, controller, model) -{ - -} - -void GraphicsScene::getNotified() -{ - -} diff --git a/BioTracker/CoreApp/BioTracker/View/GraphicsView.cpp b/BioTracker/CoreApp/BioTracker/View/GraphicsView.cpp deleted file mode 100644 index 5ab7851c..00000000 --- a/BioTracker/CoreApp/BioTracker/View/GraphicsView.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "GraphicsView.h" -#include "QTimeLine" -#include "QWheelEvent" -#include "../Controller/ControllerGraphicScene.h" - -#include - -#include -#include -#include -#include -#include -#include - -GraphicsView::GraphicsView(QWidget *parent, IController *controller, IModel *model) : - IViewGraphicsView(parent, controller, model) -{ - m_GraphicsScene = new QGraphicsScene(); - m_BackgroundImage = NULL; - - this->setScene(m_GraphicsScene); - //this->setViewport(new QGLWidget()); - - this->setBackgroundBrush(QBrush(Qt::white)); - - this->show(); - - setTransformationAnchor(AnchorUnderMouse); - setViewportUpdateMode(FullViewportUpdate); - - setDragMode(RubberBandDrag); -} - -void GraphicsView::addGraphicsItem(QGraphicsItem *item) -{ - m_GraphicsScene->addItem(item); - - update(); -} - -void GraphicsView::removeGraphicsItem(QGraphicsItem *item) -{ - m_GraphicsScene->removeItem(item); - - update(); -} - -void GraphicsView::addPixmapItem(QGraphicsItem *item) -{ - m_BackgroundImage = item; - m_GraphicsScene->addItem(item); - item->setZValue(-5); - - update(); -} - -void GraphicsView::getNotified() -{ - -} - -void GraphicsView::wheelEvent(QWheelEvent *event) -{ - //if ctrl pressed, use original functionality - if (event->modifiers() & Qt::ControlModifier) - { - QGraphicsView::wheelEvent(event); - } - //otherwise, do yours - else - { - if (event->delta() > 0) - { - scale(1.1, 1.1); - } - else - { - scale(0.9, 0.9); - } - } -} - -void GraphicsView::keyReleaseEvent(QKeyEvent *event) -{ - emit(onKeyReleaseEvent(event)); -} - -void GraphicsView::keyPressEvent(QKeyEvent * event) -{ - emit(onKeyPressEvent(event)); -} - -void GraphicsView::mousePressEvent(QMouseEvent *event) -{ - // The middle mouse button is not forwarded but handled here. - if (event->buttons() & Qt::MidButton) - { - m_ViewportDragOrigin = event->pos(); - } - else - { - const QPointF imagePosition = mapToScene(event->pos()); - const QPoint imagePositionInt = QPoint(imagePosition.x(), imagePosition.y()); - event->ignore(); - emit(onMousePressEvent(event, imagePositionInt)); - if (!event->isAccepted()) - QGraphicsView::mousePressEvent(event); - } -} - -void GraphicsView::mouseReleaseEvent(QMouseEvent*event) -{ - if (!(event->buttons() & Qt::MidButton)) - { - const QPointF imagePosition = mapToScene(event->pos()); - const QPoint imagePositionInt = QPoint(imagePosition.x(), imagePosition.y()); - event->ignore(); - emit(onMouseReleaseEvent(event, imagePositionInt)); - if (!event->isAccepted()) - QGraphicsView::mouseReleaseEvent(event); - } -} - -void GraphicsView::mouseMoveEvent(QMouseEvent*event) -{ - viewport()->update(); - // The middle mouse button is not forwarded but handled here. - if (event->buttons() & Qt::MidButton) - { - const QPoint currentPosition{ event->pos() }; - // Ignore position-reset events.. - if (currentPosition != m_ViewportDragOrigin) - { - const QPoint currentPositionScene = currentPosition; - const QPoint originPositionScene = m_ViewportDragOrigin; - const auto offset = currentPositionScene - originPositionScene; - - QGraphicsView::horizontalScrollBar()->setValue(horizontalScrollBar()->value() + offset.x() + 1); - QGraphicsView::verticalScrollBar()->setValue(verticalScrollBar()->value() + offset.y() + 1); - // Freeze mouse position in place. - QCursor::setPos(mapToGlobal(m_ViewportDragOrigin)); - } - } - else - { - const QPointF imagePosition = mapToScene(event->pos()); - const QPoint imagePositionInt = QPoint(imagePosition.x(), imagePosition.y()); - m_cursorPos = imagePositionInt; - emitCursorPosition(m_cursorPos); //to mainwindow - event->ignore(); - emit(onMouseMoveEvent(event, imagePositionInt)); - if (!event->isAccepted()) - QGraphicsView::mouseMoveEvent(event); - } -} - -void GraphicsView::receiveToggleAntialiasingFull(bool toggle){ - setRenderHint(QPainter::Antialiasing, toggle); -} \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/GraphicsView.h b/BioTracker/CoreApp/BioTracker/View/GraphicsView.h deleted file mode 100644 index a289bc70..00000000 --- a/BioTracker/CoreApp/BioTracker/View/GraphicsView.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef GRAPHICSVIEW_H -#define GRAPHICSVIEW_H - -#include "Interfaces/IView/IViewGraphicsView.h" -#include "QGraphicsScene" - -class GraphicsView : public IViewGraphicsView -{ - Q_OBJECT -public: - GraphicsView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - - void addGraphicsItem(QGraphicsItem *item); - void addPixmapItem(QGraphicsItem *item); - void removeGraphicsItem(QGraphicsItem *item); - - QGraphicsScene *m_GraphicsScene;//MARKER - - void mousePressEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent*event) override; - void mouseMoveEvent(QMouseEvent*event) override; - void keyReleaseEvent(QKeyEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; - - - // IGraphicsView interface -public Q_SLOTS: - void getNotified() override; - void receiveToggleAntialiasingFull(bool toggle); - - // QWidget interface -protected: - void wheelEvent(QWheelEvent *event) override; - -private: - QGraphicsItem *m_BackgroundImage; - QPoint m_ViewportDragOrigin{ 0, 0 }; - QPoint m_cursorPos; - -Q_SIGNALS: - // If you connect to these signals, you MUST use Qt::DirectConnection. - // You also SHOULD call event->accept() if you handle it. - // You MAY want to only handle events with isAccepted() == false. - void onMousePressEvent(QMouseEvent *event, QPoint imagePosition); - void onMouseReleaseEvent(QMouseEvent*event, QPoint imagePosition); - void onMouseMoveEvent(QMouseEvent*event, QPoint imagePosition); - void onKeyReleaseEvent(QKeyEvent *event); - void onKeyPressEvent(QKeyEvent *event); - - void emitCursorPosition(QPoint pos); - - -}; - -#endif // GRAPHICSVIEW_H diff --git a/BioTracker/CoreApp/BioTracker/View/MainWindow.cpp b/BioTracker/CoreApp/BioTracker/View/MainWindow.cpp deleted file mode 100644 index 7930c5ec..00000000 --- a/BioTracker/CoreApp/BioTracker/View/MainWindow.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -#include "MainWindow.h" -#include "ui_MainWindow.h" - -#include "util/types.h" -#include "util/singleton.h" -#include "settings/Settings.h" - -#include "Controller/ControllerMainWindow.h" -#include "View/CoreParameterView.h" -#include "VideoControllWidget.h" -#include "View/GraphicsView.h" -#include "View/AnnotationsView.h" -#include "Model/null_Model.h" -#include "Controller/null_Controller.h" - - -#include "qfiledialog.h" -#include "QLayout" -#include "QGraphicsObject" -#include -#include -#include -#include -#include "qtextedit.h" -#include -#include "qdesktopwidget.h" -#include "QToolButton" -#include "QWizard" -#include "QWizardPage" -#include "QDesktopServices" - - -MainWindow::MainWindow(QWidget* parent, IController* controller, IModel* model) : - IViewMainWindow(parent, controller, model), - ui(new Ui::MainWindow) { - _previouslySelectedTracker = ""; - _currentParameterView = 0; - _currentCoreParameterView = 0; - _currentElementView = 0; - ui->setupUi(this); - - //add cursor position label - QLabel* _cursorPosition = new QLabel("0,0"); - _cursorPosition->setObjectName("_cursorPosition"); - statusBar()->insertPermanentWidget(0, _cursorPosition); - - //TODO - ui->actionToggle_compact_menu_toolbar_2->setEnabled(false); - - //setup toolbars - setupUpperToolBar(); - setupVideoToolBar(); - ui->toolBarTools->setEnabled(false); - - ui->toolBox->setStyleSheet("QToolBox::tab {" - " background-color: #e5e5e5;}" - ); - - //resize to full size - QWidget::showMaximized(); - - createIntroductionWizard(); - - //set window icon - QApplication::setWindowIcon(QIcon(":/Logo/resources/logo/BT-3_non_transparent_rounded.ico")); - -} - -MainWindow::~MainWindow() { - delete ui; -} - -//******************************************SETUP******************************************* - -void MainWindow::setupUpperToolBar() { - - _trackerActivator = new SwitchButton("not tracking", "tracking"); - _trackerActivator->setToolTip("Activate/Disable tracking"); - QObject::connect(_trackerActivator, &SwitchButton::emitSetEnabled, this, &MainWindow::receiveSetTracking, Qt::DirectConnection); - //QAction* activatorAction = ui->toolBarMenu->addWidget(_trackerActivator); - - /////////////////////media groupbox - _mediaBox = new QGroupBox("Load media"); - //style groupbox (initial red border -> no video loaded) - _mediaBox->setStyleSheet("QGroupBox" - " {border: 1px solid #e56262;}"); - // "QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top center; padding: 0 3px;}"); - QFont font = QFont(); - font.setPointSize(8); - font.setBold(true); - _mediaBox->setFont(font); - - QHBoxLayout* mediaBoxLayout = new QHBoxLayout; - mediaBoxLayout->setContentsMargins(0, 0, 0, 0); - //mediaBoxLayout->setSpacing(0); - QToolButton* cameraButton = new QToolButton; - cameraButton->setIconSize(QSize(24, 24)); - cameraButton->setDefaultAction(ui->actionOpen_Camera); - cameraButton->setAutoRaise(true); - - QToolButton* videoButton = new QToolButton; - videoButton->setIconSize(QSize(24, 24)); - videoButton->setDefaultAction(ui->actionOpen_Video); - videoButton->setAutoRaise(true); - - QToolButton* imageButton = new QToolButton; - imageButton->setIconSize(QSize(24, 24)); - imageButton->setDefaultAction(ui->actionOpen_Picture); - imageButton->setAutoRaise(true); - - mediaBoxLayout->addWidget(videoButton); - mediaBoxLayout->addWidget(imageButton); - mediaBoxLayout->addWidget(cameraButton); - - _mediaBox->setLayout(mediaBoxLayout); - - - ui->toolBarMenu->addWidget(_mediaBox); - - ////////trackerbox - _trackerBox = new QGroupBox("Load tracker"); - //style groupbox - _trackerBox->setStyleSheet("QGroupBox" - " {border: 1px solid #e56262;}"); - // "QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top center; padding: 0 3px;}"); - - QFont font0 = QFont(); - font0.setPointSize(8); - font0.setBold(true); - _trackerBox->setFont(font0); - - QHBoxLayout* trackerBoxLayout = new QHBoxLayout; - trackerBoxLayout->setContentsMargins(0, 0, 0, 0); - - QToolButton* trackerButton = new QToolButton; - trackerButton->setIconSize(QSize(24, 24)); - trackerButton->setDefaultAction(ui->actionLoad_Tracker); - trackerButton->setAutoRaise(true); - - trackerBoxLayout->addWidget(trackerButton); - _trackerBox->setLayout(trackerBoxLayout); - - ui->toolBarMenu->addWidget(_trackerBox); - - - ////////loadSaveBox - QGroupBox* loadSaveBox = new QGroupBox("Load/Save Data"); - //style loadSaveBox - // loadSaveBox->setStyleSheet("QGroupBox" - // " {border: 1px solid #e5e5e5;border-radius: 5px;margin-top: 1ex; /* leave space at the top for the title */}" - // "QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top center; padding: 0 3px;}"); - - QFont font2 = QFont(); - font2.setPointSize(8); - font2.setBold(true); - loadSaveBox->setFont(font2); - - QHBoxLayout* loadSaveBoxLayout = new QHBoxLayout; - loadSaveBoxLayout->setContentsMargins(5, 0, 5, 0); - - QToolButton* loadFileButton = new QToolButton; - loadFileButton->setIconSize(QSize(24, 24)); - loadFileButton->setDefaultAction(ui->actionLoad_trackingdata); - loadFileButton->setAutoRaise(true); - - QToolButton* saveFileButton = new QToolButton; - saveFileButton->setIconSize(QSize(24, 24)); - saveFileButton->setDefaultAction(ui->actionSave_trackingdata); - saveFileButton->setAutoRaise(true); - - loadSaveBoxLayout->addWidget(loadFileButton); - loadSaveBoxLayout->addWidget(saveFileButton); - loadSaveBox->setLayout(loadSaveBoxLayout); - - ui->toolBarMenu->addWidget(loadSaveBox); - - //////////////////choose tracker groupbox - QGroupBox* chooseTrackerBox = new QGroupBox("Choose tracker"); - //style groupbox - // chooseTrackerBox->setStyleSheet("QGroupBox" - // " {border: 1px solid #e5e5e5;border-radius: 5px;margin-top: 1ex; /* leave space at the top for the title */}" - // "QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top center; padding: 0 3px;}"); - - QFont font1 = QFont(); - font1.setPointSize(8); - font1.setBold(true); - chooseTrackerBox->setFont(font1); - // - QHBoxLayout* chooseTrackerBoxLayout = new QHBoxLayout; - chooseTrackerBoxLayout->addWidget(ui->comboBox_TrackerSelect); - chooseTrackerBoxLayout->addWidget(_trackerActivator); - - chooseTrackerBox->setLayout(chooseTrackerBoxLayout); - - ui->toolBarMenu->addWidget(chooseTrackerBox); - - -} - -void MainWindow::checkTrackerGroupBox() { - _trackerBox->setStyleSheet("QGroupBox" - " {border: 1px solid #82c985;}"); -} - -void MainWindow::checkMediaGroupBox() { - _mediaBox->setStyleSheet("QGroupBox" - " {border: 1px solid #82c985;}"); -} - -void MainWindow::setupVideoToolBar() { - -} - - -void MainWindow::addVideoControllWidget(IView* widget) { - QLayout* layout = new QGridLayout(); - //layout->addWidget(dynamic_cast(widget)); - - QWidget* controlW = dynamic_cast(widget); - if (controlW) { - layout->addWidget(controlW->findChild("sld_video")); - } - ui->videoControls->setLayout(layout); - - //ui->videoControls->adjustSize(); - -} - -void MainWindow::addVideoView(IView* videoView) { - m_graphView = dynamic_cast(videoView); - m_graphView->setParent(ui->trackingArea); - - ui->videoViewLayout->addWidget(m_graphView); -} - -void MainWindow::addTrackerElementsView(IView *elemView) -{ - - QGraphicsObject *graphObj = dynamic_cast(elemView); - graphObj->setParent(ui->trackingArea); - - m_graphView->addGraphicsItem(graphObj); - QRectF viewSceneRect = m_graphView->sceneRect(); - - _currentElementView = graphObj; -} - -void MainWindow::addCoreElementsView(IView * coreView) -{ - QGraphicsObject *graphObj = dynamic_cast(coreView); - graphObj->setParent(ui->trackingArea); - - m_graphView->addGraphicsItem(graphObj); - _currentCoreView = graphObj; -} - -void MainWindow::addNotificationBrowser(IView * notificationBrowser) -{ - QWidget* notificationWidget = dynamic_cast(notificationBrowser); - if (notificationWidget) { - notificationWidget->updateGeometry(); - - ui->notificationTab->layout()->addWidget(notificationWidget); - - notificationWidget->setVisible(1); - } - - //createIntroductionWizard(); -} - -void MainWindow::addTrackerParameterView(IView *parameter) -{ - QWidget* pluginParameter = dynamic_cast(parameter); - - - while (auto item = ui->trackerOptions->layout()->takeAt(0)) { - delete item->widget(); - } - - ui->trackerOptions->layout()->addWidget(pluginParameter); - -} - -void MainWindow::addCoreParameterView(IView * coreParameterView) -{ - - QWidget* coreParameter = dynamic_cast(coreParameterView); - if (coreParameter) { - //add experiment widget to toolbar - QWidget* experimentWidget = coreParameter->findChild("experimentWidget"); - if (experimentWidget) { - ui->experimentItem->layout()->addWidget(experimentWidget); - } - - - ui->widget_alg->updateGeometry(); - coreParameter->updateGeometry(); - coreParameter->setContentsMargins(QMargins(0, 0, 0, 0)); - coreParameter->setParent(ui->widget_alg); - - QHBoxLayout* hLayout = new QHBoxLayout; - hLayout->addWidget(coreParameter, 100, 0); - hLayout->setContentsMargins(QMargins(0, 0, 0, 0)); //left, top, right, bottom - hLayout->setMargin(0); - - ui->widget_alg->setLayout(hLayout); - - coreParameter->setVisible(1); - _currentCoreParameterView = coreParameterView; - - - - //resize rightpanel - QList splitterSizes; - splitterSizes << 20000 << 10000; //2:1 TODO make this fixed (right panel fixed start size) - ui->mainSplitter->setSizes(splitterSizes); - - } -} - -void MainWindow::setTrackerList(QStringListModel* trackerList, QString current) { - ui->comboBox_TrackerSelect->setModel(trackerList); - ui->comboBox_TrackerSelect->setCurrentText(current); -} - -//TODO put this in a class -void MainWindow::createIntroductionWizard() { - m_introWiz = new QWizard; - - //BioTracker::Core::Settings *disableIntroWiz = GET_CORESETTINGS(CORE_CONFIGURATION); - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - bool disabled = set->getValueOrDefault("BiotrackerCore/Disable_Wizard", false); - - //dont show again checkbox - QCheckBox* noShowCheck = new QCheckBox("Don't show this again"); - noShowCheck->setChecked(disabled); - QObject::connect(noShowCheck, &QCheckBox::toggled, this, &MainWindow::toggleNoShowWiz); - - - //introduction - QWizardPage* p1 = new QWizardPage; - { - p1->setTitle("BioTracker 3 - Introduction"); - - QPixmap logoImg(":/Logo/resources/logo/BT3-big.png"); - QPixmap scaledImg = logoImg.scaled(QSize(600, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - - QLabel* imgLabel = new QLabel; - imgLabel->setPixmap(scaledImg); - imgLabel->setAttribute(Qt::WA_TranslucentBackground); - imgLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - imgLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - - QFile file(":/Introduction/resources/introduction/intro.txt"); - QLabel *introLabel = new QLabel; - introLabel->setWordWrap(true); - - //read introduction text from file - QString line; - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&file); - while (!stream.atEnd()) { - line.append(stream.readLine() + "\n"); - } - introLabel->setText(line); - } - file.close(); - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(imgLabel); - QScrollArea* textScroll = new QScrollArea; - textScroll->setFrameShape(QFrame::NoFrame); - textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textScroll->setWidget(introLabel); - textScroll->setWidgetResizable(true); - layout->addWidget(textScroll); - layout->setAlignment(Qt::AlignHCenter); - p1->setLayout(layout); - - } - - //overview - QWizardPage* p2 = new QWizardPage; - { - p2->setTitle("BioTracker 3 - Overview"); - QLabel *label = new QLabel("This is the BioTracker. Don't let yourself be overwhelmed as it is actually pretty simple."); - label->setWordWrap(true); - - QPixmap overviewImg(":/Introduction/resources/introduction/images/BioTracker.PNG"); - QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - - QLabel* imgLabel = new QLabel; - imgLabel->setPixmap(scaledImg); - imgLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - //imgLabel->setScaledContents(true); - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(imgLabel); - QScrollArea* textScroll = new QScrollArea; - textScroll->setFrameShape(QFrame::NoFrame); - textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textScroll->setWidget(label); - textScroll->setWidgetResizable(true); - layout->addWidget(textScroll); - layout->setAlignment(Qt::AlignHCenter); - p2->setLayout(layout); - } - - //toolbars - QWizardPage* p3 = new QWizardPage; - { - p3->setTitle("BioTracker 3 - Toolbars"); - - //image - QPixmap overviewImg(":/Introduction/resources/introduction/images/toolbars.png"); - QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - QLabel* imgLabel = new QLabel; - - imgLabel->setPixmap(scaledImg); - - //read toolbar text from file - QFile file(":/Introduction/resources/introduction/toolbars.txt"); - QLabel *label = new QLabel(); - label->setWordWrap(true); - - QString line; - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&file); - while (!stream.atEnd()) { - line.append(stream.readLine() + "\n"); - } - label->setText(line); - } - file.close(); - - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(imgLabel); - QScrollArea* textScroll = new QScrollArea; - textScroll->setFrameShape(QFrame::NoFrame); - textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textScroll->setWidget(label); - textScroll->setWidgetResizable(true); - layout->addWidget(textScroll); - layout->setAlignment(Qt::AlignHCenter); - p3->setLayout(layout); - } - - - //right panel - overview - QWizardPage* p4 = new QWizardPage; - { - p4->setTitle("BioTracker 3 - Right panel overview"); - - //image - QPixmap overviewImg(":/Introduction/resources/introduction/images/right_panel.png"); - QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - QLabel* imgLabel = new QLabel; - imgLabel->setPixmap(scaledImg); - - //read right panel text from file - QFile file(":/Introduction/resources/introduction/right_panel.txt"); - QLabel *label = new QLabel(); - label->setWordWrap(true); - - QString line; - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&file); - while (!stream.atEnd()) { - line.append(stream.readLine() + "\n"); - } - label->setText(line); - } - file.close(); - - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(imgLabel); - QScrollArea* textScroll = new QScrollArea; - textScroll->setFrameShape(QFrame::NoFrame); - textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textScroll->setWidget(label); - textScroll->setWidgetResizable(true); - layout->addWidget(textScroll); - layout->setAlignment(Qt::AlignHCenter); - - p4->setLayout(layout); - } - - - //how to track - QWizardPage* p5 = new QWizardPage; - { - p5->setTitle("BioTracker 3 - Tracking"); - - //image - QPixmap overviewImg(":/Introduction/resources/introduction/images/tracking.png"); - QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - QLabel* imgLabel = new QLabel; - imgLabel->setPixmap(scaledImg); - - //read tracking text from file - QFile file(":/Introduction/resources/introduction/tracking.txt"); - QLabel *label = new QLabel(); - label->setWordWrap(true); - - QString line; - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&file); - while (!stream.atEnd()) { - line.append(stream.readLine() + "\n"); - } - label->setText(line); - } - file.close(); - - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(imgLabel); - QScrollArea* textScroll = new QScrollArea; - textScroll->setFrameShape(QFrame::NoFrame); - textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textScroll->setWidget(label); - textScroll->setWidgetResizable(true); - layout->addWidget(textScroll); - layout->setAlignment(Qt::AlignHCenter); - - p5->setLayout(layout); - } - - //context menus - QWizardPage* p6 = new QWizardPage; - { - p6->setTitle("BioTracker 3 - Context menus"); - - //images - QPixmap contextEntityImg(":/Introduction/resources/introduction/images/context_entity.png"); - QPixmap scaledImg1 = contextEntityImg.scaled(QSize(300, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - QLabel* imgEntityLabel = new QLabel; - imgEntityLabel->setPixmap(scaledImg1); - - QPixmap contextVideoImg(":/Introduction/resources/introduction/images/context_video.png"); - QPixmap scaledImg2 = contextVideoImg.scaled(QSize(300, 400), Qt::KeepAspectRatio, Qt::SmoothTransformation); - QLabel* imgVideoLabel = new QLabel; - imgVideoLabel->setPixmap(scaledImg2); - - //read tracking text from file - QFile file(":/Introduction/resources/introduction/context_menus.txt"); - QLabel *label = new QLabel(); - label->setWordWrap(true); - - QString line; - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&file); - while (!stream.atEnd()) { - line.append(stream.readLine() + "\n"); - } - label->setText(line); - } - file.close(); - - - QVBoxLayout *outerLayout = new QVBoxLayout; - QHBoxLayout *imgLayout = new QHBoxLayout; - imgLayout->addWidget(imgEntityLabel); - imgLayout->addWidget(imgVideoLabel); - QFrame* imgFrame = new QFrame; - imgFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken); - imgFrame->setLayout(imgLayout); - - outerLayout->addWidget(imgFrame); - QScrollArea* textScroll = new QScrollArea; - textScroll->setFrameShape(QFrame::NoFrame); - textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - textScroll->setWidget(label); - textScroll->setWidgetResizable(true); - outerLayout->addWidget(textScroll); - outerLayout->addWidget(noShowCheck); - - outerLayout->setAlignment(Qt::AlignHCenter); - - p6->setLayout(outerLayout); - } - - - m_introWiz->addPage(p1); - m_introWiz->addPage(p2); - m_introWiz->addPage(p3); - m_introWiz->addPage(p4); - m_introWiz->addPage(p5); - m_introWiz->addPage(p6); - //m_introWiz->addPage(p7); - - - m_introWiz->setWindowTitle("Introduction"); - if (!disabled) { - QRect rec = QApplication::desktop()->availableGeometry(); - m_introWiz->resize(m_introWiz->width(), 500); - m_introWiz->show(); - //m_introWiz->showMaximized(); - } -} - -/////////////////////////////////////////// - -void MainWindow::setCorePermission(std::pair permission) { - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTADD) { - ui->actionAdd_Track->setEnabled(permission.second); - return; - } - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTREMOVE) { - ui->actionDelete_selected_tracks->setEnabled(permission.second); - return; - } - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTSWAP) { - ui->actionSwap_ID_s->setEnabled(permission.second); - return; - } -} - -void MainWindow::on_comboBox_TrackerSelect_currentIndexChanged(QString s) { - QString ct = ui->comboBox_TrackerSelect->currentText(); - if (!ct.isEmpty() && _previouslySelectedTracker != ct) { - _previouslySelectedTracker = ct; - Q_EMIT selectPlugin(ct); - } -} - -void MainWindow::setCursorPositionLabel(QPoint pos) -{ - QString posString = QString("%1, %2").arg(QString::number(pos.x()), QString::number(pos.y())); - - - QLabel* currentChild = statusBar()->findChild("_cursorPosition"); - currentChild->setText(posString); - -} - -void MainWindow::activeTrackingCheckBox() { - //ui->checkBox_TrackingActivated->setEnabled(true); - _trackerActivator->setEnabled(true); - checkTrackerGroupBox(); - ui->toolBarTools->setEnabled(true); -} - -void MainWindow::deactivateTrackingCheckBox() { - //ui->checkBox_TrackingActivated->setEnabled(false); - _trackerActivator->setEnabled(false); -} - -void MainWindow::saveDataToFile() { - static const QString fileFilter( - "tracking data files (*.csv *.dat *.json)"); - - boost::filesystem::path file; - - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - std::string locStr = set->getValueOrDefault(CFG_DEFAULT_LOC_MAN_SAVE, ""); - QString locStrQ = QString::fromStdString(locStr); - - QString f = QFileDialog::getSaveFileName(this, "Save trajectory data to file", locStrQ, fileFilter, 0); - - if (f != "") { - qobject_cast (getController())->saveTrajectoryFile(f.toStdString()); - } -} - -////////////////////////////////////////////////SLOTS///////////////////////////////////// - -void MainWindow::toggleNoShowWiz(bool toggle) { - - BioTracker::Core::Settings *disableIntroWiz = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - disableIntroWiz->setParam("BiotrackerCore/Disable_Wizard", toggle); -} - -void MainWindow::receiveSelectedCameraDevice(CameraConfiguration conf) { - qobject_cast (getController())->loadCameraDevice(conf); - -} - -void MainWindow::on_rightPanelViewControllerButton_clicked() { - QList splitterSizes = QList(); - if (ui->widgetParameterAreaOuterCanvas->isVisible()) { - _lastRightPanelWidth = ui->mainSplitter->sizes()[1]; //save last width to restore on show - _lastVideoWidgetWidth = ui->mainSplitter->sizes()[0]; - - ui->widgetParameterAreaOuterCanvas->hide(); - splitterSizes << 20000 << ui->rightPanelViewControllerWidget->minimumSizeHint().width(); - - ui->rightPanelViewControllerButton->setText("<"); - //set menu action unchecked - ui->actionRight_panel->setChecked(false); - } - else { - ui->widgetParameterAreaOuterCanvas->show(); - splitterSizes << _lastVideoWidgetWidth << _lastRightPanelWidth; - ui->rightPanelViewControllerButton->setText(">"); - - //set menu action checked - ui->actionRight_panel->setChecked(true); - } - ui->mainSplitter->setSizes(splitterSizes); -} - -void MainWindow::on_bottomPanelViewControllerButton_clicked() { - ui->videoControls->setVisible(ui->bottomPanelViewControllerButton->text() == "^"); - ui->bottomPanelViewControllerButton->setText(ui->bottomPanelViewControllerButton->text() == "v" ? "^" : "v"); -} - -void MainWindow::activateTracking() { - _trackerActivator->setState(true); -} - -void MainWindow::deactivateTracking() { - _trackerActivator->setState(false); -} - -void MainWindow::receiveSetTracking(bool toggle) { - if (toggle) { - qobject_cast (getController())->activeTracking(); - } - else { - qobject_cast (getController())->deactiveTrackring(); - } -} - -void MainWindow::resetTrackerViews() { - if (_currentElementView && _currentCoreView) { - _currentElementView->setParent(0); - _currentCoreView->setParent(0); - m_graphView->removeGraphicsItem(_currentElementView); - m_graphView->removeGraphicsItem(_currentCoreView); - } - - _currentElementView = nullptr; - _currentCoreView = nullptr; -} - -//////////////////////////utility toolbar action slots/////////////////////////// -void MainWindow::on_actionAdd_Track_triggered() { - qobject_cast (getController())->emitAddTrack(); -} -void MainWindow::on_actionDelete_selected_tracks_triggered() { - qobject_cast (getController())->emitDeleteSelectedTracks(); -} -void MainWindow::on_actionSwap_ID_s_triggered() { - qobject_cast (getController())->emitSwapIds(); - -} -void MainWindow::on_actionSelect_all_triggered() { - qobject_cast (getController())->emitSelectAll(); -} -void MainWindow::on_actionChange_the_border_color_triggered() { - qobject_cast (getController())->emitChangeColorBorder(); -} -void MainWindow::on_actionChange_the_fill_color_triggered() { - qobject_cast (getController())->emitChangeColorFill(); -} -void MainWindow::on_actionAdd_label_Annotation_triggered() { - qobject_cast (getController())->emitAddLabelAnno(); -} -void MainWindow::on_actionAdd_rectangular_annotation_triggered() { - qobject_cast (getController())->emitAddRectAnno(); -} -void MainWindow::on_actionAdd_arrow_annotation_triggered() { - qobject_cast (getController())->emitAddArrAnno(); -} -void MainWindow::on_actionAdd_elliptical_annotation_triggered() { - qobject_cast (getController())->emitAddEllAnno(); -} -void MainWindow::on_actionDelete_selected_Annotation_triggered() { - qobject_cast (getController())->emitDelSelAnno(); -} - - -///////////////////////////////menu->file slots///////////////////////////// - -void MainWindow::on_actionOpen_Video_triggered() { - static const QString videoFilter("Video files (*.avi *.wmv *.mp4 *.mkv *.mov)"); - - QString filename = QFileDialog::getOpenFileName(this, - "Open video", "", videoFilter, 0); - - if (!filename.isEmpty()) { - dynamic_cast (getController())->loadVideo({filename.toStdString().c_str()}); - } -} - -void MainWindow::on_actionLoad_Tracker_triggered() { - static const QString pluginFilter("BioTracker Tracking Plugin files (*.tracker.so *.tracker.dll *.tracker.dylib)"); - - QString filename = QFileDialog::getOpenFileName(this, - "Open BioTracker Tracking Plugin", "", pluginFilter, 0); - - if (!filename.isEmpty()) { - qobject_cast (getController())->loadTracker(filename); - } -} - -void MainWindow::on_actionOpen_Picture_triggered() { - static const QString imageFilter( - "image files (*.png *.jpg *.jpeg *.gif *.bmp *.jpe *.ppm *.tiff *.tif *.sr *.ras *.pbm *.pgm *.jp2 *.dib)"); - - std::vector files; - for (QString const& path : QFileDialog::getOpenFileNames(this, - "Open image files", "", imageFilter, 0)) { - files.push_back(boost::filesystem::path(path.toStdString())); - } - - if (!files.empty()) { - qobject_cast (getController())->loadPictures(files); - } -} - -void MainWindow::on_actionLoad_trackingdata_triggered() { - static const QString imageFilter( - "tracking data files (*.csv *.dat *.json)"); - - std::vector files; - for (QString const& path : QFileDialog::getOpenFileNames(this, - "Open tracking file", "", imageFilter, 0)) { - files.push_back(boost::filesystem::path(path.toStdString())); - } - - if (!files.empty()) { - qobject_cast (getController())->loadTrajectoryFile(files[0].string()); - } -} - -void MainWindow::on_actionSave_trackingdata_triggered() { - saveDataToFile(); -} - -void MainWindow::on_actionOpen_Camera_triggered() { - m_CameraDevice = new CameraDevice(); - - m_CameraDevice->show(); - - QObject::connect(m_CameraDevice, &CameraDevice::emitSelectedCameraDevice, this, &MainWindow::receiveSelectedCameraDevice); -} - -void MainWindow::on_actionQuit_triggered() { - qobject_cast (getController())->exit(); -} - -///////////////////////////////menu->edit slots///////////////////////////// - -void MainWindow::on_actionUndo_triggered() -{ - qobject_cast (getController())->emitUndoCommand(); -} - -void MainWindow::on_actionRedo_triggered() -{ - qobject_cast (getController())->emitRedoCommand(); -} - -void MainWindow::on_actionShowActionList_triggered() -{ - qobject_cast (getController())->emitShowActionListCommand(); -} - -void MainWindow::on_actionSettings_triggered() { - m_SettingsWindow = new SettingsWindow(); - - m_SettingsWindow->show(); -} - -///////////////////////////////menu->view slots///////////////////////////// - -//toggle toolbars actions -void MainWindow::on_actionToggle_menu_toolbar_triggered() { - bool currentState = ui->toolBarMenu->isVisible(); - ui->toolBarMenu->setVisible(!currentState); - ui->actionToggle_menu_toolbar->setText(!currentState ? "Hide menu toolbar" : "Show menu toolbar"); -} -void MainWindow::on_actionToggle_view_toolbar_triggered() { - bool currentState = ui->toolBarTools->isVisible(); - ui->toolBarTools->setVisible(!currentState); - ui->actionToggle_view_toolbar->setText(!currentState ? "Hide view toolbar" : "Show view toolbar"); -} -void MainWindow::on_actionToggle_video_toolbar_triggered() { - bool currentState = ui->toolBarVideo->isVisible(); - ui->toolBarVideo->setVisible(!currentState); - ui->actionToggle_video_toolbar->setText(!currentState ? "Hide view toolbar" : "Show view toolbar"); -} - -void MainWindow::on_actionToggle_compact_menu_toolbar_2_triggered() { - ui->toolBarMenu->setStyleSheet("QGroupBox" - " {border-style: none; margin-top: 0ex; font-size: 1px;}" - "QGroupBox::title {font-size: 1px; padding: 0 3px;}"); - - -} - -void MainWindow::on_toolBarMenu_visibilityChanged(bool visible) { - ui->actionToggle_menu_toolbar->setText(visible ? "Hide menu toolbar" : "Show menu toolbar"); -} -void MainWindow::on_toolBarTools_visibilityChanged(bool visible) { - ui->actionToggle_view_toolbar->setText(visible ? "Hide view toolbar" : "Show view toolbar"); -} -void MainWindow::on_toolBarVideo_visibilityChanged(bool visible) { - ui->actionToggle_video_toolbar->setText(visible ? "Hide video toolbar" : "Show video toolbar"); -} - -void MainWindow::on_actionBottom_panel_triggered(bool checked) { - ui->bottomPanelViewControllerButton->click(); -} -void MainWindow::on_actionRight_panel_triggered(bool checked) { - ui->rightPanelViewControllerButton->click(); -} - -void MainWindow::on_actionToggle_fullscreen_triggered() { - if (isFullScreen()) { - showNormal(); - } - else { - showFullScreen(); - } -} - -//////////////////////////////////menu->Go to slots////////////////////////////////// - -void MainWindow::on_actionOpen_Plugins_directory_triggered() { - QDesktopServices::openUrl(QUrl::fromLocalFile(CFG_DIR_PLUGINS)); -} -void MainWindow::on_actionOpen_Track_directory_triggered() { - QDesktopServices::openUrl(QUrl::fromLocalFile(CFG_DIR_TRACKS)); -} -void MainWindow::on_actionOpen_Trial_directory_triggered() { - QDesktopServices::openUrl(QUrl::fromLocalFile(CFG_DIR_TRIALS)); -} -void MainWindow::on_actionOpen_Screenshot_directory_triggered() { - QDesktopServices::openUrl(QUrl::fromLocalFile(CFG_DIR_SCREENSHOTS)); -} -void MainWindow::on_actionOpen_Videos_directory_triggered() { - QDesktopServices::openUrl(QUrl::fromLocalFile(CFG_DIR_VIDEOS)); -} - - -//////////////////////////////////menu->Help slots////////////////////////////// - -void MainWindow::on_actionUser_guide_triggered() { - QDesktopServices::openUrl(QUrl("https://github.com/BioroboticsLab/biotracker_core/wiki")); -} - -void MainWindow::on_actionAbout_triggered() { - std::string version = ""; - version = "BioTracker3

"; - - version = "Version: "; - version += GIT_HASH; - version += +"

"; - - version += "External libraries used:

"; - std::string qt = MyQT_VERSION; - version += "QT " + qt + "
"; - - std::string cv = MyCV_VERSION; - version += "OpenCV " + cv + "
"; - - std::string boost = MyBT_VERSION; - version += "Boost " + boost + "
"; - - version += "

Icons by icons8
"; - - version += "

Published under LGPL licence"; - - QMessageBox msgBox(this); - msgBox.setWindowTitle("About BioTracker"); - msgBox.setTextFormat(Qt::RichText); //this is what makes the links clickable - msgBox.setText(tr(version.c_str())); - msgBox.exec(); - - //QMessageBox::about(this, tr("About BioTracker"), tr(version.c_str())); -} - -void MainWindow::on_actionShortcuts_triggered() { - - QTableWidget* scTable = new QTableWidget(); - - scTable->setRowCount(0); - scTable->setColumnCount(2); - - scTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Shortcut")); - scTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Description")); - scTable->verticalHeader()->hide(); - - - QLinkedList> scList; - - //read from file in resources and add to linked list - QFile shortcutFile(":Shortcuts/resources/shortcuts.txt"); - - if (!shortcutFile.open(QIODevice::ReadOnly | QIODevice::Text)) - return; - - QString line; - while (!shortcutFile.atEnd()) { - QTextStream stream(&shortcutFile); - while (!stream.atEnd()) { - line = stream.readLine(); - QStringList shortCutAndDescription = line.split(':'); - if (shortCutAndDescription.size() == 2) { - scList.append(QPair(shortCutAndDescription[0], shortCutAndDescription[1])); - } - } - - } - - QLinkedList>::const_iterator sc; - for (sc = scList.constBegin(); sc != scList.constEnd(); ++sc) { - scTable->insertRow(scTable->rowCount()); - - - QTableWidgetItem* scKey = new QTableWidgetItem(sc->first); - QTableWidgetItem* scKeyInfo = new QTableWidgetItem(sc->second); - scKey->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - scKeyInfo->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - - scTable->setItem(scTable->rowCount() - 1, 0, scKey); - scTable->setItem(scTable->rowCount() - 1, 1, scKeyInfo); - } - - - //scTable->horizontalHeader()->setStretchLastSection( true ); - scTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - - QWidget* outerWidget = new QWidget(); - outerWidget->setWindowTitle("Shortcuts"); - outerWidget->resize(scTable->size()); - QVBoxLayout* vLayout = new QVBoxLayout(); - - vLayout->addWidget(scTable); - - outerWidget->setLayout(vLayout); - - - outerWidget->show(); -} - -void MainWindow::on_actionShow_introduction_triggered() { - m_introWiz->show(); -} - -///////////// -void MainWindow::closeEvent(QCloseEvent *event) { - qobject_cast (getController())->exit(); -} \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/MainWindow.h b/BioTracker/CoreApp/BioTracker/View/MainWindow.h deleted file mode 100644 index aab0b64e..00000000 --- a/BioTracker/CoreApp/BioTracker/View/MainWindow.h +++ /dev/null @@ -1,187 +0,0 @@ -#ifndef BIOTRACKER3MAINWINDOW_H -#define BIOTRACKER3MAINWINDOW_H - -//#include -#include "Interfaces/IView/IViewMainWindow.h" - -// delete -#include "GLVideoView.h" -#include "CameraDevice.h" -#include "QPointer" -#include "QStringListModel" -#include "QGraphicsObject" -#include "View/GraphicsView.h" -#include "util/types.h" -#include "SettingsWindow.h" -#include -#include "QWizard" - -#include "Utility/SwitchButton.h" - -namespace Ui { - class MainWindow; -} - -class IController; - - -/** -* This class inherits IViewMainWindow. -* It is the canvas (GUI) for most of the view of other components. -* It also provides its own fuctionality, like an introduction dialog -*/ -class MainWindow : public IViewMainWindow { - Q_OBJECT - -public: - explicit MainWindow(QWidget* parent = 0, IController* controller = 0, IModel* model = 0); - ~MainWindow(); - - void addVideoControllWidget(IView* widget); - void addVideoView(IView* videoView); - void addTrackerParameterView(IView* parameter); - void addCoreParameterView(IView* coreParameterView); - //void addExperimentView(QWidget* experimentWidget); - void addTrackerElementsView(IView *elemView); - void addCoreElementsView(IView* coreView); - void addNotificationBrowser(IView* notificationBrowser); - void setTrackerList(QStringListModel* trackerList, QString current); - void setCursorPositionLabel(QPoint pos); - void setCorePermission(std::pair permission); - - - void activeTrackingCheckBox(); - void deactivateTrackingCheckBox(); - - void closeEvent(QCloseEvent *event); - - void setupUpperToolBar(); - void setupVideoToolBar(); - - //intro wizard - void createIntroductionWizard(); - - void saveDataToFile(); - - void checkTrackerGroupBox(); - void checkMediaGroupBox(); - void activateTracking(); - - void deactivateTracking(); - - void resetTrackerViews(); - -Q_SIGNALS: - void selectPlugin(QString ct); - - private Q_SLOTS: - - void toggleNoShowWiz(bool toggle); - - //menu->File - void on_actionOpen_Video_triggered(); - - void on_actionLoad_Tracker_triggered(); - - void on_actionOpen_Picture_triggered(); - - void on_actionLoad_trackingdata_triggered(); - - void on_actionSave_trackingdata_triggered(); - - void on_actionQuit_triggered(); - - void on_actionOpen_Camera_triggered(); - - //menu->Edit - - void on_actionUndo_triggered(); - - void on_actionRedo_triggered(); - - void on_actionShowActionList_triggered(); - - void on_actionSettings_triggered(); - - //menu->View - //menu->View->Toolbars - void on_actionToggle_menu_toolbar_triggered(); - void on_actionToggle_view_toolbar_triggered(); - void on_actionToggle_compact_menu_toolbar_2_triggered(); - void on_actionToggle_video_toolbar_triggered(); - void on_actionToggle_fullscreen_triggered(); - - //menu->Go to - void on_actionOpen_Plugins_directory_triggered(); - void on_actionOpen_Track_directory_triggered(); - void on_actionOpen_Trial_directory_triggered(); - void on_actionOpen_Screenshot_directory_triggered(); - void on_actionOpen_Videos_directory_triggered(); - - - //view toolbar actions - void on_actionAdd_Track_triggered(); - void on_actionDelete_selected_tracks_triggered(); - void on_actionSwap_ID_s_triggered(); - void on_actionSelect_all_triggered(); - void on_actionChange_the_border_color_triggered(); - void on_actionChange_the_fill_color_triggered(); - void on_actionAdd_label_Annotation_triggered(); - void on_actionAdd_rectangular_annotation_triggered(); - void on_actionAdd_arrow_annotation_triggered(); - void on_actionAdd_elliptical_annotation_triggered(); - void on_actionDelete_selected_Annotation_triggered(); - - //menu->Help - - void on_actionAbout_triggered(); - - void on_actionShortcuts_triggered(); - - void on_actionUser_guide_triggered(); - - void on_actionShow_introduction_triggered(); - //GUI - - void receiveSelectedCameraDevice(CameraConfiguration conf); - - void on_comboBox_TrackerSelect_currentIndexChanged(QString s); - - void receiveSetTracking(bool toggle); - - //hider - void on_rightPanelViewControllerButton_clicked(); - void on_bottomPanelViewControllerButton_clicked(); - void on_actionBottom_panel_triggered(bool checked = false); - void on_actionRight_panel_triggered(bool checked = false); - //ui signals - void on_toolBarMenu_visibilityChanged(bool visible); - void on_toolBarTools_visibilityChanged(bool visible); - void on_toolBarVideo_visibilityChanged(bool visible); - -private: - Ui::MainWindow* ui; /**< ui file */ - GraphicsView *m_graphView; /**< media panel */ - QLabel *_cursorPosition; /**< cursor Position in media panel */ - int _lastRightPanelWidth; /**< lastRightPanelWidth for layouting */ - int _lastVideoWidgetWidth; /**< lastVideoWidgetWidth for layouting */ - QLabel* cursorPositionLabel; /**< cursonpositionlabel in status bar */ - - QPointer< CameraDevice > m_CameraDevice; /**< pointer on camera device */ - QPointer< SettingsWindow > m_SettingsWindow; /**< settings window */ - - IView *_currentParameterView; /**< current tracker paramter view */ - IView *_currentCoreParameterView; /**< current core parameter view */ - QGraphicsObject *_currentElementView; /**< current visualisation view of tracker */ - QGraphicsObject *_currentCoreView; /**< current visualisation view of core app */ - //QWidget* _currentTrackerP; /**< current tracker paramter view */ - QString _previouslySelectedTracker; /**< previous tracker */ - - SwitchButton* _trackerActivator; /**< tracking switch */ - QGroupBox* _mediaBox; /**< tracker groupbox in menu toolbar */ - QGroupBox* _trackerBox; /**< media groupbox in menu toolbar */ - - QWizard* m_introWiz; /**< introduction wizard-dialog */ -}; - -#endif // BIOTRACKER3MAINWINDOW_H diff --git a/BioTracker/CoreApp/BioTracker/View/NotificationLogBrowser.cpp b/BioTracker/CoreApp/BioTracker/View/NotificationLogBrowser.cpp deleted file mode 100644 index 51bdb883..00000000 --- a/BioTracker/CoreApp/BioTracker/View/NotificationLogBrowser.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "NotificationLogBrowser.h" -#include "QVBoxLayout" - - -NotificationLogBrowser::NotificationLogBrowser(QWidget *parent, IController *controller, IModel *model) : - IViewWidget(parent, controller, model) -{ - QVBoxLayout *layout = new QVBoxLayout(this); - - browser = new QTextBrowser(this); - browser->setLineWrapMode(QTextEdit::NoWrap); - - layout->addWidget(browser); - - setLayout(layout); - - m_font = QFont(); - m_font.setPointSize(8); - setFont(m_font); - - resize(200, 400); - - this->show(); - -} - -NotificationLogBrowser::~NotificationLogBrowser() -{ -} - -void NotificationLogBrowser::outputMessage(QtMsgType type, const QString & msg) -{ - switch (type) { - case QtDebugMsg: - browser->append(msg); - break; - - case QtWarningMsg: - browser->append(tr("- %1 ").arg(msg)); - break; - - case QtCriticalMsg: - browser->append(tr("- %1 ").arg(msg)); - break; - - case QtFatalMsg: - browser->append(tr("- %1 ").arg(msg)); - break; - } -} -void NotificationLogBrowser::getNotified() { - -} diff --git a/BioTracker/CoreApp/BioTracker/View/NotificationLogBrowser.h b/BioTracker/CoreApp/BioTracker/View/NotificationLogBrowser.h deleted file mode 100644 index eaa6c1b3..00000000 --- a/BioTracker/CoreApp/BioTracker/View/NotificationLogBrowser.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef NOTIFICATIONLOGBROWSER_H -#define NOTIFICATIONLOGBROWSER_H -#pragma once - -#include "Interfaces/IView/IViewWidget.h" -#include - -/** -* This is the view of the notifications component. -* It displays all intercepted qdebug messages (color-coded). -* http://doc.qt.io/qt-5/qdebug.html -*/ -class NotificationLogBrowser : public IViewWidget -{ - Q_OBJECT - -public: - explicit NotificationLogBrowser(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - ~NotificationLogBrowser(); - - void outputMessage(QtMsgType type, const QString &msg); - - // IViewWidget interface - public slots: - void getNotified(); - -private: - QTextBrowser *browser; - QFont m_font; - -}; - -#endif //NOTIFICATIONLOGBROWSER_H \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/SettingsWindow.cpp b/BioTracker/CoreApp/BioTracker/View/SettingsWindow.cpp deleted file mode 100644 index 2fa35b7e..00000000 --- a/BioTracker/CoreApp/BioTracker/View/SettingsWindow.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "SettingsWindow.h" - -#include "settings/Settings.h" - -#include - -SettingsWindow::SettingsWindow(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsForm) -{ - ui->setupUi(this); - - for (int i=0; icomboBoxVideoCodec->addItem(codecList[i].first.c_str()); - - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - int defaultIndex = set->getValueOrDefault(CFG_CODEC, 0); - ui->comboBoxVideoCodec->setCurrentIndex(defaultIndex); - - bool dropFrames = set->getValueOrDefault(CFG_DROPFRAMES, false); - ui->checkBoxDropFrames->setChecked(dropFrames); - - bool recordScaled = set->getValueOrDefault(CFG_RECORDSCALEDOUT, false); - ui->checkBox_scaledOutput->setChecked(recordScaled); - - - for (int i = 0; icomboBoxDefaultExporter->addItem(exporterList[i].c_str()); - - int exporter = set->getValueOrDefault(CFG_EXPORTER, 0); - ui->comboBoxDefaultExporter->setCurrentIndex(exporter); - - - ui->lineEdit_nthFrame->setValidator(new QIntValidator(this)); - int stride = set->getValueOrDefault(CFG_INPUT_FRAME_STRIDE, CFG_INPUT_FRAME_STRIDE_VAL); - ui->lineEdit_nthFrame->setText(std::to_string(stride).c_str()); - - ui->lineEdit_qp->setValidator(new QIntValidator(this)); - int qp = set->getValueOrDefault(CFG_GPU_QP, CFG_GPU_QP_VAL); - ui->lineEdit_qp->setText(std::to_string(qp).c_str()); - - std::string locStr= set->getValueOrDefault(CFG_DEFAULT_LOC_MAN_SAVE, CFG_DEFAULT_LOC_MAN_SAVE_VAL); - ui->lineEditLocationManSave->setText(QString::fromStdString(locStr)); - -#ifndef WITH_CUDA - ui->lineEdit_qp->setVisible(false); - ui->label_qp->setVisible(false); -#endif -} - -void SettingsWindow::on_buttonSaveClose_clicked() { - - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - bool recordScaled = ui->checkBox_scaledOutput->isChecked(); - set->setParam(CFG_RECORDSCALEDOUT, recordScaled); - - bool dropFrames = ui->checkBoxDropFrames->isChecked(); - set->setParam(CFG_DROPFRAMES, dropFrames); - - int codec = ui->comboBoxVideoCodec->currentIndex(); - set->setParam(CFG_CODEC, codec); - - int exporter = ui->comboBoxDefaultExporter->currentIndex(); - set->setParam(CFG_EXPORTER, exporter); - - int stride = (ui->lineEdit_nthFrame->text()).toInt(); - set->setParam(CFG_INPUT_FRAME_STRIDE, stride); - - int qp = (ui->lineEdit_qp->text()).toInt(); - set->setParam(CFG_GPU_QP, qp); - - std::string defaultManSave = (ui->lineEditLocationManSave->text()).toStdString(); - set->setParam(CFG_DEFAULT_LOC_MAN_SAVE, defaultManSave); - - this->close(); -} - -void SettingsWindow::on_pushButtonSetNewLocManSave_clicked() { - QString dirStr = QFileDialog::getExistingDirectory(this, tr("Select Directory"), "", QFileDialog::ShowDirsOnly); - if (dirStr != "") { - ui->lineEditLocationManSave->setText(dirStr); - } -} - - - -SettingsWindow::~SettingsWindow() -{ -} diff --git a/BioTracker/CoreApp/BioTracker/View/SettingsWindow.h b/BioTracker/CoreApp/BioTracker/View/SettingsWindow.h deleted file mode 100644 index 46a12ec8..00000000 --- a/BioTracker/CoreApp/BioTracker/View/SettingsWindow.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include - -#include -#include "QCameraViewfinder" -#include "QPointer" -#include "util/types.h" -#include -#include "ui_SettingsWindow.h" - -namespace Ui { - class SettingsWindow; -} - -class SettingsWindow : public QWidget -{ - Q_OBJECT - -public: - explicit SettingsWindow(QWidget *parent = 0); - ~SettingsWindow(); - - private Q_SLOTS: - //void on_buttonBox_accepted(); - - //void on_pushButton_clicked(); - void on_buttonSaveClose_clicked(); - - void on_pushButtonSetNewLocManSave_clicked(); - - //void on_comboBox_currentIndexChanged(int index); - -Q_SIGNALS: - //void emitSelectedCameraDevice(CameraConfiguration conf); - -private: - -private: - Ui::SettingsForm *ui; -}; \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/TextureObjectView.cpp b/BioTracker/CoreApp/BioTracker/View/TextureObjectView.cpp deleted file mode 100644 index 2c749e25..00000000 --- a/BioTracker/CoreApp/BioTracker/View/TextureObjectView.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "TextureObjectView.h" -#include "Model/TextureObject.h" -#include "QGraphicsScene" -#include "View/GraphicsView.h" - - -TextureObjectView::TextureObjectView(QObject *parent, IController *controller, IModel *model) : - IViewGraphicsPixmapItem(parent, controller, model) -{ - setZValue(-1); - _oldBoundingRect = QRectF(); -} - -void TextureObjectView::getNotified() -{ - TextureObject *texture = dynamic_cast(getModel()); - QPixmap pma; - pma.convertFromImage(texture->get()); - setPixmap(pma); - - //if frame is set, set the boundingrect of the scene to the size of the frame - if (texture->height() > 1) { - QGraphicsScene *scene = this->scene(); - - QRectF currentBoundingRect = this->boundingRect(); - - //check if bounding rect changed -> this means that a new video has been loaded, right? - if (currentBoundingRect != _oldBoundingRect) { - QRectF boundingWithMargins = currentBoundingRect.marginsAdded(QMarginsF(150, 150, 150, 150)); - scene->setSceneRect(boundingWithMargins); - - GraphicsView* view = dynamic_cast(scene->views()[0]); - view->fitInView(boundingWithMargins, Qt::KeepAspectRatio); - - _oldBoundingRect = currentBoundingRect; - } - - } - update(); -} - -void TextureObjectView::connectModelView() -{ - QObject::connect(getModel(), &IModel::notifyView, this, &TextureObjectView::getNotified); - - getNotified(); -} diff --git a/BioTracker/CoreApp/BioTracker/View/TrackedComponentView.cpp b/BioTracker/CoreApp/BioTracker/View/TrackedComponentView.cpp deleted file mode 100644 index 85cef70f..00000000 --- a/BioTracker/CoreApp/BioTracker/View/TrackedComponentView.cpp +++ /dev/null @@ -1,708 +0,0 @@ -#include "TrackedComponentView.h" -#include - -#include "QBrush" -#include "QPainter" -#include -#include "QGraphicsScene" -#include "QGraphicsEllipseItem" - -#include "ComponentShape.h" -#include "Model/CoreParameter.h" -#include "Controller/ControllerTrackedComponentCore.h" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "QDebug" -#include "QMenu" -#include "qlabel.h" -#include "QWidgetAction" -#include "QAction" -#include "qcolordialog.h" - -class QGraphicsSceneHoverEvent; - -TrackedComponentView::TrackedComponentView(QGraphicsItem *parent, IController *controller, IModel *model) : - IViewTrackedComponent(parent, controller, model) -{ - - m_boundingRect = QRectF(0, 0, 4080, 4080); - m_currentFrameNumber = 0; - setAcceptHoverEvents(true); - setAcceptDrops(true); - _watchingDrag = 0; - - m_permissions.insert(std::pair(ENUMS::COREPERMISSIONS::COMPONENTVIEW, true)); - m_permissions.insert(std::pair(ENUMS::COREPERMISSIONS::COMPONENTADD, true)); - m_permissions.insert(std::pair(ENUMS::COREPERMISSIONS::COMPONENTMOVE, true)); - m_permissions.insert(std::pair(ENUMS::COREPERMISSIONS::COMPONENTREMOVE, true)); - m_permissions.insert(std::pair(ENUMS::COREPERMISSIONS::COMPONENTSWAP, true)); - m_permissions.insert(std::pair(ENUMS::COREPERMISSIONS::COMPONENTROTATE, true)); -} - -void TrackedComponentView::rcvDimensionUpdate(int x, int y) { - m_boundingRect = QRectF(0, 0, x, y); - update(); -} - -QRectF TrackedComponentView::boundingRect() const -{ - return m_boundingRect; -} - -void TrackedComponentView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - IModelTrackedTrajectory *all = dynamic_cast(getModel()); - - // check if model exists - if (!all) { - return; - } -} - -void TrackedComponentView::getNotified() -{ - updateShapes(m_currentFrameNumber); - update(); -} - -bool TrackedComponentView::sceneEventFilter(QGraphicsItem *watched, QEvent *event) { - return true; -} - -bool TrackedComponentView::eventFilter(QObject *target, QEvent *event) -{ - return false; -} - -void TrackedComponentView::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ -} - -void TrackedComponentView::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ -} - -QVariant TrackedComponentView::itemChange(GraphicsItemChange change, const QVariant & value) -{ - if (change == ItemSceneHasChanged && this->scene()) { - createChildShapesAtStart(); - } - return QGraphicsItem::itemChange(change, value); -} - -void TrackedComponentView::mousePressEvent(QGraphicsSceneMouseEvent *event) { - // right clicking the view unselects all selected items so do this to avoid this behaviour - if (event->button() != Qt::LeftButton) { - event->accept(); - return; - } - QGraphicsItem::mousePressEvent(event); -} - -/// opens a context menu when right clicked -void TrackedComponentView::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) -{ - - lastClickedPos = event->pos().toPoint(); - - QMenu menu; - - - // create the info box - QWidgetAction* infoBox = new QWidgetAction(this); - QString info = QString("Position (x,y) : "); - info.append(QString("(" + QString::number(lastClickedPos.x()) + ", " + QString::number(lastClickedPos.y()) + ")")); - QLabel* infoLabel = new QLabel(info); - infoLabel->setWordWrap(true); - infoLabel->setStyleSheet("QLabel {font-weight: bold; text-align: center}"); - infoLabel->setAlignment(Qt::AlignCenter); - infoBox->setDefaultWidget(infoLabel); - menu.addAction(infoBox); - menu.addSeparator(); - QAction *addComponentAction = menu.addAction("Add trajectory here", dynamic_cast(this), SLOT(addTrajectory())); - QAction *swapIdsAction = menu.addAction("Swap ID's", dynamic_cast(this), SLOT(swapIds())); - QAction *unmarkAllAction = menu.addAction("Unmark all...", dynamic_cast(this), SLOT(unmarkAll())); - QAction *removeSelectedAction = menu.addAction("Remove selected trajectories", dynamic_cast(this), SLOT(removeTrajectories())); - - - // manage permissions - addComponentAction->setEnabled(m_permissions[ENUMS::COREPERMISSIONS::COMPONENTADD]); - swapIdsAction->setEnabled(m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP]); - removeSelectedAction->setEnabled(m_permissions[ENUMS::COREPERMISSIONS::COMPONENTREMOVE]); - - // manage swapping - swapIdsAction->setEnabled(false); - QList allSelectedItems = this->scene()->selectedItems(); - // check if two shapes are selected - if (allSelectedItems.size() == 2 && dynamic_cast(allSelectedItems[0]) && dynamic_cast(allSelectedItems[1])) { - ComponentShape* selectedItem0 = dynamic_cast(allSelectedItems[0]); - ComponentShape* selectedItem1 = dynamic_cast(allSelectedItems[1]); - // check if both shapes are swappable (check permission for each shape) and general permission - if (selectedItem0->isSwappable() && selectedItem1->isSwappable() && m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP]) { - swapIdsAction->setEnabled(true); - } - } - - // execute menu - QAction *selectedAction = menu.exec(event->screenPos()); - lastClickedPos = QPoint(0, 0); -} - -/// set permissions for this and all component shapes, which were send by the plugin -void TrackedComponentView::setPermission(std::pair permission) -{ - m_permissions[permission.first] = permission.second; - qDebug() << permission.first << " set to" << permission.second; - - - //first check if permission is for view, if not pass permission to shapes -> view has all permissions, shapes only certain ones - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTVIEW) { - this->setVisible(permission.second); - return; - } - //does not need to be propagated to shapes; only handled by view - if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTADD) { - return; - } - - QGraphicsItem* child; - foreach(child, this->childItems()) { - ComponentShape* shape = dynamic_cast(child); - if (shape) { - shape->setPermission(permission); - } - } -} - -/// at plugin load, draw each element of initial main trajectory -void TrackedComponentView::createChildShapesAtStart() { - - //flush all old children (e.g. from previous trackers) - foreach(QGraphicsItem* child, this->childItems()) { - child->hide(); - delete child; - } - - // check if scene is set - assert(this->scene()); - - // create a shape for each model-component upon plugin-init - IModelTrackedTrajectory *all = dynamic_cast(getModel()); - if (all) { - for (int i = 0; i < all->size(); i++) { - IModelTrackedTrajectory* trajectory = dynamic_cast(all->getChild(i)); - if (trajectory) { - //create componentshape for trajectory - ComponentShape* newShape = new ComponentShape(this, trajectory, trajectory->getId()); - connectShape(newShape); - } - - IModelTrackedPoint *rect = dynamic_cast(all->getChild(i)); - if (rect) { - int x = rect->getX(); - int y = rect->getY(); - int w = 20; - int h = 20; - - QGraphicsRectItem* rect = new QGraphicsRectItem(x - w / 2, y - h / 2, w, h, this); - rect->setPen(QPen(Qt::blue)); - rect->setBrush(QBrush(Qt::blue)); - rect->setFlag(ItemIsMovable); - rect->setFlag(ItemIsSelectable); - rect->setFlag(ItemSendsGeometryChanges); - rect->setData(0, i); - - } - - } - } - -} - -/// connect a newly created component shape to all slots it needs and set permissions -void TrackedComponentView::connectShape(ComponentShape* shape) { - CoreParameter* coreParams = dynamic_cast - (dynamic_cast(getController())->getCoreParameter()); - - //set type - IModelTrackedTrajectory* trajectory = shape->getTrajectory(); - - IModelTrackedPoint* point = dynamic_cast(trajectory->getChild(m_currentFrameNumber)); - if (point) { shape->setData(1, "point"); } - IModelTrackedEllipse* ellipse = dynamic_cast(trajectory->getChild(m_currentFrameNumber)); - if (ellipse) { shape->setData(1, "ellipse"); } - IModelTrackedRectangle* rectangle = dynamic_cast(trajectory->getChild(m_currentFrameNumber)); - if (rectangle) { shape->setData(1, "rectangle"); } - IModelTrackedPolygon* polygon = dynamic_cast(trajectory->getChild(m_currentFrameNumber)); - if (polygon) { shape->setData(1, "polygon"); } - - - //connect slots/signals - QObject::connect(shape, SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), - dynamic_cast(this->getController()), - SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), Qt::DirectConnection); - QObject::connect(shape, SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), - dynamic_cast(this->getController()), - SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), Qt::DirectConnection); - QObject::connect(shape, SIGNAL(emitMoveElement(IModelTrackedTrajectory*, QPoint, QPoint, uint, int)), - dynamic_cast(this->getController()), - SIGNAL(emitMoveElement(IModelTrackedTrajectory*, QPoint, QPoint, uint, int)), Qt::DirectConnection); - QObject::connect(shape, SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), - dynamic_cast(this->getController()), - SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), Qt::DirectConnection); - QObject::connect(shape, SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, double, uint)), - dynamic_cast(this->getController()), - SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, double, uint)), Qt::DirectConnection); - QObject::connect(shape, &ComponentShape::emitGoToFrame, - dynamic_cast(this->getController()), - &ControllerTrackedComponentCore::emitGoToFrame, Qt::DirectConnection); - - QObject::connect(shape, SIGNAL(broadcastMove()), this, SLOT(receiveBroadcastMove()), Qt::DirectConnection); - - //set the shapes members - shape->m_currentFramenumber = m_currentFrameNumber; - shape->setMembers(coreParams); - - //set permissions - shape->setPermission(std::pair - (ENUMS::COREPERMISSIONS::COMPONENTMOVE, m_permissions[ENUMS::COREPERMISSIONS::COMPONENTMOVE])); - shape->setPermission(std::pair - (ENUMS::COREPERMISSIONS::COMPONENTREMOVE, m_permissions[ENUMS::COREPERMISSIONS::COMPONENTREMOVE])); - shape->setPermission(std::pair - (ENUMS::COREPERMISSIONS::COMPONENTSWAP, m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP])); - shape->setPermission(std::pair - (ENUMS::COREPERMISSIONS::COMPONENTROTATE, m_permissions[ENUMS::COREPERMISSIONS::COMPONENTROTATE])); - - //update the shape - shape->updateAttributes(m_currentFrameNumber); -} - -/*********************************************************************//** -*******************************SLOTS************************************* -*************************************************************************/ - -/** -* updates componentshapes, deletes all if tracking data empty and creates new if new trajectories were added -* componentshapes are children of this view (see qt's parent-child-system) -*/ -void TrackedComponentView::updateShapes(uint framenumber) { - m_currentFrameNumber = framenumber; - - IModelTrackedTrajectory *all = dynamic_cast(getModel()); - if (!all || all->size() == 0) { - //if root is nullptr, delete all children - foreach(auto child, this->childItems()) { - delete child; - } - return; - } - - //update each shape; shape hides itself if trajectory is empty or not existant or currentchild - foreach(auto child, this->childItems()) { - ComponentShape* shape = dynamic_cast(child); - if (shape) { - shape->updateAttributes(m_currentFrameNumber); - } - } - - // check for new trajectories; for each create a new shape - if (this->childItems().size() < all->size()) { - - //iterate over trajectories from back to increase performance - for (int i = all->size() - 1; i >= 0 && this->childItems().size() <= all->size(); i--) { - IModelTrackedTrajectory* trajectory = dynamic_cast(all->getChild(i)); - - //check if trajectory already has shape object - if (trajectory && !checkTrajectory(trajectory)) { - ComponentShape* newShape = new ComponentShape(this, trajectory, trajectory->getId()); - connectShape(newShape); - } - else { - //already there or nullptr - } - - //all trajectories already have shapes - if (all->size() == this->childItems().size()) { - break; - } - } - } -} - -/** -* gets triggered when one or more shape is moved; emits move signal to tracker for all selected shapes -* if not broadcasted, only the position of actually moved componentshape is saved in tracking data -* the rest would be reset after update -*/ -void TrackedComponentView::receiveBroadcastMove() -{ - QList allSelectedItems = this->scene()->selectedItems(); - QList allSelectedEntitiesList; - - - QGraphicsItem* item; - - foreach(item, allSelectedItems) { - ComponentShape* shape = dynamic_cast(item); - if (shape) { - if (shape->isSelected()) { - allSelectedEntitiesList.append(shape); - } - } - } - - int numberSelectedEntitiesToMove = allSelectedEntitiesList.size(); - ComponentShape* entity; - foreach(entity, allSelectedEntitiesList) { - ComponentShape* shape = dynamic_cast(entity); - if (shape) { - if (shape->isSelected()) { - IModelTrackedTrajectory* shapeTrajectory = shape->getTrajectory(); - //calculate the current pos and emit it to the commands component - shape->emitMoveElement(shapeTrajectory, shape->getOldPos() + QPoint(shape->m_w / 2, shape->m_h / 2), - shape->pos().toPoint() + - QPoint(shape->m_w / 2, shape->m_h / 2), m_currentFrameNumber, numberSelectedEntitiesToMove); - numberSelectedEntitiesToMove--; - } - } - } -} - -void TrackedComponentView::receiveViewSwitch(bool lever) -{ - this->setVisible(lever); - - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->m_tracingLayer->setVisible(lever); - } - } -} - -void TrackedComponentView::receiveTrackDimensionsAll(int width, int height) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveDimensions(width, height); - } - } -} - -void TrackedComponentView::receiveTrackDimensionsSelected(int width, int height) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape && childShape->isSelected()) { - childShape->receiveDimensions(width, height); - } - } -} - -void TrackedComponentView::receiveTrackOrientationLine(bool toggle) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveToggleOrientationLine(toggle); - } - } -} - -void TrackedComponentView::receiveTrackShowId(bool toggle) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveShowId(toggle); - } - } -} - -void TrackedComponentView::receiveTrackDimensionsSetDefault() -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->setDimensionsToDefault(); - } - } -} - -void TrackedComponentView::receiveTracingSteps(int steps) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracingSteps(steps); - } - } -} - -void TrackedComponentView::receiveTracingStyle(QString style) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracingStyle(style); - } - } -} - -void TrackedComponentView::receiveTracingHistoryLength(int history) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracingLength(history); - } - } -} - -void TrackedComponentView::receiveTracingTimeDegradation(QString degradation) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracingTimeDegradation(degradation); - } - } -} - -void TrackedComponentView::receiveColorChangeBrushAll() -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - const QColorDialog::ColorDialogOptions options = QFlag(QColorDialog::ShowAlphaChannel - || QColorDialog::DontUseNativeDialog); - QColor color = QColorDialog::getColor(Qt::white, nullptr, QString("Choose fill color"), options); - // QColorDialog* cDialog = new QColorDialog(Qt::white); - // cDialog->show(); - // cDialog->activateWindow(); - // cDialog->raise(); - // cDialog->setFocus(); - - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->changeBrushColor(color); - } - } -} - -void TrackedComponentView::receiveColorChangeBorderAll() -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - QColor color = QColorDialog::getColor(Qt::white, nullptr, - QString("Choose border color"), QColorDialog::ShowAlphaChannel); - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->changePenColor(color); - } - } -} - -void TrackedComponentView::receiveColorChangeBorderSelected() -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - QColor color = QColorDialog::getColor(Qt::white, nullptr, - QString("Choose border color"), QColorDialog::ShowAlphaChannel); - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape && childShape->isSelected()) { - childShape->changePenColor(color); - } - } -} - -void TrackedComponentView::receiveColorChangeBrushSelected() -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - QColor color = QColorDialog::getColor(Qt::white, nullptr, - QString("Choose fill color"), QColorDialog::ShowAlphaChannel);; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape && childShape->isSelected()) { - childShape->changeBrushColor(color); - } - } -} - -void TrackedComponentView::receiveSelectAll() -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - if (dynamic_cast(childItem)) { - childItem->setSelected(true); - } - } -} - -///////////////////////context menu action slots/////////////// - -void TrackedComponentView::addTrajectory() -{ - IModelTrackedTrajectory *all = dynamic_cast(getModel()); - int id = -1; - if (all) { - id = all->size() + 1; - } - - if (id <= 0) { - qWarning() << "ID cannot be smaller than or equal 0"; - } - - if (!lastClickedPos.isNull()) { - //qDebug() << "TCV: new track at position " << lastClickedPos; - emitAddTrajectory(lastClickedPos, id); - lastClickedPos = QPoint(0, 0); - } - else { - //qDebug() << "TCV: new track at center of top left quarter of video"; - QPoint topLeftQuarterCenter = QPoint(this->boundingRect().width() / 8, this->boundingRect().height() / 8); - emitAddTrajectory(topLeftQuarterCenter, id); - } -} - -void TrackedComponentView::swapIds() -{ - QList allSelectedItems = this->scene()->selectedItems(); - if (allSelectedItems.size() != 2) { - qWarning() << "There need to be exactly two tracks selected to swap ID's!"; - return; - } - ComponentShape* shape0 = dynamic_cast(allSelectedItems[0]); - ComponentShape* shape1 = dynamic_cast(allSelectedItems[1]); - if (shape0 && shape1 && shape0->isSwappable() && shape1->isSwappable()) { - IModelTrackedTrajectory* trajectory0 = dynamic_cast(shape0->getTrajectory()); - IModelTrackedTrajectory* trajectory1 = dynamic_cast(shape1->getTrajectory()); - emitSwapIds(trajectory0, trajectory1); - } - else { - qWarning() << "Selected objects are not swappable"; - } -} - -void TrackedComponentView::removeTrajectories() -{ - QList allSelectedItems = this->scene()->selectedItems(); - QGraphicsItem* item; - foreach(item, allSelectedItems) { - ComponentShape* shape = dynamic_cast(item); - if (shape) { - shape->removeTrack(); - } - } -} - -void TrackedComponentView::unmarkAll() { - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->unmarkShape(); - } - } -} - -/////////////////////////////////////////////////////// - -bool TrackedComponentView::checkTrajectory(IModelTrackedTrajectory* trajectory) { - bool isVisualized = false; - - for (int i = 0; i < this->childItems().size(); i++) { - ComponentShape* shape = dynamic_cast(this->childItems()[i]); - if (shape) { - if (shape->getTrajectory() == trajectory) { - isVisualized = true; - break; - } - } - } - return isVisualized; -} - -void TrackedComponentView::receiveTracerProportions(float proportion) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracerProportions(proportion); - } - } -} - -void TrackedComponentView::receiveTracerOrientationLine(bool toggle) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracerOrientationLine(toggle); - } - } -} - -void TrackedComponentView::receiveTracerFrameNumber(bool toggle) { - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveTracerFrameNumber(toggle); - } - } -} - -void TrackedComponentView::receiveToggleAntialiasingEntities(bool toggle) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveAntialiasing(toggle); - } - } -} - -void TrackedComponentView::receiveIgnoreZoom(bool toggle) -{ - QList childrenItems = this->childItems(); - QGraphicsItem* childItem; - foreach(childItem, childrenItems) { - ComponentShape* childShape = dynamic_cast(childItem); - if (childShape) { - childShape->receiveIgnoreZoom(toggle); - } - } -} diff --git a/BioTracker/CoreApp/BioTracker/View/TrackedComponentView.h b/BioTracker/CoreApp/BioTracker/View/TrackedComponentView.h deleted file mode 100644 index 9790bdd9..00000000 --- a/BioTracker/CoreApp/BioTracker/View/TrackedComponentView.h +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef TRACKEDCOMPONENTVIEW_H -#define TRACKEDCOMPONENTVIEW_H - -#pragma once - -#include "Interfaces/IView/IViewTrackedComponent.h" -#include "Interfaces/ENUMS.h" -#include "QPoint" -#include "QSignalMapper" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "View/ComponentShape.h" - -/** -* This class inherits from the IViewTrackedComponent class and is therefore part of the Composite Pattern. -* This view is visualized in the media panel of the main window on top of the loaded medium. -* It creates a component shape for each trajectory. The component shape is the visualized current entity of the trajectory. -* Each time the tracking plugins singals tracking done to the core app, all component shapes are updated (updateshapes(framnumber)) -*/ -class TrackedComponentView : public IViewTrackedComponent -{ - Q_OBJECT -public: - TrackedComponentView(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; - - ///creates initial componentshapes - void createChildShapesAtStart(); - - /// connect a newly created component shape to all slots it needs and set permissions - void connectShape(ComponentShape* shape); - - // check if trajectory already has corresponding component shape - bool checkTrajectory(IModelTrackedTrajectory* trajectory); - - // IView interface - void setPermission(std::pair permission); - - /** - * SIGNALS - */ -signals: - void emitUpdateCornersChanged(int id, int relX, int relY); - - /// signal to commands component to add a new trajectory - void emitAddTrajectory(QPoint pos, int id); - - /// signal to commands component to swap ID's of two trajectories - void emitSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - - /** - * SLOTS - */ - public slots: - // IViewTrackedComponent interface - void getNotified() override; - - /// updates dimensions on load of new medium - void rcvDimensionUpdate(int x, int y); - - ////////////// contextmenu actions (must be parameterless because Qt actions require it) - - /// add a new trajectory --> view updates componentshapes and generates a new component shape for that trajectory - void addTrajectory(); - - /// swap id's of excatcly two selected trajectories --> also componetshapes - void swapIds(); - - /// remove all selected trajectories --> also removes componentshapes - void removeTrajectories(); - - /// unmark all component shapes (border from fat to slim) - void unmarkAll(); - - ////////////////////////////////////////////////////////////////////////////// - - /// update shapes when receiving tracking done - void updateShapes(uint framenumber); - - /// broadcast the movment to all selected componentshapes so they are moved too - void receiveBroadcastMove(); - - /// receive toggle to hide or show the view and all its component shapes - void receiveViewSwitch(bool lever); - - /// select all tracks - void receiveSelectAll(); - - /* - * set dimensions of componentshapes - */ - - /// set dimensions for all component shapes - void receiveTrackDimensionsAll(int width, int height); - - /// set dimensions for selected component shapes - void receiveTrackDimensionsSelected(int width, int height); - - /// set dimensions for to default for all componentshapes - void receiveTrackDimensionsSetDefault(); - - /* - * Change Color of componentshapes - */ - - /// open color dialog and set border color for all componentshapes - void receiveColorChangeBorderAll(); - - /// open color dialog and set border color for selected componentshapes - void receiveColorChangeBorderSelected(); - - /// open color dialog and set fill color for all componentshapes - void receiveColorChangeBrushAll(); - - /// open color dialog and set fill color for all componentshapes - void receiveColorChangeBrushSelected(); - - /* - * Tracing of componentshapes - */ - - /// set tracing history length for all componentshapes - void receiveTracingHistoryLength(int history); - - /// set tracing style for all componentshapes - void receiveTracingStyle(QString style); - - /// set tracing steps for all componentshapes - void receiveTracingSteps(int steps); - - /// set tracing time degradation style for all componentshapes - void receiveTracingTimeDegradation(QString degradation); - - /// toggle show framenumber of tracers for all componentshapes - void receiveTracerFrameNumber(bool toggle); - - /// set tracing proportions for all componentshapes - void receiveTracerProportions(float proportion); - - /// set tracer orientation line for all componentshapes - void receiveTracerOrientationLine(bool toggle); - - /* - * Misc - */ - - /// toggle antialiasing for all componentshapes - void receiveToggleAntialiasingEntities(bool toggle); - - /// set ignore zoom for all componentshapes (unused) - void receiveIgnoreZoom(bool toggle); - - /// toggle orientation line for all component shapes - void receiveTrackOrientationLine(bool toggle); - - /// toggle show id for all component shapes - void receiveTrackShowId(bool toggle); - -public: - /// updates tracking data model when new trakcing plugin is loaded - void setNewModel(IModel *model) override { setModel(model); }; - -private: - QRectF m_boundingRect; /**< bounding rect of the view */ - - std::map> _rectification; /**< id of the component */ - QGraphicsItem *_watchingDrag = nullptr; /**< unused drag bool */ - int _dragX = 0; /**< unused drag x-coordinate */ - int _dragY = 0; /**< unused drag y-coordinate */ - std::map m_permissions; /**< list of permissions to set for new component shapes */ - QPoint lastClickedPos; /**< last clicked position in the view */ - - // QGraphicsItem interface -protected: - bool sceneEventFilter(QGraphicsItem * watched, QEvent * event) override; - bool eventFilter(QObject * target, QEvent * event) override; - void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; - void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; - QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; - void mousePressEvent(QGraphicsSceneMouseEvent *event); - - int m_currentFrameNumber = 0; /**< current visualized framenumber of the medium */ -}; - -#endif // TRACKEDCOMPONENTVIEW_H diff --git a/BioTracker/CoreApp/BioTracker/View/TrackedImageView.cpp b/BioTracker/CoreApp/BioTracker/View/TrackedImageView.cpp deleted file mode 100644 index 853a2b00..00000000 --- a/BioTracker/CoreApp/BioTracker/View/TrackedImageView.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "TrackedImageView.h" - -#include -#include "Interfaces/IController/IController.h" - -#include "Model/TextureObject.h" - -TrackedImageView::TrackedImageView(QWidget *parent, IController *controller, IModel *model): - IViewOpenGLWidget(parent, controller, model) -{ - -} - -TrackedImageView::~TrackedImageView() -{ - -} - -void TrackedImageView::paintGL() -{ - TextureObject *textureObject = dynamic_cast(getModel()); - QImage img = textureObject->get(); - - - QPainter painter(this); - - painter.setBrush(QColor(0, 0, 0)); - painter.drawRect(QRect(0, 0, this->width(), this->height())); - painter.setBrush(QColor(0, 0, 0, 0)); - - QRect window; - QRect viewport; - const float viewport_skew = BioTracker::Core::ScreenHelper::calculate_viewport( - textureObject->width(), - textureObject->height(), - this->width(), - this->height(), - window, - viewport - ); - - painter.setWindow(window); - painter.setViewport(viewport); - - QRectF target(0, 0 , textureObject->width(), textureObject->height()); - QRectF source(0, 0, textureObject->width(), textureObject->height()); - - - - painter.drawImage(target, img, source); - QPainter p(this); -} - -void TrackedImageView::getNotified() -{ - this->update(); -} diff --git a/BioTracker/CoreApp/BioTracker/View/Utility/RotationHandle.cpp b/BioTracker/CoreApp/BioTracker/View/Utility/RotationHandle.cpp deleted file mode 100644 index b487bb13..00000000 --- a/BioTracker/CoreApp/BioTracker/View/Utility/RotationHandle.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "RotationHandle.h" -#include "QPainter" -#include "QGraphicsSceneMouseEvent" -#include "QCursor" -#include "QtMath" -#include "QGraphicsScene" -#include "qdebug.h" - -RotationHandle::RotationHandle(QPoint origin, QAbstractGraphicsShapeItem* parent) : - QAbstractGraphicsShapeItem(parent), _origin(origin) -{ - setFlag(ItemIsMovable); - setPen(QPen(Qt::black)); - setBrush(QBrush(Qt::red)); - //setFlag(QGraphicsItem::ItemIsSelectable); - //setFlag(ItemIgnoresTransformations); -} - -RotationHandle::~RotationHandle() -{ -} - -QRectF RotationHandle::boundingRect() const -{ - return QRectF(-5, -5, 10, 10); -} - -void RotationHandle::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) -{ - if (m_antialiasing) { - painter->setRenderHint(QPainter::Antialiasing); - } - painter->setPen(this->pen()); - painter->setBrush(this->brush()); - - painter->drawEllipse(QRect(-5, -5, 10, 10)); - - //painter->drawRect(boundingRect()); -} - -void RotationHandle::mousePressEvent(QGraphicsSceneMouseEvent * event) -{ - if (event->button() == Qt::LeftButton) { - // handle left mouse button here - - //unselect all selected items so this can be moved - QList allSelectedItems = scene()->selectedItems(); - QGraphicsItem* item; - foreach(item, allSelectedItems) { - item->setSelected(false); - } - - - setCursor(Qt::ClosedHandCursor); - update(); - } - - //pass on - QGraphicsItem::mousePressEvent(event); -} - -void RotationHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) -{ - if (event->button() == Qt::LeftButton) { - // handle left mouse button here - setCursor(Qt::ArrowCursor); - - double angleRad = atan2(this->y() - _origin.y(), this->x() - _origin.x()); - double angleDeg = qRadiansToDegrees(angleRad); - - Q_EMIT emitShapeRotation(angleDeg, true); - - update(); - } - //pass on - QGraphicsItem::mouseReleaseEvent(event); -} - -void RotationHandle::mouseMoveEvent(QGraphicsSceneMouseEvent * event) -{ - double angleRad = atan2(this->y() - _origin.y(), this->x() - _origin.x()); - double angleDeg = qRadiansToDegrees(angleRad); - - Q_EMIT emitShapeRotation(angleDeg); - - update(); - - //pass on - QGraphicsItem::mouseMoveEvent(event); -} - -void RotationHandle::setAntialiasing(bool toggle) -{ - m_antialiasing = toggle; - update(); -} diff --git a/BioTracker/CoreApp/BioTracker/View/Utility/RotationHandle.h b/BioTracker/CoreApp/BioTracker/View/Utility/RotationHandle.h deleted file mode 100644 index 688f5fa1..00000000 --- a/BioTracker/CoreApp/BioTracker/View/Utility/RotationHandle.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#ifndef ROTATIONHANDLE_H -#define ROTATIONHANDLE_H - -#include "QGraphicsObject" - -/** -* This class inherits QAbstractGraphicsShapeItem. -* It is a child of an componentshape and is used to rotate it. -* (the rotation then gets forwarded to the command compontent, -* which then forwards it to the tracking plugin -* It is attached to the end of the orientation line of the component shape -*/ -class RotationHandle : public QObject, public QAbstractGraphicsShapeItem { - Q_OBJECT - -public: - RotationHandle(QPoint origin, QAbstractGraphicsShapeItem* parent = 0); - ~RotationHandle(); - - QRectF boundingRect() const override; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - - void mousePressEvent(QGraphicsSceneMouseEvent * event) override; - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; - void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; - - void setAntialiasing(bool toggle); - -signals: - void emitShapeRotation(double angle, bool rotateEntity = false); - -private: - QPoint _origin; /**< the position in the coordinate frame of the shape object */ - bool m_antialiasing; /**< if true, antialiasing is enabled */ - -}; -#endif // ROTATIONHANDLE_H \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/Utility/SwitchButton.cpp b/BioTracker/CoreApp/BioTracker/View/Utility/SwitchButton.cpp deleted file mode 100644 index c45a833a..00000000 --- a/BioTracker/CoreApp/BioTracker/View/Utility/SwitchButton.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "SwitchButton.h" -#include "QPainter" -#include "QMouseEvent" - -void SwitchButton::setHeight(int h) { - _height = h - 2 * _margin; -} - -SwitchButton::SwitchButton(QString s0, QString s1, QWidget *parent) : QAbstractButton(parent), -_height(16), -_opacity(0.000), -_switch(false), -_margin(3), -_thumb("#d5d5d5"), -_anim(new QPropertyAnimation(this, "offset", this)), -_s0(s0), -_s1(s1) -{ - setOffset(_height / 2); - _y = _height / 2; - setBrush(QColor("#009688")); -}; - - -void SwitchButton::paintEvent(QPaintEvent *e) { - QPainter p(this); - p.setPen(Qt::NoPen); - if (isEnabled()) { - - //background rect - //p.setBrush(_switch ? brush() : Qt::black); - p.setBrush(_switch ? Qt::green : Qt::red); - //p.setOpacity(_switch ? 0.5 : 0.38); - p.setOpacity(0.5); - p.setRenderHint(QPainter::Antialiasing, true); - p.drawRoundedRect(QRect(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin), 8.0, 8.0); - - //handle - p.setBrush(_thumb); - p.setOpacity(1.0); - p.drawEllipse(QRectF(offset() - (_height / 2), _y - (_height / 2), height(), height())); - - //text - p.setPen(Qt::black); - QFont font = p.font(); - font.setPixelSize(height() - 3 * _margin); - p.setFont(font); - QRectF textRect = QRectF(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin); - p.drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter, _switch ? _s1 : _s0); - } - else { - p.setRenderHint(QPainter::Antialiasing, true); - p.setBrush(Qt::black); - p.setOpacity(0.12); - p.drawRoundedRect(QRect(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin), 8.0, 8.0); - p.setOpacity(1.0); - p.setBrush(QColor("#BDBDBD")); - p.drawEllipse(QRectF(offset() - (_height / 2), _y - (_height / 2), height(), height())); - - //text - p.setPen(Qt::black); - QFont font = p.font(); - font.setPixelSize(height() - 3 * _margin); - p.setFont(font); - QRectF textRect = QRectF(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin); - p.drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter, _switch ? _s1 : _s0); - } -} - -void SwitchButton::mouseReleaseEvent(QMouseEvent *e) { - if (e->button() & Qt::LeftButton) { - _switch = _switch ? false : true; - animateSwitch(); - - emitSetEnabled(_switch); - } - QAbstractButton::mouseReleaseEvent(e); -} - -void SwitchButton::enterEvent(QEvent *e) { - setCursor(Qt::PointingHandCursor); - QAbstractButton::enterEvent(e); -} - -void SwitchButton::animateSwitch() { - if (_switch) { - _anim->setStartValue(_height / 2); - _anim->setEndValue(width() - _height); - _anim->setDuration(240); - _anim->start(); - } - else { - _anim->setStartValue(offset()); - _anim->setEndValue(_height / 2); - _anim->setDuration(240); - _anim->start(); - } -} - -QSize SwitchButton::sizeHint() const { - return QSize(8 * (_height + _margin), _height + 2 * _margin); -} \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/Utility/SwitchButton.h b/BioTracker/CoreApp/BioTracker/View/Utility/SwitchButton.h deleted file mode 100644 index d71010db..00000000 --- a/BioTracker/CoreApp/BioTracker/View/Utility/SwitchButton.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#ifndef SWITCHBUTTON_H -#define SWITCHBUTTON_H - -#include "QAbstractButton" -#include "QPropertyAnimation" - -/** -* This class inherits QAbstractButton. -* It is an utility class to create android-like animated switches -* inspiration: https://stackoverflow.com/questions/14780517/toggle-switch-in-qt -*/ -class SwitchButton : public QAbstractButton { - Q_OBJECT - Q_PROPERTY(int offset READ offset WRITE setOffset) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(bool _switch READ state WRITE setState) - -public: - SwitchButton(QString s0, QString s1, QWidget* parent = 0); - //~SwitchButton(); - - QSize sizeHint() const override; - - void setHeight(int h); - int offset() const { return _x; } - void setOffset(int o) { _x = o; update(); } - QBrush brush() const { return _brush; } - void setBrush(const QBrush &brsh) { _brush = brsh; } - bool state() const { return _switch; } - void setState(bool toggle) { _switch = toggle; animateSwitch(); update(); } - - void animateSwitch(); - -signals: - void emitSetEnabled(bool toggle); - -protected: - void paintEvent(QPaintEvent* event) override; - void mouseReleaseEvent(QMouseEvent*) override; - void enterEvent(QEvent *e) override; - - - bool _switch; /**< state fo the switch */ - qreal _opacity; /**< opacity */ - int _x, _y, _height, _margin; /**< position and dimensions */ - QBrush _thumb, _track, _brush; - QPropertyAnimation *_anim = nullptr;/**< animation */ - QString _s0; /**< text in state 0 */ - QString _s1; /**< text in state 1 */ - -}; - - - -#endif // SWITCHBUTTON_H \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/Utility/Tracer.cpp b/BioTracker/CoreApp/BioTracker/View/Utility/Tracer.cpp deleted file mode 100644 index 160bd3d0..00000000 --- a/BioTracker/CoreApp/BioTracker/View/Utility/Tracer.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "Tracer.h" -#include "QDebug" -#include "QPen" -#include "QBrush" -#include "QPainter" -#include "QMenu" -#include "QGraphicsSceneContextMenuEvent" - -Tracer::Tracer(QVariant type, int frame, float orientation, QPointF pos, float w, float h, QPen pen, QBrush brush, QAbstractGraphicsShapeItem* parent) - :QAbstractGraphicsShapeItem(parent), _type(type.toString()), _frame(frame), _w(w), _h(h) -{ - setPos(pos); - setPen(pen); - setBrush(brush); - setRotation(_h > _w ? -90 - orientation : -orientation); -} - -Tracer::~Tracer() -{ -} - -QRectF Tracer::boundingRect() const -{ - return QRect(-_w / 2, -_h / 2, _w, _h); -} - -void Tracer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - painter->setPen(pen()); - painter->setBrush(brush()); - - if (_type == "point") { - int dim = _w <= _h ? _w : _h; - painter->drawEllipse(QRect(-dim / 2, -dim / 2, dim, dim)); - } - else if (_type == "ellipse") { - - painter->drawEllipse(QRect(-_w / 2, -_h / 2, _w, _h)); - } - else if (_type == "rectangle") { - - painter->drawRect(QRect(-_w / 2, -_h / 2, _w, _h)); - } - //default for polygon shape are point tracers for simplicity - else if (_type == "polygon") { - int dim = _w <= _h ? _w : _h; - painter->drawEllipse(QRect(-dim / 2, -dim / 2, dim, dim)); - } -} - -void Tracer::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) -{ - QMenu menu; - menu.addAction("Go to frame ", dynamic_cast(this), SLOT(goToFrame())); - menu.exec(event->screenPos()); -} - -void Tracer::goToFrame() -{ - Q_EMIT emitGoToFrame(_frame); -} diff --git a/BioTracker/CoreApp/BioTracker/View/Utility/Tracer.h b/BioTracker/CoreApp/BioTracker/View/Utility/Tracer.h deleted file mode 100644 index fc35425a..00000000 --- a/BioTracker/CoreApp/BioTracker/View/Utility/Tracer.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#ifndef TRACER_H -#define TRACER_H - -#include "QAbstractGraphicsShapeItem" - -/** -* This class inherits QAbstractGraphicsShapeItem. -* It is created by and an child of a componenntshape. -* It is a helper class used to visualize shape type tracers. -* It has a context menu to set medium to the tracer's frame -* Apart from the polygon it is visualized as the componentshapes -* current type. -*/ -class Tracer : public QObject, public QAbstractGraphicsShapeItem { - Q_OBJECT - -public: - Tracer(QVariant type, int frame, float orientation, QPointF pos, - float w, float h, QPen pen, QBrush brush, QAbstractGraphicsShapeItem* parent); - ~Tracer(); -signals: - void emitGoToFrame(int frame); - - public slots: - - //signals the media player rewind to the tracer's frame - void goToFrame(); - -protected: - // Interface of QAbstractGraphicsShapeItem - QRectF boundingRect() const override; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; - - - //member - QString _type; /**< type visualized */ - int _frame; /**< corresponding frame */ - float _orientation; /**< orientation of tracer --> of corresponding entity */ - QPointF pos; /**< position in coordinateframe of parent shape object */ - float _w; /**< width */ - float _h; /**< height */ -}; - - - -#endif // TRACER_H diff --git a/BioTracker/CoreApp/BioTracker/View/VideoControllWidget.cpp b/BioTracker/CoreApp/BioTracker/View/VideoControllWidget.cpp deleted file mode 100644 index 5271324e..00000000 --- a/BioTracker/CoreApp/BioTracker/View/VideoControllWidget.cpp +++ /dev/null @@ -1,324 +0,0 @@ -#include "VideoControllWidget.h" -#include "ui_VideoControllWidget.h" -#include "Controller/ControllerPlayer.h" -#include "Model/MediaPlayer.h" - -#include -#include -#include -#include - -VideoControllWidget::VideoControllWidget(QWidget* parent, IController* controller, IModel* model) : - IViewWidget(parent, controller, model), - ui(new Ui::VideoControllWidget) { - ui->setupUi(this); - m_RecO = false; - m_RecI = false; - m_Paus = false; - - m_iconPause.addFile(QStringLiteral("qrc:/Images/resources/pause-sign.png"), - QSize(), QIcon::Normal, QIcon::Off); - m_iconPlay.addFile(QStringLiteral("qrc:/Images/resources/arrow-forward1.png"), - QSize(), QIcon::Normal, QIcon::Off); - - ui->sld_video->setMinimum(0); - this->setSelectedView("Original"); - updateGeometry(); -} - -VideoControllWidget::~VideoControllWidget() { - delete ui; -} - -void VideoControllWidget::setSelectedView(QString str) { - ControllerPlayer* controller = dynamic_cast(getController()); - controller->changeImageView(str); -} - -void VideoControllWidget::setVideoViewComboboxModel(QStringListModel* comboboxModel) { -} - -void VideoControllWidget::getNotified() { - MediaPlayer* mediaPlayer = dynamic_cast(getModel()); - - ui->actionNext_frame->setEnabled(mediaPlayer->getForwardState()); - ui->actionPrev_frame->setEnabled(mediaPlayer->getBackwardState()); - ui->actionPlay_Pause->setEnabled(mediaPlayer->getPlayState()); - ui->actionStop->setEnabled(mediaPlayer->getStopState()); - - m_Paus = mediaPlayer->getPauseState(); - - if (m_Paus) { - ui->actionPlay_Pause->setIcon(QIcon(":/Images/resources/pause-sign.png")); - } - else { - ui->actionPlay_Pause->setIcon(QIcon(":/Images/resources/arrow-forward1.png")); - } - - m_RecI = mediaPlayer->getRecIState(); - if (m_RecI) { - ui->actionRecord_cam->setIcon(QIcon(":/Images/resources/recordingCam.png")); - } - else { - ui->actionRecord_cam->setIcon(QIcon(":/Images/resources/recordCam.png")); - } - - int currentFrameNr = mediaPlayer->getCurrentFrameNumber(); - int totalNumberOfFrames = mediaPlayer->getTotalNumberOfFrames(); - int mediaFps = mediaPlayer->getFpsOfSourceFile(); - //ui->frame_num_edit->setText(QString::number(currentFrameNr)); - ui->frame_num_spin->setMaximum(totalNumberOfFrames); - ui->frame_num_spin->setValue(currentFrameNr); - ui->sld_video->setValue(currentFrameNr); - - QString currentVideoTime = QDateTime::fromMSecsSinceEpoch(((float)currentFrameNr / (float)mediaFps) * 1000).toUTC().toString("hh:mm:ss:zzz"); - - - ui->time_edit->setText(currentVideoTime); - - - //Write current fps label every 1/2 second - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - long long dt = std::chrono::duration_cast(now - lastFpsSet).count(); - int fps = mediaPlayer->getCurrentFPS(); - if (dt > 500 || fps <= 0) { - ui->lcd_currentFpsNum->display(fps); - lastFpsSet = now; - - // for average fps calculation - _fpsSum += fps; - _fpsCounter += 1; - - } - - ui->fps_label->setText(QString::number(mediaFps)); - double cfps = mediaPlayer->getCurrentFPS(); - - - if (totalNumberOfFrames >= 1) { - ui->sld_video->setEnabled(true); - ui->sld_video->setMaximum(totalNumberOfFrames - 1); - - int intervalPower = floor(log10(totalNumberOfFrames)); - int tickInterval = pow(10, intervalPower > 0 ? floor(log10(totalNumberOfFrames)) - 1 : 0); - - ui->sld_video->setTickInterval(tickInterval); - } -} - - -// void VideoControllWidget::on_button_nextFrame_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); -// controller->nextFrame(); -// } - -// void VideoControllWidget::on_button_playPause_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); - -// if (m_Paus) { -// controller->pause(); -// } else { -// controller->play(); -// } -// } - -// void VideoControllWidget::on_button_stop_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); -// controller->stop(); -// } - -// void VideoControllWidget::on_button_previousFrame_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); -// controller->prevFrame(); -// } - -void VideoControllWidget::on_DurationChanged(int position) { - -} - -void VideoControllWidget::on_PositionChanged(int position) { - -} - - -// void VideoControllWidget::on_button_record_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); - -// int success = controller->recordOutput(); -// if (success == 1) { -// QPixmap pix(":/Images/resources/recording.png"); -// QIcon icon(pix); -// ui->actionRecord_all->setIcon(icon); -// //ui->actionRecord_all->setIconSize(QSize(32,32)); -// } -// else { -// QPixmap pix(":/Images/resources/record.png"); -// QIcon icon(pix); -// ui->actionRecord_all->setIcon(icon); -// //ui->actionRecord_all->setIconSize(QSize(32, 32)); -// } -// } - -// void VideoControllWidget::on_button_record_cam_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); - -// int success = controller->recordInput(); -// } - -// void VideoControllWidget::on_button_screenshot_clicked() { -// ControllerPlayer* controller = dynamic_cast(getController()); -// controller->takeScreenshot(); -// } - -void VideoControllWidget::on_comboBoxSelectedView_currentTextChanged(const QString& arg1) { - /*QString name = arg1;*/ -} - -void VideoControllWidget::on_sld_video_sliderReleased() { -} - -void VideoControllWidget::on_sld_video_actionTriggered(int action) -{ - ControllerPlayer* controller = dynamic_cast(getController()); - int position = ui->sld_video->sliderPosition(); - controller->setGoToFrame(position); -} - - -/** - * If the video slider is moved, this function sets the value to the current frame number lable - */ -void VideoControllWidget::on_sld_video_sliderMoved(int position) { - //ui->frame_num_edit->setText(QString::number(position)); - ui->frame_num_spin->setValue(position); - MediaPlayer* mediaPlayer = dynamic_cast(getModel()); - int mediaFps = mediaPlayer->getFpsOfSourceFile(); - QString currentVideoTime = QDateTime::fromMSecsSinceEpoch(((float)position / (float)mediaFps) * 1000).toUTC().toString("hh:mm:ss:zzz"); - ui->time_edit->setText(currentVideoTime); -} - -void VideoControllWidget::on_doubleSpinBoxTargetFps_editingFinished() { - double val = ui->doubleSpinBoxTargetFps->value(); - ControllerPlayer* controller = dynamic_cast(getController()); - controller->setTargetFps(val); -} - -void VideoControllWidget::on_frame_num_spin_editingFinished() { - int val = ui->frame_num_spin->value(); - ControllerPlayer* controller = dynamic_cast(getController()); - controller->setGoToFrame(val); -} - - -//actions -void VideoControllWidget::on_actionPlay_Pause_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - - if (m_Paus) { - controller->pause(); - //qDebug() << "The average fps of this run was: " << _fpsSum / _fpsCounter; - } - else { - controller->play(); - _fpsSum = 0; - _fpsCounter = 0; - } -} -void VideoControllWidget::on_actionStop_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - controller->stop(); -} -void VideoControllWidget::on_actionNext_frame_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - controller->nextFrame(); -} -void VideoControllWidget::on_actionPrev_frame_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - controller->prevFrame(); -} -void VideoControllWidget::on_actionScreenshot_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - QString filePathStr = controller->takeScreenshot(); - QFileInfo fi(filePathStr); - QString filePathAbs = fi.absoluteFilePath(); - QString msgText = "The Screenshot has been saved to:\n " + filePathAbs; - - //QMessageBox::information(nullptr, "Screenshot taken!", msgText); - - QMessageBox msgBox; - msgBox.setText("You took a screenshot!"); - msgBox.setInformativeText(msgText); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - QPushButton *goToFileDirButton = msgBox.addButton(tr("Show in folder"), QMessageBox::ActionRole); - QPushButton *openFileButton = msgBox.addButton(tr("Open screenshot"), QMessageBox::ActionRole); - - msgBox.setIcon(QMessageBox::Information); - msgBox.exec(); - - if (msgBox.clickedButton() == goToFileDirButton) { - QUrl fileDirUrl = QUrl::fromLocalFile(fi.absolutePath()); - QDesktopServices::openUrl(fileDirUrl); - } - else if (msgBox.clickedButton() == openFileButton) { - QUrl fileUrl = QUrl::fromLocalFile(filePathAbs); - QDesktopServices::openUrl(fileUrl); - } -} -void VideoControllWidget::on_actionRecord_cam_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - - int success = controller->recordInput(); -} -void VideoControllWidget::on_actionRecord_all_triggered(bool checked) { - ControllerPlayer* controller = dynamic_cast(getController()); - - int success = controller->recordOutput(); - if (success == 1) { - QPixmap pix(":/Images/resources/recording.png"); - QIcon icon(pix); - ui->actionRecord_all->setIcon(icon); - //ui->actionRecord_all->setIconSize(QSize(32,32)); - } - else { - QPixmap pix(":/Images/resources/record.png"); - QIcon icon(pix); - ui->actionRecord_all->setIcon(icon); - //ui->actionRecord_all->setIconSize(QSize(32, 32)); - } -} - -MainWindow* VideoControllWidget::getMainWindow() -{ - foreach(QWidget *widget, qApp->topLevelWidgets()) - if (MainWindow *mainWindow = dynamic_cast(widget)) - return mainWindow; - return NULL; -} - -void VideoControllWidget::setupVideoToolbar() { - MainWindow* mw = getMainWindow(); - - if (mw) { - QToolBar* videoToolBar = mw->findChild("toolBarVideo"); - if (videoToolBar) { - - videoToolBar->addAction(ui->actionPrev_frame); - videoToolBar->addSeparator(); - videoToolBar->addAction(ui->actionPlay_Pause); - videoToolBar->addSeparator(); - videoToolBar->addAction(ui->actionStop); - videoToolBar->addSeparator(); - videoToolBar->addAction(ui->actionNext_frame); - videoToolBar->addSeparator(); - videoToolBar->addAction(ui->actionScreenshot); - videoToolBar->addSeparator(); - videoToolBar->addAction(ui->actionRecord_cam); - videoToolBar->addSeparator(); - videoToolBar->addAction(ui->actionRecord_all); - videoToolBar->addSeparator(); - - videoToolBar->addWidget(ui->scrollAreaVideoInfo); - } - } -} diff --git a/BioTracker/CoreApp/BioTracker/main.cpp b/BioTracker/CoreApp/BioTracker/main.cpp deleted file mode 100644 index f31faaa7..00000000 --- a/BioTracker/CoreApp/BioTracker/main.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "BioTracker3App.h" -#include "GuiContext.h" -#include "opencv2/core/core.hpp" -#include -#include "QVector" -#include "Model/MediaPlayerStateMachine/PlayerParameters.h" -#include "util/types.h" - -#include "util/CLIcommands.h" -#include "Interfaces/IModel/IModelTrackedComponent.h" - -//This will hide the console. -//See https://stackoverflow.com/questions/2139637/hide-console-of-windows-application -#ifdef _WIN32 -#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") -#endif - -int main(int argc, char* argv[]) { - QApplication app(argc, argv); - CLI::optionParser(argc, argv); - - qRegisterMetaType("cv::Mat"); - qRegisterMetaType>("std::shared_ptr"); - qRegisterMetaType("std::size_t"); - qRegisterMetaType("size_t"); - qRegisterMetaType>("std::vector"); - qRegisterMetaType("BiotrackerTypes::AreaType"); - qRegisterMetaType>("QVector"); - qRegisterMetaType("playerParameters*"); - qRegisterMetaType("CameraConfiguration"); - qRegisterMetaTypeStreamOperators>("QList"); - - boost::filesystem::create_directory(boost::filesystem::path(CFG_DIR_PLUGINS)); - boost::filesystem::create_directory(boost::filesystem::path(CFG_DIR_VIDEOS)); - boost::filesystem::create_directory(boost::filesystem::path(CFG_DIR_TRACKS)); - boost::filesystem::create_directory(boost::filesystem::path(CFG_DIR_TRIALS)); - boost::filesystem::create_directory(boost::filesystem::path(CFG_DIR_SCREENSHOTS)); - - BioTracker3App bioTracker3(&app); - GuiContext context(&bioTracker3); - bioTracker3.setBioTrackerContext(&context); - bioTracker3.runBioTracker(); - - app.exec(); -} diff --git a/BioTracker/CoreApp/BioTracker/util/CLIcommands.h b/BioTracker/CoreApp/BioTracker/util/CLIcommands.h deleted file mode 100644 index 105874da..00000000 --- a/BioTracker/CoreApp/BioTracker/util/CLIcommands.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - - - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "settings/Settings.h" -#include "util/types.h" - -class CLI { -public: - static int optionParser(int ac, char* av[]) - { - - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - - //Taken from http://www.boost.org/doc/libs/1_64_0/libs/program_options/example/option_groups.cpp - using namespace boost; - using namespace boost::program_options; - try { - // Declare three groups of options. - options_description general("General options"); - general.add_options() - ("help", "Produce this help message") - ("usePlugin", value(), "Uses plugin from given filepath") - ("video", value(), "Loads a video from given filepath") - ; - - options_description gui("GUI options"); - //gui.add_options() - // ("display", value(), "display to use") - // ; - - // Declare an options description instance which will include - // all the options - options_description all("Allowed options"); - all.add(general).add(gui); - - // Declare an options description instance which will be shown - // to the user - options_description visible("Allowed options"); - visible.add(general).add(gui); - - - variables_map vm; - store(parse_command_line(ac, av, all), vm); - - if (vm.count("help")) { - std::cout << visible; - exit(0); - } - if (vm.count("usePlugin")) { - const std::string& s = vm["usePlugin"].as(); - std::string *usePlugins = new std::string(s); - set->storeValue("usePlugins", (void*)usePlugins); - } - if (vm.count("video")) { - const std::string& s = vm["video"].as(); - std::string *video = new std::string(s); - set->storeValue("video", (void*)video); - } - } - catch (std::exception& e) { - std::cout << e.what() << "\n"; - } - } -}; diff --git a/BioTracker/CoreApp/BioTracker/util/Exceptions.h b/BioTracker/CoreApp/BioTracker/util/Exceptions.h deleted file mode 100644 index d31b8df8..00000000 --- a/BioTracker/CoreApp/BioTracker/util/Exceptions.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - - -namespace BioTracker { -namespace Core { - -struct video_open_error : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct file_not_found : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct directory_not_found : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct device_open_error : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct invalid_tracker_lib_error : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct path_creation_error : std::runtime_error { - using std::runtime_error::runtime_error; -}; - -} -} diff --git a/BioTracker/CoreApp/BioTracker/util/PanZoomState.h b/BioTracker/CoreApp/BioTracker/util/PanZoomState.h deleted file mode 100644 index 47dffca5..00000000 --- a/BioTracker/CoreApp/BioTracker/util/PanZoomState.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "boost/optional.hpp" -#include - -namespace BioTracker { -namespace Core { - -/** -* @brief Used to store mouse cursor offsets while panning. -*/ -struct CurrentPanState { - QPointF lastPos; - - CurrentPanState(const QPointF lastPos) - : lastPos(lastPos) { - } -}; - -/** - * @brief Stores the current zoom and pan offsets. While panning, panState stores the last mouse cursor position. - */ -struct PanZoomState { - float zoomFactor = 0.f; - float panX = 0.f; - float panY = 0.f; - bool isChanged = false; - - boost::optional panState; -}; - -} -} diff --git a/BioTracker/CoreApp/BioTracker/util/ParamNames.h b/BioTracker/CoreApp/BioTracker/util/ParamNames.h deleted file mode 100644 index 72b2d583..00000000 --- a/BioTracker/CoreApp/BioTracker/util/ParamNames.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include // std::string - -#include - -#include -#include - -namespace ConfigParam { -static const boost::filesystem::path CONFIG_PATH = boost::filesystem::path( - QDir::toNativeSeparators( - QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).toStdString()); -static const boost::filesystem::path BASE_PATH = CONFIG_PATH / "BioTracker"; -static const boost::filesystem::path CONFIGURATION_FILE = BASE_PATH / "config.json"; -static const boost::filesystem::path GEOMETRY_FILE = BASE_PATH / "geometry.cfg"; -static const boost::filesystem::path STATE_FILE = BASE_PATH / "state.cfg"; -static const boost::filesystem::path MODULE_PATH = BASE_PATH / "modules"; -} - -namespace TrackerParam { -static const std::string TRACKING_ENABLED = "TRACKERPARAM.TRACKING_ENABLED"; - -static const std::string SELECTED_TRACKER = "TRACKERPARAM.SELECTED_TRACKER"; -} - -namespace GuiParam { -enum class MediaType : uint8_t { - NoMedia = 0, - Video, - Images, - Camera -}; - -enum class VideoMode : uint8_t { - Playing = 0, - Paused, - Stopped, - Init -}; - - -static const std::string MEDIA_TYPE = "GUIPARAM.MEDIA_TYPE"; -static const std::string SHORTCUT_PLAY = "GUIPARAM.SHORTCUT_PLAY"; -static const std::string SHORTCUT_NEXT = "GUIPARAM.SHORTCUT_NEXT"; -static const std::string SHORTCUT_PREV = "GUIPARAM.SHORTCUT_PREV"; -static const std::string SHORTCUT_ZOOM = "GUIPARAM.SHORTCUT_ZOOM"; -static const std::string SHORTCUT_TRACKING = "GUIPARAM.SHORTCUT_TRACKING"; - -static const std::string PAUSED_AT_FRAME = "GUIPARAM.PAUSED_AT_FRAME"; -} - -namespace PictureParam { -//path to picture -static const std::string PICTURE_FILES = "PICTUREPARAM.PICTURE_FILES"; -} - -namespace CaptureParam { -// Video path -static const std::string CAP_VIDEO_FILE = "CAPTUREPARAM.CAP_VIDEO_FILE"; -static const std::string CAP_SCREENSHOT_PATH = - "CAPTUREPARAM.CAP_SCREENSHOT_PATH"; -static const std::string CAP_CAMERA_ID = "CAPTUREPARAM.CAP_CAMERA_ID"; - -// Video paths -static const std::string ENABLE_RECORD_RAW = - "CAPTUREPARAM.ENABLE_RECORD_RAW"; -static const std::string ENABLE_RECORD_TRACKING = - "CAPTUREPARAM.ENABLE_RECORD_TRACKING"; -static const std::string ENABLE_RECORD_TRACK_INFO = - "CAPTUREPARAM.ENABLE_RECORD_TRACK_INFO"; - -static const std::string RECORDING_TRACKING_PATH = - "CAPTUREPARAM.RECORDING_TRACKING_PATH"; -static const std::string RECORDING_RAW_PATH = - "CAPTUREPARAM.RECORDING_RAW_PATH"; -static const std::string TRACKING_INFO_OUTPUT_PATH = - "CAPTUREPARAM.TRACKING_INFO_OUTPUT_PATH"; - -enum CAP_TYPE_ENUM { - CAP_FROM_CAM = 0, - CAP_FROM_FILE = 1 -}; - -enum CAP_STATE_ENUM { - CAP_FINISHED = 0, - CAP_PAUSE = 1, - CAP_AVAILABLE = 2, - CAP_EXITED = 3 -}; -} - diff --git a/BioTracker/CoreApp/BioTracker/util/ScreenHelper.h b/BioTracker/CoreApp/BioTracker/util/ScreenHelper.h deleted file mode 100644 index ee8496ad..00000000 --- a/BioTracker/CoreApp/BioTracker/util/ScreenHelper.h +++ /dev/null @@ -1,208 +0,0 @@ -#pragma once - -#include // QRect -#include // QPoint -#include "PanZoomState.h" -#include "math.h" - -/** - * Screen helper functions - */ -namespace BioTracker { -namespace Core { -namespace ScreenHelper { - -/** - * @brief calculate_viewport - * @param im_w width of the image - * @param im_h height of the image - * @param w width of the videoview - * @param h height of the videoview - * @param window OUT parameter - * @param viewport OUT parameter - */ -inline float calculate_viewport( - const int im_w, const int im_h, - const int w, const int h, - QRect &window, QRect &viewport) { - - // We use setWindow and setViewport to fit the video into the - // given video widget frame (with width "w" and height "h") - // we later need to adjust an offset caused the use of different - // dimensions for window and viewport. - const float im_wf = static_cast(im_w); - const float im_hf = static_cast(im_h); - const float w_f = static_cast(w); - const float h_f = static_cast(h); - - float ratio = 0; - int offset_top = 0; - int offset_left = 0; - - if ((im_wf/im_hf) > (w_f/h_f)) { - // image ratio is bigger (wider image than window) - ratio = im_wf / w_f; - const float px = w_f / im_wf; - const float px_im_hf = px * im_hf; - offset_top = h/2 - static_cast(px_im_hf / 2); - } else { - // window ratio is bigger (narrow image) - ratio = im_hf / h_f; - const float px = h_f / im_hf; - const float px_im_wf = px * im_wf; - offset_left = w/2 - static_cast(px_im_wf / 2); - } - - const int screen_w = static_cast(im_wf * ratio); - const int screen_h = static_cast(im_hf * ratio); - - window.setX(0); - window.setY(0); - window.setWidth(screen_w); - window.setHeight(screen_h); - - viewport.setX(offset_left); - viewport.setY(offset_top); - viewport.setWidth(im_w); - viewport.setHeight(im_h); - - // adjust the panning as the viewport is potentially scewed - // and mouse movements given by the window are not translated - // one-to-one anymore - return screen_w / im_wf; -} - -/** - * @brief getImDimsInScreenCoords - * Calculates the actual dimension of the image with all zoom, pan and - * viewport transformations applied - * @return a rectangle that represents the position and dimension of the - * image in the videoview element - */ -inline QRect getImDimsInScreenCoords( - const PanZoomState zoomState, - const int im_w, const int im_h, - const int w, const int h) { - - QRect viewport, window; - const float viewportRatio = calculate_viewport(im_w, im_h, w, h, window, viewport); - const float zoom = 1 + zoomState.zoomFactor; - // back-translate the pan to non-zoomed coordinate space - float realPanX = -zoomState.panX; - float realPanY = -zoomState.panY; - realPanX += (viewport.x()); - realPanY += (viewport.y()); - - // The image in screen coords - QRect actualIm( - static_cast(realPanX), static_cast(realPanY), - static_cast((im_w / viewportRatio) * zoom), - static_cast((im_h / viewportRatio) * zoom) - ); - return actualIm; -} - -/** - * @brief imageToScreenCoords - */ -inline QPoint imageToScreenCoords( - const PanZoomState zoomState, - const int im_w, const int im_h, - const int w, const int h, - const QPoint poi) { - QPoint result; - const QRect actualIm = getImDimsInScreenCoords(zoomState, im_w, im_h, w, h); - const float one_step_x = actualIm.width() / static_cast(im_w); - const float one_step_y = actualIm.height() / static_cast(im_h); - const int actualPosXInIm = static_cast(round(poi.x() * one_step_x)); - const int actualPosYInIm = static_cast(round(poi.y() * one_step_y)); - result.setX(actualPosXInIm + actualIm.x()); - result.setY(actualPosYInIm + actualIm.y()); - return result; -} - -/** - * @brief screenToImageCoords - * Translate the window coordinates to the actual image coords - * @param im_w image width - * @param im_h image height - * @param w width of the videoview - * @param h height of the videoview - * @param poi Point in Screen Coords - */ -inline QPoint screenToImageCoords( - const BioTracker::Core::PanZoomState zoomState, - const int im_w, const int im_h, - const int w, const int h, - QPoint poi) { - QPoint result(0, 0); - - // The image in screen coords - QRect actualIm = getImDimsInScreenCoords(zoomState, im_w, im_h, w, h); - - const float im_wf = static_cast(im_w); - const float im_hf = static_cast(im_h); - const float one_step_x = im_wf / actualIm.width(); - const float one_step_y = im_hf / actualIm.height(); - - const float transformedX = (-actualIm.x() + poi.x()) * one_step_x; - const float transformedY = (-actualIm.y() + poi.y()) * one_step_y; - - result.setX(static_cast(round(transformedX))); - result.setY(static_cast(round(transformedY))); - - return result; -} - -/** - * @brief zoomTo - * Modifies the panzoomstate so that the cursor (zoomCenter) will point to the same - * location in the image as prior to the zoom - * @param im_w width of the image (in px) - * @param im_h height of the image (in px) - * @param w width of the videoview element - * @param h height of the videoview element - */ -inline PanZoomState zoomTo( - PanZoomState state, - const int im_w, - const int im_h, - const int w, - const int h, - const float deltaZoom, - const QPoint zoomCenter) { - - const QPoint imPos = screenToImageCoords(state, im_w, im_h, w, h, zoomCenter); - - const float oldZoomFactor = state.zoomFactor; - const float newZoomFactor = state.zoomFactor - (deltaZoom/2000); - - if (newZoomFactor <= -1.0f) { - // MAX VALUE - return state; - } - - const float zoom = 1 + newZoomFactor; - - const float oldPanX = state.panX / (1 + oldZoomFactor); - const float oldPanY = state.panY / (1 + oldZoomFactor); - - // zoom with origin in (0/0) - state.panX = oldPanX * zoom; - state.panY = oldPanY * zoom; - state.zoomFactor = newZoomFactor; - - // As we do not want to zoom to (0/0) but rather keep the focus on the chosen - // image position (zoomCenter) we now have to "back-translate" to our initial - // position - const QPoint translatedZoomCenter = imageToScreenCoords(state, im_w, im_h, w, h, imPos); - const QPoint translate = translatedZoomCenter - zoomCenter; - state.panX += translate.x(); - state.panY += translate.y(); - state.isChanged = true; - return state; -} - -} -} -} diff --git a/BioTracker/CoreApp/BioTracker/util/VideoCoder.cpp b/BioTracker/CoreApp/BioTracker/util/VideoCoder.cpp deleted file mode 100644 index 29caf9d8..00000000 --- a/BioTracker/CoreApp/BioTracker/util/VideoCoder.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include "VideoCoder.h" -#include -#include - -#ifdef _WIN32 -#include -#include -#endif - -#define mySleep(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)); - -void MutexLinkedList::push(std::shared_ptr imbuffer, bool dropFrames) { - - if (dropFrames) { - while (images.size() > MAXIMUMQUEUE) - pop(); - } - else { - while (images.size() > MAXIMUMQUEUE) - mySleep(10); - } - - _Access.lock(); - - images.push_back(imbuffer); - unsigned long s = images.size(); - unsigned long w = imbuffer->getWidth(); - unsigned long h = imbuffer->getHeight(); - //if (s*w*h / 1024 / 1024 > BUFFER_HARDLIMIT) { - // std::cout << "ERROR: Buffer exceeds hardlimit (" << BUFFER_HARDLIMIT << " MB). Exiting. " << std::endl; - // std::exit(1); - //} - _Access.unlock(); -} - -std::shared_ptr MutexLinkedList::pop() { - _Access.lock(); - if (images.size()>0) { - std::shared_ptr img = images.front(); - images.pop_front(); - _Access.unlock(); - return img; - } - _Access.unlock(); - - return std::make_shared(); -} - -void MutexLinkedList::MutexLinkedList::clear() { - _Access.lock(); - while (images.size()>0) { - images.pop_front(); - } - _Access.unlock(); -} - - -//Simple function to get the current size of the buffer in elements. -//Locks the data structure. -int MutexLinkedList::size() { - int tsize = 0; - _Access.lock(); - tsize = images.size(); - _Access.unlock(); - return tsize; -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -void YuvConverter::convert() -{ - int w = inImg.size().width; - int h = inImg.size().height; - unsigned char *prtM = inImg.data; - unsigned int stride = 1; - //Y - int x, y; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - //This works but is horribly slow! - //out0[y * w + x] = inImg.at(y, x)[0]; - //out1[y * w + x] = inImg.at(y, x)[1]; - //out2[y * w + x] = inImg.at(y, x)[2]; - //This works and is quite a bunch faster - out0[y * w + x] = (uint8_t)(*prtM); - prtM++; - out1[y * w + x] = (uint8_t)(*prtM); - prtM++; - out2[y * w + x] = (uint8_t)(*prtM); - prtM++; - } - } -} - -void YuvConverter::convert420() -{ - int w = inImg.size().width; - int h = inImg.size().height; - unsigned char *prtM = inImg.data; - unsigned int stride = 1; - //Y - int x, y; - for (y = 0; y < (h / 3 * 2); y++) { - for (x = 0; x < w; x++) { - unsigned char ch = (uint8_t)(*prtM); - out0[y * w + x] = ch; - prtM++; - } - } - - for (y = 0; y < (h / 3 * 1); y++) { - for (x = 0; x < w/2; x++) { - out2[y * w + x] = (uint8_t)(*prtM); - prtM++; - out1[y * w + x] = (uint8_t)(*prtM); - prtM++; - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////// - -void Worker::run() { - -#ifdef WITH_CUDA - if (m_nvEncoder) { - unsigned char *o0 = m_nvEncoder->getYuvChannel(0); - unsigned char *o1 = m_nvEncoder->getYuvChannel(1); - unsigned char *o2 = m_nvEncoder->getYuvChannel(2); - std::shared_ptr mat; - while (1) { - while ((mat = ll.pop())->getWidth() == -1) { - mySleep(10); - if (m_abort) return; - } - if (m_abort) return; - - cv::Mat writeMat; - cv::cvtColor(*(mat->_img), writeMat, CV_BGR2YUV_I420);//CV_BGR2YUV_I420 //CV_BGR2YUV - int chans = writeMat.channels(); - YuvConverter yc(writeMat, o0, o1, o2); - yc.convert420(); - m_nvEncoder->encodeNext(); - } - } - else -#endif - { - std::shared_ptr mat; - while (1) { - while ((mat = ll.pop())->getWidth() == -1) { - mySleep(10); - if (m_abort) return; - } - if (m_abort) return; - - m_vWriter->write(*mat->_img); - } - - } -} - -int VideoCoder::toggle(int w, int h, double fps) { - - //Grab the codec from config file - BioTracker::Core::Settings *set = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - std::string codecStr = codecList[set->getValueOrDefault(CFG_CODEC, 0)].second; - m_dropFrames = set->getValueOrDefault(CFG_DROPFRAMES, CFG_DROPFRAMES_VAL); - m_qp = set->getValueOrDefault(CFG_GPU_QP, CFG_GPU_QP_VAL); - if (fps == -1) { - fps = m_fps; - } - - - if (!m_recording) - { - worker = std::make_shared(); - - //Check which one to use - if (codecStr == "X264") { - int codec = CV_FOURCC('X', 'V', 'I', 'D'); - vWriter = std::make_shared(getTimeAndDate(std::string(CFG_DIR_VIDEOS)+"CameraCapture", ".avi"), codec, fps, CvSize(w, h), 1); - m_recording = vWriter->isOpened(); - vWriter->set(cv::VIDEOWRITER_PROP_QUALITY, 100); - std::cout << "Video is open:" << m_recording << std::endl; - m_recType = 2; - int ok = start(); - m_recording = (ok == 1 ? false : true); - } - else if (codecStr == "X264GPU") { -#ifdef WITH_CUDA - auto cfg = m_nvEncoder->getEncodeConfig(); - cfg->fps = fps; - cfg->width = w; - cfg->height = h; - cfg->codec = NV_ENC_H264; - cfg->inputFormat = NV_ENC_BUFFER_FORMAT_NV12;//NV_ENC_BUFFER_FORMAT_NV12;//NV_ENC_BUFFER_FORMAT_YUV444 - const std::string f = getTimeAndDate(std::string(CFG_DIR_VIDEOS) + "CameraCapture", ".avi"); - char* chr = strdup(f.c_str()); - m_nvEncoder->setOutfile(chr); - cfg->qp = m_qp; - m_recType = 1; - int ok = start(); - free(chr); - m_recording = (ok == 1 ? false : true); - std::cout << "Video is open:" << m_recording << std::endl; -#endif - } - } - else { - m_recording = false; - if (m_recType == 1) - stop(); - if (m_recType == 2) - stop();//vWriter->release(); - vWriter = 0; - } - if (!m_recording) - m_recType = 0; - return m_recording; -} - -void VideoCoder::add(std::shared_ptr m, int needsConversion) { - worker->ll.push(std::make_shared(m, needsConversion), m_dropFrames); -} - -int VideoCoder::start() { -#ifdef WITH_CUDA - if (m_recType == 1) { - int ok = m_nvEncoder->init(); - if (ok > 0) - return ok; - worker->m_nvEncoder = m_nvEncoder; - worker->start(); - } - else -#endif - if (m_recType == 2) { - worker->m_vWriter = vWriter; - worker->start(); - } - - return 0; -} - -void VideoCoder::stop() { - if (m_recType > 0) { - worker->m_abort = true; - worker->wait(); -#ifdef WITH_CUDA - if (m_nvEncoder) - m_nvEncoder->close(); -#endif - if (vWriter) - vWriter->release(); - worker->ll.clear(); - } -} - - - diff --git a/BioTracker/CoreApp/BioTracker/util/VideoCoder.h b/BioTracker/CoreApp/BioTracker/util/VideoCoder.h deleted file mode 100644 index 979f577d..00000000 --- a/BioTracker/CoreApp/BioTracker/util/VideoCoder.h +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - - -#include - -#include -#include - -#include "util/misc.h" -#ifdef WITH_CUDA -#include "EncoderInterface.h" -#endif - -#include "settings/Settings.h" -#include "util/types.h" - -#define MAXIMUMQUEUE 30 - -class YuvConverter -{ -private: - cv::Mat& inImg; - unsigned char* out0; - unsigned char* out1; - unsigned char* out2; -public: - YuvConverter(cv::Mat& inputImgage - , unsigned char* o0 - , unsigned char* o1 - , unsigned char* o2) - : inImg(inputImgage), out0(o0), out1(o1), out2(o2) { - } - void convert(); - void convert420(); -}; - -class ImageBuffer { -public: - std::shared_ptr _img; - int _needsConversion; - - ImageBuffer(std::shared_ptr pimg, int ncv) : _img(pimg), _needsConversion(ncv) { - - } - ImageBuffer(){} - - int getWidth() { - if (_img) - return _img->size().width; - return -1; - } - - int getHeight() { - if (_img) - return _img->size().height; - return -1; - } -}; - -class MutexLinkedList { -public: - std::list> images; - std::mutex _Access; - - void push(std::shared_ptr imbuffer, bool dropFrames = false); - - std::shared_ptr pop(); - - void clear(); - - - //Simple function to get the current size of the buffer in elements. - //Locks the data structure. - virtual int size(); - - MutexLinkedList() {} - ~MutexLinkedList() {} -}; - -class Worker : public QThread -{ - Q_OBJECT - -public: - MutexLinkedList ll; - bool m_abort; -#ifdef WITH_CUDA - std::shared_ptr m_nvEncoder; -#endif - std::shared_ptr m_vWriter; - - Worker() { - m_abort = false; - }; - void run(); - - public slots: - - //void doWork(const QString ¶meter); - -}; - -class VideoCoder : public QObject -{ - Q_OBJECT - -public: - VideoCoder(double fps) { -#ifdef WITH_CUDA - m_nvEncoder = std::make_shared(); -#endif - m_recType = 0; - m_recording = false; - m_dropFrames = false; - m_fps = fps; - } - - VideoCoder() : VideoCoder(1) { - } - - ~VideoCoder() { - stop(); - } - - int toggle(int w, int h, double fps = -1); - - void add(std::shared_ptr m, int needsConversion = 0); - - int start(); - void stop(); -#ifdef WITH_CUDA - std::shared_ptr m_nvEncoder; -#endif - -private: - - std::shared_ptr worker; - std::shared_ptr vWriter; - int m_recType; - int m_recording; - bool m_dropFrames; - int m_qp; - double m_fps; -signals: - void operate(const QString &); -}; - diff --git a/BioTracker/CoreApp/BioTracker/util/stdext.h b/BioTracker/CoreApp/BioTracker/util/stdext.h deleted file mode 100644 index ada7c5d7..00000000 --- a/BioTracker/CoreApp/BioTracker/util/stdext.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef STDEXT_H -#define STDEXT_H - -/* implementation of std::make_unique for c++<14 - * implementation according to N3656 - * see: http://isocpp.org/files/papers/N3656.txt - */ - -#include -#if (!defined(_MSC_VER) && __cplusplus <= 201103L) || (defined(_MSC_VER) && _MSC_VER < 1800) -#include -#include -#include - -namespace std { -template struct _Unique_if { - typedef unique_ptr _Single_object; -}; - -template struct _Unique_if { - typedef unique_ptr _Unknown_bound; -}; - -template struct _Unique_if { - typedef void _Known_bound; -}; - -template -typename _Unique_if::_Single_object -make_unique(Args &&... args) { - return unique_ptr(new T(std::forward(args)...)); -} - -template -typename _Unique_if::_Unknown_bound -make_unique(size_t n) { - typedef typename remove_extent::type U; - return unique_ptr(new U[n]()); -} - -template -typename _Unique_if::_Known_bound -make_unique(Args &&...) = delete; -} -#endif - -#endif diff --git a/BioTracker/CoreApp/BioTracker/util/types.h b/BioTracker/CoreApp/BioTracker/util/types.h deleted file mode 100644 index d119c62d..00000000 --- a/BioTracker/CoreApp/BioTracker/util/types.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - - -#include - -#ifndef CORE_CONFIGURATION -#define CORE_CONFIGURATION "BiotrackerCore.ini" -#define CFG_CODEC "BiotrackerCore/CodecUsed" -#define CFG_DROPFRAMES "BiotrackerCore/DropFrames" -#define CFG_DROPFRAMES_VAL false -#define CFG_RECORDSCALEDOUT "BiotrackerCore/RecordScaledOutput" -#define CFG_EXPORTER "BiotrackerCore/DataExporter" -#define CFG_RECORD_FPS "BiotrackerCore/Record_FPS" -#define CFG_RECORD_FPS_VAL -1 -#define CFG_CAMERA_DEFAULT_W "BiotrackerCore/CameraWidth" -#define CFG_CAMERA_DEFAULT_W_VAL -1 -#define CFG_CAMERA_DEFAULT_H "BiotrackerCore/CameraHeight" -#define CFG_CAMERA_DEFAULT_H_VAL -1 -#define CFG_INPUT_FRAME_STRIDE "BiotrackerCore/FrameStride" -#define CFG_INPUT_FRAME_STRIDE_VAL 1 -#define CFG_GPU_QP "BiotrackerCore/GPU_QP" -#define CFG_GPU_QP_VAL 15 -#define CFG_SER_CSVSEP "Serializers/CSV_SEPARATOR" -#define CFG_SER_CSVSEP_VAL ";" -#define CFG_DEFAULT_LOC_MAN_SAVE "BiotrackerCore/DefaultLocationManualSave" -#define CFG_DEFAULT_LOC_MAN_SAVE_VAL "" - - -#define CFG_DIR_PLUGINS "./Plugins/" -#define CFG_DIR_VIDEOS "./Videos/" -#define CFG_DIR_TRACKS "./Tracks/" -#define CFG_DIR_TRIALS "./Tracks/Trials/" -#define CFG_DIR_SCREENSHOTS "./Screenshots/" -#define CFG_DIR_TEMP "./temp/" -#define CFG_AREA_DEFINITIONS "./areas.csv" -#endif - -namespace BiotrackerTypes{ - enum AreaType { - NONE = -1, - RECT = 0, - APPERTURE = 1, - COMBINED = 2 - }; - -} - -namespace AREADESCRIPTOR -{ - const std::string CN_ARENA = "TRACKERPARAM/CN_CORNERS_ARENA"; - const std::string CN_APPERTURE = "TRACKERPARAM/CN_CORNERS_APPERTURE"; - const std::string CN_APPERTURE_TYPE = "TRACKERPARAM/CN_CORNERS_APPERTURE_TYPE"; - const std::string DISP_AREA = "TRACKERPARAM/DISPLAY_TRACKING_AREA"; - const std::string DISP_RECT = "TRACKERPARAM/DISPLAY_RECTIFICATION_AREA"; - const std::string RECT_W = "RECTIFICATION/WIDTH"; - const int RECT_W_DEFAULT = 100; - const std::string RECT_H = "RECTIFICATION/HEIGHT"; - const int RECT_H_DEFAULT = 100; -} - - -const std::vector> codecList = { - std::pair("X264 (CPU)", "X264"), -#ifdef WITH_CUDA - std::pair("X264 (GPU)", "X264GPU") -#endif -}; - -const std::vector exporterList = { - std::string("CSV"), - std::string("Serialize"), - std::string("Json") -}; - -class CameraConfiguration -{ -public: - CameraConfiguration() : - _id(0), _width(CFG_CAMERA_DEFAULT_W_VAL), _height(CFG_CAMERA_DEFAULT_H_VAL), _fps(CFG_RECORD_FPS_VAL), _recordInput(false), _fourcc("X264") { - } - CameraConfiguration(int p_id, int p_width, int p_height, double p_fps, bool p_recordInput, std::string p_fourcc) : - _id(p_id), _width(p_width), _height(p_height), _fps(p_fps), _recordInput(p_recordInput), _fourcc(p_fourcc) { - } - - int _id; - int _width; - int _height; - bool _recordInput; - double _fps; - std::string _fourcc; -}; - - - diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/BioTrackerInterfaces.pro b/BioTracker/Interfaces/BioTrackerInterfaces/BioTrackerInterfaces.pro deleted file mode 100644 index 0df957c2..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/BioTrackerInterfaces.pro +++ /dev/null @@ -1,53 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-12-01T17:31:27 -# -#------------------------------------------------- - -QT += widgets - -TARGET = BioTrackerInterfaces -TEMPLATE = lib -CONFIG += staticlib - -SOURCES += \ - Interfaces/IModel/IObject.cpp \ - Interfaces/IView/IView.cpp \ - Interfaces/IView/IViewGraphicsScene.cpp \ - Interfaces/IView/IViewMainWindow.cpp \ - Interfaces/IView/IViewOpenGLWidget.cpp \ - Interfaces/IView/IViewTrackedComponent.cpp \ - Interfaces/IView/IViewWidget.cpp \ - Interfaces/IBioTrackerContext.cpp \ - Interfaces/IController/IController.cpp \ - Interfaces/IModel/IModel.cpp \ - Interfaces/IView/IViewGraphicsPixmapItem.cpp \ - Interfaces/IView/IViewGraphicsView.cpp \ - Interfaces/IModel/IModelTrackedComponent.cpp \ - Interfaces/IModel/IModelTrackedComponentFactory.cpp \ - Interfaces/IModel/IModelTrackedTrajectory.cpp \ - Interfaces/IModel/IModelTrackingAlgorithm.cpp - -HEADERS += \ - Interfaces/IModel/IObject.h \ - Interfaces/IView/IView.h \ - Interfaces/IView/IViewGraphicsScene.h \ - Interfaces/IView/IViewMainWindow.h \ - Interfaces/IView/IViewOpenGLWidget.h \ - Interfaces/IView/IViewTrackedComponent.h \ - Interfaces/IView/IViewWidget.h \ - Interfaces/ENUMS.h \ - Interfaces/IBioTrackerContext.h \ - Interfaces/IBioTrackerPlugin.h \ - Interfaces/IController/IController.h \ - Interfaces/IModel/IModel.h \ - Interfaces/IView/IViewGraphicsPixmapItem.h \ - Interfaces/IView/IViewGraphicsView.h \ - Interfaces/IModel/IModelTrackedComponent.h \ - Interfaces/IModel/IModelTrackedComponentFactory.h \ - Interfaces/IModel/IModelTrackedTrajectory.h \ - Interfaces/IModel/IModelTrackingAlgorithm.h -unix { - target.path = /usr/lib - INSTALLS += target -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/CMakeLists.txt b/BioTracker/Interfaces/BioTrackerInterfaces/CMakeLists.txt deleted file mode 100644 index 9b516426..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -############################################################## -#### Biotracker: Interfaces -############################################################## - -set(INCLUDE_DIRS - ${INCLUDE_DIRS} - ${OpenCV_INCLUDE_DIRS} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Gui_INCLUDE_DIRS} - ${Qt5Xml_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} - ${CMAKE_CURRENT_SOURCE_DIR} - ) - -# Visual studio out-of-source friendly source groups -set(_plugin_src_root_path ${CMAKE_CURRENT_SOURCE_DIR}) -file( - GLOB_RECURSE _plugin_source_list - LIST_DIRECTORIES false - "${_plugin_src_root_path}/*.c*" - "${_plugin_src_root_path}/*.h*" - "${_plugin_src_root_path}/*.ui*" -) -foreach(_plugin_source IN ITEMS ${_plugin_source_list}) - get_filename_component(_plugin_source_path "${_plugin_source}" PATH) - file(RELATIVE_PATH _plugin_source_path_rel "${_plugin_src_root_path}" "${_plugin_source_path}") - string(REPLACE "/" "\\" _plugin_group_path "${_plugin_source_path_rel}") - source_group("${_plugin_group_path}" FILES "${_plugin_source}") -endforeach() - -message("Configuring Biotracker_interfaces...") -set(EXE_NAME Biotracker_interfaces) -add_library(${EXE_NAME} STATIC ${_plugin_source_list} ) -target_include_directories(${EXE_NAME} PUBLIC ${INCLUDE_DIRS}) -target_link_libraries(${EXE_NAME} ${OpenCV_LIBRARIES}) -target_link_libraries(${EXE_NAME} Qt5::Core Qt5::Gui Qt5::Xml Qt5::Network Qt5::Widgets) - -set_target_properties(${EXE_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) -set_target_properties(${EXE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO -) - diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/ENUMS.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/ENUMS.h deleted file mode 100644 index 26acd1a4..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/ENUMS.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef ENUMS_H -#define ENUMS_H - -#include - -class ENUMS : public QObject -{ - Q_OBJECT -public: - - - enum CONTROLLERTYPE { - NO_CTR, - MAINWINDOW, - TEXTUREOBJECT, - PLAYER, - COMPONENT, - TRACKING, - GRAPHICSVIEW, - TRACKEDCOMPONENTCORE, - PLUGIN, - DATAEXPORT, - ANNOTATIONS, - AREADESCRIPTOR, - COREPARAMETER, - COMMANDS, - NOTIFICATION - }; - - Q_ENUM(CONTROLLERTYPE) - enum COREPERMISSIONS { - COMPONENTVIEW, - COMPONENTMOVE, - COMPONENTREMOVE, - COMPONENTSWAP, - COMPONENTADD, - COMPONENTROTATE - }; - Q_ENUM(COREPERMISSIONS) - - explicit ENUMS(QObject *parent = 0); - -}; - -#endif // ENUMS_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerContext.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerContext.cpp deleted file mode 100644 index 9eb71ed0..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerContext.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "IBioTrackerContext.h" -#include "Interfaces/IController/IController.h" - -#include "QDebug" - - -IBioTrackerContext::IBioTrackerContext(QObject *parent) : - QObject(parent) -{ - -} - -void IBioTrackerContext::createApplication() -{ - createAppController(); - connectController(); -} - - -void IBioTrackerContext::createAppController() -{ - -} - -IController *IBioTrackerContext::requestController(ENUMS::CONTROLLERTYPE ctrtype) -{ - return m_ControllersMap.value(ctrtype); -} - -void IBioTrackerContext::connectController() -{ - -} - -void IBioTrackerContext::addController(IController *ctr) -{ - m_ControllersMap.insert(ctr->getControllerType(), ctr); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerContext.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerContext.h deleted file mode 100644 index c1ca6883..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerContext.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef IBIOTRACKERCONTEXT_H -#define IBIOTRACKERCONTEXT_H - -#include -#include "QMap" -#include "QString" -#include "Interfaces/ENUMS.h" - - -class IController; -class IBioTrackerContext : public QObject -{ - Q_OBJECT -public: - IBioTrackerContext(QObject *parent = 0); - ~IBioTrackerContext() {} - - void createApplication(); - - IController * requestController(ENUMS::CONTROLLERTYPE ctrtype); - -protected: - virtual void createAppController(); - virtual void connectController(); - - void addController(IController * ctr); -protected: - QMap m_ControllersMap; - - - -}; - -#endif // IBIOTRACKERCONTEXT_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerPlugin.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerPlugin.cpp deleted file mode 100644 index 6e00a551..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerPlugin.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "IBioTrackerPlugin.h" - -IView *IBioTrackerPlugin::getTrackerParameterWidget() { return nullptr; }; -IView *IBioTrackerPlugin::getTrackerElementsWidget() { return nullptr; }; -IModel *IBioTrackerPlugin::getTrackerComponentModel() { return nullptr; }; -void IBioTrackerPlugin::sendCorePermissions() { return; }; -IModelTrackedComponentFactory *IBioTrackerPlugin::getComponentFactory() { return nullptr; }; -void IBioTrackerPlugin::connectInterfaces() { return; }; -void IBioTrackerPlugin::receiveAreaDescriptor(IModelAreaDescriptor *areaDescr) { return; }; \ No newline at end of file diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerPlugin.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerPlugin.h deleted file mode 100644 index 115eb82c..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IBioTrackerPlugin.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef IBIOTRACKERPLUGIN_H -#define IBIOTRACKERPLUGIN_H - -#include "QObject" - -#include "Interfaces/IController/IController.h" -#include "Interfaces/IModel/IModelDataExporter.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include "Interfaces/IModel/IModelTrackedComponentFactory.h" -#include "opencv2/core/core.hpp" -#include "memory" - -class IBioTrackerPlugin : public QObject -{ - Q_OBJECT -public: - ~IBioTrackerPlugin() {} - - virtual void createPlugin() = 0; - - /** - * Hook for the tracker options to add to the GUI - */ - virtual IView *getTrackerParameterWidget(); - /** - * Hook for the tracking data visualization of the tracker - */ - virtual IView *getTrackerElementsWidget(); - /** - * Hook for the tracking data to visualize and export in the core app - */ - virtual IModel *getTrackerComponentModel(); - /** - * Hook for the core permissions - */ - virtual void sendCorePermissions(); - /** - * Hook for the component factory to deserialize in the core app - */ - virtual IModelTrackedComponentFactory *getComponentFactory(); - -private: - virtual void connectInterfaces(); - -Q_SIGNALS: - virtual void emitCvMat(std::shared_ptr mat, QString name) = 0; - /** - * Will be sent when tracking is doen to multiple components of the core app - * An example is the visualisation which is then updated - */ - virtual void emitTrackingDone(uint framenumber) = 0; - virtual void emitChangeDisplayImage(QString str) = 0; - virtual void emitCorePermission(std::pair) = 0; - -public Q_SLOTS: - virtual void receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber) = 0; - /** - * Recieves area descriptor data for rectification (px to cm) and for tracking arena boundary - */ - virtual void receiveAreaDescriptor(IModelAreaDescriptor *areaDescr); - -//private Q_SLOTS: -// virtual void receiveCvMatFromController(std::shared_ptr mat, QString name) = 0; -}; - -#define IBioTrackerPlugin_iid "de.fu-berlin.mi.biorobotics.IBioTrackerPlugin" - -Q_DECLARE_INTERFACE(IBioTrackerPlugin, IBioTrackerPlugin_iid) - -#endif // IBIOTRACKERPLUGIN_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IController/IController.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IController/IController.cpp deleted file mode 100644 index 9c898cd9..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IController/IController.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "IController.h" - - -IController::IController(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : QObject(parent), - m_BioTrackerContext(context), - m_ControllerType(ctr) -{ - -} - -void IController::cleanup() { - -} - -IBioTrackerContext *IController::getBioTrackerContext() -{ - return m_BioTrackerContext.data(); -} - -void IController::connectModelToController() -{ - -} - -void IController::createComponents() -{ - createModel(); - createView(); - connectModelToController(); -} - -void IController::connectComponents() -{ - connectControllerToController(); -} - -void IController::addView(IView *view) { - m_View = view; -} - -void IController::addModel(IModel *model) { - m_Model = model; -} - -IModel *IController::getModel() { - return m_Model.data(); -} - -IView *IController::getView() { - return m_View; -} - -ENUMS::CONTROLLERTYPE IController::getControllerType() -{ - return m_ControllerType; -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IController/IController.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IController/IController.h deleted file mode 100644 index 616c224d..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IController/IController.h +++ /dev/null @@ -1,56 +0,0 @@ - -#ifndef ICONTROLLER_H -#define ICONTROLLER_H - -#include -#include "QMap" -#include "QPointer" - -#include "Interfaces/IView/IView.h" -#include "Interfaces/IModel/IModel.h" -#include "Interfaces/IBioTrackerContext.h" -#include "Interfaces/ENUMS.h" - - -class IController : public QObject { - Q_OBJECT - public: - explicit IController(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - /** - * @brief - */ - void createComponents(); - - /** - * @brief connectComponents - */ - void connectComponents(); - - virtual void cleanup(); - - void addView(IView *view); - void addModel(IModel *model); - IModel *getModel(); - IView *getView(); - - ENUMS::CONTROLLERTYPE getControllerType(); - IBioTrackerContext *getBioTrackerContext(); - -protected: - virtual void createModel() = 0; - virtual void createView() = 0; - virtual void connectModelToController() = 0; - virtual void connectControllerToController() = 0; - -protected: - QPointer< IBioTrackerContext > m_BioTrackerContext; - - IView *m_View; - QPointer m_Model; - - ENUMS::CONTROLLERTYPE m_ControllerType; - -}; - -#endif // ICONTROLLER_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModel.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModel.cpp deleted file mode 100644 index 3de1fa44..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModel.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "IModel.h" - -IModel::IModel(QObject *parent) : QObject(parent) { - -} - -IModel::~IModel() { - -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModel.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModel.h deleted file mode 100644 index 171e4731..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModel.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef IMODEL_H -#define IMODEL_H - -#include - -#include "memory" - -class IModel : public QObject { - Q_OBJECT - public: - explicit IModel(QObject *parent = 0); - ~IModel(); - - Q_SIGNALS: - - void notifyView(); - - public Q_SLOTS: -}; - -#endif // IMODEL_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelAreaDescriptor.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelAreaDescriptor.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelAreaDescriptor.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelAreaDescriptor.h deleted file mode 100644 index 4f3efb48..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelAreaDescriptor.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "IModel.h" -#include -#include - -class IModelAreaDescriptor :public IModel -{ - Q_OBJECT - -public: - IModelAreaDescriptor(QObject *parent = 0) : IModel(parent) {}; - //~IModelAreaDescriptor(); - -public: - - virtual bool inTrackingArea(cv::Point2f point_cm) = 0; - - /** - * Transform the provided pixel coordinates into world coordinates and return world coordinates. - * @param: pixelCoords, a list of points. - * @return: world coordinates in as a list. - */ - virtual cv::Point2f pxToCm(cv::Point point_px) = 0; - - /** - * Transform the provided pixel point into world coordinates and return world point. - * @param: point, a pixel point, used opencv point - * @return: world point. - */ - virtual cv::Point2f cmToPx(cv::Point2f point_cm) = 0; -public: - -}; - diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelDataExporter.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelDataExporter.cpp deleted file mode 100644 index 672137e8..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelDataExporter.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "IModelDataExporter.h" - - - -IModelDataExporter::IModelDataExporter(QObject *parent) : - IModel(parent) -{ -} - - -IModelDataExporter::~IModelDataExporter() -{ -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelDataExporter.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelDataExporter.h deleted file mode 100644 index c33168f4..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelDataExporter.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "IModel.h" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "Interfaces/IModel/IModelTrackedComponent.h" -#include -#include -/** -* Interface for the data exporters in the core app -* Besides serializing to files also includes deserializing from files -* Current exporters are CSV, generic and JSON. -*/ -class IModelDataExporter :public IModel -{ - Q_OBJECT - -public: - IModelDataExporter(QObject *parent = 0); - ~IModelDataExporter(); - - virtual void open(IModelTrackedTrajectory *root) = 0; - virtual void write(int idx) = 0; - virtual void writeAll(std::string f) = 0; - virtual void close() = 0; - virtual void finalizeAndReInit() = 0; - void setFps(float fps) { _fps = fps; }; - void setTitle(std::string title) { _title = title; }; - virtual void finalize() = 0; - - virtual void loadFile(std::string file) = 0; - virtual QString getSuffix() = 0; - -public: - IModelTrackedTrajectory *_root; - float _fps; - std::string _title; - -signals: - void fileWritten(QFileInfo file); -}; - diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponent.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponent.cpp deleted file mode 100644 index 1dd5f654..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponent.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "IModelTrackedComponent.h" -#include -#include -#include "Interfaces/IModel/IModelTrackedComponentFactory.h" -#include "IModelTrackedTrajectory.h" - -IModelTrackedComponentFactory* factory = nullptr; - -IModelTrackedComponent::IModelTrackedComponent(QObject *parent) : - IModel(parent) -{ - -} - -IModelComponentEuclidian2D::IModelComponentEuclidian2D(QObject *parent) : - IModelTrackedComponent(parent) -{ - -} - -IModelComponentTemporal2D::IModelComponentTemporal2D(QObject *parent) : - IModelComponentEuclidian2D(parent) -{ - -} - -IModelTrackedPoint::IModelTrackedPoint(QObject *parent) : - IModelComponentTemporal2D(parent) -{ - -} - -IModelTrackedPolygon::IModelTrackedPolygon(QObject *parent) : - IModelComponentTemporal2D(parent) -{ - -} - -IModelTrackedEllipse::IModelTrackedEllipse(QObject *parent) : - IModelTrackedPoint(parent) -{ - -} - -IModelTrackedRectangle::IModelTrackedRectangle(QObject *parent) : - IModelTrackedPoint(parent) -{ - -} - -QDataStream &operator<<(QDataStream &ds, const QList &data) { - ds << qint64(data.size()); - for (int i = 0; imetaObject()->className()); - else - ds << QString("NULL"); - ds << *(data[i]); - } - return ds; -} - -QDataStream &operator >> (QDataStream &ds, QList &data) { - qint64 s; - ds >> s; - for (int i = 0; i> cn; - std::string sss = cn.toStdString(); - IModelTrackedComponent* cp = static_cast(factory->getNewTrackedElement(cn)); - ds >> (*cp); - data.append(cp); - } - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const IModelTrackedComponent &data) { - for (int i = 0; ipropertyCount(); ++i) - { - if (data.metaObject()->property(i).isStored(&data)) - { - QVariant v = data.metaObject()->property(i).read(&data); - ds << data.metaObject()->property(i).read(&data); - } - } - return ds; -} - -QDataStream &operator>>(QDataStream &ds, IModelTrackedComponent &data) { - QVariant var; - for (int i = 0; ipropertyCount(); ++i) - { - if (data.metaObject()->property(i).isStored(&data)) - { - ds >> var; - data.metaObject()->property(i).write(&data, var); - } - } - return ds; -} - diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponent.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponent.h deleted file mode 100644 index cc47f9d5..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponent.h +++ /dev/null @@ -1,344 +0,0 @@ -#ifndef ITRACKEDCOMPONENT_H -#define ITRACKEDCOMPONENT_H - -#include "IModel.h" -#include - -#include -#include -#include -#include - - -/** -* This is the common interface for all TrackedComponents (IModelTrackedTrajectory and any leaf class). -* It is part of the Composite Pattern and is the equivalent to the abstract Component class. -* This class is derived from IModel from the Model-View-Controller structure. -* A TrackedComponent has a QObject as parent and it -* has a methode called operate() that needs to be implemented -* by all derivatives of this interface class. -*/ - -/* -* Blank component -*/ - -class IModelTrackedComponent : public IModel -{ - Q_OBJECT - /* - Q_PROPERTY-System: http://doc.qt.io/qt-5/properties.html - */ - Q_PROPERTY(bool valid READ getValid() WRITE setValid STORED true) - Q_PROPERTY(double id READ getId() WRITE setId STORED true) -public: - /** - * The constructor of the IModelTrackedComponent class is able to receive a QObject as parent. - */ - IModelTrackedComponent(QObject *parent = 0); - /* - Getters, Setters & Checkers - */ - virtual void setValid(bool v) { _valid = v; }; - virtual void setId(int id) { _id = id; }; - virtual void setFixed(bool fixed) { _fixed = fixed; }; - virtual void setParent(IModelTrackedComponent *p) { _parentNode = p; }; - virtual int getId() { return _id; }; - virtual bool getValid() { return _valid; }; - virtual bool getFixed() { return _fixed; }; - - /** - * The methode operate() must be implemented by every derivative of this class. - */ - virtual void operate() = 0; - -protected: - int _id; /**< id of the component */ - bool _valid; /**< validity of the component; if invalid -> not visualized */ - bool _fixed; /**< fix status; if fixed the tracked should not change state*/ - IModelTrackedComponent *_parentNode = nullptr; /**< parent */ -}; - - -Q_DECLARE_METATYPE(QList) -/** -* Serialization operator for multiple components. -*/ -QDataStream &operator<<(QDataStream &ds, const QList &data); -/** -* Deserialization operator for multiple components. -*/ -QDataStream &operator>>(QDataStream &ds, QList &data); -/** -* Serialization operator for one component. -*/ -QDataStream &operator<<(QDataStream &out, const IModelTrackedComponent &painting); -/** -* Deserialization operator for one component. -*/ -QDataStream &operator>>(QDataStream &in, IModelTrackedComponent &painting); - -/***************************************************************************//** -* This is a node of the Composite Pattern -* This class is derived from IModelTrackedComponent. -* It includes positional data like x,y-coordinates (in px and _coordinateUnit), the orientation in rad and deg -* and the width and height (in px and _coordinateUnit) -*******************************************************************************/ - -class IModelComponentEuclidian2D : public IModelTrackedComponent { -public: - Q_OBJECT - /* - Q_PROPERTY-System: http://doc.qt.io/qt-5/properties.html - */ - Q_PROPERTY(QString coordinateUnit READ getCoordinateUnit() WRITE setCoordinateUnit STORED true) - Q_PROPERTY(float x READ getX() WRITE setX STORED hasX) - Q_PROPERTY(float y READ getY() WRITE setY STORED hasY) - Q_PROPERTY(float w READ getW() WRITE setW STORED hasW) - Q_PROPERTY(float h READ getH() WRITE setH STORED hasH) - Q_PROPERTY(float wpx READ getWpx() WRITE setWpx STORED hasWpx) - Q_PROPERTY(float hpx READ getHpx() WRITE setHpx STORED hasHpx) - Q_PROPERTY(float rad READ getRad() WRITE setRad STORED hasRad) - Q_PROPERTY(float deg READ getDeg() WRITE setDeg STORED hasDeg) - Q_PROPERTY(float xpx READ getXpx() WRITE setXpx STORED hasXpx) - Q_PROPERTY(float ypx READ getYpx() WRITE setYpx STORED hasYpx) - -public: - /** - * The constructor of the IModelTrackedComponent class is able to receive a QObject as parent. - * It should not be implemented as it is a not a leaf or a composite - */ - IModelComponentEuclidian2D(QObject *parent = 0); - - /* Returns a human-readable string about coordinate units. - * Freely enter something like "px", "cm" or "um". This will be annotated in the output. - */ - virtual QString getCoordinateUnit() { return "cm"; }; - virtual void setCoordinateUnit(QString c) { _coordinateUnit = c; }; - - /* - Getters, Setters & Checkers - */ - virtual void setX(float x) = 0; - virtual void setY(float y) = 0; - virtual void setW(float w) = 0; - virtual void setH(float h) = 0; - virtual void setXpx(float h) = 0; - virtual void setYpx(float h) = 0; - virtual void setWpx(float h) = 0; - virtual void setHpx(float h) = 0; - virtual void setRad(float r) = 0; - virtual void setDeg(float d) = 0; - - virtual float getX() = 0; - virtual float getY() = 0; - virtual float getW() = 0; - virtual float getH() = 0; - virtual float getXpx() = 0; - virtual float getYpx() = 0; - virtual float getWpx() = 0; - virtual float getHpx() = 0; - virtual float getRad() = 0; - virtual float getDeg() = 0; - - virtual bool hasX() = 0; - virtual bool hasY() = 0; - virtual bool hasW() = 0; - virtual bool hasH() = 0; - virtual bool hasXpx() = 0; - virtual bool hasYpx() = 0; - virtual bool hasWpx() = 0; - virtual bool hasHpx() = 0; - virtual bool hasRad() = 0; - virtual bool hasDeg() = 0; - -protected: - QString _coordinateUnit; /**< coordinate unit, will be saved in exported file */ - float _x; /**< x-coordinate in coordinate unit*/ - float _y; /**< y-coordinate in coordinate unit*/ - float _w; /**< width in coordinate unit*/ - float _h; /**< height in coordinate unit*/ - float _rad; /**< orientation in rad */ - float _deg; /**< orientation in deg */ - float _xpx; /**< x-coordinate in px */ - float _ypx; /**< y-coordinate in px */ - float _wpx; /**< width in px */ - float _hpx; /**< height in px */ -}; - -/***************************************************************************//** -* This is a node of the Composite Pattern -* This class is derived from IModelComponentEuclidian2D. -* It expands it from 2D to 3D. -* Reserved for future 3D tracking. -*******************************************************************************/ -class IModelComponentEuclidian3D : public IModelComponentEuclidian2D { -public: - Q_OBJECT - /* - Q_PROPERTY-System: http://doc.qt.io/qt-5/properties.html - */ - Q_PROPERTY(float z READ getZ() WRITE setZ STORED hasZ) - Q_PROPERTY(float zpx READ getZpx() WRITE setZpx STORED hasZpx) - Q_PROPERTY(float d READ getD() WRITE setD STORED hasD) - Q_PROPERTY(float dpx READ getDpx() WRITE setDpx STORED hasDpx) - Q_PROPERTY(float rada2 READ getRadAxis2() WRITE setRadAxis2 STORED hasRadAxis2) - Q_PROPERTY(float rada3 READ getRadAxis3() WRITE setRadAxis3 STORED hasRadAxis3) - -public: - /* - Getters, Setters & Checkers - */ - virtual void setZ(float z) = 0; - virtual void setZpx(float z) = 0; - virtual void setD(float h) = 0; - virtual void setDpx(float d) = 0; - virtual void setRadAxis2(float r) = 0; - virtual void setRadAxis3(float r) = 0; - - virtual float getZ() = 0; - virtual float getZpx() = 0; - virtual float getD() = 0; - virtual float getDpx() = 0; - virtual float getRadAxis2() = 0; - virtual float getRadAxis3() = 0; - - virtual bool hasZ() = 0; - virtual bool hasD() = 0; - virtual bool hasZpx() = 0; - virtual bool hasDpx() = 0; - virtual bool hasRadAxis2() = 0; - virtual bool hasRadAxis3() = 0; - -protected: - float _z; /**< z-coordinate in coordinate unit */ - float _zpx; /**< z-coordinate in px */ - float _d; /**< d in coordinate unit*/ - float _dpx; /**< d in px */ - float _rada2; /**< rotation two */ - float _rada3; /**< rotation three */ -}; - -/***************************************************************************//** -* This is a node of the Composite Pattern -* This class is derived from IModelComponentEuclidian2D. -* It expands it to 2D with timestamps. -*******************************************************************************/ -class IModelComponentTemporal2D : public IModelComponentEuclidian2D { -public: - Q_OBJECT - /* - Q_PROPERTY-System: http://doc.qt.io/qt-5/properties.html - */ - Q_PROPERTY(qint64 time READ getTime() WRITE setTime STORED hasTime) - Q_PROPERTY(QString timeString READ getTimeString() WRITE setTimeString STORED hasTimeString) - -public: - /** - * The constructor of the IModelComponentTemporal2D class is able to receive a QObject as parent. - * It should not be implemented as it is a not a leaf nore a composite - */ - IModelComponentTemporal2D(QObject *parent = 0); - - /* - Getters, Setters & Checkers - */ - virtual void setTime(qint64 t) = 0; - virtual qint64 getTime() = 0; - virtual bool hasTime() = 0; - virtual void setTimeString(QString t) = 0; - virtual QString getTimeString() = 0; - virtual bool hasTimeString() = 0; - -protected: - qint64 _time; /**< UNIX timestamp */ - QString _timeString; /**< timestamp a formatted as string */ -}; - -/***************************************************************************//** -* This is a leaf of the Composite Pattern -* This class is derived from IModelComponentTemporal2D. -* It includes 2D and time data. -* This interface can be visualized in the core application if the tracking data implements it. -* A circular point will be visualized with the radius of min(width,height) -* The position is the center of the point. -*******************************************************************************/ -class IModelTrackedPoint : public IModelComponentTemporal2D -{ - Q_OBJECT - -public: - /** - * The constructor of the IModelTrackedPoint class is able to receive a QObject as parent. - */ - IModelTrackedPoint(QObject *parent = 0); -}; - -/***************************************************************************//** -* This is a leaf of the Composite Pattern -* This class is derived from IModelComponentTemporal2D. -* It includes 2D and time data and a polygon. -* This interface can be visualized in the core application if the tracking data implements it. -* An irregular polygon defined by a list of polygons will be visualized. -*******************************************************************************/ - -class IModelTrackedPolygon : public IModelComponentTemporal2D -{ - Q_OBJECT - -public: - - /** - * The constructor of the IModelTrackedPolygon class is able to receive a QObject as parent. - */ - IModelTrackedPolygon(QObject *parent = 0); - - /* - Getters, Setters & Checkers - */ - virtual void setPolygon(QList polygons) = 0; - virtual QList getPolygon() = 0; - virtual float hasPolygon() = 0; - -protected: - QList _polygon; /**< List of polygons, all will be drawn when vizualized */ -}; - -/***************************************************************************//** -* This is a leaf of the Composite Pattern -* This class is derived from IModelComponentTemporal2D. -* It includes 2D and time data. -* This interface can be visualized in the core application if the tracking data implements it. -* An ellipse will be visualized. The position is the center of the ellipse. -*******************************************************************************/ -class IModelTrackedEllipse : public IModelTrackedPoint -{ - Q_OBJECT - -public: - /** - * The constructor of the IModelTrackedEllipse class is able to receive a QObject as parent. - */ - IModelTrackedEllipse(QObject *parent = 0); - -}; - -/***************************************************************************//** -* This is a leaf of the Composite Pattern -* This class is derived from IModelComponentTemporal2D. -* It includes 2D and time data. -* This interface can be visualized in the core application if the tracking data implements it. -* A rectangle will be visualized. The position is the center of the rectangle. -*******************************************************************************/ -class IModelTrackedRectangle : public IModelTrackedPoint -{ - Q_OBJECT - -public: - /** - * The constructor of the IModelTrackedRectangle class is able to receive a QObject as parent. - */ - IModelTrackedRectangle(QObject *parent = 0); -}; - -#endif // ITRACKEDCOMPONENT_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponentFactory.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponentFactory.cpp deleted file mode 100644 index 454ef199..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponentFactory.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "IModelTrackedComponentFactory.h" - -IModelTrackedComponentFactory::IModelTrackedComponentFactory() { - -} - -IModelTrackedComponentFactory::~IModelTrackedComponentFactory() -{ - -} - -IModelTrackedComponent *IModelTrackedComponentFactory::getNewTrackedElement(QString name) -{ - return createTrackedElement(name); -} - -IModelTrackedComponent *IModelTrackedComponentFactory::getNewTrackedObject(QString name) -{ - return createTrackedObject(name); -} - -IModelTrackedComponent *IModelTrackedComponentFactory::getNewTrackedTrajectory(QString name) -{ - return createTrackedTrajectory(name); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponentFactory.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponentFactory.h deleted file mode 100644 index 4fe0b211..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedComponentFactory.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef ITRACKEDCOMPONENTFACTORY_H -#define ITRACKEDCOMPONENTFACTORY_H - -#include "Interfaces/IModel/IModel.h" -#include "Interfaces/IModel/IModelTrackedComponent.h" - -class IModelTrackedComponentFactory : public IModel -{ - Q_OBJECT - - public: - IModelTrackedComponentFactory(); - virtual ~IModelTrackedComponentFactory() = 0; - - IModelTrackedComponent *getNewTrackedElement(QString name); - IModelTrackedComponent *getNewTrackedObject(QString name); - IModelTrackedComponent *getNewTrackedTrajectory(QString name); - virtual QList getElementTypes() = 0; - -protected: - virtual IModelTrackedComponent *createTrackedElement(QString name) = 0; - virtual IModelTrackedComponent *createTrackedObject(QString name) = 0; - virtual IModelTrackedComponent *createTrackedTrajectory(QString name) = 0; - -}; - -#endif // ITRACKEDCOMPONENTFACTORY_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedTrajectory.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedTrajectory.cpp deleted file mode 100644 index bc869f68..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedTrajectory.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "IModelTrackedTrajectory.h" -#include "qdebug.h" - -int IModelTrackedTrajectory::nextID = -1; - -IModelTrackedTrajectory::IModelTrackedTrajectory(QObject *parent) : - IModelTrackedComponent(parent) -{ - _id = ++nextID; -} - -void IModelTrackedTrajectory::operate() -{ - // please implement this method in an TrackedObject class - -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedTrajectory.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedTrajectory.h deleted file mode 100644 index b6089721..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackedTrajectory.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef ITRACKEDOTRAJECTORY_H -#define ITRACKEDOTRAJECTORY_H - -#include "Interfaces/IModel/IModelTrackedComponent.h" - -/** - * This interface class derives from IModelTrackedComponent. - * This class is part of the Composite Pattern and represents the the abstract Composite class. - * Its purpose is to define the responsibility - * for adding, deleting and returning leaf objects. - * - * - * Its the Plugin Developers full responsibility to choos an internal data structure. This could be e.g. Map, List or Vector. - */ -class IModelTrackedTrajectory : public IModelTrackedComponent -{ - Q_OBJECT - Q_PROPERTY(QList childNodes READ getChildNodes() WRITE setChildNodes STORED hasChildNodes); -public: - /** - * The constructor. - */ - IModelTrackedTrajectory(QObject *parent); - - /** - * This methode must be implemented by all derivatives. Its purpose is to provide a mechanism for adding Leaf components to this structure. - */ - virtual void add(IModelTrackedComponent *comp, int pos) = 0; - - /** - * This methode must be implemented by all derivatives. Its functionality shall be a mechanism for removing Leaf components from this structure. - */ - virtual bool remove(IModelTrackedComponent *comp) = 0; - - /** - * This methode must be implemented by all derivatives. Its functionality shall be a mechanism for removing all Leaf components from this structure. - */ - virtual void clear() = 0; - - /** - * This methode must be implemented by all derivatives. Its functionality shall be a mechanism for determining the count/number of children. - */ - virtual int size() = 0; - - /** - * This should simply return a child object by an index. - */ - virtual IModelTrackedComponent* getChild(int index) = 0; - - virtual IModelTrackedComponent* getValidChild(int index) = 0; - - virtual int validCount() = 0; - - - /** - * This shoudd simply return a last child object (highest index). - */ - virtual IModelTrackedComponent *getLastChild() = 0; - - void setTime(std::chrono::system_clock::time_point t) { _time = t; }; - std::chrono::system_clock::time_point getTime() { return _time; }; - - - QList getChildNodes() { - return _TrackedComponents; - } - void setChildNodes(QList n) { - _TrackedComponents = n; - } - bool hasChildNodes() { - return true; - } - - // ITrackedComponent interface -public: - void operate(); - std::chrono::system_clock::time_point _time; - -protected: - static int nextID; - - QList _TrackedComponents; -}; - -#endif // ITRACKEDOTRAJECTORY_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackingAlgorithm.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackingAlgorithm.cpp deleted file mode 100644 index cdf89f6c..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackingAlgorithm.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "IModelTrackingAlgorithm.h" - -IModelTrackingAlgorithm::IModelTrackingAlgorithm(QObject *parent) : - IModel(parent) -{ - -} - -//void ITrackingAlgorithm::setTrackedComponentFactory(ITrackedComponentFactory *factory) -//{ -// m_TrackedComponentFactory = factory; -//} - -//void ITrackingAlgorithm::setTrackedComponent(ITrackedComponent *trackedComponent) -//{ -// m_TrackedComponent = trackedComponent; -//} - -//ITrackedComponentFactory *ITrackingAlgorithm::getTrackedComponentFactory() -//{ -// return m_TrackedComponentFactory; -//} - -//ITrackedComponent *ITrackingAlgorithm::getTrackedComponent() -//{ -// return m_TrackedComponent; -//} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackingAlgorithm.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackingAlgorithm.h deleted file mode 100644 index 722ffef6..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IModelTrackingAlgorithm.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ITRACKINGALGORITHM_H -#define ITRACKINGALGORITHM_H - -#include "IModel.h" -#include "opencv2/core/core.hpp" - -class IModelTrackingAlgorithm :public IModel { - Q_OBJECT - public: - IModelTrackingAlgorithm(QObject *parent = 0); - - virtual void doTracking(std::shared_ptr image, uint frameNumber) = 0; - -signals: - void emitTrackingDone(); - void emitChangeDisplayImage(QString str); - - -}; - -#endif // ITRACKINGALGORITHM_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IObject.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IObject.cpp deleted file mode 100644 index 9f339496..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IObject.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "IObject.h" - -IObject::IObject() : - IModel(0) { - -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IObject.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IObject.h deleted file mode 100644 index 715e3894..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/IObject.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef IOBJECT_H -#define IOBJECT_H - -#include "Interfaces/IModel/IModel.h" - -// #include "biotracker/util/platform.h" - -class IObject : public IModel { - Q_OBJECT - public: - IObject(); -}; - -#endif // IOBJECT_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/Serializable.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/Serializable.cpp deleted file mode 100644 index 96c86e53..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/Serializable.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "Serializable.h" - -#include -#include - - -QDataStream &operator<<(QDataStream &ds, const Serializable &data) { - for (int i = 0; ipropertyCount(); ++i) - { - if (data.metaObject()->property(i).isStored(&data)) - { - ds << data.metaObject()->property(i).read(&data); - } - } - return ds; -} -QDataStream &operator>>(QDataStream &ds, Serializable &data) { - QVariant var; - for (int i = 0; ipropertyCount(); ++i) - { - if (data.metaObject()->property(i).isStored(&data)) - { - ds >> var; - data.metaObject()->property(i).write(&data, var); - } - } - return ds; -} \ No newline at end of file diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/Serializable.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/Serializable.h deleted file mode 100644 index d7083b5e..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IModel/Serializable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -class Serializable : public QObject -{ - Q_OBJECT -}; - -QDataStream &operator<<(QDataStream &out, const Serializable &data); -QDataStream &operator>>(QDataStream &in, Serializable &data); diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IView.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IView.cpp deleted file mode 100644 index 5743123b..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IView.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "IView.h" -#include "Interfaces/IController/IController.h" - -IView::IView(IController *controller, IModel *model): - mController(controller), - mModel(model) -{ - -} - -void IView::setModel(IModel *model) { - mModel = model; -} - -IView::~IView() { - -} - -IController *IView::getController() { - return mController; -} - -IModel *IView::getModel() { - return mModel; -} - -const IController *IView::getController() const { - return mController; -} - -const IModel *IView::getModel() const { - return mModel; -} - -void IView::setPermission(std::pair) { - -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IView.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IView.h deleted file mode 100644 index 554a7b32..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IView.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef IVIEW_H -#define IVIEW_H - -#include "Interfaces/IModel/IModel.h" -#include "Interfaces/ENUMS.h" - -class IController; -class IView { - - public: - IView(IController *controller = 0, IModel *model = 0); - virtual ~IView() = 0; - - virtual void setNewModel(IModel *model) = 0; - void setPermission(std::pair < ENUMS::COREPERMISSIONS, bool >); - - protected: - virtual void connectModelView() = 0; - void setModel(IModel *model); - IController *getController(); - const IController *getController() const; - IModel *getModel(); - const IModel *getModel() const; - private: - IController *mController; - IModel *mModel; -}; - -#endif // IVIEW_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsPixmapItem.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsPixmapItem.cpp deleted file mode 100644 index 372da22e..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsPixmapItem.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "IViewGraphicsPixmapItem.h" - -IViewGraphicsPixmapItem::IViewGraphicsPixmapItem(QObject *parent, IController *controller, IModel *model) : - QObject(parent), - IView(controller, model) -{ - -} - -void IViewGraphicsPixmapItem::setNewModel(IModel *model) -{ - if (getModel() != nullptr) { - QObject::disconnect(getModel(), 0, this, 0); - } - - setModel(model); - - if (getModel() != nullptr) { - connectModelView(); - } - - update(); -} - diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsPixmapItem.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsPixmapItem.h deleted file mode 100644 index 16cf08a9..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsPixmapItem.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef IGRAPHICSPIXMAPITEM_H -#define IGRAPHICSPIXMAPITEM_H - -#include "IView.h" -#include "QObject" -#include "QGraphicsPixmapItem" - -class IViewGraphicsPixmapItem : public QObject, public QGraphicsPixmapItem, public IView -{ - Q_OBJECT -public: - IViewGraphicsPixmapItem(QObject *parent = 0, IController *controller = 0, IModel *model = 0); - - // IView interface -public: - void setNewModel(IModel *model) override; - -public Q_SLOTS: - virtual void getNotified() = 0; -}; - -#endif // IGRAPHICSPIXMAPITEM_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsScene.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsScene.cpp deleted file mode 100644 index c1bf252d..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsScene.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "IViewGraphicsScene.h" - -IViewGraphicsScene::IViewGraphicsScene(QObject *parent, IController *controller, IModel *model) : - QGraphicsScene(parent), - IView(controller, model) -{ - -} - -void IViewGraphicsScene::setNewModel(IModel *model) -{ - -} - -void IViewGraphicsScene::connectModelView() -{ - QObject::connect(getModel(), &IModel::notifyView, this, &IViewGraphicsScene::getNotified); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsScene.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsScene.h deleted file mode 100644 index 6b2e0db6..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsScene.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef IVIEWGRAPHICSSCENE_H -#define IVIEWGRAPHICSSCENE_H - -#include "QGraphicsScene" -#include "IView.h" - -class IViewGraphicsScene : public QGraphicsScene, public IView -{ - Q_OBJECT -public: - IViewGraphicsScene(QObject *parent = 0, IController *controller = 0, IModel *model = 0); - - // IView interface -public: - virtual void setNewModel(IModel *model) override; - -protected: - virtual void connectModelView() override; - -public Q_SLOTS: - virtual void getNotified() = 0; -}; - -#endif // IVIEWGRAPHICSSCENE_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsView.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsView.cpp deleted file mode 100644 index 1efd2407..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsView.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "IViewGraphicsView.h" - - -IViewGraphicsView::IViewGraphicsView(QWidget *parent, IController *controller, IModel *model) : - QGraphicsView(parent), - IView(controller, model) -{ - -} - -void IViewGraphicsView::setNewModel(IModel *model) -{ - -} - -void IViewGraphicsView::connectModelView() -{ - QObject::connect(getModel(), &IModel::notifyView, this, &IViewGraphicsView::getNotified); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsView.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsView.h deleted file mode 100644 index 486288d8..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewGraphicsView.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef IGRAPHICSVIEW_H -#define IGRAPHICSVIEW_H - -#include "QGraphicsView" -#include "IView.h" - -class IViewGraphicsView : public QGraphicsView, public IView -{ - Q_OBJECT -public: - IViewGraphicsView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - - // IView interface -public: - void setNewModel(IModel *model) override; - -protected: - void connectModelView() override; - -public Q_SLOTS: - virtual void getNotified() = 0; -}; - -#endif // IGRAPHICSVIEW_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewMainWindow.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewMainWindow.cpp deleted file mode 100644 index cea4f77e..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewMainWindow.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "IViewMainWindow.h" - -IViewMainWindow::IViewMainWindow(QWidget *parent, IController *controller, IModel *model) : - QMainWindow(parent), - IView(controller, model) { - -} - -IViewMainWindow::~IViewMainWindow() { - -} - -void IViewMainWindow::setNewModel(IModel *model) { - model = nullptr; - setModel(model); -} - -void IViewMainWindow::connectModelView() { - // this function is not used in MainWindow -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewMainWindow.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewMainWindow.h deleted file mode 100644 index e61939e7..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewMainWindow.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef IVIEWMAINWINDOW_H -#define IVIEWMAINWINDOW_H - -#include -#include "Interfaces/IView/IView.h" - -class IViewMainWindow : public QMainWindow, public IView { - public: - IViewMainWindow(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - ~IViewMainWindow(); - - private: - void setNewModel(IModel *model); - void connectModelView(); -}; - -#endif // IVIEWMAINWINDOW_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewOpenGLWidget.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewOpenGLWidget.cpp deleted file mode 100644 index 2b799f3c..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewOpenGLWidget.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "IViewOpenGLWidget.h" - -IViewOpenGLWidget::IViewOpenGLWidget(QWidget *parent, IController *controller, IModel *model) : - QOpenGLWidget(parent), - IView(controller) { - setNewModel(model); -} - -IViewOpenGLWidget::~IViewOpenGLWidget() { - -} - -void IViewOpenGLWidget::setNewModel(IModel *model) { - if (getModel() != nullptr) { - QObject::disconnect(getModel(), 0, this, 0); - } - - setModel(model); - - if (getModel() != nullptr) { - connectModelView(); - } - - update(); -} - -void IViewOpenGLWidget::connectModelView() { - QObject::connect(getModel(), &IModel::notifyView, this, &IViewOpenGLWidget::getNotified); -} - -void IViewOpenGLWidget::initializeGL() { - connectModelView(); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewOpenGLWidget.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewOpenGLWidget.h deleted file mode 100644 index e3a23b47..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewOpenGLWidget.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef IVIEWOPENGLWIDGET_H -#define IVIEWOPENGLWIDGET_H - -#include "Interfaces/IView/IView.h" -#include -#include -#include - - -class IViewOpenGLWidget: public QOpenGLWidget, protected QOpenGLFunctions, public IView { - public: - IViewOpenGLWidget(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - ~IViewOpenGLWidget(); - - void setNewModel(IModel *model); - - public Q_SLOTS: - virtual void getNotified() = 0; - - protected: - void connectModelView(); - void initializeGL() override; -}; - -#endif // IVIEWOPENGLWIDGET_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewTrackedComponent.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewTrackedComponent.cpp deleted file mode 100644 index ec38b2cc..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewTrackedComponent.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "IViewTrackedComponent.h" - -IViewTrackedComponent::IViewTrackedComponent(QGraphicsItem *parent, IController *controller, IModel *model) : - QGraphicsObject(parent), - IView(controller, model) -{ - -} - -IViewTrackedComponent::~IViewTrackedComponent() -{ - -} - -void IViewTrackedComponent::setNewModel(IModel *model) -{ - -} - -void IViewTrackedComponent::connectModelView() -{ - QObject::connect(getModel(), &IModel::notifyView, this, &IViewTrackedComponent::getNotified); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewTrackedComponent.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewTrackedComponent.h deleted file mode 100644 index d2cc6df3..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewTrackedComponent.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef IVIEWTRACKEDCOMPONENT_H -#define IVIEWTRACKEDCOMPONENT_H - -#include "IView.h" -#include "QGraphicsObject" - -/** - * This is the common interface for all views representing a TrackedComponents class (IModelTrackedTrajectory and any leaf class). - * This class is derived from IView from the Model-View-Controller structure and visializes the data from its IModel object. - * A IViewTrackedComponent has a QGraphicsItem. - */ - -class IViewTrackedComponent : public QGraphicsObject, public IView -{ - Q_OBJECT -public: - /** - * The constructor hase a QGraphicsItem object as Parent, an IController object as its controller and an IModel object. - */ - IViewTrackedComponent(QGraphicsItem *parent = 0, IController *controller = 0, IModel *model = 0); - ~IViewTrackedComponent(); - - // IView interface -public: - void setNewModel(IModel *model) override; - -protected: - void connectModelView() override; - -public Q_SLOTS: - virtual void getNotified() = 0; - -}; - -#endif // IVIEWTRACKEDCOMPONENT_H diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewWidget.cpp b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewWidget.cpp deleted file mode 100644 index a0a81504..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewWidget.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "IViewWidget.h" - -IViewWidget::IViewWidget(QWidget *parent, IController *controller, IModel *model): - QWidget(parent), - IView(controller) { - setNewModel(model); -} - -void IViewWidget::setNewModel(IModel *model) { - setModel(model); - if (getModel() != nullptr) { - connectModelView(); - } -} - -void IViewWidget::connectModelView() { - QObject::connect(getModel(), &IModel::notifyView, this, &IViewWidget::getNotified); -} diff --git a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewWidget.h b/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewWidget.h deleted file mode 100644 index 375ffd45..00000000 --- a/BioTracker/Interfaces/BioTrackerInterfaces/Interfaces/IView/IViewWidget.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef IVIEWWIDGET_H -#define IVIEWWIDGET_H - -#include -#include "Interfaces/IView/IView.h" - -class IViewWidget : public QWidget, public IView { - Q_OBJECT - public: - explicit IViewWidget(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - - void setNewModel(IModel *model); - - public Q_SLOTS: - virtual void getNotified() = 0; - - private: - void connectModelView(); -}; - -#endif // IVIEWWIDGET_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.cpp b/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.cpp deleted file mode 100644 index fc69b1ce..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "BioTrackerPlugin.h" -#include "PluginContext.h" - -#include "Controller/ControllerTrackingAlgorithm.h" -#include "Controller/ControllerTrackedComponent.h" - -#include "util/singleton.h" -#include "settings/Settings.h" - -#include "View/TrackedElementView.h" -#include "Model/TrackedComponents/TrackedComponentFactory.h" - -BioTrackerPlugin::BioTrackerPlugin() { -} - -IView* BioTrackerPlugin::getTrackerParameterWidget() { - return qobject_cast (m_TrackerController)->getTrackingParameterWidget(); -} -IView *BioTrackerPlugin::getTrackerElementsWidget() -{ - return qobject_cast (m_ComponentController)->getTrackingElementsWidget(); -} - -// forwards tracked component model to coreApp -IModel* BioTrackerPlugin::getTrackerComponentModel() { - return qobject_cast (m_ComponentController)->getModel(); -} - -IModelTrackedComponentFactory *BioTrackerPlugin::getComponentFactory() { - return new TrackedComponentFactory(); -} - -#if QT_VERSION < 0x050000 -Q_EXPORT_PLUGIN2(BioTrackerPlugin, BioTrackerPlugin) -#endif // QT_VERSION < 0x050000 - - -void BioTrackerPlugin::createPlugin() { - m_PluginContext = new PluginContext(); - m_PluginContext->createApplication(); - - IController * ctr = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - m_ComponentController = qobject_cast(ctr); - - IController * ctr2 = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::TRACKING); - m_TrackerController = qobject_cast(ctr2); - - connectInterfaces(); -} - -void BioTrackerPlugin::connectInterfaces() { - ControllerTrackingAlgorithm* ctrAlg = qobject_cast (m_TrackerController); - ControllerTrackedComponent* ctrTrC = qobject_cast (m_ComponentController); - - //controllertrackingalgorithm - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitCvMat, this, &BioTrackerPlugin::receiveCvMatFromController); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitTrackingDone, this, &BioTrackerPlugin::receiveTrackingDone); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitChangeDisplayImage, this, &BioTrackerPlugin::receiveChangeDisplayImage); - QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrAlg, &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); - //tracking algorithm - QObject::connect(static_cast(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::receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber) { - qobject_cast (m_TrackerController)->doTracking(mat, frameNumber); - - Q_EMIT emitCurrentFrameNumber(frameNumber); -} - -void BioTrackerPlugin::receiveCurrentFrameNumberFromMainApp(uint frameNumber) { - Q_EMIT emitCurrentFrameNumber(frameNumber); -} - -void BioTrackerPlugin::receiveCvMatFromController(std::shared_ptr mat, QString name) { - Q_EMIT emitCvMat(mat, name); -} - -void BioTrackerPlugin::receiveTrackingDone(uint framenumber) { - Q_EMIT emitTrackingDone(framenumber); -} - -void BioTrackerPlugin::receiveChangeDisplayImage(QString str) { - Q_EMIT emitChangeDisplayImage(str); -} - -void BioTrackerPlugin::receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory) { - Q_EMIT emitRemoveTrajectory(trajectory); -} - -void BioTrackerPlugin::receiveAddTrajectory(QPoint pos) { - Q_EMIT emitAddTrajectory(pos); -} - -void BioTrackerPlugin::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) { - Q_EMIT emitSwapIds(trajectory0, trajectory1); -} - -void BioTrackerPlugin::sendCorePermissions() { - // get plugin settings - BioTracker::Core::Settings *pluginSettings = BioTracker::Util::TypedSingleton::getInstance(CONFIGPARAM::CONFIG_INI_FILE); - - // signal permissions - bool enableView = pluginSettings->getValueOrDefault(GUIPARAM::ENABLE_CORE_COMPONENT_VIEW, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTVIEW, enableView)); - bool enableMove = pluginSettings->getValueOrDefault(GUIPARAM::ENABLE_CORE_COMPONENT_MOVE, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTMOVE, enableMove)); - bool enableRemove = pluginSettings->getValueOrDefault(GUIPARAM::ENABLE_CORE_COMPONENT_REMOVE, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTREMOVE, enableRemove)); - bool enableSwap = pluginSettings->getValueOrDefault(GUIPARAM::ENABLE_CORE_COMPONENT_ID_SWAP, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTSWAP, enableSwap)); - bool enableAdd = pluginSettings->getValueOrDefault(GUIPARAM::ENABLE_CORE_COMPONENT_ADD, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTADD, enableAdd)); - bool enableRotate = pluginSettings->getValueOrDefault(GUIPARAM::ENABLE_CORE_COMPONENT_ROTATE, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTROTATE, enableRotate)); -} - diff --git a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.h b/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.h deleted file mode 100644 index 488b9abe..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef BIOTRACKERPLUGIN_H -#define BIOTRACKERPLUGIN_H - -#include "biotrackerplugin_global.h" -#include "opencv2/core/core.hpp" -#include "Interfaces/IBioTrackerContext.h" - -#include "Interfaces/IBioTrackerPlugin.h" - - -#include "QPointer" -#include "memory" -#include "QPoint" - -class BIOTRACKERPLUGINSHARED_EXPORT BioTrackerPlugin : public IBioTrackerPlugin { - Q_OBJECT - Q_PLUGIN_METADATA(IID "de.fu-berlin.mi.biorobotics.BioTrackerPlugin" FILE "BioTrackerPlugin.json") - Q_INTERFACES(IBioTrackerPlugin) - - public: - BioTrackerPlugin(); - - // IBioTrackerPlugin interface - IView* getTrackerParameterWidget(); - IView *getTrackerElementsWidget(); - IModel* getTrackerComponentModel(); - IModelTrackedComponentFactory *getComponentFactory(); - - public: - void createPlugin(); - void receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber); - void sendCorePermissions(); - - private: - void connectInterfaces(); -signals: - void emitCvMat(std::shared_ptr mat, QString name); - void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - void emitCorePermission(std::pair 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); - -private slots: - void receiveCvMatFromController(std::shared_ptr mat, QString name); - void receiveTrackingDone(uint framenumber); - void receiveChangeDisplayImage(QString str); - void receiveAreaDescriptor(IModelAreaDescriptor *areaDescr); - -private: - IController *m_TrackerController; - IController *m_ComponentController; - IController *m_AreaDescrController; - - IBioTrackerContext *m_PluginContext; - -public: - QList m_CorePermissions; - - -}; - -#endif // BIOTRACKERPLUGIN_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.json b/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.json deleted file mode 100644 index 4bf579c1..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.json +++ /dev/null @@ -1,6 +0,0 @@ -{ "type" : "TrackingPlugin", - "name" : "Background Subtraction Tracker", - "longname" : "some long name", - "version" : "1.1", - "dependencies" : [] -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.pro b/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.pro deleted file mode 100644 index 54ff62f5..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/BioTrackerPlugin.pro +++ /dev/null @@ -1,70 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-11-25T11:43:53 -# -#------------------------------------------------- - -QT += widgets - -TEMPLATE = lib -CONFIG += plugin -TARGET = $$qtLibraryTarget(IBioTrackerPlugin) - -INCLUDEPATH += ../../Interfaces/BioTrackerInterfaces/ -LIBS += ../../Interfaces/build-BioTrackerInterfaces-Desktop-Debug/libBioTrackerInterfaces.a - -DEFINES += BIOTRACKERPLUGIN_LIBRARY - -INCLUDEPATH += /usr/local/include/opencv -LIBS += -L/usr/local/lib \ --lopencv_core \ --lopencv_imgproc \ --lopencv_highgui \ --lopencv_ml \ --lopencv_video \ --lopencv_features2d \ --lopencv_calib3d \ --lopencv_objdetect \ --lopencv_contrib \ --lopencv_legacy \ --lopencv_flann - -SOURCES += BioTrackerPlugin.cpp \ - Model/TrackedComponents/TrackedComponentFactory.cpp \ - Model/TrackedComponents/TrackedElement.cpp \ - Model/TrackedComponents/TrackedTrajectory.cpp \ - Model/BioTrackerTrackingAlgorithm.cpp \ - Model/null_Model.cpp \ - Controller/ControllerTrackingAlgorithm.cpp \ - Controller/null_Controller.cpp \ - Controller/ControllerTrackedComponent.cpp \ - View/TrackedElementView.cpp \ - Model/TrackerParameter.cpp \ - View/TrackerParameterView.cpp - - -HEADERS += BioTrackerPlugin.h\ - biotrackerplugin_global.h \ - Model/TrackedComponents/TrackedComponentFactory.h \ - Model/TrackedComponents/TrackedElement.h \ - Model/TrackedComponents/TrackedTrajectory.h \ - Model/BioTrackerTrackingAlgorithm.h \ - Model/null_Model.h \ - Controller/ControllerTrackingAlgorithm.h \ - Controller/null_Controller.h \ - Controller/ControllerTrackedComponent.h \ - View/TrackedElementView.h \ - Model/TrackerParameter.h \ - View/TrackerParameterView.h - - -unix { - target.path = /usr/lib - INSTALLS += target -} - -DISTFILES += \ - BioTrackerPlugin.json - -FORMS += \ - View/TrackerParameterView.ui diff --git a/BioTracker/Plugin/BackgroundSubtraction/CMakeLists.txt b/BioTracker/Plugin/BackgroundSubtraction/CMakeLists.txt deleted file mode 100644 index 62aa2ff0..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -############################################################## -#### Biotracker: BackgroundSubtraction -############################################################## - - -add_definitions( -DBIOTRACKERPLUGIN_LIBRARY=1 ) - -include(${util_cmakes}CMakeVSSugar.txt) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -message("Configuring BackgroundSubtraction...") -set(EXE_NAME BackgroundSubtraction.tracker) -add_library(${EXE_NAME} SHARED ${_util_source_list} ) - -target_link_libraries(${EXE_NAME} ${LIBS}) -target_link_libraries (${EXE_NAME} Qt5::Core Qt5::Gui Qt5::Xml Qt5::Network Qt5::Widgets) -target_link_libraries (${EXE_NAME} Qt5::Multimedia Qt5::MultimediaWidgets Qt5::OpenGL ) -target_link_libraries(${EXE_NAME} Biotracker_interfaces Biotracker_utility) -target_link_libraries(${EXE_NAME} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES}) - -include_directories(${Boost_INCLUDE_DIRS}) - -set_target_properties(${EXE_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) -set_target_properties(${EXE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO -) \ No newline at end of file diff --git a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackedComponent.cpp b/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackedComponent.cpp deleted file mode 100644 index 57b1ac92..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackedComponent.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "ControllerTrackedComponent.h" -#include "Model/TrackedComponents/TrackedElement.h" -#include "Model/TrackedComponents/TrackedTrajectory.h" -#include "View/TrackedElementView.h" -#include "qdebug.h" -#include "qmath.h" - -ControllerTrackedComponent::ControllerTrackedComponent(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - m_currentFrameNumber = 0; -} - -void ControllerTrackedComponent::createView() -{ - m_View = new TrackedElementView(0, this, m_Model); -} - -void ControllerTrackedComponent::connectModelToController() -{ - -} - -void ControllerTrackedComponent::connectControllerToController() -{ -} - -void createTrajectories(int count, TrackedTrajectory* all) { -} - -void ControllerTrackedComponent::createModel() -{ - TrackedTrajectory *t = new TrackedTrajectory(this, "All"); - m_Model = t; -} - - -IView *ControllerTrackedComponent::getTrackingElementsWidget() -{ - return m_View; -} - -void ControllerTrackedComponent::receiveRemoveTrajectory(IModelTrackedTrajectory * trajectory) -{ - trajectory->setValid(false); - qDebug() << "TRACKER: Track" << trajectory->getId() << "set invalid"; -} - -void ControllerTrackedComponent::receiveRemoveTrajectoryId(int id) -{ - TrackedTrajectory* allTraj = qobject_cast(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(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) -{ - trajectory->getChild(frameNumber)->setValid(true); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "set valid"; -} - -void ControllerTrackedComponent::receiveRemoveTrackEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) -{ - 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); - - TrackedTrajectory* newTraj = new TrackedTrajectory(); - TrackedElement* firstElem = new TrackedElement(newTraj, "n.a.", newTraj->getId()); - - 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(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) -{ - TrackedTrajectory* traj = dynamic_cast(trajectory); - // don't move when frame number under 0 and main trajectory (id's: 0)!! - if (!(traj->getId() == 0) && frameNumber >= 0) { - TrackedElement* element = dynamic_cast(traj->getChild(frameNumber)); - - //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!"; - } - - FishPose newPose = FishPose(newPosCm, newPosPx, oldPose.orientation_rad(), oldPose.orientation_deg(), oldPose.width(), oldPose.height(), oldPose.getScore()); - - element->setFishPose(newPose); - } -} - -void ControllerTrackedComponent::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) -{ - TrackedTrajectory* traj0 = dynamic_cast(trajectory0); - TrackedTrajectory* traj1 = dynamic_cast(trajectory1); - - if (traj0 && traj1) { - if (traj0->getId() !=0 && traj1->getId() !=0) { - int traj0Id = traj0->getId(); - int traj1Id = traj1->getId(); - - traj0->setId(traj1Id); - traj1->setId(traj0Id); - - qDebug() << "TRACKER: Swap IDs " << traj0Id << "and " << traj1Id; - } - } -} - -void ControllerTrackedComponent::receiveToggleFixTrack(IModelTrackedTrajectory * trajectory, bool toggle) -{ - qDebug() << "TRACKER: Fix trajectory " << trajectory->getId(); - trajectory->setFixed(toggle); -} - -void ControllerTrackedComponent::receiveEntityRotation(IModelTrackedTrajectory * trajectory, double angle, uint frameNumber) -{ - TrackedTrajectory* traj = dynamic_cast(trajectory); - if (traj) { - IModelTrackedPoint* pointLike = dynamic_cast(traj->getChild(frameNumber)); - if (pointLike) { - pointLike->setDeg(float(angle)); - pointLike->setRad(float(qDegreesToRadians(angle))); - } - } -} - -void ControllerTrackedComponent::receiveCurrentFrameNumber(uint framenumber) -{ - m_currentFrameNumber = (int)framenumber; -} - -void ControllerTrackedComponent::receiveAreaDescriptorUpdate(IModelAreaDescriptor * areaDescr) -{ - m_areaDescr = areaDescr; -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackedComponent.h b/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackedComponent.h deleted file mode 100644 index 355098dc..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackedComponent.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef CONTROLLERTRACKEDCOMPONENT_H -#define CONTROLLERTRACKEDCOMPONENT_H - -#include "Interfaces/IController/IController.h" -#include "QPoint" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" - -class ControllerTrackedComponent : public IController -{ - Q_OBJECT -public: - ControllerTrackedComponent(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COMPONENT); - - 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 receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - - //members - int m_currentFrameNumber; - IModelAreaDescriptor* m_areaDescr; -}; - -#endif // CONTROLLERTRACKEDCOMPONENT_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackingAlgorithm.cpp b/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackingAlgorithm.cpp deleted file mode 100644 index f33954a3..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackingAlgorithm.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "ControllerTrackingAlgorithm.h" -#include "ControllerTrackedComponent.h" - -#include "Model/TrackerParameter.h" -#include "View/TrackerParameterView.h" -#include "View/TrackedElementView.h" - -ControllerTrackingAlgorithm::ControllerTrackingAlgorithm(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - m_BioTrackerContext = context; -} - -void ControllerTrackingAlgorithm::connectControllerToController() -{ - IController * ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - QPointer< ControllerTrackedComponent > ctrComponent = qobject_cast(ctr); - - m_TrackedTrajectoryMajor = ctrComponent->getModel(); -} - -void ControllerTrackingAlgorithm::doTracking(std::shared_ptr mat, uint number) -{ - qobject_cast(m_Model)->doTracking(mat, number); -} - -IView *ControllerTrackingAlgorithm::getTrackingParameterWidget() -{ - return m_View; -} - -void ControllerTrackingAlgorithm::createModel() -{ - connectControllerToController(); - - m_TrackingParameter = new TrackerParameter(this); - - m_Model = new BioTrackerTrackingAlgorithm(m_TrackingParameter, m_TrackedTrajectoryMajor); -} - -void ControllerTrackingAlgorithm::createView() -{ - m_View = new TrackerParameterView(0, this, m_TrackingParameter); -} - -void ControllerTrackingAlgorithm::connectModelToController() -{ - BioTrackerTrackingAlgorithm *trackingAlg = qobject_cast(m_Model); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitCvMatA, this, &ControllerTrackingAlgorithm::receiveCvMatFromTrackingAlgorithm); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitTrackingDone, this, &ControllerTrackingAlgorithm::receiveTrackingDone); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, this, &ControllerTrackingAlgorithm::receiveChangeDisplayImage); - QObject::connect(this, &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, trackingAlg, &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); - - QObject::connect(static_cast(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(ctr)->getView(); - TrackedElementView *v2 = dynamic_cast(v); - QObject::connect(trackingAlg, SIGNAL(emitDimensionUpdate(int, int)), v2, SLOT(rcvDimensionUpdate(int, int))); -} - -void ControllerTrackingAlgorithm::receiveCvMatFromTrackingAlgorithm(std::shared_ptr mat, QString name) -{ - Q_EMIT emitCvMat(mat, name); -} - -void ControllerTrackingAlgorithm::receiveTrackingDone(uint framenumber) -{ - Q_EMIT emitTrackingDone(framenumber); -} - -void ControllerTrackingAlgorithm::receiveChangeDisplayImage(QString str) { - Q_EMIT emitChangeDisplayImage(str); -} - -void ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - Q_EMIT emitAreaDescriptorUpdate(areaDescr); -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackingAlgorithm.h b/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackingAlgorithm.h deleted file mode 100644 index 75e565a4..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Controller/ControllerTrackingAlgorithm.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef CONTROLLERTRACKINGALGORITHM_H -#define CONTROLLERTRACKINGALGORITHM_H - -#include "Interfaces/IController/IController.h" -#include "Model/BioTrackerTrackingAlgorithm.h" -#include "Interfaces/IBioTrackerContext.h" -#include "Interfaces/IModel/IModelDataExporter.h" - - -class ControllerTrackingAlgorithm : public IController -{ - Q_OBJECT -public: - ControllerTrackingAlgorithm(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - // IController interface -public: - void connectControllerToController() override; - - void doTracking(std::shared_ptr mat, uint number); - - IView *getTrackingParameterWidget(); - -public Q_SLOTS: - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - -Q_SIGNALS: - void emitCvMat(std::shared_ptr mat, QString name); - void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - -private Q_SLOTS: - void receiveCvMatFromTrackingAlgorithm(std::shared_ptr mat, QString name); - void receiveTrackingDone(uint framenumber); - void receiveChangeDisplayImage(QString str); - -private: - IModel* m_TrackingParameter; - IModel *m_TrackedTrajectoryMajor; -}; - -#endif // CONTROLLERTRACKINGALGORITHM_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Controller/null_Controller.cpp b/BioTracker/Plugin/BackgroundSubtraction/Controller/null_Controller.cpp deleted file mode 100644 index 612c02f3..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/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/BioTracker/Plugin/BackgroundSubtraction/Controller/null_Controller.h b/BioTracker/Plugin/BackgroundSubtraction/Controller/null_Controller.h deleted file mode 100644 index a0fcc211..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/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/BioTracker/Plugin/BackgroundSubtraction/Model/BioTrackerTrackingAlgorithm.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/BioTrackerTrackingAlgorithm.cpp deleted file mode 100644 index ec512b81..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/BioTrackerTrackingAlgorithm.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "BioTrackerTrackingAlgorithm.h" -#include -#include "TrackedComponents/TrackedComponentFactory.h" -#include - -#include "settings/Settings.h" - -BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IModel *parameter, IModel *trajectory) : _ipp((TrackerParameter*)parameter) -{ - _TrackingParameter = (TrackerParameter*)parameter; - _TrackedTrajectoryMajor = (TrackedTrajectory*)trajectory; - _nn2d = std::make_shared(_TrackedTrajectoryMajor); - BioTracker::Core::Settings *set = _TrackingParameter->getSettings(); - - _noFish = -1; - - if (set->getValueOrDefault(FISHTANKPARAM::FISHTANK_ENABLE_NETWORKING, false)) { - _listener = new TcpListener(this); - _listener->listen(QHostAddress::Any, set->getValueOrDefault(FISHTANKPARAM::FISHTANK_NETWORKING_PORT, 54444)); - QObject::connect(_listener, SIGNAL(newConnection()), _listener, SLOT(acceptConnection())); - } - - - _lastImage = nullptr; - _lastFramenumber = -1; -} - - -void BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - _AreaInfo = areaDescr; - _bd.setAreaInfo(_AreaInfo); -} - -BioTrackerTrackingAlgorithm::~BioTrackerTrackingAlgorithm() -{ -} - -std::vector 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 last; - for (int i = 0; i < _TrackedTrajectoryMajor->size(); i++) { - TrackedTrajectory *t = dynamic_cast(_TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - TrackedElement *e = (TrackedElement *)t->getLastChild(); - last.push_back(e->getFishPose()); - } - } - return last; -} - -void BioTrackerTrackingAlgorithm::refreshPolygon() { - -} - -void BioTrackerTrackingAlgorithm::receiveParametersChanged() { - if (_lastFramenumber >= 0 && _lastImage && !_lastImage->empty()) { - doTracking(_lastImage, _lastFramenumber); - } -} - -void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map> *images) { - - std::shared_ptr sendImage; - //Send forth whatever the user selected - switch (_TrackingParameter->getSendImage()) { - case 0: //Send none - //sendImage = images.find(std::string("Original"))->second; - //Q_EMIT emitCvMatA(sendImage, QString("Original")); - Q_EMIT emitChangeDisplayImage("Original"); - break; - case 1: - sendImage = images->find(std::string("Binarized"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Binarized")); - Q_EMIT emitChangeDisplayImage(QString("Binarized")); - break; - case 2: - sendImage = images->find(std::string("Eroded"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Eroded")); - Q_EMIT emitChangeDisplayImage(QString("Eroded")); - break; - case 3: - sendImage = images->find(std::string("Dilated"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Dilated")); - Q_EMIT emitChangeDisplayImage(QString("Dilated")); - break; - case 4: - sendImage = images->find(std::string("Difference"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Difference")); - Q_EMIT emitChangeDisplayImage(QString("Difference")); - break; - case 5: - sendImage = images->find(std::string("Background"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Background")); - Q_EMIT emitChangeDisplayImage(QString("Background")); - break; - } -} - -void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr 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; - } - - 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); - } - - 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(); - //resetFishHistory(_noFish); - _nn2d = std::make_shared(_TrackedTrajectoryMajor); - } - - if (_TrackingParameter->getResetBackground()) { - _TrackingParameter->setResetBackground(false); - _ipp.resetBackgroundImage(); - } - - //Do the preprocessing - std::map> images = _ipp.preProcess(p_image); - std::shared_ptr dilated = images.find(std::string("Dilated"))->second; - std::shared_ptr greyMat = images.find(std::string("Greyscale"))->second; - - //Find blobs via ellipsefitting - _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); - _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); - std::vector blobs = _bd.getPoses(*dilated, *greyMat); - - // 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 fish = getLastPositionsAsPose(); - - //Find new positions using 2D nearest neighbour - std::tuple, std::vector> poses = _nn2d->getNewPoses(_TrackedTrajectoryMajor, framenumber, blobs); - - //Insert new poses into data structure - int trajNumber = 0; - for (int i = 0; i < _TrackedTrajectoryMajor->size(); i++) { - TrackedTrajectory *t = dynamic_cast(_TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - TrackedElement *e = new 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 ps = std::get<0>(poses); - _listener->sendPositions(framenumber, ps, std::vector(), start); - } - - sendSelectedImage(&images); - - //First the user still wants to see the original image, right? - if (framenumber==1) { - Q_EMIT emitChangeDisplayImage("Original"); - } - - std::string newSel = _TrackingParameter->getNewSelection(); - - Q_EMIT emitTrackingDone(framenumber); -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/BioTrackerTrackingAlgorithm.h b/BioTracker/Plugin/BackgroundSubtraction/Model/BioTrackerTrackingAlgorithm.h deleted file mode 100644 index edd23c64..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/BioTrackerTrackingAlgorithm.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef BIOTRACKERTRACKINGALGORITHM_H -#define BIOTRACKERTRACKINGALGORITHM_H - - -#include "Interfaces/IModel/IModel.h" - -#include "TrackerParameter.h" - -#include -#include "Interfaces/IModel/IModelTrackingAlgorithm.h" -#include "Interfaces/IModel/IModelDataExporter.h" -#include "Model/TrackedComponents/TrackedElement.h" -#include "Model/TrackedComponents/TrackedTrajectory.h" -#include "Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h" -#include "Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h" -#include "Model/TrackingAlgorithm/NN2dMapper.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include - -#include "Model/Network/TcpListener.h" - -class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm -{ - Q_OBJECT -public: - BioTrackerTrackingAlgorithm(IModel* parameter, IModel* trajectory); - ~BioTrackerTrackingAlgorithm(); - -Q_SIGNALS: - void emitCvMatA(std::shared_ptr image, QString name); - void emitDimensionUpdate(int x, int y); - void emitTrackingDone(uint framenumber); - - // ITrackingAlgorithm interface -public Q_SLOTS: - void doTracking(std::shared_ptr image, uint framenumber) override; - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - void receiveParametersChanged(); - -private: - void refreshPolygon(); - void sendSelectedImage(std::map>* images); - - std::vector getLastPositionsAsPose(); - - TrackedTrajectory* _TrackedTrajectoryMajor; - TrackerParameter* _TrackingParameter; - IModelAreaDescriptor* _AreaInfo; - - TcpListener* _listener; - - ImagePreProcessor _ipp; - BlobsDetector _bd; - std::shared_ptr _nn2d; - - // background subtraction - cv::Ptr _pMOG; - - int _noFish; - - //std::ofstream _ofs; - - int _imageX; - int _imageY; - - std::shared_ptr _lastImage; - uint _lastFramenumber; -}; - -#endif // BIOTRACKERTRACKINGALGORITHM_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/Network/TcpListener.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/Network/TcpListener.cpp deleted file mode 100644 index be733377..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/Network/TcpListener.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "TcpListener.h" - -#include - -TcpListener::TcpListener(QObject *parent) : QTcpServer(parent) -{ -} - -void TcpListener::acceptConnection() -{ - while (this->hasPendingConnections()) - { - QTcpSocket *socket = this->nextPendingConnection(); - _sockets.push_back(socket); - } -} - -void TcpListener::sendPositionsToSocket(std::string packet) -{ - - std::vector::iterator sock_it = _sockets.begin(); - for (sock_it = _sockets.begin(); sock_it != _sockets.end(); ++sock_it) - (*sock_it)->write(packet.c_str()); -} - -std::string TcpListener::sendPositions( - int frameNo, - const std::vector& poses, - const std::vector& polygon, - std::chrono::system_clock::time_point ts) -{ - 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 << ";"; - } - - int fishCount = poses.size(); - int fi = 0; - str << "fishcount:" << fishCount << ";"; - - 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(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; - -#ifdef SAVETRACKINGPACKAGES - _trackingInfoOutputFile4Simulation << str.str(); -#endif - sendPositionsToSocket(str.str()); - return str.str(); -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/Network/TcpListener.h b/BioTracker/Plugin/BackgroundSubtraction/Model/Network/TcpListener.h deleted file mode 100644 index 635ca8f9..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/Network/TcpListener.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "Model/TrackedComponents/pose/FishPose.h" - -#include -#include - -class TcpListener : public QTcpServer -{ - Q_OBJECT - -public: - TcpListener(QObject *parent = 0); - -public slots: - void acceptConnection(); - void sendPositionsToSocket(std::string packet); - std::string sendPositions(int frameNo, - const std::vector& poses, - const std::vector& polygon, - std::chrono::system_clock::time_point ts); - -private: - std::vector _sockets; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedComponentFactory.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedComponentFactory.cpp deleted file mode 100644 index 6d78033c..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedComponentFactory.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "TrackedComponentFactory.h" - -#include "TrackedTrajectory.h" -#include "TrackedElement.h" - -TrackedComponentFactory::TrackedComponentFactory() -{ - -} - -TrackedComponentFactory::~TrackedComponentFactory() -{ - -} - -QList TrackedComponentFactory::getElementTypes() { - return QList{ "TrackedElement" }; -} - -IModelTrackedComponent *TrackedComponentFactory::createTrackedElement(QString name) -{ - return new TrackedElement(this, "n.a."); -} - -IModelTrackedComponent *TrackedComponentFactory::createTrackedObject(QString name) -{ - TrackedTrajectory *t = new TrackedTrajectory(); - TrackedElement *e = new TrackedElement(this, "n.a.", 0); - t->add(e, 0); - return t; -} - -IModelTrackedComponent *TrackedComponentFactory::createTrackedTrajectory(QString name) -{ - return new TrackedTrajectory(); -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedComponentFactory.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedComponentFactory.h deleted file mode 100644 index 408d7232..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedComponentFactory.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TRACKEDCOMPONENTFACTORY_H -#define TRACKEDCOMPONENTFACTORY_H - -#include "Interfaces/IModel/IModelTrackedComponentFactory.h" - -class TrackedComponentFactory : public IModelTrackedComponentFactory -{ - Q_OBJECT -public: - TrackedComponentFactory(); - ~TrackedComponentFactory(); - - QList getElementTypes() override; - - // ITrackedComponentFactory interface -protected: - IModelTrackedComponent *createTrackedElement(QString name) override; - IModelTrackedComponent *createTrackedObject(QString name) override; - IModelTrackedComponent *createTrackedTrajectory(QString name) override; -}; - -#endif // TRACKEDOBJECTFACTORY_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedElement.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedElement.cpp deleted file mode 100644 index 8b0795fc..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedElement.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "TrackedElement.h" -#include "TrackedTrajectory.h" -#include "QDebug" -#include "QRect" -#include "QBrush" -#include "QPainter" -#include "QtMath" - -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(_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) { - _time = 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 dur(remainder); - _timeSysclck += dur; -}; - -qint64 TrackedElement::getTime() { - qint64 q(std::chrono::duration_cast(_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/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedElement.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedElement.h deleted file mode 100644 index f1408a76..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedElement.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef TRACKEDELEMENT_H -#define TRACKEDELEMENT_H - -#include "QGraphicsItem" -#include "Interfaces/IModel/IModelTrackedComponent.h" -#include "QString" -#include "Model/TrackedComponents/pose/FishPose.h" -#include - -/** -* 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); - - 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; }; - - - 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; }; - - void pressed(); - void notPressed(); - bool getPressedStatus(); - - void setFishPose(FishPose p); - FishPose getFishPose(); - - // ITrackedPoint interface -public: - void operate(); - -private: - std::chrono::system_clock::time_point _timeSysclck; - QString _unit = "cm"; - FishPose _pose; -}; - -#endif // TRACKEDELEMENT_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedTrajectory.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedTrajectory.cpp deleted file mode 100644 index 23d4318d..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedTrajectory.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "TrackedTrajectory.h" -#include "QDebug" -#include "TrackedElement.h" - -void TrackedTrajectory::triggerRecalcValid() { - g_calcValid = 1; -} - -void TrackedTrajectory::setValid(bool v) { - _valid = v; - if (_parentNode) { - TrackedTrajectory* n = dynamic_cast(_parentNode); - if (n) - n->triggerRecalcValid(); - } -} - -TrackedTrajectory::TrackedTrajectory(QObject *parent, QString name) : - IModelTrackedTrajectory(parent), - name(name) -{ - setFixed(false); - g_calcValid = 1; - g_validCount = 0; - _size = 0; - _valid = true; -} - -void TrackedTrajectory::operate() -{ - qDebug() << "Printing all TrackedElements in TrackedObject " << name; - qDebug() << "========================= Begin =========================="; - for (int i = 0; i < _TrackedComponents.size(); ++i) { - dynamic_cast(_TrackedComponents.at(i))->operate(); - } - qDebug() << "======================== End ========================="; -} - -void TrackedTrajectory::add(IModelTrackedComponent *comp, int pos) -{ - - comp->setParent(this); - - if (pos < 0) { - _TrackedComponents.append(comp); - _size++; - g_validCount++; - } - else if (_size <= pos) { - while (_size < pos) - { - _TrackedComponents.append(nullptr); - _size++; - } - - _TrackedComponents.append(comp); - _size++; - g_validCount++; - } - else { - _TrackedComponents[pos] = comp; - } -} - -bool TrackedTrajectory::remove(IModelTrackedComponent *comp) -{ - g_calcValid = 1; - comp->setValid(false); - return true; -} - -void TrackedTrajectory::clear() -{ - g_calcValid = 1; - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (dynamic_cast(el)) - dynamic_cast(el)->clear(); - } - _TrackedComponents.clear(); - _size = 0; -} - -IModelTrackedComponent* TrackedTrajectory::getChild(int index) -{ - if (index < 0) - return nullptr; - - if (index == _size - 1) { - return _TrackedComponents.back(); - } - - return (_size > index ? _TrackedComponents.at(index) : nullptr); -} - -IModelTrackedComponent* TrackedTrajectory::getValidChild(int index) -{ - int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (el){ - if (c == index && el->getValid()) - return el; - c += el->getValid() ? 1 : 0; - } - } - - return nullptr; -} - -IModelTrackedComponent* TrackedTrajectory::getLastChild() -{ - if (_TrackedComponents.empty()) - return nullptr; - return _TrackedComponents.back(); -} - -int TrackedTrajectory::size() -{ - return (_size == 0 ? _size = _TrackedComponents.size() : _size); -} - -int TrackedTrajectory::validCount() -{ - if (g_calcValid == 1) { - int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (el) - c += el->getValid() ? 1 : 0; - } - - g_validCount = c; - g_calcValid = 0; - return c; - } - else { - return g_validCount; - } -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedTrajectory.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedTrajectory.h deleted file mode 100644 index cd454be1..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/TrackedTrajectory.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef TRACKEDOTRAJECTORY_H -#define TRACKEDOTRAJECTORY_H - -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "QList" -#include "QString" - -/** - * 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 IModelTrackedTrajectory { - Q_OBJECT - - public: - TrackedTrajectory(QObject *parent = 0, QString name = "n.a."); - - // 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; -}; - -#endif // TRACKEDOTRAJECTORY_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/FishPose.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/FishPose.cpp deleted file mode 100644 index 8e13956f..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/FishPose.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#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) -{ - 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(); -} - -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::max() : 1.0/distance; -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/FishPose.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/FishPose.h deleted file mode 100644 index 849bb4cd..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/FishPose.h +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include "Model/TrackedComponents/pose/IPose.h" -#include -#include - -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); - -private: - cv::Point2f _position_cm; - cv::Point _position_px; - float _radAngle; - float _degAngle; - float _width; - float _height; - float _score; - time_t _timev; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/IPose.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/IPose.h deleted file mode 100644 index 1d315abc..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackedComponents/pose/IPose.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -class IPose -{ -public: - virtual ~IPose() {} - - /** - * 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 orientation in degree. - */ - virtual float orientation_deg() const = 0; - - /** - * Gets the fish orientation in radian. - */ - virtual float orientation_rad() const = 0; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackerParameter.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackerParameter.cpp deleted file mode 100644 index e837c065..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackerParameter.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "TrackerParameter.h" -#include "util/singleton.h" - -TrackerParameter::TrackerParameter(QObject *parent) : - IModel(parent) -{ - _settings = BioTracker::Util::TypedSingleton::getInstance(CONFIGPARAM::CONFIG_INI_FILE); - //_settings = new BioTracker::Core::Settings(CONFIGPARAM::CONFIG_INI_FILE); - - _BinarizationThreshold = _settings->getValueOrDefault(TRACKERPARAM::THRESHOLD_BINARIZING, 40); - _SizeErode = _settings->getValueOrDefault(TRACKERPARAM::SIZE_ERODE, 8); - _SizeDilate = _settings->getValueOrDefault(TRACKERPARAM::SIZE_DILATE, 8); - _MinBlobSize = _settings->getValueOrDefault(TRACKERPARAM::MIN_BLOB_SIZE, 40); - _MaxBlobSize = _settings->getValueOrDefault(TRACKERPARAM::MAX_BLOB_SIZE, 999999); - - _mog2History = _settings->getValueOrDefault(TRACKERPARAM::BG_MOG2_HISTORY, 200); - _mog2VarThresh = _settings->getValueOrDefault(TRACKERPARAM::BG_MOG2_VAR_THRESHOLD, 64); - _mog2BackgroundRatio = _settings->getValueOrDefault(TRACKERPARAM::BG_MOG2_BACKGROUND_RATIO, 0.05); - - _doNetwork = _settings->getValueOrDefault(FISHTANKPARAM::FISHTANK_ENABLE_NETWORKING, false); - _networkPort = _settings->getValueOrDefault(FISHTANKPARAM::FISHTANK_NETWORKING_PORT, 54444); - - _Threshold = 12345; - - _doBackground = true; - _sendImage = 0; //Send no image - _resetBackground = false; - - Q_EMIT notifyView(); -} - -void TrackerParameter::setThreshold(int x) -{ - _Threshold = x; - - Q_EMIT notifyView(); -} - -int TrackerParameter::getThreshold() -{ - return _Threshold; -} - -void TrackerParameter::setBinarizationThreshold(int x) -{ - _BinarizationThreshold = x; - _settings->setParam(TRACKERPARAM::THRESHOLD_BINARIZING, x); - Q_EMIT notifyView(); -} - -int TrackerParameter::getBinarizationThreshold() -{ - return _BinarizationThreshold; -} \ No newline at end of file diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackerParameter.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackerParameter.h deleted file mode 100644 index abc7969b..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackerParameter.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef TRACKERPARAMETER_H -#define TRACKERPARAMETER_H - - -#include "Interfaces/IModel/IModel.h" -#include "settings/Settings.h" -#include "Model/TrackingAlgorithm/ParamNames.h" - -class TrackerParameter : public IModel -{ - Q_OBJECT -public: - TrackerParameter(QObject *parent = 0); - - void setThreshold(int x); - - int getThreshold(); - - BioTracker::Core::Settings *getSettings() { return _settings; }; - - void setBinarizationThreshold(int x); - int getBinarizationThreshold(); - - int getSizeErode() { return _SizeErode; }; - void setSizeErode(int x) { - _SizeErode = x; - Q_EMIT notifyView(); - }; - - int getSizeDilate() { return _SizeDilate; }; - void setSizeDilate(int x) { - _SizeDilate = x; - Q_EMIT notifyView(); - }; - - int getmog2History() { return _mog2History; }; - void setmog2History(int x) { - _mog2History = x; - Q_EMIT notifyView(); - }; - - int getmog2VarThresh() { return _mog2VarThresh; }; - void setmog2VarThresh(int x) { - _mog2VarThresh = x; - Q_EMIT notifyView(); - }; - - double getmog2BackgroundRatio() { return _mog2BackgroundRatio; }; - void setmog2BackgroundRatio(double x) { - _mog2BackgroundRatio = x; - Q_EMIT notifyView(); - }; - - double getMinBlobSize() { return _MinBlobSize; }; - void setMinBlobSize(double x) { - _MinBlobSize = x; - Q_EMIT notifyView(); - }; - - double getMaxBlobSize() { return _MaxBlobSize; }; - void setMaxBlobSize(double x) { - _MaxBlobSize = x; - Q_EMIT notifyView(); - }; - - bool getDoBackground() { return _doBackground; }; - void setDoBackground(bool x) { - _doBackground = x; - Q_EMIT notifyView(); - }; - - bool getDoNetwork() { return _doNetwork; }; - void setDoNetwork(bool x) { - _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; - _settings->setParam(FISHTANKPARAM::FISHTANK_FISH_AMOUNT, x); - Q_EMIT notifyView(); - }; - - std::string getNewSelection() { return _newSelection; }; - void setNewSelection(std::string x) { - _newSelection = x; - } - - - void setAll( - int Threshold, - int BinarizationThreshold, - int SizeErode, - int SizeDilate, - int mog2History, - int mog2VarThresh, - double mog2BackgroundRatio, - int minBlobSize, - int maxBlobSize) - { - _Threshold = Threshold; - _BinarizationThreshold = BinarizationThreshold; - _SizeErode = SizeErode; - _SizeDilate = SizeDilate; - _mog2History = mog2History; - _mog2VarThresh = mog2VarThresh; - _mog2BackgroundRatio = mog2BackgroundRatio; - _MinBlobSize = minBlobSize; - _MaxBlobSize = maxBlobSize; - _settings->setParam(TRACKERPARAM::THRESHOLD_BINARIZING, BinarizationThreshold); - _settings->setParam(TRACKERPARAM::SIZE_ERODE, SizeErode); - _settings->setParam(TRACKERPARAM::SIZE_DILATE, SizeDilate); - _settings->setParam(TRACKERPARAM::MIN_BLOB_SIZE, minBlobSize); - _settings->setParam(TRACKERPARAM::MAX_BLOB_SIZE, maxBlobSize); - _settings->setParam(TRACKERPARAM::BG_MOG2_HISTORY, mog2History); - _settings->setParam(TRACKERPARAM::BG_MOG2_VAR_THRESHOLD, mog2VarThresh); - _settings->setParam(TRACKERPARAM::BG_MOG2_BACKGROUND_RATIO, mog2BackgroundRatio); - Q_EMIT notifyView(); - }; - - - -private: - BioTracker::Core::Settings *_settings; - - int _Threshold; - int _BinarizationThreshold; - int _SizeErode; - int _SizeDilate; - int _mog2History; - int _mog2VarThresh; - double _mog2BackgroundRatio; - int _MinBlobSize; - int _MaxBlobSize; - - bool _doBackground; - int _sendImage; - bool _resetBackground; - int _noFish; - - int _networkPort; - bool _doNetwork; - - std::string _newSelection; -}; - -#endif // TRACKERPARAMETER_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/NN2dMapper.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/NN2dMapper.cpp deleted file mode 100644 index 96644a9d..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/NN2dMapper.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#include "NN2dMapper.h" - -#include "helper/CvHelper.h" -#include -#include -#include - -float dif(float a, float b) { - return fmod((std::abs(b - a)), CV_PI); -} - -NN2dMapper::NN2dMapper(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(_tree->getChild(i)); - if (t && t->getValid()){ - _mapLastConfidentAngle.insert(std::pair(cid, std::numeric_limits::quiet_NaN())); - cid++; - } - } -} - -// 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 a, std::tuple b) const { - return std::get<0>(a) > std::get<0>(b); - } - -}; - -FishPose getFishpose(TrackedTrajectory* traj, uint frameid, uint id) { - IModelTrackedComponent* comp = traj->getValidChild(id); - TrackedTrajectory* ct = dynamic_cast(comp); - if (ct) { - TrackedElement *el = dynamic_cast(ct->getChild(frameid-1)); - if (el) - return el->getFishPose(); - } - return FishPose(); -} - -std::tuple, std::vector> NN2dMapper::getNewPoses(TrackedTrajectory* traj, uint frameid, std::vector 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 blobs = convertBlobPosesToFishPoses(blobPoses); - - int sizeF = traj->validCount(); - int sizeB = blobs.size(); - std::vector>> propMap; - - //Create propability matrix and sort it - for (int i = 0; i < sizeF ; i++) { - std::vector> currentFish; - FishPose cpose = getFishpose(traj, frameid, i); - for (int j = 0; j < sizeB ; j++) { - currentFish.push_back(std::tuple(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 bestMatchesProps; - std::vector 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(); - 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 pnow = bestMatchesPoses[i].position_cm(); - } - double dir = CvHelper::getAngleToTarget(p, pnow); - //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); - 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; - 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); - bestMatchesPoses[i].set_orientation_deg(dir * 180.0f / CV_PI); - } - _mapLastConfidentAngle[i] = dir; - } - return std::tuple, std::vector>(bestMatchesPoses,bestMatchesProps); -} - -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; -} - -TrackedTrajectory* getChildOfType(TrackedTrajectory* tree, int tid) { - int cid = 0; - for (int i = 0; i < tree->size(); i++) { - TrackedTrajectory* t = dynamic_cast(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) -{ - //Get corresponding trajectory - TrackedTrajectory* t = getChildOfType((TrackedTrajectory*)_tree, trackid); - //return 0; - - // can't give estimate if not enough poses available - if (t->size() < 3) return std::numeric_limits::quiet_NaN(); - - //std::deque::const_reverse_iterator iter = _histComponents.rbegin(); - int start = std::max(t->size()-20, 0); - TrackedElement* e = (TrackedElement*)t->getChild(start); - if (!e) - return std::numeric_limits::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; isize(); i++) - { - TrackedElement* ecur = (TrackedElement*)t->getChild(i); - if (!ecur) - return std::numeric_limits::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(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::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 NN2dMapper::convertBlobPosesToFishPoses(std::vector blobPoses) -{ - std::vector 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/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/NN2dMapper.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/NN2dMapper.h deleted file mode 100644 index 5d2aa07b..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/NN2dMapper.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include -#include "Model/TrackedComponents/pose/FishPose.h" -#include -#include -#include "Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h" - -class NN2dMapper -{ -public: - - /** - * The contructor with parameters. - */ - NN2dMapper(TrackedTrajectory *tree); - - ~NN2dMapper(void) {}; - - std::tuple, std::vector> getNewPoses(TrackedTrajectory* traj, uint frameid, std::vector blobPoses); - std::vector convertBlobPosesToFishPoses(std::vector blobPoses); - float estimateOrientationRad(int trackid, float *confidence); - bool correctAngle(int trackid, FishPose &pose); - - std::map _mapLastConfidentAngle; - TrackedTrajectory *_tree; - -protected: - -}; - diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/ParamNames.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/ParamNames.h deleted file mode 100644 index 7e7a5879..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/ParamNames.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include -#include - - -namespace CONFIGPARAM -{ - // System config - const std::string CONFIG_INI_FILE = "./BSTrackerConfig.ini"; -} - -namespace APPLICATIONPARAM -{ - // System config - const std::string APP_VERSION = "APPLICATIONPARAM/APP_VERSION"; -} - -namespace TRACKERPARAM -{ - - // Parameter for the opencv BackgroundSubtractorMOG2 class - const std::string BG_MOG2_HISTORY = "TRACKERPARAM/BG_MOG2_HISTORY"; - const std::string BG_MOG2_VAR_THRESHOLD = "TRACKERPARAM/BG_MOG2_VAR_THRESHOLD"; - const std::string BG_MOG2_BACKGROUND_RATIO = "TRACKERPARAM/BG_MOG2_BACKGROUND_RATIO"; - - // Blob dectection issue - const std::string MAX_BLOB_SIZE = "TRACKERPARAM/MAX_BLOB_SIZE"; - const std::string MIN_BLOB_SIZE = "TRACKERPARAM/MIN_BLOB_SIZE"; - - // Parameters for image pre-processing step - const std::string SIZE_ERODE = "TRACKERPARAM/SIZE_ERODE"; - const std::string SIZE_DILATE = "TRACKERPARAM/SIZE_DILATE"; - const std::string THRESHOLD_BINARIZING = "TRACKERPARAM/THRESHOLD_BINARIZING"; - //const std::string GAUSSIAN_BLUR_SIZE = "TRACKERPARAM/GAUSSIAN_BLUR_SIZE"; -} - -namespace GUIPARAM -{ - // FPS label - const std::string ENABLE_LABEL_FPS = "GUIPARAM/ENABLE_LABEL_FPS"; - // Fish id label - const std::string ENABLE_LABEL_FISH_ID = "GUIPARAM/ENABLE_LABEL_FISH_ID"; - // Replica marker - const std::string ENABLE_LABEL_REPLICA = "GUIPARAM/ENABLE_LABEL_REPLICA"; - // Fish position - const std::string ENABLE_LABEL_FISH_POS = "GUIPARAM/ENABLE_LABEL_FISH_POS"; - // Fish orientation - const std::string ENABLE_LABEL_FISH_ORI = "GUIPARAM/ENABLE_LABEL_FISH_ORI"; - // Fish history - const std::string ENABLE_LABEL_FISH_HISTORY = "GUIPARAM/ENABLE_LABEL_FISH_HISTORY"; - // Blobs - const std::string ENABLE_SHOW_BLOBS = "GUIPARAM/ENABLE_SHOW_BLOBS"; - // Swap fish id - const std::string ENABLE_SWAP_FISH_ID = "GUIPARAM/ENABLE_SWAP_FISH_ID"; - - - - // Core view of tracked components - const std::string ENABLE_CORE_COMPONENT_VIEW = "GUIPARAM/ENABLE_CORE_COMPONENT_VIEW"; - // Move components in core view - const std::string ENABLE_CORE_COMPONENT_MOVE = "GUIPARAM/ENABLE_CORE_COMPONENT_MOVE"; - // Remove components in core view - const std::string ENABLE_CORE_COMPONENT_REMOVE = "GUIPARAM/ENABLE_CORE_COMPONENT_REMOVE"; - // Swap component id in core view - const std::string ENABLE_CORE_COMPONENT_ID_SWAP = "GUIPARAM/ENABLE_CORE_COMPONENT_ID_SWAP"; - // Add component in core view - const std::string ENABLE_CORE_COMPONENT_ADD = "GUIPARAM/ENABLE_CORE_COMPONENT_ADD"; - // Rotate component in core view - const std::string ENABLE_CORE_COMPONENT_ROTATE = "GUIPARAM/ENABLE_CORE_COMPONENT_ROTATE"; -} - -namespace FISHTANKPARAM -{ - // Tank area - const std::string FISHTANK_AREA_WIDTH = "FISHTANKPARAM/FISHTANK_AREA_WIDTH"; - const std::string FISHTANK_AREA_HEIGHT = "FISHTANKPARAM/FISHTANK_AREA_HEIGHT"; - const std::string FISHTANK_FISH_AMOUNT = "FISHTANKPARAM/FISHTANK_FISH_AMOUNT"; - const std::string FISHTANK_AREA_CORNER1 = "FISHTANKPARAM/FISHTANK_AREA_CORNER1"; - const std::string FISHTANK_AREA_CORNER2 = "FISHTANKPARAM/FISHTANK_AREA_CORNER2"; - const std::string FISHTANK_AREA_CORNER3 = "FISHTANKPARAM/FISHTANK_AREA_CORNER3"; - const std::string FISHTANK_AREA_CORNER4 = "FISHTANKPARAM/FISHTANK_AREA_CORNER4"; - const std::string FISHTANK_ENABLE_NETWORKING = "FISHTANKPARAM/FISHTANK_ENABLE_NETWORKING"; - const std::string FISHTANK_NETWORKING_PORT = "FISHTANKPARAM/FISHTANK_NETWORKING_PORT"; -} - diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp deleted file mode 100644 index 7ea09b3e..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp +++ /dev/null @@ -1,257 +0,0 @@ -#include "BlobContour.h" - -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; -} -CBlobContour::CBlobContour(CvPoint 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); - -} - - -//! Copy constructor -CBlobContour::CBlobContour( CBlobContour *source ) -{ - if (source != NULL ) - { - *this = *source; - } -} - -CBlobContour::~CBlobContour() -{ - // let parent blob deallocate all contour and contour point memory - m_contour = NULL; - m_contourPoints = NULL; -} - - -//! Copy operator -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; -} - - -/** -- 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); -} - -//! 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; - } -} - -/** -- FUNCIÓ: GetPerimeter -- 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 -*/ -double CBlobContour::GetPerimeter() -{ - // is calculated? - if (m_perimeter != -1) - { - return m_perimeter; - } - - if( IsEmpty() ) - return 0; - - m_perimeter = cvContourPerimeter( GetContourPoints() ); - - return m_perimeter; -} - -/** -- FUNCIÓ: GetArea -- FUNCIONALITAT: Computes area from chain code -- PARÀMETRES: - - -- RESULTAT: - - May give negative areas for clock wise contours -- RESTRICCIONS: - - -- AUTOR: rborras -- DATA DE CREACIÓ: 2008/04/30 -- MODIFICACIÓ: Data. Autor. Descripció. -- NOTA: Algorithm derived from "Properties of contour codes", G.R. Wilson -*/ -double CBlobContour::GetArea() -{ - // 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 ); - - -} - -//! 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; - CvPoint 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/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h deleted file mode 100644 index b7fbcd7d..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef BLOBCONTOUR_H_INCLUDED -#define BLOBCONTOUR_H_INCLUDED - - -#include "list" -#include -//#include "cxtypes.h" //AO -#include // - -//! Type of chain codes -typedef unsigned char t_chainCode; -//! Type of list of chain codes -typedef CvSeq* t_chainCodeList; -//! Type of list of points -typedef CvSeq* t_PointList; - - -//! Max order of calculated moments -#define MAX_MOMENTS_ORDER 3 - - -//! Blob contour class (in crack code) -class CBlobContour -{ - friend class CBlob; - friend class CBlobProperties; //AO - -public: - //! Constructors - CBlobContour(); - CBlobContour(CvPoint 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: - - CvPoint 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 - CvPoint 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 - - diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h deleted file mode 100644 index 55fd8a9f..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h +++ /dev/null @@ -1,22 +0,0 @@ -/************************************************************************ - BlobLibraryConfiguration.h - -FUNCIONALITAT: Configuració del comportament global de la llibreria -AUTOR: Inspecta S.L. -MODIFICACIONS (Modificació, Autor, Data): - -FUNCTIONALITY: Global configuration of the library -AUTHOR: Inspecta S.L. -MODIFICATIONS (Modification, Author, Date): - -**************************************************************************/ - -//! Indica si es volen fer servir les MatrixCV o no -//! Use/Not use the MatrixCV class -//#define MATRIXCV_ACTIU - -//! Uses/not use the blob object factory -//#define BLOB_OBJECT_FACTORY - -//! Show/not show blob access errors -//#define _SHOW_ERRORS //AO: Only works for WIN. diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp deleted file mode 100644 index 2974547a..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp +++ /dev/null @@ -1,502 +0,0 @@ -#include -#include "BlobOperators.h" - -/*************************************************************************** - Implementació de les classes per al càlcul de característiques sobre el blob - - Implementation of the helper classes to perform operations on blobs -/**************************************************************************/ - -/** -- FUNCTION: Moment -- FUNCTIONALITY: Calculates the pq moment of the blob -- PARAMETERS: -- RESULT: - - returns the pq moment or 0 if the moment it is not implemented -- RESTRICTIONS: - - Currently, implemented moments up to 3 -- AUTHOR: Ricard Borràs -- CREATION DATE: 20-07-2004. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetMoment::operator()(CBlob &blob) -{ - 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. - -- 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. -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 20-07-2004. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: CBlobGetHullPerimeter -- 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 -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetHullPerimeter::operator()(CBlob &blob) -{ - CvSeq *convexHull; - double perimeter; - - convexHull = blob.GetConvexHull(); - - if( convexHull ) - perimeter = fabs(cvArcLength(convexHull,CV_WHOLE_SEQ,1)); - else - return 0; - - cvClearSeq(convexHull); - - return perimeter; -} - -double CBlobGetHullArea::operator()(CBlob &blob) -{ - CvSeq *convexHull; - double area; - - convexHull = blob.GetConvexHull(); - - if( convexHull ) - area = fabs(cvContourArea(convexHull)); - else - return 0; - - cvClearSeq(convexHull); - - return area; -} - -/** -- FUNCTION: CBlobGetMinXatMinY -- FUNCTIONALITY: Calculates the minimum X on the minimum Y -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetMinXatMinY::operator()(CBlob &blob) -{ - double result = LONG_MAX; - - CvSeqReader reader; - CvPoint 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; -} - -/** -- FUNCTION: CBlobGetMinXatMinY -- FUNCTIONALITY: Calculates the minimum Y on the maximum X -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetMinYatMaxX::operator()(CBlob &blob) -{ - double result = LONG_MAX; - - CvSeqReader reader; - CvPoint 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; -} - -/** -- FUNCTION: CBlobGetMaxXatMaxY -- FUNCTIONALITY: Calculates the maximum X on the maximum Y -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetMaxXatMaxY::operator()(CBlob &blob) -{ - double result = LONG_MIN; - - CvSeqReader reader; - CvPoint 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; -} - -/** -- FUNCTION: CBlobGetMaxYatMinX -- FUNCTIONALITY: Calculates the maximum Y on the minimum X -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetMaxYatMinX::operator()(CBlob &blob) -{ - double result = LONG_MIN; - - CvSeqReader reader; - CvPoint 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 -- FUNCTIONALITY: Calculates the elongation of the blob ( length/breadth ) -- PARAMETERS: -- RESULT: -- RESTRICTIONS: - - 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 ampladaC,longitudC,amplada,longitud; - - double tmp; - - 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(ampladaC<=0.0) return 0; - longitudC=(double) blob.Area()/ampladaC; - - longitud=MAX( longitudC , ampladaC ); - amplada=MIN( longitudC , ampladaC ); - - return (double) longitud/amplada; -} - -/** - Retorna la compacitat del blob -*/ -/** -- FUNCTION: CBlobGetCompactness -- FUNCTIONALITY: Calculates the compactness of the blob - ( maximum for circle shaped blobs, minimum for the rest) -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -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; -} - -/** - Retorna la rugositat del blob -*/ -/** -- FUNCTION: CBlobGetRoughness -- FUNCTIONALITY: Calculates the roughness of the blob - ( ratio between perimeter and convex hull perimeter) -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetRoughness::operator()(CBlob &blob) -{ - CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter(); - - double hullPerimeter = getHullPerimeter(blob); - - if( hullPerimeter != 0.0 ) - return blob.Perimeter() / hullPerimeter;//HullPerimeter(); - - return 0.0; -} - -/** - Retorna la longitud del blob -*/ -/** -- FUNCTION: CBlobGetLength -- 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 -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetLength::operator()(CBlob &blob) -{ - double ampladaC,longitudC; - double tmp; - - 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(ampladaC<=0.0) return 0; - longitudC=(double) blob.Area()/ampladaC; - - return MAX( longitudC , ampladaC ); -} - -/** - Retorna l'amplada del blob -*/ -/** -- FUNCTION: CBlobGetBreadth -- 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 -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetBreadth::operator()(CBlob &blob) -{ - double ampladaC,longitudC; - double tmp; - - 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(ampladaC<=0.0) return 0; - longitudC = (double) blob.Area()/ampladaC; - - return MIN( longitudC , ampladaC ); -} - -/** - 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 -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double CBlobGetDistanceFromPoint::operator()(CBlob &blob) -{ - double xmitjana, ymitjana; - CBlobGetXCenter getXCenter; - CBlobGetYCenter getYCenter; - - xmitjana = m_x - getXCenter( blob ); - ymitjana = m_y - getYCenter( blob ); - - return sqrt((xmitjana*xmitjana)+(ymitjana*ymitjana)); -} - -/** -- FUNCTION: BlobGetXYInside -- FUNCTIONALITY: Calculates whether a point is inside the - rectangular bounding box of a blob -- PARAMETERS: -- RESULT: - - 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) -{ - if( blob.GetExternalContour()->GetContourPoints() ) - { - return cvPointPolygonTest( blob.GetExternalContour()->GetContourPoints(), m_p,0) >= 0; - } - - return 0; -} -#ifdef BLOB_OBJECT_FACTORY - -/** -- FUNCIÓ: RegistraTotsOperadors -- FUNCIONALITAT: Registrar tots els operadors definits a blob.h -- PARÀMETRES: - - fabricaOperadorsBlob: fàbrica on es registraran els operadors -- RESULTAT: - - Modifica l'objecte fabricaOperadorsBlob -- RESTRICCIONS: - - Només es registraran els operadors de blob.h. Si se'n volen afegir, cal afegir-los amb - el mètode Register de la fàbrica. -- AUTOR: rborras -- DATA DE CREACIÓ: 2006/05/18 -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -void RegistraTotsOperadors( t_OperadorBlobFactory &fabricaOperadorsBlob ) -{ - // blob shape - fabricaOperadorsBlob.Register( CBlobGetArea().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetBreadth().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetCompactness().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetElongation().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetExterior().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetLength().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetPerimeter().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetRoughness().GetNom(), Type2Type()); - - // blob color - fabricaOperadorsBlob.Register( CBlobGetMean(NULL).GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetStdDev(NULL).GetNom(), Type2Type()); - - // extern pixels - fabricaOperadorsBlob.Register( CBlobGetExternPerimeterRatio().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetExternHullPerimeterRatio().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetExternPerimeter().GetNom(), Type2Type()); - - - // hull - fabricaOperadorsBlob.Register( CBlobGetHullPerimeter().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetHullArea().GetNom(), Type2Type()); - - - // elipse info - fabricaOperadorsBlob.Register( CBlobGetMajorAxisLength().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMinorAxisLength().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetAxisRatio().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetOrientation().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetOrientationCos().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetAreaElipseRatio().GetNom(), Type2Type()); - - // min an max - fabricaOperadorsBlob.Register( CBlobGetMaxX().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMaxY().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMinX().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMinY().GetNom(), Type2Type()); - - fabricaOperadorsBlob.Register( CBlobGetMaxXatMaxY().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMaxYatMinX().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMinXatMinY().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetMinYatMaxX().GetNom(), Type2Type()); - - // coordinate info - fabricaOperadorsBlob.Register( CBlobGetXYInside().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetDiffY().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetDiffX().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetXCenter().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetYCenter().GetNom(), Type2Type()); - fabricaOperadorsBlob.Register( CBlobGetDistanceFromPoint().GetNom(), Type2Type()); - - // moments - fabricaOperadorsBlob.Register( CBlobGetMoment().GetNom(), Type2Type()); - -} - -#endif //BLOB_OBJECT_FACTORY \ No newline at end of file diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h deleted file mode 100644 index 4fbc1c81..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h +++ /dev/null @@ -1,754 +0,0 @@ -#ifndef BLOB_OPERATORS_H_INCLUDED -#define BLOB_OPERATORS_H_INCLUDED - -#include "blob.h" - -/************************************************************************** - Definició de les classes per a fer operacions sobre els blobs - - Helper classes to perform operations on blobs -**************************************************************************/ - -//! Factor de conversió de graus a radians -#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(){}; - - //! Aply operator to blob - virtual double operator()(CBlob &blob) = 0; - //! Get operator name - virtual const char *GetNom() = 0; - - operator COperadorBlob*() - { - return (COperadorBlob*)this; - } -}; - -typedef COperadorBlob funcio_calculBlob; - -#ifdef BLOB_OBJECT_FACTORY - /** - Funció per comparar dos identificadors dins de la fàbrica de COperadorBlobs - */ - struct functorComparacioIdOperador - { - bool operator()(const char* s1, const char* s2) const - { - return strcmp(s1, s2) < 0; - } - }; - - //! Definition of Object factory type for COperadorBlob objects - typedef ObjectFactory t_OperadorBlobFactory; - - //! Funció global per a registrar tots els operadors definits a blob.h - void RegistraTotsOperadors( t_OperadorBlobFactory &fabricaOperadorsBlob ); - -#endif - - -//! 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"; - } -}; - - -//! 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"; - } -}; - -//! Classe per calcular el perimetre d'un blob -//! Class to get the perimeter of a blob -class CBlobGetPerimeter: public COperadorBlob -{ -public: - 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"; - } -private: - 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: - - 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; - -}; - -//! Classe per calcular la compacitat d'un blob -//! Class to calculate the compactness of a blob -class CBlobGetCompactness: public COperadorBlob -{ -public: - 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 -{ -public: - 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 -{ -public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetBreadth"; - } -}; - -//! Classe per calcular la diferència en X del blob -class CBlobGetDiffX: public COperadorBlob -{ -public: - 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 -{ -public: - 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"; - } - -private: - //! 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - 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"; - } - -private: - // 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"; - } -private: - 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"; - } -private: - 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 -//! 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; - -}; - -//! 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 -{ -public: - 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 -{ -public: - 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 -{ -public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); - - 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 -{ -public: - 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(); - - 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 -{ -public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); - - 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"; - } -}; - -//! 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 -{ -public: - 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 -{ -public: - double operator()(CBlob &blob) - { - double major,minor; - CBlobGetMajorAxisLength getMajor; - CBlobGetMinorAxisLength getMinor; - - major = getMajor(blob); - minor = getMinor(blob); - - 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"; - } - -private: - //! punt que considerem - //! point to be considered - CvPoint2D32f m_p; -}; - -#endif //!BLOB_OPERATORS_H_INCLUDED diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp deleted file mode 100644 index 64b72654..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "BlobProperties.h" - - -/** -- FUNCIÓ: GetPerimeter -- 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 -*/ -#define SQRT2 1.414213562 - -/** -- FUNCIÓ: GetPerimeter -- 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 CBlobProperties::GetArea() -{ - 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Ó: 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; - - perimeter = m_externalContour.GetPerimeter(); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - perimeter += (*itContour).GetPerimeter(); - itContour++; - } - return perimeter; -} - - diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h deleted file mode 100644 index 51c10172..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h +++ /dev/null @@ -1,70 +0,0 @@ - -//! Disable warnings referred to 255 character truncation for the std:map -#pragma warning( disable : 4786 ) - -#ifndef BLOB_PROPERTIES_H_INCLUDED -#define BLOB_PROPERTIES_H_INCLUDED - -#include -#include "BlobLibraryConfiguration.h" -#include "BlobContour.h" - - -#ifdef BLOB_OBJECT_FACTORY - //! Object factory pattern implementation - #include "..\inspecta\DesignPatterns\ObjectFactory.h" -#endif - - -//! Type of labelled images -typedef unsigned int t_labelType; - -//! Max order of calculated moments -#define MAX_MOMENTS_ORDER 3 - - -//! Blob class -class CBlobProperties -{ - typedef std::list t_contourList; - -public: - - CBlobProperties(); - virtual ~CBlobProperties(); - - //! Get blob area - double GetArea(); - - //! Get blob perimeter - double GetPerimeter(); - - //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) - double GetMoment(int p, int q); - - - ////////////////////////////////////////////////////////////////////////// - // 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; - -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]; - -}; - -#endif //!BLOB_PROPERTIES_H_INCLUDED - diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp deleted file mode 100644 index 09869837..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp +++ /dev/null @@ -1,943 +0,0 @@ -/************************************************************************ - BlobResult.cpp - -FUNCIONALITAT: Implementació de la classe CBlobResult -AUTOR: Inspecta S.L. -MODIFICACIONS (Modificació, Autor, Data): - -**************************************************************************/ - -#include -#include -#include -#include -#include "BlobResult.h" - -//! Show errors functions: only works for windows releases -#ifdef _SHOW_ERRORS - #include //suport per a CStrings - #include //suport per a AfxMessageBox -#endif - -/************************************************************************** - Constructors / Destructors -**************************************************************************/ - - -/** -- FUNCIÓ: CBlobResult -- FUNCIONALITAT: Constructor estandard. -- PARÀMETRES: -- RESULTAT: -- Crea un CBlobResult sense cap blob -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 20-07-2004. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: CBlobResult -- FUNCTIONALITY: Standard constructor -- PARAMETERS: -- RESULT: - - creates an empty set of blobs -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -CBlobResult::CBlobResult() -{ - 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. -- 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). - -- RESULTAT: - - objecte CBlobResult amb els blobs de la imatge source -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: CBlob -- 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 neighbouring 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 -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -CBlobResult::CBlobResult(IplImage *source, IplImage *mask, uchar backgroundColor ) -{ - 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. -- PARÀMETRES: - - source: objecte que es copiarà -- RESULTAT: - - objecte CBlobResult amb els blobs de l'objecte source -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: CBlobResult -- FUNCTIONALITY: Copy constructor -- PARAMETERS: - - source: object to copy -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -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++; - } -} - - - -/** -- FUNCIÓ: ~CBlobResult -- FUNCIONALITAT: Destructor estandard. -- PARÀMETRES: -- RESULTAT: - - Allibera la memòria reservada de cadascun dels blobs de la classe -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: ~CBlobResult -- FUNCTIONALITY: Destructor -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -CBlobResult::~CBlobResult() -{ - ClearBlobs(); -} - -/************************************************************************** - Operadors / Operators -**************************************************************************/ - - -/** -- FUNCIÓ: operador = -- FUNCIONALITAT: Assigna un objecte source a l'actual -- PARÀMETRES: - - source: objecte a assignar -- RESULTAT: - - Substitueix els blobs actuals per els de l'objecte source -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: Assigment operator -- FUNCTIONALITY: -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -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; -} - - -/** -- FUNCIÓ: operador + -- FUNCIONALITAT: Concatena els blobs de dos CBlobResult -- PARÀMETRES: - - source: d'on s'agafaran els blobs afegits a l'actual -- RESULTAT: - - retorna un nou CBlobResult amb els dos CBlobResult concatenats -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- NOTA: per la implementació, els blobs del paràmetre es posen en ordre invers -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: + operator -- FUNCTIONALITY: Joins the blobs in source with the current ones -- PARAMETERS: - - source: object to copy the blobs -- RESULT: - - 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; -} - -/************************************************************************** - Operacions / Operations -**************************************************************************/ - -/** -- FUNCIÓ: AddBlob -- FUNCIONALITAT: Afegeix un blob al conjunt -- PARÀMETRES: - - blob: blob a afegir -- RESULTAT: - - 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 ) -{ - if( blob != NULL ) - m_blobs.push_back( new CBlob( blob ) ); -} - - -#ifdef MATRIXCV_ACTIU - -/** -- FUNCIÓ: GetResult -- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe -- PARÀMETRES: - - evaluador: Qualsevol objecte derivat de COperadorBlob -- RESULTAT: - - Retorna un array de double's amb el resultat per cada blob -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: GetResult -- FUNCTIONALITY: Computes the function evaluador on all the blobs of the class - and returns a vector with the result -- PARAMETERS: - - 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 -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -double_vector CBlobResult::GetResult( funcio_calculBlob *evaluador ) const -{ - if( GetNumBlobs() <= 0 ) - { - return double_vector(); - } - - // definim el resultat - double_vector result = double_vector( GetNumBlobs() ); - // i iteradors sobre els blobs i el resultat - double_vector::iterator itResult = result.GetIterator(); - 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; -} -#endif - -/** -- FUNCIÓ: GetSTLResult -- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe -- PARÀMETRES: - - evaluador: Qualsevol objecte derivat de COperadorBlob -- RESULTAT: - - Retorna un array de double's STL amb el resultat per cada blob -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: GetResult -- FUNCTIONALITY: Computes the function evaluador on all the blobs of the class - and returns a vector with the result -- PARAMETERS: - - 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 -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -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; -} - -/** -- FUNCIÓ: GetNumber -- 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. -- RESULTAT: - - Retorna un double amb el resultat -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- 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 ) -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -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] ); -} - -/////////////////////////// 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 -- 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). -- RESULTAT: - - Deixa els blobs resultants del filtrat a destination -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: Filter -- FUNCTIONALITY: Get some blobs from the class based on conditions on measures - 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 -- 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 -- 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 - -{ - // 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 -- 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). -- RESULTAT: - - Deixa els blobs resultants del filtrat a destination -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/** -- FUNCTION: Filter (const version) -- FUNCTIONALITY: Get some blobs from the class based on conditions on measures - 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 -- 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 -- 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*/) - -{ - 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 -{ - 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 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= 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= 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 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 -- RESULTAT: -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/* -- FUNCTION: GetBlob -- FUNCTIONALITY: Gets the n-th blob (without ordering the blobs) -- PARAMETERS: - - indexblob: index in the blob array -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -CBlob CBlobResult::GetBlob(int indexblob) const -{ - if( indexblob < 0 || indexblob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); - - return *m_blobs[indexblob]; -} -CBlob *CBlobResult::GetBlob(int indexblob) -{ - if( indexblob < 0 || indexblob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); - - 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 -- 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) -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/* -- 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 -- 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 -{ - // 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() ); - - 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 -- RESTRICCIONS: -- AUTOR: Ricard Borràs Navarra -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/* -- FUNCTION: ClearBlobs -- FUNCTIONALITY: Clears all the blobs from the object and releases all its memory -- PARAMETERS: -- RESULT: -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -void CBlobResult::ClearBlobs() -{ - 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 -- PARÀMETRES: - - 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. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/* -- FUNCTION: RaiseError -- FUNCTIONALITY: Error handling function -- PARAMETERS: - - errorCode: reason of the error -- RESULT: - - in _SHOW_ERRORS version, shows a message box with the error. In release is silent. - In both cases throws an exception with the error. -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -void CBlobResult::RaiseError(const int errorCode) const -{ -//! Do we need to show errors? -#ifdef _SHOW_ERRORS - CString msg, format = "Error en CBlobResult: %s"; - - switch (errorCode) - { - case EXCEPTION_BLOB_OUT_OF_BOUNDS: - msg.Format(format, "Intentant accedir a un blob no existent"); - break; - default: - msg.Format(format, "Codi d'error desconegut"); - break; - } - - AfxMessageBox(msg); - -#endif - throw errorCode; -} - - - -/************************************************************************** - Auxiliars / Auxiliary functions -**************************************************************************/ - - -/** -- FUNCIÓ: PrintBlobs -- 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 -- RESULTAT: -- RESTRICCIONS: -- AUTOR: Ricard Borràs -- DATA DE CREACIÓ: 25-05-2005. -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -/* -- FUNCTION: PrintBlobs -- FUNCTIONALITY: Prints some blob features in an ASCII file -- PARAMETERS: - - 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 -{ - 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\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/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h deleted file mode 100644 index a218c8b3..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h +++ /dev/null @@ -1,171 +0,0 @@ -/************************************************************************ - BlobResult.h - -FUNCIONALITAT: Definició de la classe CBlobResult -AUTOR: Inspecta S.L. -MODIFICACIONS (Modificació, Autor, Data): - -FUNCTIONALITY: Definition of the CBlobResult class -AUTHOR: Inspecta S.L. -MODIFICATIONS (Modification, Author, Date): - -**************************************************************************/ - - -#if !defined(_CLASSE_BLOBRESULT_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "BlobLibraryConfiguration.h" -#include -#include - -#ifdef MATRIXCV_ACTIU - #include "matrixCV.h" -#else - // llibreria STL - #include "vector" - //! Vector de doubles - typedef std::vector double_stl_vector; -#endif - -#include // vectors de la STL -#include -#include "blob.h" -#include "BlobOperators.h" -#include "ComponentLabeling.h" -/************************************************************************** - 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 -{ -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(IplImage *source, IplImage *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 ); - -#ifdef MATRIXCV_ACTIU - //! Calcula un valor sobre tots els blobs de la classe retornant una MatrixCV - //! Computes some property on all the blobs of the class - double_vector GetResult( funcio_calculBlob *evaluador ) const; -#endif - //! Calcula un valor sobre tots els blobs de la classe retornant un std::vector - //! 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; - -protected: - - //! Vector amb els blobs - //! Vector with all the blobs - Blob_vector m_blobs; -}; - -#endif // !defined(_CLASSE_BLOBRESULT_INCLUDED) diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp deleted file mode 100644 index 5aff3125..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp +++ /dev/null @@ -1,630 +0,0 @@ - -#include "ComponentLabeling.h" - -#include -#include -#include -#include - -//! Conversion from freeman code to coordinate increments (counterclockwise) -static const CvPoint freemanCodeIncrement[8] = - { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} }; - - - -/** -- FUNCIÓ: -- FUNCIONALITAT: -- PARÀMETRES: - - -- RESULTAT: - - -- RESTRICCIONS: - - -- AUTOR: rborras -- DATA DE CREACIÓ: 2008/04/29 -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -inline unsigned char GET_ABOVE_IMAGEPIXEL( unsigned char *currentPixel, IplImage *image ) -{ - return *(currentPixel - image->widthStep); -} -inline unsigned char GET_BELOW_IMAGEPIXEL( unsigned char *currentPixel, IplImage *image ) -{ - return *(currentPixel + image->widthStep); -} - - - -inline unsigned char GET_IMAGE_PIXEL( IplImage *image, CvPoint p ) -{ - return *(image->imageData + p.x + p.y *image->widthStep); -} - -inline bool GET_IMAGEMASK_PIXEL( IplImage *mask, CvPoint p ) -{ - if( mask != NULL ) - return ((unsigned char)*(mask->imageData + p.x + p.y *mask->widthStep)) > 0; - else - return true; -} -inline bool GET_BELOW_VISITEDPIXEL( bool *currentPixel, int 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( CvPoint p, t_labelType *labels, int imageWidth, int newLabel ) -{ - *(labels + p.y * imageWidth + p.x) = newLabel; -} - - -inline void ASSIGN_VISITED( CvPoint p, bool *visitedPoints, int imageWidth ) -{ - *(visitedPoints + p.y * imageWidth + p.x) = true; -} - -/** -- FUNCIÓ: ComponentLabeling -- 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 -- 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 -*/ -bool ComponentLabeling( IplImage* inputImage, - IplImage* 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; - CvSize imageSizes; - CvPoint currentPoint; - - // verify input image - if( !CV_IS_IMAGE( inputImage ) ) - return false; - - // verify that input image and mask image has same size - if( maskImage ) - { - if( !CV_IS_IMAGE(maskImage) || - maskImage->width != inputImage->width || - maskImage->height != inputImage->height ) - return false; - } - - imageSizes = cvSize(inputImage->width,inputImage->height); - - imageWidth = inputImage->width; - imageHeight = inputImage->height; - - // create auxiliary buffers that are initialized to 0 - t_labelType *labelledImage = (t_labelType*)calloc(inputImage->width * inputImage->height, sizeof(t_labelType)); - bool *visitedPoints = (bool*)calloc(inputImage->width * inputImage->height, 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 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 = [](const IplImage * const & image, const int &row, const int &column) - { - return (unsigned char*)image->imageData + row * image->widthStep + 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 lock(foregroundPointAccessMutex); - foregroundPoints.emplace_back(pointX, pointY); - } - } - }; - - // start one parallel thread for each region - std::vector> 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->widthStep + column; - }; - - auto getImageDataLabelled = [&](const int &row, const int &column) - { - return labelledImage + row * inputImage->widthStep + 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 = cvPoint(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 = cvPoint(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; -} - -/* Original code */ -/* -bool ComponentLabeling(IplImage* inputImage, - IplImage* maskImage, - unsigned char backgroundColor, - Blob_vector &blobs) -{ - int i, j; - // row major vector with visited points - bool *visitedPoints, *pVisitedPoints, internalContour, externalContour; - unsigned char *pInputImage, *pMask, *pAboveInputImage, *pBelowInputImage, - *pAboveMask, *pBelowMask; - int imageWidth, imageHeight, currentLabel, contourLabel; - // row major vector with labelled image - t_labelType *labelledImage, *pLabels; - //! current blob pointer - CBlob *currentBlob; - CvSize imageSizes; - CvPoint currentPoint; - - // verify input image - if (!CV_IS_IMAGE(inputImage)) - return false; - - // verify that input image and mask image has same size - if (maskImage) - { - if (!CV_IS_IMAGE(maskImage) || - maskImage->width != inputImage->width || - maskImage->height != inputImage->height) - return false; - } - else - { - pMask = NULL; - pAboveMask = NULL; - pBelowMask = NULL; - } - - imageSizes = cvSize(inputImage->width, inputImage->height); - - imageWidth = inputImage->width; - imageHeight = inputImage->height; - - // create auxiliary buffers - labelledImage = (t_labelType*)malloc(inputImage->width * inputImage->height * sizeof(t_labelType)); - visitedPoints = (bool*)malloc(inputImage->width * inputImage->height * sizeof(bool)); - - // initialize it to 0 - memset(labelledImage, 0, inputImage->width * inputImage->height * sizeof(t_labelType)); - memset(visitedPoints, false, inputImage->width * inputImage->height * sizeof(bool)); - - // initialize pointers and label counter - pLabels = labelledImage; - pVisitedPoints = visitedPoints; - currentLabel = 1; - - for (j = 0; j < imageHeight; j++) - { - // don't verify if we area on first or last row, it will verified on pointer access - pAboveInputImage = (unsigned char*)inputImage->imageData + (j - 1) * inputImage->widthStep; - pBelowInputImage = (unsigned char*)inputImage->imageData + (j + 1) * inputImage->widthStep; - - pInputImage = (unsigned char*)inputImage->imageData + j * inputImage->widthStep; - - if (maskImage) - { - pMask = (unsigned char*)maskImage->imageData + j * maskImage->widthStep; - // don't verify if we area on first or last row, it will verified on pointer access - pAboveMask = (unsigned char*)maskImage->imageData + (j - 1) * maskImage->widthStep; - pBelowMask = (unsigned char*)maskImage->imageData + (j + 1) * maskImage->widthStep; - - } - - for (i = 0; i < imageWidth; i++, pInputImage++, pMask++, pAboveInputImage++, pBelowInputImage++, - pAboveMask++, pBelowMask++) - { - // ignore background pixels or 0 pixels in mask - if ((*pInputImage == backgroundColor) || (maskImage && *pMask == 0)) - { - pLabels++; - pVisitedPoints++; - continue; - } - - // new external contour: current label == 0 and above pixel is background - if (j > 0) - { - externalContour = ((*pAboveInputImage == backgroundColor) || - (maskImage && *pAboveMask == 0)) && - (*pLabels == 0); - } - else - externalContour = (*pLabels == 0); - - // new internal contour: below pixel is background and not visited - if (!externalContour && j < imageHeight - 1) - { - internalContour = *pBelowInputImage == backgroundColor && - !GET_BELOW_VISITEDPIXEL(pVisitedPoints, imageWidth); - } - else - { - internalContour = false; - } - - - if (externalContour) - { - currentPoint = cvPoint(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 = cvPoint(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); - } - - } - - pLabels++; - pVisitedPoints++; - - } - } - - - // free auxiliary buffers - free(labelledImage); - free(visitedPoints); - - return true; -} -*/ - -/** -- FUNCIÓ: -- FUNCIONALITAT: -- PARÀMETRES: - - -- RESULTAT: - - -- RESTRICCIONS: - - -- AUTOR: rborras -- DATA DE CREACIÓ: 2008/04/29 -- MODIFICACIÓ: Data. Autor. Descripció. -*/ -void contourTracing( IplImage *image, - IplImage *maskImage, - CvPoint contourStart, t_labelType *labels, bool *visitedPoints, t_labelType label, - bool internalContour, unsigned char backgroundColor, CBlobContour *currentBlobcontour ) -{ - CvPoint 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->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->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->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ó. -*/ -CvPoint tracer( IplImage *image, IplImage *maskImage, CvPoint P, bool *visitedPoints, - short initialMovement, - unsigned char backgroundColor, short &movement ) -{ - int d; - CvPoint 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->width || - pNext.y < 0 || pNext.y >= image->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->width ); - } - } - - // no possible movement was found - movement = -1; - pNext.x = P.x; - pNext.y = P.y; - - return pNext; -} - - diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h deleted file mode 100644 index d6e714e6..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h +++ /dev/null @@ -1,30 +0,0 @@ -#if !defined(_COMPONENT_LABELING_H_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED - -#include "vector" -#include "BlobContour.h" -#include "blob.h" - - -//! definició de que es un vector de blobs -typedef std::vector Blob_vector; - - - -bool ComponentLabeling( IplImage* inputImage, - IplImage* maskImage, - unsigned char backgroundColor, - Blob_vector &blobs ); - - -void contourTracing( IplImage *image, IplImage *mask, CvPoint contourStart, t_labelType *labels, - bool *visitedPoints, t_labelType label, - bool internalContour, unsigned char backgroundColor, - CBlobContour *currentBlobContour ); - -CvPoint tracer( IplImage *image, IplImage *mask, CvPoint P, bool *visitedPoints, - short initialMovement, - unsigned char backgroundColor, short &movement ); - - -#endif //!_CLASSE_BLOBRESULT_INCLUDED diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp deleted file mode 100644 index fd197466..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp +++ /dev/null @@ -1,706 +0,0 @@ -/************************************************************************ - 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): - -**************************************************************************/ - - -#include "blob.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; -} -CBlob::CBlob( t_labelType id, CvPoint startPoint, CvSize 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 ) -{ - m_storage = NULL; - *this = src; -} - -CBlob::CBlob( const CBlob *src ) -{ - if (src != NULL ) - { - m_storage = NULL; - *this = *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; -} - -CBlob::~CBlob() -{ - ClearContours(); - - if( m_storage ) - cvReleaseMemStorage( &m_storage ); -} - -void CBlob::ClearContours() -{ - t_contourList::iterator it; - - it = m_internalContours.begin(); - - while (it != m_internalContours.end()) - { - (*it).ResetChainCode(); - it++; - } - m_internalContours.clear(); - - m_externalContour.ResetChainCode(); - -} -void CBlob::AddInternalContour( const CBlobContour &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; -} - -/** -- FUNCIÓ: 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; -} - -/** -- 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; - - perimeter = m_externalContour.GetPerimeter(); - - 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 -- 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 */) -{ - 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 -- 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 -*/ -double CBlob::ExternPerimeter( IplImage *maskImage, bool xBorder /* = true */, bool yBorder /* = true */) -{ - t_PointList externContour, externalPoints; - CvSeqReader reader; - CvSeqWriter writer; - CvPoint 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 neighbours 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; -} - -/** -- FUNCIÓ: Mean -- FUNCIONALITAT: Get blob mean color in input image -- PARÀMETRES: - - 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 ) -{ - // 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; - CvPoint 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(), CV_RGB(255,255,255), CV_RGB(255,255,255),0, CV_FILLED, 8, - offset ); - - // draw internal contours - t_contourList::iterator it = m_internalContours.begin(); - while(it != m_internalContours.end() ) - { - cvDrawContours( mask, (*it).GetContourPoints(), CV_RGB(0,0,0), CV_RGB(0,0,0),0, CV_FILLED, 8, - 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 ) -{ - // 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; - CvPoint 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ó. -- NOTA: Calculation is made using second order moment aproximation -*/ -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); - } - 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 -- PARAMETERS: - - imatge: where to paint - - color: colour to paint the blob -- RESULT: - - 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*/) -{ - 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 -- RESULT: - - true if no error ocurred -- RESTRICTIONS: -- AUTHOR: Ricard Borràs -- CREATION DATE: 25-05-2005. -- MODIFICATION: Date. Author. Description. -*/ -t_PointList CBlob::GetConvexHull() -{ - CvSeq *convexHull = NULL; - - if( m_externalContour.GetContourPoints() ) - convexHull = cvConvexHull2( m_externalContour.GetContourPoints(), m_storage, - CV_COUNTER_CLOCKWISE, 1 ); - - return convexHull; -} - -/** -- FUNCTION: JoinBlob -- FUNCTIONALITY: Add's external contour to current external contour -- PARAMETERS: - - blob: blob from which extract the added external contour -- RESULT: - - 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 ) -{ - 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 ); - -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h deleted file mode 100644 index e4c80f83..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h +++ /dev/null @@ -1,172 +0,0 @@ -/************************************************************************ - 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 -AUTHOR: Inspecta S.L. -MODIFICATIONS (Modification, Author, Date): - -**************************************************************************/ - -//! Disable warnings referred to 255 character truncation for the std:map -#pragma warning( disable : 4786 ) - -#ifndef CBLOB_INSPECTA_INCLUDED -#define CBLOB_INSPECTA_INCLUDED - -#include -#include "BlobLibraryConfiguration.h" -#include "BlobContour.h" - - -#ifdef BLOB_OBJECT_FACTORY - //! Object factory pattern implementation - #include "..\inspecta\DesignPatterns\ObjectFactory.h" -#endif - - -//! Type of labelled images -typedef unsigned int t_labelType; - - -//! Blob class -class CBlob -{ - typedef std::list t_contourList; - -public: - CBlob(); - CBlob( t_labelType id, CvPoint startPoint, CvSize 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 - CvSize m_originalImageSize; -}; - -#endif //CBLOB_INSPECTA_INCLUDED diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp deleted file mode 100644 index 01df0085..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "IDetector.h" - -#include "helper/CvHelper.h" -template - -std::vector IDetector::convertBlobPosesToFishPoses(std::vector blobPoses) -{ - std::vector 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/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h deleted file mode 100644 index 722b937e..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "Model/TrackedComponents/pose/FishPose.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include "Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h" - -template -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 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 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 convertBlobPosesToFishPoses(std::vector 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; - - /** - * 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; - } - -private: - virtual std::vector findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) = 0; - -protected: - IModelAreaDescriptor* _areaInfo; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp deleted file mode 100644 index aa7d449b..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "BlobPose.h" - -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(void) -{ -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h deleted file mode 100644 index 4ebaf7b5..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include - -class BlobPose -{ -public: - /** - * 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 standard destructor. - */ - ~BlobPose(void); - - /** - * 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 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 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; } - - /** - * 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; } - -private: - bool _used; - cv::Point2f _center_cm; - cv::Point _center_px; - float _angle_degree; - float _width; - float _height; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp deleted file mode 100644 index 731aaa2a..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "BlobsDetector.h" -#include "helper/CvHelper.h" - -#include -BlobsDetector::BlobsDetector(void) : - _mask(nullptr), - _minBlobSize(1), //TODO Min blob size - _maxBlobSize(99999) //TODO Max blob size -{} - - -void BlobsDetector::filterBlobsBySize(CBlobResult& blobs) -{ - //std::cout << "start blobs: " << blobs.GetNumBlobs() << std::endl; - // blobs smaller than the provided blob size - blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER_OR_EQUAL, minBlobSize()); - //std::cout << "min filtered blobs: " << blobs.GetNumBlobs() << " min: " << minBlobSize() << std::endl; - // blobs bigger than the provided blob size - blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_LESS_OR_EQUAL, maxBlobSize()); - //std::cout << "max filtered blobs: " << blobs.GetNumBlobs() << " max: " << maxBlobSize() << std::endl; -} - -bool isLeft(CvPoint a, CvPoint b, CvPoint c) { - return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0; -} - -std::vector BlobsDetector::findBlobs(const cv::Mat& processedImage, const cv::Mat& oriImage) -{ - std::vector blobPoses; - - IplImage iplBinImage(processedImage); - IplImage *img = 0; - if (_mask) - img = new IplImage(*_mask); - - CBlob *currentBlob; - CBlobResult blobs(&iplBinImage, img, 0); - delete img; - - // filter the blobs by size criteria - filterBlobsBySize(blobs); - - 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); - - // apply homography - cv::Point2f blobPose_cm =_areaInfo->pxToCm(blobPose_px); - - // ignore blobs outside the tracking area - if (!_areaInfo->inTrackingArea(blobPose_px)) - continue; - /* - CBlobContour * contour = currentBlob->GetExternalContour(); - t_PointList externContour = contour->GetContourPoints(); - CvMemStorage storage; - CvPoint actualPoint, previousPoint; - CvSeqReader reader; - cvStartReadSeq(externContour, &reader); - - // which contour pixels touch border? - for (int j = 0; j < externContour->total; j++) - { - CV_READ_SEQ_ELEM(actualPoint, reader); - if (j == 0) previousPoint = actualPoint; - //std::cout << actualPoint.x << "/" << actualPoint.y << std::endl; - //std::cout << isLeft(CvPoint a, CvPoint b, actualPoint) << std::endl; - - previousPoint = actualPoint; - }*/ - - 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); - //std::cout << "angle: " << blobPose_angle_deg << std::endl; - 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)); - } - - return blobPoses; -} - -std::vector 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; - } -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h deleted file mode 100644 index 22b82fa4..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h" - -#include "Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h" -#include "Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h" - -class BlobsDetector : public 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. - */ - BlobsDetector(void); - - virtual ~BlobsDetector(void) {} - - void setMask(cv::Mat *mask) { _mask = mask; } - - std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - - - 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; }; - -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 findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - double _minBlobSize; - double _maxBlobSize; - - cv::Mat *_mask; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp deleted file mode 100644 index 0faf91b7..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "SimpleBlobsDetector.h" -#include "helper/CvHelper.h" -#include - -SimpleBlobsDetector::SimpleBlobsDetector(void) : _mask(nullptr) -{ - initParams(); -} - -void SimpleBlobsDetector::initParams() -{ - _params.minThreshold = 15;//SystemProperty::instance().getValueOfParam(TRACKERPARAM::THRESHOLD_BINARIZING); - _params.maxThreshold = 50;//SystemProperty::instance().getValueOfParam(TRACKERPARAM::THRESHOLD_BINARIZING); // THRESHOLD_BINARIZING=30 - _params.thresholdStep = 5; - - _params.filterByArea = true; - // blobs bigger than the provided blob size - _params.minArea = 1;//SystemProperty::instance().getValueOfParam(TRACKERPARAM::MIN_BLOB_SIZE); - _params.maxArea = 999999;//SystemProperty::instance().getValueOfParam(TRACKERPARAM::MAX_BLOB_SIZE); - - //_params.filterByConvexity = true; - //_params.minConvexity = SystemProperty::instance().getValueOfParam(TRACKERPARAM::MIN_BLOB_SIZE); - //_params.maxConvexity = SystemProperty::instance().getValueOfParam(TRACKERPARAM::MAX_BLOB_SIZE); - - _params.filterByInertia = false; - //_params.minInertiaRatio = 0.0f; - //_params.maxInertiaRatio = 1.0f; - - _params.filterByColor = true; - _params.blobColor = 255; - - _params.filterByCircularity = false; - - _params.minDistBetweenBlobs = 0; //std::numeric_limits::min(); -} - - -std::vector SimpleBlobsDetector::findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) -{ - std::vector blobPoses; - - std::vector keyPoints; - - cv::Ptr blobDetector = cv::SimpleBlobDetector::create(_params); - - blobDetector->detect( binImage, keyPoints); - - 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); - - // apply homography - cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); - - if (!_areaInfo->inTrackingArea(blobPose_px)) - continue; - - 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)); - } - - /*std::cout << keyPoints.size() << std::endl; - - cv::drawKeypoints( processedImage, keyPoints, out, CV_RGB(255,0,0),cv::DrawMatchesFlags::DEFAULT);*/ - - /*approxContours.resize( contours.size() ); - - for( int i = 0; i < contours.size(); ++i ) - { - cv::approxPolyDP( cv::Mat(contours[i]), approxContours[i], 4, 1 ); - cv::drawContours( out, contours, i, CV_RGB(rand()&255, rand()&255, rand()&255) ); - cv::drawContours( out, approxContours, i, CV_RGB(rand()&255, rand()&255, rand()&255) ); - }*/ - - return blobPoses; -} - - -std::vector 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; - } -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h deleted file mode 100644 index 7946f10e..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h" - -#include "Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h" -#include "Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h" - -#include "opencv2/features2d/features2d.hpp" -#include "opencv2/objdetect/objdetect.hpp" - -class SimpleBlobsDetector : public IDetector -{ -public: - - /** - * The contructor with parameters. - */ - SimpleBlobsDetector(void); - - virtual ~SimpleBlobsDetector(void) {} - - void setMask(cv::Mat *mask) { _mask = mask; } - - std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - - 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 findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp deleted file mode 100644 index cd65b94f..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "ContourPose.h" - -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(void) -{ -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h deleted file mode 100644 index 4e7e3da2..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include - -class ContourPose -{ -public: - /** - * 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 standard destructor. - */ - ~ContourPose(void); - - /** - * 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 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 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; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp deleted file mode 100644 index 3b2fa8d8..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "ContoursDetector.h" -#include "helper/CvHelper.h" - -std::vector ContoursDetector::findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) -{ - std::vector contourPoses; - - return contourPoses; -} - -std::vector ContoursDetector::findContours(const cv::Mat& binImage, const cv::Mat& oriImage) -{ - return findBlobs(binImage,oriImage); -} - -void ContoursDetector::createMask(std::vector points) -{} -// if (_xRes == 0 || _yRes == 0) -// return; -// -// mask = cvCreateImage(cvSize(_xRes, _yRes), IPL_DEPTH_8U,1);//erstellt schwarzweiß bild -// -// //folgender Block setzt die Pixel schwarz -// for( int y=0; yheight; y++ ) { -// uchar* ptr = (uchar*) ( mask->imageData + y * mask->widthStep ); -// for( int x=0; xwidth; x++ ) { -// ptr[x+2] = 0; -// } -// } -// -// CvPoint maskPoints[4]; -// -// for(int z=0;z<4;z++) -// { -// maskPoints[z] = points[z]; -// } -// -// //Array im Array von Polygonen. Hier Größe eins, da nur eins erzeugt wird -// CvPoint* contours[1]={ -// maskPoints, -// }; -// -// //Anzahl der Punkte der Polygone. Anzahl wie oben -// int contours_n[1]={ -// 4, -// }; -// -// //opencv Funktion zum erstellen und ausfüllen eines polygons in weiss -// cvFillPoly(mask, contours, contours_n, 1, cvScalar(255)); -// -// //Visualisierung zum Debuggen -// //cvNamedWindow("MyWindow",CV_WINDOW_AUTOSIZE); -// //cvShowImage("MyWindow", mask); -// //cvWaitKey(0); -// //cvReleaseImage(&mask); -// //cvDestroyWindow("MyWindow"); -//} - - -std::vector 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; -} \ No newline at end of file diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h deleted file mode 100644 index ecd46d54..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h" - -#include "Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h" - -class ContoursDetector : public IDetector -{ -public: - - /** - * The contructor with parameters. - */ - ContoursDetector(void) {} - - ~ContoursDetector(void) {} - - std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - - 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 findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - std::vector findContours(const cv::Mat& binImage, const cv::Mat& oriImage); - - void createMask(std::vector points); - - cv::Mat _mask; -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp deleted file mode 100644 index bb9c66b3..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ /dev/null @@ -1,219 +0,0 @@ -#include "ImagePreProcessor.h" - -#include - -#include -#include - -QMutex bgsMutex; -QMutex oriImageMutex; -QMutex initBgkFrameNumMutex; -QMutex mog2Mutex; - -ImagePreProcessor::ImagePreProcessor(TrackerParameter* p_TrackingParameter) : - _maxBackgroundImageInitTime(0), //BG_MOG2_INIT_FRAME_NUMBER TODO - _bkgSubMethodMog2(false) -{ - _TrackingParameter = p_TrackingParameter; - init(); -} - -ImagePreProcessor::~ImagePreProcessor(void) -{ -} - -void ImagePreProcessor::setBkgFrameNum(int frameNum) -{ - QMutexLocker locker(&initBgkFrameNumMutex); - _maxBackgroundImageInitTime = frameNum; -} - -int ImagePreProcessor::getBkgFrameNum() -{ - QMutexLocker locker(&initBgkFrameNumMutex); - return _maxBackgroundImageInitTime; -} - - -void ImagePreProcessor::init() -{ - QMutexLocker locker(&bgsMutex); - - m_backgroundImage = std::make_shared(); - m_foregroundImage = std::make_shared(); - - _pMOG = cv::createBackgroundSubtractorMOG2( - _TrackingParameter->getmog2History(), - _TrackingParameter->getmog2VarThresh(), - true); //Shadow detection - - _backgroundSubtractionEnabled = true; - _backgroundEnabled = true; - _erodeEnabled = true; - _dilateEnabled = true; - _gaussianBlurEnabled = false; - _binarizeEnabled = true; - _resetBackgroundImageEnabled = false; -} - -cv::Mat ImagePreProcessor::binarize(cv::Mat& image) -{ - //cv::cvtColor( image, grayImage, CV_BGR2GRAY ); - - cv::Mat binarizedImage; - - if (image.channels() >= 3) - cv::cvtColor(image, binarizedImage, CV_BGR2GRAY); - else - image.copyTo(binarizedImage); - - if (binarizedImage.data) - cv::threshold(binarizedImage, binarizedImage, m_TrackingParameter->getBinarizationThreshold(), 255, cv::THRESH_BINARY); - - return binarizedImage; -} - -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 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 ImagePreProcessor::backgroundSubtraction(cv::Mat& image) -{ - if (false)//(isEnabledMog2()) - { - //QMutexLocker locker(&bgsMutex); - cv::Mat fgMaskMOG; - _pMOG->setBackgroundRatio(m_TrackingParameter->getmog2BackgroundRatio()); - - _pMOG->apply(image, fgMaskMOG); //fg mask generated by MOG method - _pMOG->getBackgroundImage(*m_backgroundImage); - return fgMaskMOG; - } - - // otherwise, custom background subtraction - - if (!m_backgroundImage->data) - image.copyTo(*m_backgroundImage); - - // calculate the image difference - const double alpha = m_TrackingParameter->getmog2BackgroundRatio(); - - const int &imageWidth = m_backgroundImage->cols; - const int &imageHeight = m_backgroundImage->rows; - const int totalRegionsX = 4; - const int totalRegionsY = 4; - const int totalRegions = totalRegionsX * totalRegionsY; - const int regionWidth = imageWidth / totalRegionsX; - const int regionHeight = imageHeight / totalRegionsY; - - cv::Mat results(imageHeight, imageWidth, image.type()); - - auto workOnRegion = [&](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_backgroundImage)(subArea); - cv::Mat subImage = image(subArea); - cv::Mat subResults = results(subArea); - - subResults = (subBackground - subImage); - subBackground = (1.0 - alpha) * subBackground + alpha * subImage; - }; - - std::vector> 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(); - - return results; -} - -std::map> ImagePreProcessor::preProcess(std::shared_ptr p_image) -{ - std::shared_ptr greyMat = std::make_shared(); - std::shared_ptr binarizedImage = std::make_shared(); - std::shared_ptr erodedImage = std::make_shared(); - std::shared_ptr dilatedImage = std::make_shared(); - //cv::Mat test; - - cv::cvtColor(*p_image, *greyMat, CV_BGR2GRAY); - //cv::cvtColor(*p_image, test, CV_BGR2GRAY); - - // 1. step: do the background subtraction - *m_foregroundImage = backgroundSubtraction(*greyMat); - - // 2. step: binarize the image - *binarizedImage = binarize(*m_foregroundImage); - - // 3. step: erode the image - *erodedImage = erode(*binarizedImage); - - // 4. step: dilate the image - *dilatedImage = dilate(*erodedImage); - - std::map> all; - all.insert(std::pair>(std::string("Greyscale"), greyMat)); - all.insert(std::pair>(std::string("Background"), m_backgroundImage)); - all.insert(std::pair>(std::string("Difference"), m_foregroundImage)); - all.insert(std::pair>(std::string("Binarized"), binarizedImage)); - all.insert(std::pair>(std::string("Eroded"), erodedImage)); - all.insert(std::pair>(std::string("Dilated"), dilatedImage)); - - return all; -} - -void ImagePreProcessor::resetBackgroundImage() -{ - // this will reset the background at the next opportunity - init(); -} - -bool ImagePreProcessor::isEnabledMog2() -{ - return _bkgSubMethodMog2; -} - -void ImagePreProcessor::setEnabledMog2(bool enable) -{ - QMutexLocker locker(&mog2Mutex); - _bkgSubMethodMog2 = enable; -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h deleted file mode 100644 index a0011b2e..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include - - -#include - -#include "helper/StringHelper.h" -#include "Model/TrackerParameter.h" - - -class ImagePreProcessor -{ -public: - - /** - * The standard constructor. - */ - ImagePreProcessor(TrackerParameter* p_TrackingParameter); - - /** - * The standard destructor. - */ - ~ImagePreProcessor(void); - - /** - * Init function. Sets the property for the imge pre-processing. - * @return void. - */ - void init(); - - /** - * A computer vision method to binarize an image. - * @param: image, image to binarize, - * @return: a binarized image. - */ - cv::Mat binarize(cv::Mat& image); - - /** - * 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> preProcess(std::shared_ptr p_image); - - /** - * The method updates the image background. - * @return: void. - */ - void resetBackgroundImage(); - TrackerParameter* m_TrackingParameter; - -private: - - - cv::Mat _outputImage; - - int m_Mog2ShadowDetection = true; - std::shared_ptr m_backgroundImage; - std::shared_ptr m_foregroundImage; - - // background subtraction - cv::Ptr _pMOG; - - //parameters for image pre-processing - bool _backgroundSubtractionEnabled; - bool _backgroundEnabled; - bool _binarizeEnabled; - bool _erodeEnabled; - bool _dilateEnabled; - bool _gaussianBlurEnabled; - bool _resetBackgroundImageEnabled; - - int _maxBackgroundImageInitTime; - bool _bkgSubMethodMog2; - - TrackerParameter* _TrackingParameter; - - // functions - void setBkgFrameNum(int); - int getBkgFrameNum(); - - void setEnabledMog2(bool); - bool isEnabledMog2(); -}; diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/null_Model.cpp b/BioTracker/Plugin/BackgroundSubtraction/Model/null_Model.cpp deleted file mode 100644 index db2793d0..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/null_Model.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "null_Model.h" - -null_Model::null_Model() -{ - -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/Model/null_Model.h b/BioTracker/Plugin/BackgroundSubtraction/Model/null_Model.h deleted file mode 100644 index 8dabf466..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/Model/null_Model.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NULL_MODEL_H -#define NULL_MODEL_H - -#include "Interfaces/IModel/IModel.h" - -class null_Model : public IModel -{ - Q_OBJECT -public: - null_Model(); -}; - -#endif // NULL_MODEL_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/PluginContext.cpp b/BioTracker/Plugin/BackgroundSubtraction/PluginContext.cpp deleted file mode 100644 index 52fea1ff..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/PluginContext.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "PluginContext.h" - -#include "Controller/ControllerTrackingAlgorithm.h" -#include "Controller/ControllerTrackedComponent.h" - -PluginContext::PluginContext(QObject *parent) : - IBioTrackerContext(parent) -{ - QPointer< IController > ComponentController = new ControllerTrackedComponent(this, this, ENUMS::CONTROLLERTYPE::COMPONENT); - QPointer< IController > TrackingController = new ControllerTrackingAlgorithm(this, this, ENUMS::CONTROLLERTYPE::TRACKING); - - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMPONENT, ComponentController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKING, TrackingController); -} - -void PluginContext::createAppController() -{ - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->createComponents(); - } -} - -void PluginContext::connectController() -{ - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->connectComponents(); - } -} - - diff --git a/BioTracker/Plugin/BackgroundSubtraction/PluginContext.h b/BioTracker/Plugin/BackgroundSubtraction/PluginContext.h deleted file mode 100644 index aab040e7..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/PluginContext.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "Interfaces/IBioTrackerContext.h" -#include "Interfaces/IController/IController.h" - -class PluginContext : public IBioTrackerContext -{ - Q_OBJECT - -public: - PluginContext(QObject *parent = 0); - - // IBioTrackerContext interface -protected: - void createAppController() override; - void connectController() override; -}; - diff --git a/BioTracker/Plugin/BackgroundSubtraction/View/TrackedElementView.cpp b/BioTracker/Plugin/BackgroundSubtraction/View/TrackedElementView.cpp deleted file mode 100644 index 2703982e..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/View/TrackedElementView.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "TrackedElementView.h" -#include "Model/TrackedComponents/TrackedElement.h" -#include "Model/TrackedComponents/TrackedTrajectory.h" -#include "QBrush" -#include "QPainter" -#include "QGraphicsScene" -#include -#include "settings/Settings.h" -#include "Model/TrackingAlgorithm/ParamNames.h" -#include "util/misc.h" -#include "QDebug" - -class QGraphicsSceneHoverEvent; - -TrackedElementView::TrackedElementView(QGraphicsItem *parent, IController *controller, IModel *model) : - IViewTrackedComponent(parent, controller, model) -{ - TrackedElement *elem = dynamic_cast(getModel()); - _boundingRect = QRectF(0,0, 100, 100); -} - -void TrackedElementView::rcvDimensionUpdate(int x, int y) { - _boundingRect = QRectF(0, 0, x, y); - update(); -} - -QRectF TrackedElementView::boundingRect() const -{ - - return _boundingRect; -} - - -void TrackedElementView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - QGraphicsScene *scene = this->scene(); - - //Dev note: You could do some meaningful drawing here. - //So far, the core does everything we need. -} - -void TrackedElementView::getNotified() -{ - update(); -} - diff --git a/BioTracker/Plugin/BackgroundSubtraction/View/TrackedElementView.h b/BioTracker/Plugin/BackgroundSubtraction/View/TrackedElementView.h deleted file mode 100644 index 420fd769..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/View/TrackedElementView.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TRACKEDELEMENTVIEW_H -#define TRACKEDELEMENTVIEW_H - -#include "Interfaces/IView/IViewTrackedComponent.h" - -/** - * 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. - */ -class TrackedElementView : public IViewTrackedComponent -{ - Q_OBJECT -public: - 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; - - // IViewTrackedComponent interface -public Q_SLOTS: - void getNotified() override; - void rcvDimensionUpdate(int x, int y); - -public Q_SIGNAL: - void emitUpdateCornersChanged(int id, int relX, int relY); - -private: - QRectF _boundingRect; - -}; - -#endif // TRACKEDELEMENTVIEW_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.cpp b/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.cpp deleted file mode 100644 index 5c8ad730..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "TrackerParameterView.h" -#include "ui_TrackerParameterView.h" - -#include - -TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : - IViewWidget(parent, controller, model), - _ui(new Ui::TrackerParameterView) -{ - _ui->setupUi(this); - getNotified(); - - - QObject::connect(_ui->lineEdit_2_binThresh, SIGNAL(valueChanged(int)), this, SLOT(on_pushButton_clicked())); - QObject::connect(_ui->lineEdit_3_SizeErode, SIGNAL(valueChanged(int)), this, SLOT(on_pushButton_clicked())); - QObject::connect(_ui->lineEdit_4_SizeDilate, SIGNAL(valueChanged(int)), this, SLOT(on_pushButton_clicked())); - QObject::connect(_ui->lineEdit_8_MinBlob, SIGNAL(valueChanged(int)), this, SLOT(on_pushButton_clicked())); - QObject::connect(_ui->lineEdit_9MaxBlob, SIGNAL(valueChanged(int)), this, SLOT(on_pushButton_clicked())); - QObject::connect(_ui->lineEdit_7_MogBack, SIGNAL(valueChanged(double)), this, SLOT(on_pushButton_clicked())); - - _ui->pushButton->setVisible(false); -} - -TrackerParameterView::~TrackerParameterView() -{ - delete _ui; -} - -void TrackerParameterView::on_pushButtonResetBackground_clicked() { - TrackerParameter *parameter = qobject_cast(getModel()); - parameter->setResetBackground(true); -} - -void TrackerParameterView::on_comboBoxSendImage_currentIndexChanged(int v) { - TrackerParameter *parameter = qobject_cast(getModel()); - parameter->setSendImage(v); - parameter->setNewSelection(_ui->comboBoxSendImage->currentText().toStdString()); -} - - -void TrackerParameterView::on_pushButton_clicked() -{ - TrackerParameter *parameter = qobject_cast(getModel()); - - int setBinarizationThreshold = _ui->lineEdit_2_binThresh->text().toInt(); - int setSizeErode = _ui->lineEdit_3_SizeErode->text().toInt(); - int setSizeDilate = _ui->lineEdit_4_SizeDilate->text().toInt(); - int setmog2History = 0;// ui->lineEdit_5_MogHist->text().toInt(); - int setmog2VarThresh = 0;// ui->lineEdit_6_MogThresh->text().toInt(); - int setMinBlobSize = _ui->lineEdit_8_MinBlob->text().toInt(); - int setMaxBlobSize = _ui->lineEdit_9MaxBlob->text().toInt(); - - double setmog2BackgroundRatio = _ui->lineEdit_7_MogBack->value(); - - parameter->setAll(0, setBinarizationThreshold, setSizeErode, setSizeDilate, setmog2History, setmog2VarThresh, - setmog2BackgroundRatio, setMinBlobSize, setMaxBlobSize); - - Q_EMIT parametersChanged(); -} - -void TrackerParameterView::getNotified() -{ - TrackerParameter *parameter = qobject_cast(getModel()); - - int val = parameter->getBinarizationThreshold(); - _ui->lineEdit_2_binThresh->setValue(val); - - val = parameter->getSizeErode(); - _ui->lineEdit_3_SizeErode->setValue(val); - - val = parameter->getSizeDilate(); - _ui->lineEdit_4_SizeDilate->setValue(val); - - double dval = parameter->getmog2BackgroundRatio(); - _ui->lineEdit_7_MogBack->setValue(dval); - - val = parameter->getMinBlobSize(); - _ui->lineEdit_8_MinBlob->setValue(val); - - val = parameter->getMaxBlobSize(); - _ui->lineEdit_9MaxBlob->setValue(val); -} diff --git a/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.h b/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.h deleted file mode 100644 index 44296f02..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef TRACKERPARAMETERVIEW_H -#define TRACKERPARAMETERVIEW_H - -#include "Interfaces/IView/IViewWidget.h" -#include "Model/TrackerParameter.h" - -namespace Ui { - class TrackerParameterView; -} - -class TrackerParameterView : public IViewWidget -{ - Q_OBJECT - -public: - explicit TrackerParameterView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - ~TrackerParameterView(); - -private slots: - void on_pushButton_clicked(); - void on_pushButtonResetBackground_clicked(); - //void on_pushButtonNoFish_clicked(); - void on_comboBoxSendImage_currentIndexChanged(int v); - //void on_checkBoxNetwork_stateChanged(int v); - //void on_checkBoxBackground_stateChanged(int v); - //void on_checkBoxTrackingArea_stateChanged(int v); - - -public: - signals: - void trackingAreaType(int v); - void parametersChanged(); - -private: - Ui::TrackerParameterView *_ui; - - // IViewWidget interface -public slots: - - void getNotified(); -}; - -#endif // TRACKERPARAMETERVIEW_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.ui b/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.ui deleted file mode 100644 index 5fc284f2..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/View/TrackerParameterView.ui +++ /dev/null @@ -1,421 +0,0 @@ - - - TrackerParameterView - - - - 0 - 0 - 304 - 481 - - - - Form - - - false - - - - 6 - - - 0 - - - 9 - - - 0 - - - 0 - - - - - false - - - QFrame::NoFrame - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - - - true - - - - - 0 - 0 - 304 - 472 - - - - - 9 - - - 0 - - - - - - - #frame{color: #e5e5e5;} - - - QFrame::Box - - - QFrame::Plain - - - - 3 - - - 5 - - - 5 - - - 5 - - - 5 - - - - - Set the binarization threshold - - - - - - Binarization Threshold - - - - - - - Set the binarization threshold - - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Set the erosion size - - - - - - Size Erode - - - - - - - Set the erosion size - - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Set the dilation size - - - - - - Size Dilate - - - - - - - Set the dilation size - - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Set the background ratio - - - - - - Background Ratio - - - - - - - Set the background ratio - - - 6 - - - 1.000000000000000 - - - 0.001000000000000 - - - 0.001000000000000 - - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Set the minimal blob size - - - - - - Min Blob Size - - - - - - - Set the minimal blob size - - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Sets the maximum blob size - - - - - - Max Blob Size - - - - - - - Sets the maximum blob size - - - 10000 - - - - - - - - - - Set the parameters for the tracking plugin - - - Set Values - - - - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - Send Image: - - - - - - - Choose which image to display for the next frames. Tracking must be actived. - - - Original - - - - Original - - - - - Binarized - - - - - Eroded - - - - - Dilated - - - - - Difference - - - - - Background - - - - - - - - Reset the current background - - - Reset Background - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - diff --git a/BioTracker/Plugin/BackgroundSubtraction/biotrackerplugin_global.h b/BioTracker/Plugin/BackgroundSubtraction/biotrackerplugin_global.h deleted file mode 100644 index 770f7d21..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/biotrackerplugin_global.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef BIOTRACKERPLUGIN_GLOBAL_H -#define BIOTRACKERPLUGIN_GLOBAL_H - -#include - -#if defined(BIOTRACKERPLUGIN_LIBRARY) -# define BIOTRACKERPLUGINSHARED_EXPORT Q_DECL_EXPORT -#else -# define BIOTRACKERPLUGINSHARED_EXPORT Q_DECL_IMPORT -#endif - -#endif // BIOTRACKERPLUGIN_GLOBAL_H diff --git a/BioTracker/Plugin/BackgroundSubtraction/helper/CvHelper.cpp b/BioTracker/Plugin/BackgroundSubtraction/helper/CvHelper.cpp deleted file mode 100644 index 49d6565a..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/helper/CvHelper.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include "CvHelper.h" - -#include "helper/StringHelper.h" - -CvPoint CvHelper::subtractTwoCvPoints(CvPoint a, CvPoint b) -{ - return cvPoint(a.x - b.x, a.y - b.y); -} - -CvPoint CvHelper::addTwoCvPoints(CvPoint a, CvPoint b) -{ - return cvPoint(a.x + b.x, a.y + b.y); -} - -CvPoint CvHelper::multCvPoint(double scalar, CvPoint p) -{ - return cvPoint(scalar * p.x, scalar * p.y); -} - -QPointF CvHelper::norm(double x, double y) -{ - double distance = qSqrt(x * x + y * y); - - 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()); -} - -QPointF CvHelper::norm(QPointF p) -{ - 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) ) ); -} - -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))); -} - -double CvHelper::getSqDistance(double x1, double y1, double x2, double 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) -{ - 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()); -} - -double CvHelper::getDistance(QPointF p1, QPointF p2) -{ - 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); -} - -double CvHelper::getDistance(cv::Point3f p1, cv::Point3f p2) -{ - 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))); -} - -double CvHelper::getSqDistance(cv::Point2f p1, cv::Point2f p2) -{ - 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); -} - -double CvHelper::orientation(cv::Point2f front, cv::Point2f back) -{ - 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; -} - -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())); -} - -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 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::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::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 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 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); -// double cosT = ab / (a*b); -// return qAcos(cosT); -//} - -double CvHelper::getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos) { - return qAtan2(targetPos.x - currentPos.x, targetPos.y - currentPos.y); -} - -std::deque CvHelper::convertMat2Point2fDeque(cv::Mat mat) -{ - std::deque point2fS; - - if(mat.cols != 2) - return point2fS; - - for (int row = 0; row < mat.rows; row++) - { - float x = mat.at(row,0); - float y = mat.at(row,1); - point2fS.push_back(cv::Point2f(x,y)); - } - - return point2fS; -} - -cv::Mat CvHelper::convertPoint2fDeque2Mat(std::deque points) -{ - cv::Mat mat; - - if(points.empty()) - return mat; - - mat = cv::Mat(points.size(), 2, CV_32F); - - for (int i = 0; i < points.size(); i++) - { - cv::Point2f p = points.at(i); - mat.at(i,0)= p.x; - mat.at(i,1)= p.y; - } - - return mat; -} - -QList> CvHelper::convertMatList2Point2fDequeList(QList mats) -{ - QList> 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::Mat G = (cv::Mat_(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(0,0) = point2Mirror.x; - point2MirrorMat.at(0,1) = point2Mirror.y; - - cv::Mat pointOfOriginMat(1/*rows*/,2 /* cols */,CV_32F); - pointOfOriginMat.at(0,0) = pointOfOrigin.x; - pointOfOriginMat.at(0,1) = pointOfOrigin.y; - - cv::Mat point2MirrorFromOrigin = point2MirrorMat - pointOfOriginMat; - - cv::Mat point2MirrorMatT; - cv::transpose(point2MirrorFromOrigin, point2MirrorMatT); - - cv::Mat mirrowedPointMat = (G * point2MirrorMatT); - - cv::Mat mirrowedPointMatT; - cv::transpose(mirrowedPointMat, mirrowedPointMatT); - - cv::Mat finalMat = mirrowedPointMatT + pointOfOriginMat; - - return cv::Point2f(finalMat.at(0,0),finalMat.at(0,1)); -} - -std::deque CvHelper::getMirrowPoints(std::deque points2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad) -{ - std::deque 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 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 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); - - cv::Point2f front(xOff2,yOff2); - cv::Point2f back(xOff1,yOff1); - - std::deque points; - - points.push_back(front); - points.push_back(back); - return points; -} - - -std::vector CvHelper::convertMat2Vector(cv::Mat mat) -{ - std::vector value(mat.rows); - for (int i = 0; i < value.size(); i++) - { - cv::Point p((int)mat.at(i,0),(int)mat.at(i,1)); - value.at(i) = p; - } - return value; -} - -cv::Mat CvHelper::convertVector2Mat(std::vector vect) -{ - cv::Mat mat(vect.size(),2,CV_32F); - for (int i = 0; i < vect.size(); i++) - { - mat.at(i,0) = (float)vect.at(i).x; - mat.at(i,1) = (float)vect.at(i).y; - } - return mat; -} - -float CvHelper::degToRad(float deg) -{ - return deg * CV_PI / 180.0; -} - -float CvHelper::radToDeg(float rad) -{ - 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; -} - -float CvHelper::stdStringToFloat(std::string string) -{ - float numb; - std::istringstream iss(string); - if (!(iss >> numb)) - { - throw "String cannot convert to float number!"; - } - - return numb; -} - -std::string CvHelper::convertStdVectorCvPointToStdString(std::vector 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 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]; - - 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; - - int width = cvSize_value.width; - int height = cvSize_value.height; - - cvSizeString.append(StringHelper::iToSS(height)).append("x").append(StringHelper::iToSS(width)); - - return cvSizeString; -} - -std::string CvHelper::cvSize2fToSS(cv::Size2f cvSize2f_value) -{ - std::string cvSize2fString; - - float width = cvSize2f_value.width; - float height = cvSize2f_value.height; - - cvSize2fString.append(StringHelper::fToSS(height)).append("x").append(StringHelper::fToSS(width)); - - return cvSize2fString; -} - -std::string CvHelper::cvSize2fToSS(QString width, QString height) -{ - std::string cvSize2fString; - - cvSize2fString.append(height.toStdString()).append("x").append(width.toStdString()); - - return cvSize2fString; -} - -std::string CvHelper::getCurrentDatetimeAsStd() -{ - return QDateTime::currentDateTime().toString("_yyMMddThhmmss").toUtf8().constData(); -} - -bool CvHelper::isFrameSizeEqual(cv::Size o1, cv::Size o2) -{ - bool equal = false; - - if (o1.width == o2.width && o1.height == o2.height) - equal = true; - - return equal; -} \ No newline at end of file diff --git a/BioTracker/Plugin/BackgroundSubtraction/helper/CvHelper.h b/BioTracker/Plugin/BackgroundSubtraction/helper/CvHelper.h deleted file mode 100644 index c608a15d..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/helper/CvHelper.h +++ /dev/null @@ -1,197 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - - -/** - * Computer vision helper class, contains only static methods - */ -namespace CvHelper -{ - /** - * Subtract operation for two CvPoints. - * @return: the difference of the CvPoints. - */ - CvPoint subtractTwoCvPoints(CvPoint a, CvPoint b); - - /** - * Add operation for two CvPoints. - * @return: the sum of the CvPoints. - */ - CvPoint addTwoCvPoints(CvPoint a, CvPoint b); - - CvPoint multCvPoint(double scalar, CvPoint 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 getMirrowPoints(std::deque points2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad); - std::deque getMirrowLine(cv::Point2f pointOfOrigin, float width, float height, float angelAsGrad); - - - std::deque convertMat2Point2fDeque(cv::Mat mat); - cv::Mat convertPoint2fDeque2Mat(std::deque points); - QList> convertMatList2Point2fDequeList(QList mats); - std::vector convertMat2Vector(cv::Mat mat); - cv::Mat convertVector2Mat(std::vector 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 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/BioTracker/Plugin/BackgroundSubtraction/helper/StringHelper.cpp b/BioTracker/Plugin/BackgroundSubtraction/helper/StringHelper.cpp deleted file mode 100644 index 4f4b3f8d..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/helper/StringHelper.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "StringHelper.h" - -#include -#include - - -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; -} - - -bool StringHelper::startsWithDigit(std::string const &fullString) -{ - if(fullString.empty()) - return false; - - - if(isdigit(fullString.at(0))) - { - return true; - } - - return false; - -} - -bool StringHelper::startsWithDigitQ(QString fullString) -{ - 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; - } - - } - - return false; -} - -std::string StringHelper::iToSS(int int_num) -{ - 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"); -} - -std::string StringHelper::fToSS(float float_num) -{ - return QString::number(float_num).toUtf8().constData(); -} - - -std::string StringHelper::toStdString(QString qString) -{ - return qString.toUtf8().constData(); -} - -QString StringHelper::toQString(std::string stdString) -{ - 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; -} - -int StringHelper::split(std::string &txt, std::vector &strs, char ch) -{ - 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 ) ); - initialPos = pos + 1; - - pos = txt.find( ch, initialPos ); - } - - // Add the last one - 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/BioTracker/Plugin/BackgroundSubtraction/helper/StringHelper.h b/BioTracker/Plugin/BackgroundSubtraction/helper/StringHelper.h deleted file mode 100644 index 10f05d6a..00000000 --- a/BioTracker/Plugin/BackgroundSubtraction/helper/StringHelper.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include -#include -#include - -/** - * String handling helper class - */ -class StringHelper -{ -public: - 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); - - - static bool startsWithDigitQ(QString fullString); - static bool startsWithDigit(std::string const &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 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 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 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 &strs, char ch); -}; diff --git a/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.cpp b/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.cpp deleted file mode 100644 index 47bec0a0..00000000 --- a/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "BioTrackerPlugin.h" -#include "PluginContext.h" - -#include "Controller/ControllerTrackingAlgorithm.h" -#include "Controller/ControllerTrackedComponent.h" - -#include "util/singleton.h" -#include "settings/Settings.h" - -#include "View/TrackedElementView.h" -#include "TrackedComponents/TrackedComponentFactory.h" - -BioTrackerPlugin::BioTrackerPlugin() { -} - -IView* BioTrackerPlugin::getTrackerParameterWidget() { - return qobject_cast (m_TrackerController)->getTrackingParameterWidget(); -} -IView *BioTrackerPlugin::getTrackerElementsWidget() -{ - return qobject_cast (m_ComponentController)->getTrackingElementsWidget(); -} - -// forwards tracked component model to coreApp -IModel* BioTrackerPlugin::getTrackerComponentModel() { - return qobject_cast (m_ComponentController)->getModel(); -} - -IModelTrackedComponentFactory *BioTrackerPlugin::getComponentFactory() { - return new TrackedComponentFactory(); -} - -#if QT_VERSION < 0x050000 -Q_EXPORT_PLUGIN2(BioTrackerPlugin, BioTrackerPlugin) -#endif // QT_VERSION < 0x050000 - - -void BioTrackerPlugin::createPlugin() { - m_PluginContext = new PluginContext(); - m_PluginContext->createApplication(); - - IController * ctr = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - m_ComponentController = qobject_cast(ctr); - - IController * ctr2 = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::TRACKING); - m_TrackerController = qobject_cast(ctr2); - - connectInterfaces(); -} - -void BioTrackerPlugin::connectInterfaces() { - ControllerTrackingAlgorithm* ctrAlg = qobject_cast (m_TrackerController); - ControllerTrackedComponent* ctrTrC = qobject_cast (m_ComponentController); - - //controllertrackingalgorithm - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitCvMat, this, &BioTrackerPlugin::receiveCvMatFromController); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitTrackingDone, this, &BioTrackerPlugin::receiveTrackingDone); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitChangeDisplayImage, this, &BioTrackerPlugin::receiveChangeDisplayImage); - QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrAlg, &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); - //tracking algorithm - QObject::connect(static_cast(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::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::receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber) { - qobject_cast (m_TrackerController)->doTracking(mat, frameNumber); - - Q_EMIT emitCurrentFrameNumber(frameNumber); -} - -void BioTrackerPlugin::receiveCurrentFrameNumberFromMainApp(uint frameNumber) { - Q_EMIT emitCurrentFrameNumber(frameNumber); -} - -void BioTrackerPlugin::receiveCvMatFromController(std::shared_ptr mat, QString name) { - Q_EMIT emitCvMat(mat, name); -} - -void BioTrackerPlugin::receiveTrackingDone(uint framenumber) { - Q_EMIT emitTrackingDone(framenumber); -} - -void BioTrackerPlugin::receiveChangeDisplayImage(QString str) { - Q_EMIT emitChangeDisplayImage(str); -} - -void BioTrackerPlugin::receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory) { - Q_EMIT emitRemoveTrajectory(trajectory); -} - -void BioTrackerPlugin::receiveAddTrajectory(QPoint pos) { - Q_EMIT emitAddTrajectory(pos); -} - -void BioTrackerPlugin::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) { - Q_EMIT emitSwapIds(trajectory0, trajectory1); -} - -void BioTrackerPlugin::sendCorePermissions() { - // get plugin settings - BioTracker::Core::Settings *pluginSettings = BioTracker::Util::TypedSingleton::getInstance(LUKASKANADE::CONFIGPARAM::CONFIG_INI_FILE); - - // signal permissions - bool enableView = pluginSettings->getValueOrDefault(LUKASKANADE::GUIPARAM::ENABLE_CORE_COMPONENT_VIEW, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTVIEW, enableView)); - bool enableMove = pluginSettings->getValueOrDefault(LUKASKANADE::GUIPARAM::ENABLE_CORE_COMPONENT_MOVE, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTMOVE, enableMove)); - bool enableRemove = pluginSettings->getValueOrDefault(LUKASKANADE::GUIPARAM::ENABLE_CORE_COMPONENT_REMOVE, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTREMOVE, enableRemove)); - bool enableSwap = pluginSettings->getValueOrDefault(LUKASKANADE::GUIPARAM::ENABLE_CORE_COMPONENT_ID_SWAP, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTSWAP, enableSwap)); - bool enableAdd = pluginSettings->getValueOrDefault(LUKASKANADE::GUIPARAM::ENABLE_CORE_COMPONENT_ADD, true); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTADD, enableAdd)); - bool enableRotate = pluginSettings->getValueOrDefault(LUKASKANADE::GUIPARAM::ENABLE_CORE_COMPONENT_ROTATE, false); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTROTATE, enableRotate)); -} - diff --git a/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.h b/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.h deleted file mode 100644 index 5ffb1261..00000000 --- a/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef BIOTRACKERPLUGIN_H -#define BIOTRACKERPLUGIN_H - -#include "biotrackerplugin_global.h" -#include "opencv2/core/core.hpp" -#include "Interfaces/IBioTrackerContext.h" - -#include "Interfaces/IBioTrackerPlugin.h" -#include "TrackedComponents/TrackedComponentFactory.h" - -#include "QPointer" -#include "memory" -#include "QPoint" - -class BIOTRACKERPLUGINSHARED_EXPORT BioTrackerPlugin : public IBioTrackerPlugin { - Q_OBJECT - Q_PLUGIN_METADATA(IID "de.fu-berlin.mi.biorobotics.BioTrackerPlugin" FILE "BioTrackerPlugin.json") - Q_INTERFACES(IBioTrackerPlugin) - - public: - BioTrackerPlugin(); - - // IBioTrackerPlugin interface - IView* getTrackerParameterWidget(); - IView *getTrackerElementsWidget(); - IModel* getTrackerComponentModel(); - IModelTrackedComponentFactory *getComponentFactory(); - - public: - void createPlugin(); - void receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber); - void sendCorePermissions(); - - private: - void connectInterfaces(); -signals: - void emitCvMat(std::shared_ptr mat, QString name); - void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - void emitCorePermission(std::pair 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); - -private slots: - void receiveCvMatFromController(std::shared_ptr mat, QString name); - void receiveTrackingDone(uint framenumber); - void receiveChangeDisplayImage(QString str); - void receiveAreaDescriptor(IModelAreaDescriptor *areaDescr); - -private: - IController *m_TrackerController; - IController *m_ComponentController; - IController *m_AreaDescrController; - - IBioTrackerContext *m_PluginContext; - -public: - QList m_CorePermissions; - - -}; - -#endif // BIOTRACKERPLUGIN_H diff --git a/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.json b/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.json deleted file mode 100644 index 60679d9b..00000000 --- a/BioTracker/Plugin/LukasKanade/BioTrackerPlugin.json +++ /dev/null @@ -1,6 +0,0 @@ -{ "type" : "TrackingPlugin", - "name" : "Lukas Kanade Tracker", - "longname" : "some long name", - "version" : "1.1", - "dependencies" : [] -} diff --git a/BioTracker/Plugin/LukasKanade/CMakeLists.txt b/BioTracker/Plugin/LukasKanade/CMakeLists.txt deleted file mode 100644 index fbcddc28..00000000 --- a/BioTracker/Plugin/LukasKanade/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -############################################################## -#### Biotracker: LukasKanade -############################################################## - -add_definitions( -DBIOTRACKERPLUGIN_LIBRARY=1 ) -include(${util_cmakes}CMakeVSSugar.txt) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -message("Configuring LukasKanade...") -set(EXE_NAME LukasKanade.tracker) -add_library(${EXE_NAME} SHARED ${_util_source_list} ) - -target_link_libraries(${EXE_NAME} ${LIBS}) -target_link_libraries (${EXE_NAME} Qt5::Core Qt5::Gui Qt5::Xml Qt5::Network Qt5::Widgets) -target_link_libraries (${EXE_NAME} Qt5::Multimedia Qt5::MultimediaWidgets Qt5::OpenGL ) -target_link_libraries(${EXE_NAME} Biotracker_interfaces Biotracker_utility) -target_link_libraries(${EXE_NAME} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES}) - -include_directories(${Boost_INCLUDE_DIRS}) - -set_target_properties(${EXE_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) -set_target_properties(${EXE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO -) - - - - diff --git a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackedComponent.cpp b/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackedComponent.cpp deleted file mode 100644 index fe71f80a..00000000 --- a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackedComponent.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "ControllerTrackedComponent.h" -#include "TrackedComponents/TrackedElement.h" -#include "TrackedComponents/TrackedTrajectory.h" -#include "View/TrackedElementView.h" -#include "qdebug.h" -#include "qmath.h" - -ControllerTrackedComponent::ControllerTrackedComponent(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - m_currentFrameNumber = 0; -} - -void ControllerTrackedComponent::createView() -{ - m_View = new TrackedElementView(0, this, m_Model); -} - -void ControllerTrackedComponent::connectModelToController() -{ - -} - -void ControllerTrackedComponent::connectControllerToController() -{ -} - -void createTrajectories(int count, TrackedTrajectory* all) { - //This should be done using a factory, right? - for (int i = 0; i < count; i++) { - TrackedTrajectory *t = new TrackedTrajectory(); - t->setValid(true); - TrackedElement *e = new TrackedElement(t, "n.a.", t->getId()); - t->add(e); - all->add(t, i); - } -} - -void ControllerTrackedComponent::createModel() -{ - TrackedTrajectory *t = new TrackedTrajectory(this, "All"); - - m_Model = t; -} - - -IView *ControllerTrackedComponent::getTrackingElementsWidget() -{ - return m_View; -} - -void ControllerTrackedComponent::receiveRemoveTrajectory(IModelTrackedTrajectory * trajectory) -{ - trajectory->setValid(false); - qDebug() << "TRACKER: Trajectory" << trajectory->getId() << "set invalid"; -} - -void ControllerTrackedComponent::receiveRemoveTrajectoryId(int id) -{ - TrackedTrajectory* allTraj = qobject_cast(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(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) -{ - trajectory->getChild(frameNumber)->setValid(true); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "set valid"; -} - -void ControllerTrackedComponent::receiveRemoveTrackEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) -{ - trajectory->getChild(frameNumber)->setValid(false); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "set invalid"; -} - -void ControllerTrackedComponent::receiveAddTrajectory(QPoint position) -{ - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - - TrackedTrajectory* newTraj = new TrackedTrajectory(); - TrackedElement* firstElem = new TrackedElement(newTraj, "n.a.", newTraj->getId()); - firstElem->setX(position.x()); - firstElem->setY(position.y()); - firstElem->setTime(start); - firstElem->setValid(true); - newTraj->add(firstElem, m_currentFrameNumber); - TrackedTrajectory* allTraj = qobject_cast(m_Model); - if (allTraj) { - allTraj->add(newTraj); - qDebug() << "TRACKER: Track added at" << firstElem->getX() << "," << firstElem->getY(); - } -} - -void ControllerTrackedComponent::receiveMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint position) -{ - TrackedTrajectory* traj = dynamic_cast(trajectory); - if (!(traj->getId() == 0) && frameNumber >= 0) { - TrackedElement* element = dynamic_cast(traj->getChild(frameNumber)); - //TODO setX, setY do not work correctly as pose not yet accessible - if (element) { - element->setX(position.x()); - element->setY(position.y()); - //qDebug() << "plugin-pos:" << position; - } - else { - qDebug() << "TRACKER: Entity to move not found (moved and deleted?): " << position; - } - } -} - -void ControllerTrackedComponent::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) -{ - //TODO do this, not just nothing - TrackedTrajectory* traj0 = dynamic_cast(trajectory0); - TrackedTrajectory* traj1 = dynamic_cast(trajectory1); - - // dont't move main trajectory (id's: 0)!! - if (!(traj0->getId() == 0) && !(traj1->getId() == 0)) { - int traj0Id = traj0->getId(); - int traj1Id = traj1->getId(); - - traj0->setId(traj1Id); - traj1->setId(traj0Id); - - qDebug() << "TRACKER: Swap IDs " << traj0Id << "and " << traj1Id; - } -} - -void ControllerTrackedComponent::receiveToggleFixTrack(IModelTrackedTrajectory * trajectory, bool toggle) -{ - trajectory->setFixed(toggle); -} - -void ControllerTrackedComponent::receiveEntityRotation(IModelTrackedTrajectory * trajectory, double angle, uint frameNumber) -{ - TrackedTrajectory* traj = dynamic_cast(trajectory); - if (traj) { - IModelTrackedPoint* pointLike = dynamic_cast(traj->getChild(frameNumber)); - if (pointLike) { - pointLike->setDeg(float(angle)); - pointLike->setRad(float(qDegreesToRadians(angle))); - } - } -} - -void ControllerTrackedComponent::receiveCurrentFrameNumber(uint framenumber) -{ - m_currentFrameNumber = (int)framenumber; -} diff --git a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackedComponent.h b/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackedComponent.h deleted file mode 100644 index 5424e95c..00000000 --- a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackedComponent.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef CONTROLLERTRACKEDCOMPONENT_H -#define CONTROLLERTRACKEDCOMPONENT_H - -#include "Interfaces/IController/IController.h" -#include "QPoint" -#include "Interfaces/IModel/IModelTrackedTrajectory.h" - -class ControllerTrackedComponent : public IController -{ - Q_OBJECT -public: - ControllerTrackedComponent(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COMPONENT); - - 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); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - - //members - int m_currentFrameNumber; -}; - -#endif // CONTROLLERTRACKEDCOMPONENT_H diff --git a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackingAlgorithm.cpp b/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackingAlgorithm.cpp deleted file mode 100644 index 6e4973a3..00000000 --- a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackingAlgorithm.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "ControllerTrackingAlgorithm.h" -#include "ControllerTrackedComponent.h" - -#include "Model/TrackerParameter.h" -#include "View/TrackerParameterView.h" -#include "View/TrackedElementView.h" - -ControllerTrackingAlgorithm::ControllerTrackingAlgorithm(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) -{ - m_BioTrackerContext = context; -} - -void ControllerTrackingAlgorithm::connectControllerToController() -{ - IController * ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - QPointer< ControllerTrackedComponent > ctrComponent = qobject_cast(ctr); - - m_TrackedTrajectoryMajor = ctrComponent->getModel(); -} - -void ControllerTrackingAlgorithm::doTracking(std::shared_ptr mat, uint number) -{ - qobject_cast(m_Model)->doTracking(mat, number); -} - -IView *ControllerTrackingAlgorithm::getTrackingParameterWidget() -{ - return m_View; -} - -void ControllerTrackingAlgorithm::createModel() -{ - connectControllerToController(); - - m_TrackingParameter = new TrackerParameter(this); - - m_Model = new BioTrackerTrackingAlgorithm(m_TrackingParameter, m_TrackedTrajectoryMajor); -} - -void ControllerTrackingAlgorithm::createView() -{ - m_View = new TrackerParameterView(0, this, m_TrackingParameter); -} - -void ControllerTrackingAlgorithm::connectModelToController() -{ - BioTrackerTrackingAlgorithm *trackingAlg = qobject_cast(m_Model); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitCvMatA, this, &ControllerTrackingAlgorithm::receiveCvMatFromTrackingAlgorithm); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitTrackingDone, this, &ControllerTrackingAlgorithm::receiveTrackingDone); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, this, &ControllerTrackingAlgorithm::receiveChangeDisplayImage); - QObject::connect(this, &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, trackingAlg, &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); - - QObject::connect(static_cast(m_View), &TrackerParameterView::parametersChanged, - trackingAlg, &BioTrackerTrackingAlgorithm::receiveParametersChanged); - - //enable the tracker to send video dimension updates to the view via signal - IController* ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - IView *v = qobject_cast(ctr)->getView(); - TrackedElementView *v2 = dynamic_cast(v); - QObject::connect(trackingAlg, SIGNAL(emitDimensionUpdate(int, int)), v2, SLOT(rcvDimensionUpdate(int, int))); -} - -void ControllerTrackingAlgorithm::receiveCvMatFromTrackingAlgorithm(std::shared_ptr mat, QString name) -{ - Q_EMIT emitCvMat(mat, name); -} - -void ControllerTrackingAlgorithm::receiveTrackingDone(uint framenumber) -{ - Q_EMIT emitTrackingDone(framenumber); -} - -void ControllerTrackingAlgorithm::receiveChangeDisplayImage(QString str) { - Q_EMIT emitChangeDisplayImage(str); -} - -void ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - Q_EMIT emitAreaDescriptorUpdate(areaDescr); -} diff --git a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackingAlgorithm.h b/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackingAlgorithm.h deleted file mode 100644 index 75e565a4..00000000 --- a/BioTracker/Plugin/LukasKanade/Controller/ControllerTrackingAlgorithm.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef CONTROLLERTRACKINGALGORITHM_H -#define CONTROLLERTRACKINGALGORITHM_H - -#include "Interfaces/IController/IController.h" -#include "Model/BioTrackerTrackingAlgorithm.h" -#include "Interfaces/IBioTrackerContext.h" -#include "Interfaces/IModel/IModelDataExporter.h" - - -class ControllerTrackingAlgorithm : public IController -{ - Q_OBJECT -public: - ControllerTrackingAlgorithm(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - // IController interface -public: - void connectControllerToController() override; - - void doTracking(std::shared_ptr mat, uint number); - - IView *getTrackingParameterWidget(); - -public Q_SLOTS: - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - -Q_SIGNALS: - void emitCvMat(std::shared_ptr mat, QString name); - void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - -private Q_SLOTS: - void receiveCvMatFromTrackingAlgorithm(std::shared_ptr mat, QString name); - void receiveTrackingDone(uint framenumber); - void receiveChangeDisplayImage(QString str); - -private: - IModel* m_TrackingParameter; - IModel *m_TrackedTrajectoryMajor; -}; - -#endif // CONTROLLERTRACKINGALGORITHM_H diff --git a/BioTracker/Plugin/LukasKanade/Controller/null_Controller.cpp b/BioTracker/Plugin/LukasKanade/Controller/null_Controller.cpp deleted file mode 100644 index 612c02f3..00000000 --- a/BioTracker/Plugin/LukasKanade/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/BioTracker/Plugin/LukasKanade/Controller/null_Controller.h b/BioTracker/Plugin/LukasKanade/Controller/null_Controller.h deleted file mode 100644 index a0fcc211..00000000 --- a/BioTracker/Plugin/LukasKanade/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/BioTracker/Plugin/LukasKanade/Model/BioTrackerTrackingAlgorithm.cpp b/BioTracker/Plugin/LukasKanade/Model/BioTrackerTrackingAlgorithm.cpp deleted file mode 100644 index 8817d87e..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/BioTrackerTrackingAlgorithm.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include "BioTrackerTrackingAlgorithm.h" -#include -#include "TrackedComponents/TrackedComponentFactory.h" -#include - -#include "settings/Settings.h" - -BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IModel *parameter, IModel *trajectory) -{ - _TrackingParameter = (TrackerParameter*)parameter; - _TrackedTrajectoryMajor = (TrackedTrajectory*)trajectory; - BioTracker::Core::Settings *set = _TrackingParameter->getSettings(); - - _lastImage = nullptr; - _lastFramenumber = -1; -} - - -void BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - _AreaInfo = areaDescr; -} - -BioTrackerTrackingAlgorithm::~BioTrackerTrackingAlgorithm() -{ -} - -void BioTrackerTrackingAlgorithm::receiveParametersChanged() { - if (_lastFramenumber >= 0 && _lastImage && !_lastImage->empty()) { - doTracking(_lastImage, _lastFramenumber); - } -} - - -void clampPosition(std::vector &pos, int w, int h) { - // When points are outside the image boarders they cannot be rescued anymore - // This function clamps them to be inside the image again which is actually not - // very nice. See: https://github.com/BioroboticsLab/biotracker_lucasKanade/issues/8 - for (cv::Point2f &p : pos) { - if (p.x < 0) { - p.x = 0; - } - else if (p.x > w) { - p.x = w - 1; - } - if (p.y < 0) { - p.y = 0; - } - else if (p.y > h) { - p.y = h - 1; - } - } -} - -std::vector getPoints(TrackedTrajectory* trackedTrajectoryMajor, int frameNo) { - - std::vector points; - int trajNumber = 0; - for (int i = 0; i < trackedTrajectoryMajor->size(); i++) { - TrackedTrajectory *t = dynamic_cast(trackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - IModelTrackedPoint* p = dynamic_cast(t->getChild(frameNo)); - if (p != nullptr) { - points.push_back(cv::Point2f(p->getX(), p->getY())); - } - else { - points.push_back(cv::Point2f(100, 100)); - } - - trajNumber++; - } - } - return points; -} - -void setPoints(TrackedTrajectory* trackedTrajectoryMajor, int frameNo, std::vector points) { - - int trajNumber = 0; - for (int i = 0; i < trackedTrajectoryMajor->size(); i++) { - TrackedTrajectory *t = dynamic_cast(trackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !points.empty() && !t->getFixed()) { - cv::Point2f p = points[0]; - points.erase(points.begin()); - TrackedElement *e = new TrackedElement(t, "n.a.", t->getId()); - e->setPoint(p); - t->add(e, frameNo); - - trajNumber++; - } - } -} - - -void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr p_image, uint framenumber) -{ - - //dont do nothing if we ain't got an image - if (p_image->empty()) { - return; - } - - 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); - } - -// std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - - int noFish = _TrackedTrajectoryMajor->validCount(); - cv::Mat gray; - cv::cvtColor(*p_image, gray, cv::COLOR_BGR2GRAY); - int wndSizeInt = _TrackingParameter->getWndSize(); - cv::Size wndSize = cv::Size(wndSizeInt, wndSizeInt); - cv::TermCriteria termcrit(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 20, 0.03); - - //if current frame is first frame return - if (framenumber == 0) { - Q_EMIT emitTrackingDone(framenumber); - return; - } - - std::vector prevPts = getPoints(_TrackedTrajectoryMajor, framenumber-1); - - if (_lastImage == nullptr || _lastImage->empty()) { - _lastImage = p_image; - } - - if (!prevPts.empty()){ - std::vector err; - - // calculate pyramids: - const size_t maxLevel = 10; - std::vector prevPyr; - cv::buildOpticalFlowPyramid(*_lastImage, prevPyr, wndSize, maxLevel); - - std::vector pyr; - cv::buildOpticalFlowPyramid(*p_image, pyr, wndSize, maxLevel); - - std::vector newPoints; - std::vector status; - cv::calcOpticalFlowPyrLK( - prevPyr, /* prev */ - pyr, /* next */ - prevPts, /* prevPts */ - newPoints, /* nextPts */ - status, /* status */ - err /* err */ - , wndSize, /* winSize */ - maxLevel, /* maxLevel */ - termcrit, /* criteria */ - 0, /* flags */ - 0.001 /* minEigThreshold */ - ); - - clampPosition(newPoints, p_image->size().width, p_image->size().height); - setPoints(_TrackedTrajectoryMajor, framenumber, newPoints); - } - - - Q_EMIT emitCvMatA(p_image, QString("Original")); - Q_EMIT emitChangeDisplayImage("Original"); - - - Q_EMIT emitTrackingDone(framenumber); - - _lastImage = p_image; - _lastFramenumber = framenumber; -} - diff --git a/BioTracker/Plugin/LukasKanade/Model/BioTrackerTrackingAlgorithm.h b/BioTracker/Plugin/LukasKanade/Model/BioTrackerTrackingAlgorithm.h deleted file mode 100644 index a59879e2..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/BioTrackerTrackingAlgorithm.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BIOTRACKERTRACKINGALGORITHM_H -#define BIOTRACKERTRACKINGALGORITHM_H - - -#include "Interfaces/IModel/IModel.h" - -#include "TrackerParameter.h" - -#include -#include "Interfaces/IModel/IModelTrackingAlgorithm.h" -#include "Interfaces/IModel/IModelDataExporter.h" -#include "TrackedComponents/TrackedElement.h" -#include "TrackedComponents/TrackedTrajectory.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include - -class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm -{ - Q_OBJECT -public: - BioTrackerTrackingAlgorithm(IModel* parameter, IModel* trajectory); - ~BioTrackerTrackingAlgorithm(); - -Q_SIGNALS: - void emitCvMatA(std::shared_ptr image, QString name); - void emitDimensionUpdate(int x, int y); - void emitTrackingDone(uint framenumber); - - // ITrackingAlgorithm interface -public Q_SLOTS: - void doTracking(std::shared_ptr image, uint framenumber) override; - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); - void receiveParametersChanged(); - -private: - void refreshPolygon(); - void sendSelectedImage(std::map>* images); - - void resetFishHistory(int noFish); - - TrackedTrajectory* _TrackedTrajectoryMajor; - TrackerParameter* _TrackingParameter; - IModelAreaDescriptor* _AreaInfo; - - int _imageX; - int _imageY; - - std::shared_ptr _lastImage; - uint _lastFramenumber; -}; - -#endif // BIOTRACKERTRACKINGALGORITHM_H diff --git a/BioTracker/Plugin/LukasKanade/Model/ParamNames.h b/BioTracker/Plugin/LukasKanade/Model/ParamNames.h deleted file mode 100644 index 102b4752..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/ParamNames.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include -#include - -namespace LUKASKANADE { - - namespace CONFIGPARAM - { - // System config - const std::string CONFIG_INI_FILE = "./LKTrackerConfig.ini"; - } - - namespace APPLICATIONPARAM - { - // System config - const std::string APP_VERSION = "APPLICATIONPARAM/APP_VERSION"; - } - - namespace TRACKERPARAM - { - const std::string WNDSIZE = "TRACKERPARAM/WNDSIZE"; - - } - - namespace GUIPARAM - { - // FPS label - const std::string ENABLE_LABEL_FPS = "GUIPARAM/ENABLE_LABEL_FPS"; - // Fish id label - const std::string ENABLE_LABEL_FISH_ID = "GUIPARAM/ENABLE_LABEL_FISH_ID"; - // Replica marker - const std::string ENABLE_LABEL_REPLICA = "GUIPARAM/ENABLE_LABEL_REPLICA"; - // Fish position - const std::string ENABLE_LABEL_FISH_POS = "GUIPARAM/ENABLE_LABEL_FISH_POS"; - // Fish orientation - const std::string ENABLE_LABEL_FISH_ORI = "GUIPARAM/ENABLE_LABEL_FISH_ORI"; - // Fish history - const std::string ENABLE_LABEL_FISH_HISTORY = "GUIPARAM/ENABLE_LABEL_FISH_HISTORY"; - // Blobs - const std::string ENABLE_SHOW_BLOBS = "GUIPARAM/ENABLE_SHOW_BLOBS"; - // Swap fish id - const std::string ENABLE_SWAP_FISH_ID = "GUIPARAM/ENABLE_SWAP_FISH_ID"; - - // Core view of tracked components - const std::string ENABLE_CORE_COMPONENT_VIEW = "GUIPARAM/ENABLE_CORE_COMPONENT_VIEW"; - // Move components in core view - const std::string ENABLE_CORE_COMPONENT_MOVE = "GUIPARAM/ENABLE_CORE_COMPONENT_MOVE"; - // Remove components in core view - const std::string ENABLE_CORE_COMPONENT_REMOVE = "GUIPARAM/ENABLE_CORE_COMPONENT_REMOVE"; - // Swap component id in core view - const std::string ENABLE_CORE_COMPONENT_ID_SWAP = "GUIPARAM/ENABLE_CORE_COMPONENT_ID_SWAP"; - // Add component in core view - const std::string ENABLE_CORE_COMPONENT_ADD = "GUIPARAM/ENABLE_CORE_COMPONENT_ADD"; - // Rotate component in core view - const std::string ENABLE_CORE_COMPONENT_ROTATE = "GUIPARAM/ENABLE_CORE_COMPONENT_ROTATE"; - } - -} - diff --git a/BioTracker/Plugin/LukasKanade/Model/TrackerParameter.cpp b/BioTracker/Plugin/LukasKanade/Model/TrackerParameter.cpp deleted file mode 100644 index 41eda3e3..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/TrackerParameter.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "TrackerParameter.h" -#include "util/singleton.h" -#include "Model/ParamNames.h" - -TrackerParameter::TrackerParameter(QObject *parent) : - IModel(parent) -{ - _settings = BioTracker::Util::TypedSingleton::getInstance(LUKASKANADE::CONFIGPARAM::CONFIG_INI_FILE); - //_settings = new BioTracker::Core::Settings(CONFIGPARAM::CONFIG_INI_FILE); - - m_wndSize = _settings->getValueOrDefault(LUKASKANADE::TRACKERPARAM::WNDSIZE, 31); - - - Q_EMIT notifyView(); -} diff --git a/BioTracker/Plugin/LukasKanade/Model/TrackerParameter.h b/BioTracker/Plugin/LukasKanade/Model/TrackerParameter.h deleted file mode 100644 index ebf1f600..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/TrackerParameter.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef TRACKERPARAMETER_H -#define TRACKERPARAMETER_H - - -#include "Interfaces/IModel/IModel.h" -#include "settings/Settings.h" -#include "Model/ParamNames.h" - -class TrackerParameter : public IModel -{ - Q_OBJECT -public: - TrackerParameter(QObject *parent = 0); - - BioTracker::Core::Settings *getSettings() { return _settings; }; - - int getWndSize() { return m_wndSize; }; - void setWndSize(int x) { - m_wndSize = x; - Q_EMIT notifyView(); - }; - - void setAll( - int wndSize) - { - m_wndSize = wndSize; - _settings->setParam(LUKASKANADE::TRACKERPARAM::WNDSIZE, wndSize); - Q_EMIT notifyView(); - }; - - - -private: - BioTracker::Core::Settings *_settings; - - int m_wndSize; - -}; - -#endif // TRACKERPARAMETER_H diff --git a/BioTracker/Plugin/LukasKanade/Model/null_Model.cpp b/BioTracker/Plugin/LukasKanade/Model/null_Model.cpp deleted file mode 100644 index db2793d0..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/null_Model.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "null_Model.h" - -null_Model::null_Model() -{ - -} diff --git a/BioTracker/Plugin/LukasKanade/Model/null_Model.h b/BioTracker/Plugin/LukasKanade/Model/null_Model.h deleted file mode 100644 index 8dabf466..00000000 --- a/BioTracker/Plugin/LukasKanade/Model/null_Model.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NULL_MODEL_H -#define NULL_MODEL_H - -#include "Interfaces/IModel/IModel.h" - -class null_Model : public IModel -{ - Q_OBJECT -public: - null_Model(); -}; - -#endif // NULL_MODEL_H diff --git a/BioTracker/Plugin/LukasKanade/PluginContext.cpp b/BioTracker/Plugin/LukasKanade/PluginContext.cpp deleted file mode 100644 index 52fea1ff..00000000 --- a/BioTracker/Plugin/LukasKanade/PluginContext.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "PluginContext.h" - -#include "Controller/ControllerTrackingAlgorithm.h" -#include "Controller/ControllerTrackedComponent.h" - -PluginContext::PluginContext(QObject *parent) : - IBioTrackerContext(parent) -{ - QPointer< IController > ComponentController = new ControllerTrackedComponent(this, this, ENUMS::CONTROLLERTYPE::COMPONENT); - QPointer< IController > TrackingController = new ControllerTrackingAlgorithm(this, this, ENUMS::CONTROLLERTYPE::TRACKING); - - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMPONENT, ComponentController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKING, TrackingController); -} - -void PluginContext::createAppController() -{ - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->createComponents(); - } -} - -void PluginContext::connectController() -{ - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->connectComponents(); - } -} - - diff --git a/BioTracker/Plugin/LukasKanade/PluginContext.h b/BioTracker/Plugin/LukasKanade/PluginContext.h deleted file mode 100644 index aab040e7..00000000 --- a/BioTracker/Plugin/LukasKanade/PluginContext.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "Interfaces/IBioTrackerContext.h" -#include "Interfaces/IController/IController.h" - -class PluginContext : public IBioTrackerContext -{ - Q_OBJECT - -public: - PluginContext(QObject *parent = 0); - - // IBioTrackerContext interface -protected: - void createAppController() override; - void connectController() override; -}; - diff --git a/BioTracker/Plugin/LukasKanade/View/TrackedElementView.cpp b/BioTracker/Plugin/LukasKanade/View/TrackedElementView.cpp deleted file mode 100644 index 9f120c73..00000000 --- a/BioTracker/Plugin/LukasKanade/View/TrackedElementView.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "TrackedElementView.h" -#include "TrackedComponents/TrackedElement.h" -#include "TrackedComponents/TrackedTrajectory.h" -#include "QBrush" -#include "QPainter" -#include "QGraphicsScene" -#include -#include "settings/Settings.h" -#include "Model/ParamNames.h" -#include "util/misc.h" - -class QGraphicsSceneHoverEvent; - -TrackedElementView::TrackedElementView(QGraphicsItem *parent, IController *controller, IModel *model) : - IViewTrackedComponent(parent, controller, model) -{ - TrackedElement *elem = dynamic_cast(getModel()); - _boundingRect = QRectF(0,0, 100, 100); -} - -void TrackedElementView::rcvDimensionUpdate(int x, int y) { - _boundingRect = QRectF(0, 0, x, y); - update(); -} - -QRectF TrackedElementView::boundingRect() const -{ - - return _boundingRect; -} - - -void TrackedElementView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - QGraphicsScene *scene = this->scene(); - - //Dev note: You could do some meaningful drawing here. - //So far, the core does everything we need. -} - -void TrackedElementView::getNotified() -{ - update(); -} - diff --git a/BioTracker/Plugin/LukasKanade/View/TrackedElementView.h b/BioTracker/Plugin/LukasKanade/View/TrackedElementView.h deleted file mode 100644 index 420fd769..00000000 --- a/BioTracker/Plugin/LukasKanade/View/TrackedElementView.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TRACKEDELEMENTVIEW_H -#define TRACKEDELEMENTVIEW_H - -#include "Interfaces/IView/IViewTrackedComponent.h" - -/** - * 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. - */ -class TrackedElementView : public IViewTrackedComponent -{ - Q_OBJECT -public: - 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; - - // IViewTrackedComponent interface -public Q_SLOTS: - void getNotified() override; - void rcvDimensionUpdate(int x, int y); - -public Q_SIGNAL: - void emitUpdateCornersChanged(int id, int relX, int relY); - -private: - QRectF _boundingRect; - -}; - -#endif // TRACKEDELEMENTVIEW_H diff --git a/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.cpp b/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.cpp deleted file mode 100644 index 5a78eceb..00000000 --- a/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "TrackerParameterView.h" -#include "ui_TrackerParameterView.h" - -#include - -TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : - IViewWidget(parent, controller, model), - ui(new Ui::TrackerParameterView) -{ - ui->setupUi(this); - - QObject::connect(ui->lineEdit_wndSize, SIGNAL(valueChanged(int)), this, SLOT(on_pushButton_clicked())); - getNotified(); -} - -TrackerParameterView::~TrackerParameterView() -{ - delete ui; -} - -void TrackerParameterView::on_pushButton_clicked() -{ - TrackerParameter *parameter = qobject_cast(getModel()); - - int setWndSize = ui->lineEdit_wndSize->text().toInt(); - - parameter->setAll(setWndSize); - - Q_EMIT parametersChanged(); -} - -void TrackerParameterView::getNotified() -{ - TrackerParameter *parameter = qobject_cast(getModel()); - - int val = parameter->getWndSize(); - ui->lineEdit_wndSize->setValue(val); -} diff --git a/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.h b/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.h deleted file mode 100644 index 427f2542..00000000 --- a/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef TRACKERPARAMETERVIEW_H -#define TRACKERPARAMETERVIEW_H - -#include "Interfaces/IView/IViewWidget.h" -#include "Model/TrackerParameter.h" - -namespace Ui { - class TrackerParameterView; -} - -class TrackerParameterView : public IViewWidget -{ - Q_OBJECT - -public: - explicit TrackerParameterView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); - ~TrackerParameterView(); - -private slots: - void on_pushButton_clicked(); - - -public: - signals: - void trackingAreaType(int v); - void parametersChanged(); - -private: - Ui::TrackerParameterView *ui; - - // IViewWidget interface -public slots: - - void getNotified(); -}; - -#endif // TRACKERPARAMETERVIEW_H diff --git a/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.ui b/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.ui deleted file mode 100644 index fc761172..00000000 --- a/BioTracker/Plugin/LukasKanade/View/TrackerParameterView.ui +++ /dev/null @@ -1,169 +0,0 @@ - - - TrackerParameterView - - - - 0 - 0 - 304 - 481 - - - - Form - - - false - - - - 6 - - - 0 - - - 9 - - - 0 - - - 0 - - - - - false - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - - - true - - - - - 0 - 0 - 302 - 470 - - - - - 9 - - - 0 - - - - - - - - - Window size - - - - - - - Set the window size - - - 3 - - - 255 - - - 2 - - - 17 - - - - - - - - - - - Iteration count - - - - - - - - - - - - - - Accuracy (eps) - - - - - - - - - - - - - - the algorithm calculates the minimum eigen value of a 2x2 normal matrix of optical flow equations (this matrix is called a spatial gradient matrix in [Bouguet00]), divided by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding feature is filtered out and its flow is not processed, so it allows to remove bad points and get a performance boost. - - - minEigThreshold - - - - - - - the algorithm calculates the minimum eigen value of a 2x2 normal matrix of optical flow equations (this matrix is called a spatial gradient matrix in [Bouguet00]), divided by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding feature is filtered out and its flow is not processed, so it allows to remove bad points and get a performance boost. - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - diff --git a/BioTracker/Plugin/LukasKanade/biotrackerplugin_global.h b/BioTracker/Plugin/LukasKanade/biotrackerplugin_global.h deleted file mode 100644 index 770f7d21..00000000 --- a/BioTracker/Plugin/LukasKanade/biotrackerplugin_global.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef BIOTRACKERPLUGIN_GLOBAL_H -#define BIOTRACKERPLUGIN_GLOBAL_H - -#include - -#if defined(BIOTRACKERPLUGIN_LIBRARY) -# define BIOTRACKERPLUGINSHARED_EXPORT Q_DECL_EXPORT -#else -# define BIOTRACKERPLUGINSHARED_EXPORT Q_DECL_IMPORT -#endif - -#endif // BIOTRACKERPLUGIN_GLOBAL_H diff --git a/BioTracker/Utils/BioTrackerUtils/BioTrackerUtils.pro b/BioTracker/Utils/BioTrackerUtils/BioTrackerUtils.pro deleted file mode 100644 index 6f612020..00000000 --- a/BioTracker/Utils/BioTrackerUtils/BioTrackerUtils.pro +++ /dev/null @@ -1,58 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-12-08T10:23:47 -# -#------------------------------------------------- - -QT += widgets -QT += opengl - -TARGET = BioTrackerUtils -TEMPLATE = lib -CONFIG += staticlib - -INCLUDEPATH += /usr/local/include/opencv -LIBS += -L/usr/local/lib \ --lopencv_core \ --lopencv_imgproc \ --lopencv_highgui \ --lopencv_ml \ --lopencv_video \ --lopencv_features2d \ --lopencv_calib3d \ --lopencv_objdetect \ --lopencv_contrib \ --lopencv_legacy \ --lopencv_flann - - -SOURCES += \ - src/settings/Settings.cpp \ - src/settings/StringTranslator.cpp \ - src/settings/SystemCompatibilityCheck.cpp \ - src/util/imagePreProcessor/ImagePreProcessor.cpp \ - src/util/CvHelper.cpp \ - src/util/stringTools.cpp - -HEADERS += \ - settings/Messages.h \ - settings/ParamNames.h \ - settings/Settings.h \ - settings/StringTranslator.h \ - settings/SystemCompatibilityCheck.h \ - util/imagePreProcessor/IImageProcessor.h \ - util/imagePreProcessor/ImagePreProcessor.h \ - util/CvHelper.h \ - util/MutexWrapper.h \ - util/platform.h \ - util/QtRaiiWrapper.hpp \ - util/ScreenHelper.h \ - util/singleton.h \ - util/stdext.h \ - util/stringTools.h \ - Exceptions.h \ - PanZoomState.h -unix { - target.path = /usr/lib - INSTALLS += target -} diff --git a/BioTracker/Utils/BioTrackerUtils/CMakeCommon/CMakeVSSugar.txt b/BioTracker/Utils/BioTrackerUtils/CMakeCommon/CMakeVSSugar.txt deleted file mode 100644 index 7067153f..00000000 --- a/BioTracker/Utils/BioTrackerUtils/CMakeCommon/CMakeVSSugar.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(_util_src_root_path ${CMAKE_CURRENT_SOURCE_DIR}) -file( - GLOB_RECURSE _util_source_list - LIST_DIRECTORIES false - "${_util_src_root_path}/*.c*" - "${_util_src_root_path}/*.h*" - "${_util_src_root_path}/*.ui*" -) - -foreach(_util_source IN ITEMS ${_util_source_list}) - get_filename_component(_util_source_path "${_util_source}" PATH) - file(RELATIVE_PATH _util_source_path_rel "${_util_src_root_path}" "${_util_source_path}") - string(REPLACE "/" "\\" _util_group_path "${_util_source_path_rel}") - source_group("${_util_group_path}" FILES "${_util_source}") -endforeach() \ No newline at end of file diff --git a/BioTracker/Utils/BioTrackerUtils/CMakeLists.txt b/BioTracker/Utils/BioTrackerUtils/CMakeLists.txt deleted file mode 100644 index 2e293e1a..00000000 --- a/BioTracker/Utils/BioTrackerUtils/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -############################################################## -#### Biotracker: Utility -############################################################## - -# Visual studio out-of-source friendly source groups -include(CMakeCommon/CMakeVSSugar.txt) - -set(util_cmakes "${CMAKE_CURRENT_SOURCE_DIR}/CMakeCommon/" CACHE INTERNAL "util_cmakes") - -message("Configuring Biotracker_utility...") -set(EXE_NAME Biotracker_utility) -add_library(${EXE_NAME} STATIC ${_util_source_list} ) -target_link_libraries(${EXE_NAME} Biotracker_interfaces) -target_link_libraries(${EXE_NAME} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES}) -target_link_libraries(${EXE_NAME} Qt5::Core Qt5::Gui Qt5::Xml Qt5::Network Qt5::Widgets) -include_directories(${Boost_INCLUDE_DIRS}) -target_include_directories(${EXE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -set_target_properties(${EXE_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) -set_target_properties(${EXE_NAME} PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO -) \ No newline at end of file diff --git a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedComponentFactory.cpp b/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedComponentFactory.cpp deleted file mode 100644 index f0641538..00000000 --- a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedComponentFactory.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "TrackedComponentFactory.h" - -#include "TrackedTrajectory.h" -#include "TrackedElement.h" - -TrackedComponentFactory::TrackedComponentFactory() -{ - -} - -TrackedComponentFactory::~TrackedComponentFactory() -{ - -} - -QList TrackedComponentFactory::getElementTypes() { - return QList{ "TrackedElement" }; -} - -IModelTrackedComponent *TrackedComponentFactory::createTrackedElement(QString name) -{ - return new TrackedElement(this, "n.a."); -} - -IModelTrackedComponent *TrackedComponentFactory::createTrackedObject(QString name) -{ - TrackedTrajectory *t = new TrackedTrajectory(); - TrackedElement *e = new TrackedElement(this, "n.a.", 0); - t->add(e, 0); - return t; -} - -IModelTrackedComponent *TrackedComponentFactory::createTrackedTrajectory(QString name) -{ - return new TrackedTrajectory(); -} diff --git a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedComponentFactory.h b/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedComponentFactory.h deleted file mode 100644 index 70b0d8ee..00000000 --- a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedComponentFactory.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef TRACKEDCOMPONENTFACTORY_H -#define TRACKEDCOMPONENTFACTORY_H - -#include "Interfaces/IModel/IModelTrackedComponentFactory.h" - -class TrackedComponentFactory : public IModelTrackedComponentFactory -{ - Q_OBJECT -public: - TrackedComponentFactory(); - ~TrackedComponentFactory(); - - QList getElementTypes() override; - // ITrackedComponentFactory interface -protected: - IModelTrackedComponent *createTrackedElement(QString name) override; - IModelTrackedComponent *createTrackedObject(QString name) override; - IModelTrackedComponent *createTrackedTrajectory(QString name) override; -}; - -#endif // TRACKEDOBJECTFACTORY_H diff --git a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedElement.cpp b/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedElement.cpp deleted file mode 100644 index 9d7d35f0..00000000 --- a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedElement.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "TrackedElement.h" -#include "QDebug" -#include "QRect" -#include "QBrush" -#include "QPainter" - -TrackedElement::TrackedElement(QObject *parent, QString name, int id) : - IModelTrackedPoint(parent), - _name(name), - _id(id) -{ - _x = 0; - _y = 0; - _valid = false; - _fixed = false; -} - -QString TrackedElement::getName() -{ - return _name; -} - -void TrackedElement::setPoint(cv::Point2f p) -{ - _x = p.x; - _y = p.y; - _valid = true; - Q_EMIT notifyView(); -} - -cv::Point2f TrackedElement::getPoint() -{ - return cv::Point2f(_x, _y); -} - -void TrackedElement::setX(float val) { - _x = val; -}; - -void TrackedElement::setY(float val) { - _y = val; -}; - -float TrackedElement::getX() { - return _x; -} - -float TrackedElement::getY() { - return _y; -} - -float TrackedElement::getXpx() { - return _x; -} - -float TrackedElement::getYpx() { - return _y; -} - -void TrackedElement::operate() -{ - qDebug() << "I am TrackedElement " << _name; -} - - diff --git a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedElement.h b/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedElement.h deleted file mode 100644 index fa8b9f9f..00000000 --- a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedElement.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef TRACKEDELEMENT_H -#define TRACKEDELEMENT_H - -#include "QGraphicsItem" -#include "Interfaces/IModel/IModelTrackedComponent.h" -#include "QString" -#include -#include -#include - -/** -* 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); - - QString getName(); - QString getCoordinateUnit() override { return "px"; }; - - 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) { - _timeSysclck = t; - }; - void setTime(qint64 t) { - _time = t; - std::string::size_type sz = 0; - long long ll = t / 1000; - std::time_t tm(ll); - _timeSysclck = std::chrono::system_clock::from_time_t(tm); - }; - void setTimeString(QString t) { _timeString = t; }; - void setValid(bool v) { _valid = v; }; - void setFixed(bool f) { _fixed = f; }; - - float getX(); - float getY(); - float getXpx(); - float getYpx(); - float getW() { return 0; }; - float getH() { return 0; }; - float getWpx() { return 0; }; - float getHpx() { return 0; }; - float getRad() { return 0; }; - float getDeg() { return 0; }; - int getId() { return _id; }; - qint64 getTime() { - qint64 q(std::chrono::duration_cast(_timeSysclck.time_since_epoch()).count()); - return q; - }; - QString getTimeString() { - std::time_t t = std::chrono::system_clock::to_time_t(_timeSysclck); - QDateTime dt; - dt.setTime_t(t); - _timeString = dt.toString(); - return _timeString; - }; - 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 false; }; - bool hasYpx() { return false; }; - bool hasWpx() { return false; }; - bool hasHpx() { return false; }; - bool hasRad() { return false; }; - bool hasDeg() { return false; }; - bool hasTime() { return true; }; - bool hasTimeString() { return true; }; - - void setPoint(cv::Point2f p); - cv::Point2f getPoint(); - - // ITrackedPoint interface -public: - void operate(); - -private: - std::chrono::system_clock::time_point _timeSysclck; - QString _name; - float _x; - float _y; - int _id; - bool _valid; - bool _fixed; -}; - -#endif // TRACKEDELEMENT_H diff --git a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedTrajectory.cpp b/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedTrajectory.cpp deleted file mode 100644 index bb118ebd..00000000 --- a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedTrajectory.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "TrackedTrajectory.h" -#include "QDebug" -#include "TrackedElement.h" - -TrackedTrajectory::TrackedTrajectory(QObject *parent, QString name) : - IModelTrackedTrajectory(parent), - name(name) -{ - setFixed(false); - setValid(true); -} - -void TrackedTrajectory::operate() -{ - qDebug() << "Printing all TrackedElements in TrackedObject " << name; - qDebug() << "========================= Begin =========================="; - for (int i = 0; i < _TrackedComponents.size(); ++i) { - dynamic_cast(_TrackedComponents.at(i))->operate(); - } - qDebug() << "======================== End ========================="; -} - -void TrackedTrajectory::add(IModelTrackedComponent *comp, int pos) -{ - if (pos < 0) { - _TrackedComponents.append(comp); - } - else if (_TrackedComponents.size() <= pos) { - while (_TrackedComponents.size() < pos) - _TrackedComponents.append(0); - - _TrackedComponents.append(comp); - } - else { - _TrackedComponents[pos] = comp; - } -} - -bool TrackedTrajectory::remove(IModelTrackedComponent *comp) -{ - return _TrackedComponents.removeOne(comp); //Do not actually remove, just invalidate / replace by dummy -} - -void TrackedTrajectory::clear() -{ - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (dynamic_cast(el)) - dynamic_cast(el)->clear(); - } - _TrackedComponents.clear(); -} - -IModelTrackedComponent* TrackedTrajectory::getChild(int index) -{ - return (_TrackedComponents.size() > index ? _TrackedComponents.at(index) : nullptr); -} - -IModelTrackedComponent* TrackedTrajectory::getLastChild() -{ - return _TrackedComponents.at(_TrackedComponents.size()-1); -} - -IModelTrackedComponent* TrackedTrajectory::getValidChild(int index) -{ - int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (el) { - if (c == index && el->getValid()) - return el; - c += el->getValid() ? 1 : 0; - } - } - - return nullptr; -} - -int TrackedTrajectory::size() -{ - return _TrackedComponents.size(); -} - -int TrackedTrajectory::validCount() -{ - int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents){ - if (el) - c += el->getValid() ? 1 : 0; - } - - return c; -} diff --git a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedTrajectory.h b/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedTrajectory.h deleted file mode 100644 index 11710c76..00000000 --- a/BioTracker/Utils/BioTrackerUtils/TrackedComponents/TrackedTrajectory.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef TRACKEDOTRAJECTORY_H -#define TRACKEDOTRAJECTORY_H - -#include "Interfaces/IModel/IModelTrackedTrajectory.h" -#include "QList" -#include "QString" - -/** - * 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 IModelTrackedTrajectory { - Q_OBJECT - - public: - TrackedTrajectory(QObject *parent = 0, QString name = "n.a."); - - // 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(); - -private: - QList _TrackedComponents; - - QString name; -}; - -#endif // TRACKEDOTRAJECTORY_H diff --git a/BioTracker/Utils/BioTrackerUtils/settings/Messages.h b/BioTracker/Utils/BioTrackerUtils/settings/Messages.h deleted file mode 100644 index 53e9b117..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/Messages.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -namespace BioTracker { -namespace Core { - -namespace Messages { -namespace System { - -static const std::string APPLICATION_CANNOT_START = - "Application cannot start"; -static const std::string NO_OPENGL = - "This system has no OpenGL support!"; -static const std::string MISSING_CONFIGURATION_FILE = - "Configuration file is missing! Using default parameters."; - -} - -enum class MessageType : size_t { - NOTIFICATION = 0, - WARNING, - FAIL, - FILE_OPEN -}; - -inline MessageType fromInt(const size_t v) { - return static_cast(v); -} - -} - -using Messages::MessageType; - -} -} - diff --git a/BioTracker/Utils/BioTrackerUtils/settings/ParamNames.h b/BioTracker/Utils/BioTrackerUtils/settings/ParamNames.h deleted file mode 100644 index 72b2d583..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/ParamNames.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include // std::string - -#include - -#include -#include - -namespace ConfigParam { -static const boost::filesystem::path CONFIG_PATH = boost::filesystem::path( - QDir::toNativeSeparators( - QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).toStdString()); -static const boost::filesystem::path BASE_PATH = CONFIG_PATH / "BioTracker"; -static const boost::filesystem::path CONFIGURATION_FILE = BASE_PATH / "config.json"; -static const boost::filesystem::path GEOMETRY_FILE = BASE_PATH / "geometry.cfg"; -static const boost::filesystem::path STATE_FILE = BASE_PATH / "state.cfg"; -static const boost::filesystem::path MODULE_PATH = BASE_PATH / "modules"; -} - -namespace TrackerParam { -static const std::string TRACKING_ENABLED = "TRACKERPARAM.TRACKING_ENABLED"; - -static const std::string SELECTED_TRACKER = "TRACKERPARAM.SELECTED_TRACKER"; -} - -namespace GuiParam { -enum class MediaType : uint8_t { - NoMedia = 0, - Video, - Images, - Camera -}; - -enum class VideoMode : uint8_t { - Playing = 0, - Paused, - Stopped, - Init -}; - - -static const std::string MEDIA_TYPE = "GUIPARAM.MEDIA_TYPE"; -static const std::string SHORTCUT_PLAY = "GUIPARAM.SHORTCUT_PLAY"; -static const std::string SHORTCUT_NEXT = "GUIPARAM.SHORTCUT_NEXT"; -static const std::string SHORTCUT_PREV = "GUIPARAM.SHORTCUT_PREV"; -static const std::string SHORTCUT_ZOOM = "GUIPARAM.SHORTCUT_ZOOM"; -static const std::string SHORTCUT_TRACKING = "GUIPARAM.SHORTCUT_TRACKING"; - -static const std::string PAUSED_AT_FRAME = "GUIPARAM.PAUSED_AT_FRAME"; -} - -namespace PictureParam { -//path to picture -static const std::string PICTURE_FILES = "PICTUREPARAM.PICTURE_FILES"; -} - -namespace CaptureParam { -// Video path -static const std::string CAP_VIDEO_FILE = "CAPTUREPARAM.CAP_VIDEO_FILE"; -static const std::string CAP_SCREENSHOT_PATH = - "CAPTUREPARAM.CAP_SCREENSHOT_PATH"; -static const std::string CAP_CAMERA_ID = "CAPTUREPARAM.CAP_CAMERA_ID"; - -// Video paths -static const std::string ENABLE_RECORD_RAW = - "CAPTUREPARAM.ENABLE_RECORD_RAW"; -static const std::string ENABLE_RECORD_TRACKING = - "CAPTUREPARAM.ENABLE_RECORD_TRACKING"; -static const std::string ENABLE_RECORD_TRACK_INFO = - "CAPTUREPARAM.ENABLE_RECORD_TRACK_INFO"; - -static const std::string RECORDING_TRACKING_PATH = - "CAPTUREPARAM.RECORDING_TRACKING_PATH"; -static const std::string RECORDING_RAW_PATH = - "CAPTUREPARAM.RECORDING_RAW_PATH"; -static const std::string TRACKING_INFO_OUTPUT_PATH = - "CAPTUREPARAM.TRACKING_INFO_OUTPUT_PATH"; - -enum CAP_TYPE_ENUM { - CAP_FROM_CAM = 0, - CAP_FROM_FILE = 1 -}; - -enum CAP_STATE_ENUM { - CAP_FINISHED = 0, - CAP_PAUSE = 1, - CAP_AVAILABLE = 2, - CAP_EXITED = 3 -}; -} - diff --git a/BioTracker/Utils/BioTrackerUtils/settings/Settings.cpp b/BioTracker/Utils/BioTrackerUtils/settings/Settings.cpp deleted file mode 100644 index 032891d7..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/Settings.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "settings/Settings.h" - -#include - -#include -#include - -#include "util/Exceptions.h" -#include "settings/Messages.h" - - -namespace boost { - void throw_exception(std::exception const & e) {}; -} - -namespace BioTracker { -namespace Core { - -const boost::property_tree::ptree Settings::getDefaultParams() { - boost::property_tree::ptree pt; - - return pt; -} - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/settings/Settings.h b/BioTracker/Utils/BioTrackerUtils/settings/Settings.h deleted file mode 100644 index 3a61e29a..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/Settings.h +++ /dev/null @@ -1,234 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -#include "../util/stringTools.h" // (un)escape_non_ascii -#include "StringTranslator.h" -#include "ParamNames.h" -#include -#include "util/singleton.h" - -#define GET_CORESETTINGS BioTracker::Util::TypedSingleton::getInstance - -namespace { -template class Ref> -struct is_specialization : std::false_type {}; - -template class Ref, typename... Args> -struct is_specialization, Ref>: std::true_type {}; -} - -namespace BioTracker { -namespace Core { - -class Settings { -private: - std::string _confFile; - std::mutex _m; - std::map _dataStore; - -public: - - /* This is a singleton. Get it using something like: - * SettingsIAC *myInstance = SettingsIAC::getInstance(); - */ - Settings(std::string config) { - //_m.lock(); - //Setting default file, if unset - if (config == "") _confFile = "config.ini"; - else _confFile = config; - - std::ifstream conf(_confFile.c_str()); - if (conf.good()) - { - boost::property_tree::read_json(_confFile, _ptree); - } - else { - _ptree = getDefaultParams(); - boost::property_tree::write_json(_confFile, _ptree); - } - //_m.unlock(); - } - - void storeValue(std::string key, void* value) { - _dataStore.insert(std::pair(key, value)); - } - - void* readValue(std::string key) { - std::map::iterator it = _dataStore.find(key); - if (it != _dataStore.end()) { - return it->second; - } - return nullptr; - } - - // C++ 11 style - // ======= - Settings(Settings const&) = delete; - void operator=(Settings const&) = delete; - - /** - * Sets the parameter. - * @param paramName name of the parameter, - * @param paramValue value of the parameter, - */ - template - void setParam(std::string const ¶mName, T &¶mValue) { - //_m.lock(); - _ptree.put(paramName, preprocess_value(std::forward(paramValue))); - boost::property_tree::write_json(_confFile, _ptree); - //_m.unlock(); - } - - /** - * Sets the vector of values of a parameter. - * @param paramName name of the parameter, - * @param paramVector vector of values of the parameter, - */ - template - void setParam(std::string const ¶mName, std::vector &¶mVector) { - //_m.lock(); - boost::property_tree::ptree subtree; - for (T &value : paramVector) { - boost::property_tree::ptree valuetree; - valuetree.put("", value); - subtree.push_back(std::make_pair("", valuetree)); - } - _ptree.put_child(paramName, subtree); - boost::property_tree::write_json(_confFile, _ptree); - //_m.unlock(); - } - - /** - * Gets the parameter value provided by parameter name. - * @param paramName the parameter name, - * @return the value of the parameter as the specified type. - */ - template - typename std::enable_if::value, T>::type - getValueOfParam(const std::string ¶mName) const { - //_m.lock(); - auto a = postprocess_value(_ptree.get(paramName)); - //_m.unlock(); - return a; - } - - /** - * Gets the vector of values provided by parameter name. - * - * Throws an boost exception if parameter does not exist. - * - * @param paramName the parameter name, - * @return the vector of values of the parameter with the specified type. - */ - template - typename std::enable_if::value, T>::type - getValueOfParam(const std::string ¶mName) const { - //_m.lock(); - T result; - for (auto &item : _ptree.get_child(paramName)) { - result.push_back(postprocess_value( - item.second.get_value())); - } - //_m.unlock(); - return result; - } - - /** - * Gets either the parameter value provided by parameter name, if it - * exists, or a empty boost::optional otherwise. - * @param paramName the parameter name, - * @return the value of the parameter wrapped in a boost::optional. - */ - template - boost::optional maybeGetValueOfParam(const std::string ¶mName) { - //_m.lock(); - auto a = _ptree.get_optional(paramName); - //_m.unlock(); - return a; - } - - /** - * Gets the parameter value provided by parameter name. - * If the parameter is not set yet, set to default value and return it. - * @param paramName the parameter name, - * @param defaultValue the default parameter value, - * @return the value of the parameter as the specified type. - */ - template - T getValueOrDefault(const std::string ¶mName, const T &defaultValue) { - //_m.lock(); - boost::optional value = maybeGetValueOfParam(paramName); - T t; - if (value) { - t = value.get(); - } else { - setParam(paramName, defaultValue); - t = defaultValue; - } - //_m.unlock(); - return t; - } - - private: - boost::property_tree::ptree _ptree; - - static const boost::property_tree::ptree getDefaultParams(); - - /** - * preprocesses paramValue before it's stored in the boost config tree - * - * default implementation: forward value - * - */ - template - static T preprocess_value(T &¶mValue) { - return std::forward(paramValue); - } - - /** - * postprocesses paramValue after it's extracted from the boost config tree - * - * default implementation: forward value - * - */ - template - static T postprocess_value(T &¶mValue) { - return std::forward(paramValue); - } - -}; - -/** - * std::string specialisation as a workaround for a bug in boost's config tree - * - * this function escapes every non-ASCII character - * - * (the tree correctly escapes non-ASCII characters and stores them - * as "\u00XX" where XX is the character's hex value, but it can't read these - * values correctly) - * - */ -template<> -inline std::string Settings::preprocess_value(std::string &¶mValue) { - return Util::escape_non_ascii(paramValue); -} - -/** - * std::string specialisation as a workaround for a bug in boost's config tree - * - * (the tree converts escaped non-ASCII characters ("\u00XX") to "\xFF") - * - */ -template<> -inline std::string Settings::postprocess_value(std::string &¶mValue) { - return Util::unescape_non_ascii(paramValue); -} - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/settings/StringTranslator.cpp b/BioTracker/Utils/BioTrackerUtils/settings/StringTranslator.cpp deleted file mode 100644 index 7b91e3e3..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/StringTranslator.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "settings/StringTranslator.h" - -namespace { -typedef GuiParam::MediaType EnumType; -} - -namespace StringTranslator { -template<> -const BiMapContainer::bm_type BiMapContainer::value = - boost::assign::list_of::bm_type::relation> - (EnumType::NoMedia, "NoMedia") - (EnumType::Images, "Images") - (EnumType::Video, "Video"); -} diff --git a/BioTracker/Utils/BioTrackerUtils/settings/StringTranslator.h b/BioTracker/Utils/BioTrackerUtils/settings/StringTranslator.h deleted file mode 100644 index 7a64c709..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/StringTranslator.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "ParamNames.h" - -namespace StringTranslator { - -template -struct BiMapContainer { - typedef boost::bimap bm_type; - typename bm_type::relation bm_relation; - static const bm_type value; -}; - -// enables conversion from/to an arbitrary type and an std::string by using -// a boost::bimap. Requires a template specialization of BiMapContainer with -// external_type. -template -struct StringTranslator { - typedef std::string internal_type; - typename BiMapContainer::bm_type bm_type; - - const boost::bimap bimap = - BiMapContainer::value; - - boost::optional get_value(const internal_type &internal) { - return boost::optional(bimap.right.at(internal)); - } - - boost::optional put_value(const external_type &external) { - return boost::optional(bimap.left.at(external)); - } -}; - -} - -namespace boost { -namespace property_tree { - -// template specialization for EnumTranslator for GUIPARAM::MediaType -// this allows boost::property_tree to store a string representation of -// MediaType in the settings file -template<> -struct translator_between { - typedef StringTranslator::StringTranslator type; -}; - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/settings/SystemCompatibilityCheck.cpp b/BioTracker/Utils/BioTrackerUtils/settings/SystemCompatibilityCheck.cpp deleted file mode 100644 index 4db315bf..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/SystemCompatibilityCheck.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "settings/SystemCompatibilityCheck.h" - -//#include - -bool SystemCompatibilityCheck::checkOpenGLSupport() { - return true;//QGLFormat::hasOpenGL(); -} diff --git a/BioTracker/Utils/BioTrackerUtils/settings/SystemCompatibilityCheck.h b/BioTracker/Utils/BioTrackerUtils/settings/SystemCompatibilityCheck.h deleted file mode 100644 index 829f1af1..00000000 --- a/BioTracker/Utils/BioTrackerUtils/settings/SystemCompatibilityCheck.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "util/platform.h" - -namespace SystemCompatibilityCheck { -/** - * Check the system supports openGL. - * @return true, system supports openGL, false otherwise. - */ -bool BIOTRACKER_DLLEXPORT checkOpenGLSupport(); -} - diff --git a/BioTracker/Utils/BioTrackerUtils/util/CvHelper.cpp b/BioTracker/Utils/BioTrackerUtils/util/CvHelper.cpp deleted file mode 100644 index bc0146bc..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/CvHelper.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * CvHelper.cpp - * - * Created on: May 12, 2015 - * Author: tobias - */ - -#include "util/CvHelper.h" - -namespace BioTracker { -namespace Core { -namespace CvHelper { - -std::string cvDataType2str(int type) { - const int depth = CV_MAT_DEPTH(type); - const int cn = CV_MAT_CN(type); - std::string result = "CV_"; - - switch (depth) { - case CV_8U: - result += "8U"; - break; - case CV_8S: - result += "8S"; - break; - case CV_16U: - result += "16U"; - break; - case CV_16S: - result += "16S"; - break; - case CV_32S: - result += "32S"; - break; - case CV_32F: - result += "32F"; - break; - case CV_64F: - result += "64F"; - break; - default: - result += "UNKOWN"; - break; - } - result += "C" + std::to_string(cn); - return result; -} - -} -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/CvHelper.h b/BioTracker/Utils/BioTrackerUtils/util/CvHelper.h deleted file mode 100644 index 606e9984..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/CvHelper.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include // cv::Point, cv::Rect -#include // QRect -#include // QPoint -#include // std::string; std::to_string(int) - -/** - * Computer vision helper functions - */ -namespace BioTracker { -namespace Core { -namespace CvHelper { -struct cv_point_compare_less_x { - template - bool operator()(const CV_POINT &lhs, const CV_POINT &rhs) const { - return lhs.x < rhs.x; - } -}; - -struct cv_point_compare_less_y { - template - bool operator()(const CV_POINT &lhs, const CV_POINT &rhs) const { - return lhs.y < rhs.y; - } -}; - -inline cv::Rect toCv(const QRect &rect) { - return cv::Rect(rect.x(), rect.y(), rect.width(), rect.height()); -} - -inline QRect toQt(const cv::Rect &rect) { - return QRect(rect.x,rect.y,rect.width,rect.height); -} - -inline QPoint toQt(const cv::Point &point) { - return QPoint(point.x, point.y); -} - -/** - * @see: http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare - */ -struct cv_vec_compare_less_lexicographically { - template - bool operator()(const CV_VEC &lhs, const CV_VEC &rhs) const { - for (int i = 0; i < CV_VEC::channels; ++i) { - if (lhs[i] < rhs[i]) { - return true; - } - if (rhs[i] < lhs[i]) { - return false; - } - } - return false; - } -}; - -/** - * converts an opencv data type value (int) to the name of the corresponding macro i.e. "CV_\d+[UFS]C\d" - * - * @see: cv::DataType::type - * - * @example: - * CvHelper::cvDataType2str( CV_8UC3 ) --> std::string( "CV_8UC3" ) - * - */ -std::string cvDataType2str(int type); - -} -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/Exceptions.h b/BioTracker/Utils/BioTrackerUtils/util/Exceptions.h deleted file mode 100644 index d31b8df8..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/Exceptions.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - - -namespace BioTracker { -namespace Core { - -struct video_open_error : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct file_not_found : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct directory_not_found : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct device_open_error : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct invalid_tracker_lib_error : std::invalid_argument { - using std::invalid_argument::invalid_argument; -}; - -struct path_creation_error : std::runtime_error { - using std::runtime_error::runtime_error; -}; - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/MutexWrapper.h b/BioTracker/Utils/BioTrackerUtils/util/MutexWrapper.h deleted file mode 100644 index 760626cd..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/MutexWrapper.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H -#define THREAD_SAFETY_ANALYSIS_MUTEX_H - -#include - -// Enable thread safety attributes only with clang. -// The attributes can be safely erased when compiling with other compilers. -#if defined(__clang__) && (!defined(SWIG)) -#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op -#endif - -#define CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) - -#define SCOPED_CAPABILITY \ - THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -#define GUARDED_BY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -#define PT_GUARDED_BY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -#define ACQUIRED_BEFORE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -#define ACQUIRED_AFTER(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define REQUIRES(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) - -#define REQUIRES_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) - -#define ACQUIRE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) - -#define ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) - -#define RELEASE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) - -#define RELEASE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) - -#define TRY_ACQUIRE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) - -#define TRY_ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) - -#define EXCLUDES(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -#define ASSERT_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) - -#define ASSERT_SHARED_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) - -#define RETURN_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -#define NO_THREAD_SAFETY_ANALYSIS \ - THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - - -// Defines an annotated interface for mutexes. -// These methods can be implemented to use any internal mutex implementation. -class CAPABILITY("mutex") Mutex { - public: - // Acquire/lock this mutex exclusively. Only one thread can have exclusive - // access at any one time. Write operations to guarded data require an - // exclusive lock. - void Lock() ACQUIRE() { - mutex.lock(); - } - - // Acquire/lock this mutex for read operations, which require only a shared - // lock. This assumes a multiple-reader, single writer semantics. Multiple - // threads may acquire the mutex simultaneously as readers, but a writer - // must wait for all of them to release the mutex before it can acquire it - // exclusively. - void ReaderLock() ACQUIRE_SHARED(); - - // Release/unlock an exclusive mutex. - void Unlock() RELEASE() { - mutex.unlock(); - } - - // Release/unlock a shared mutex. - void ReaderUnlock() RELEASE_SHARED(); - - // Try to acquire the mutex. Returns true on success, and false on failure. - bool TryLock() TRY_ACQUIRE(true) { - return mutex.try_lock(); - } - - // Try to acquire the mutex for read operations. - bool ReaderTryLock() TRY_ACQUIRE_SHARED(true); - - // Assert that this mutex is currently held by the calling thread. - void AssertHeld() ASSERT_CAPABILITY(this); - - // Assert that is mutex is currently held for read operations. - void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this); - private: - std::mutex mutex; -}; - - -// MutexLocker is an RAII class that acquires a mutex in its constructor, and -// releases it in its destructor. -class SCOPED_CAPABILITY MutexLocker { - private: - Mutex &mutex; - - public: - MutexLocker(Mutex &mu) ACQUIRE(mu) : mutex(mu) { - mutex.Lock(); - } - ~MutexLocker() RELEASE() { - mutex.Unlock(); - } -}; - - -#ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES -// The original version of thread safety analysis the following attribute -// definitions. These use a lock-based terminology. They are still in use -// by existing thread safety code, and will continue to be supported. - -// Deprecated. -#define PT_GUARDED_VAR \ - THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded) - -// Deprecated. -#define GUARDED_VAR \ - THREAD_ANNOTATION_ATTRIBUTE__(guarded) - -// Replaced by REQUIRES -#define EXCLUSIVE_LOCKS_REQUIRED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) - -// Replaced by REQUIRES_SHARED -#define SHARED_LOCKS_REQUIRED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) - -// Replaced by CAPABILITY -#define LOCKABLE \ - THREAD_ANNOTATION_ATTRIBUTE__(lockable) - -// Replaced by SCOPED_CAPABILITY -#define SCOPED_LOCKABLE \ - THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -// Replaced by ACQUIRE -#define EXCLUSIVE_LOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) - -// Replaced by ACQUIRE_SHARED -#define SHARED_LOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) - -// Replaced by RELEASE and RELEASE_SHARED -#define UNLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) - -// Replaced by TRY_ACQUIRE -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) - -// Replaced by TRY_ACQUIRE_SHARED -#define SHARED_TRYLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) - -// Replaced by ASSERT_CAPABILITY -#define ASSERT_EXCLUSIVE_LOCK(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) - -// Replaced by ASSERT_SHARED_CAPABILITY -#define ASSERT_SHARED_LOCK(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) - -// Replaced by EXCLUDE_CAPABILITY. -#define LOCKS_EXCLUDED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -// Replaced by RETURN_CAPABILITY -#define LOCK_RETURNED(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -#endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES - -#endif // THREAD_SAFETY_ANALYSIS_MUTEX_H diff --git a/BioTracker/Utils/BioTrackerUtils/util/PanZoomState.h b/BioTracker/Utils/BioTrackerUtils/util/PanZoomState.h deleted file mode 100644 index e273fc3d..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/PanZoomState.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "boost/optional.hpp" - -namespace BioTracker { -namespace Core { - -/** -* @brief Used to store mouse cursor offsets while panning. -*/ -struct CurrentPanState { - QPointF lastPos; - - CurrentPanState(const QPointF lastPos) - : lastPos(lastPos) { - } -}; - -/** - * @brief Stores the current zoom and pan offsets. While panning, panState stores the last mouse cursor position. - */ -struct PanZoomState { - float zoomFactor = 0.f; - float panX = 0.f; - float panY = 0.f; - bool isChanged = false; - - boost::optional panState; -}; - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/QtRaiiWrapper.hpp b/BioTracker/Utils/BioTrackerUtils/util/QtRaiiWrapper.hpp deleted file mode 100644 index cc4b626f..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/QtRaiiWrapper.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -namespace BioTracker { -namespace Util { - -/** - * source: http://stackoverflow.com/a/28125217 - */ -template class QtRaiiWrapper : public UiClass -{ -public: - QtRaiiWrapper(ParentClass *parent) - { - this->setupUi(parent); - } -}; - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/ScreenHelper.h b/BioTracker/Utils/BioTrackerUtils/util/ScreenHelper.h deleted file mode 100644 index ee8496ad..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/ScreenHelper.h +++ /dev/null @@ -1,208 +0,0 @@ -#pragma once - -#include // QRect -#include // QPoint -#include "PanZoomState.h" -#include "math.h" - -/** - * Screen helper functions - */ -namespace BioTracker { -namespace Core { -namespace ScreenHelper { - -/** - * @brief calculate_viewport - * @param im_w width of the image - * @param im_h height of the image - * @param w width of the videoview - * @param h height of the videoview - * @param window OUT parameter - * @param viewport OUT parameter - */ -inline float calculate_viewport( - const int im_w, const int im_h, - const int w, const int h, - QRect &window, QRect &viewport) { - - // We use setWindow and setViewport to fit the video into the - // given video widget frame (with width "w" and height "h") - // we later need to adjust an offset caused the use of different - // dimensions for window and viewport. - const float im_wf = static_cast(im_w); - const float im_hf = static_cast(im_h); - const float w_f = static_cast(w); - const float h_f = static_cast(h); - - float ratio = 0; - int offset_top = 0; - int offset_left = 0; - - if ((im_wf/im_hf) > (w_f/h_f)) { - // image ratio is bigger (wider image than window) - ratio = im_wf / w_f; - const float px = w_f / im_wf; - const float px_im_hf = px * im_hf; - offset_top = h/2 - static_cast(px_im_hf / 2); - } else { - // window ratio is bigger (narrow image) - ratio = im_hf / h_f; - const float px = h_f / im_hf; - const float px_im_wf = px * im_wf; - offset_left = w/2 - static_cast(px_im_wf / 2); - } - - const int screen_w = static_cast(im_wf * ratio); - const int screen_h = static_cast(im_hf * ratio); - - window.setX(0); - window.setY(0); - window.setWidth(screen_w); - window.setHeight(screen_h); - - viewport.setX(offset_left); - viewport.setY(offset_top); - viewport.setWidth(im_w); - viewport.setHeight(im_h); - - // adjust the panning as the viewport is potentially scewed - // and mouse movements given by the window are not translated - // one-to-one anymore - return screen_w / im_wf; -} - -/** - * @brief getImDimsInScreenCoords - * Calculates the actual dimension of the image with all zoom, pan and - * viewport transformations applied - * @return a rectangle that represents the position and dimension of the - * image in the videoview element - */ -inline QRect getImDimsInScreenCoords( - const PanZoomState zoomState, - const int im_w, const int im_h, - const int w, const int h) { - - QRect viewport, window; - const float viewportRatio = calculate_viewport(im_w, im_h, w, h, window, viewport); - const float zoom = 1 + zoomState.zoomFactor; - // back-translate the pan to non-zoomed coordinate space - float realPanX = -zoomState.panX; - float realPanY = -zoomState.panY; - realPanX += (viewport.x()); - realPanY += (viewport.y()); - - // The image in screen coords - QRect actualIm( - static_cast(realPanX), static_cast(realPanY), - static_cast((im_w / viewportRatio) * zoom), - static_cast((im_h / viewportRatio) * zoom) - ); - return actualIm; -} - -/** - * @brief imageToScreenCoords - */ -inline QPoint imageToScreenCoords( - const PanZoomState zoomState, - const int im_w, const int im_h, - const int w, const int h, - const QPoint poi) { - QPoint result; - const QRect actualIm = getImDimsInScreenCoords(zoomState, im_w, im_h, w, h); - const float one_step_x = actualIm.width() / static_cast(im_w); - const float one_step_y = actualIm.height() / static_cast(im_h); - const int actualPosXInIm = static_cast(round(poi.x() * one_step_x)); - const int actualPosYInIm = static_cast(round(poi.y() * one_step_y)); - result.setX(actualPosXInIm + actualIm.x()); - result.setY(actualPosYInIm + actualIm.y()); - return result; -} - -/** - * @brief screenToImageCoords - * Translate the window coordinates to the actual image coords - * @param im_w image width - * @param im_h image height - * @param w width of the videoview - * @param h height of the videoview - * @param poi Point in Screen Coords - */ -inline QPoint screenToImageCoords( - const BioTracker::Core::PanZoomState zoomState, - const int im_w, const int im_h, - const int w, const int h, - QPoint poi) { - QPoint result(0, 0); - - // The image in screen coords - QRect actualIm = getImDimsInScreenCoords(zoomState, im_w, im_h, w, h); - - const float im_wf = static_cast(im_w); - const float im_hf = static_cast(im_h); - const float one_step_x = im_wf / actualIm.width(); - const float one_step_y = im_hf / actualIm.height(); - - const float transformedX = (-actualIm.x() + poi.x()) * one_step_x; - const float transformedY = (-actualIm.y() + poi.y()) * one_step_y; - - result.setX(static_cast(round(transformedX))); - result.setY(static_cast(round(transformedY))); - - return result; -} - -/** - * @brief zoomTo - * Modifies the panzoomstate so that the cursor (zoomCenter) will point to the same - * location in the image as prior to the zoom - * @param im_w width of the image (in px) - * @param im_h height of the image (in px) - * @param w width of the videoview element - * @param h height of the videoview element - */ -inline PanZoomState zoomTo( - PanZoomState state, - const int im_w, - const int im_h, - const int w, - const int h, - const float deltaZoom, - const QPoint zoomCenter) { - - const QPoint imPos = screenToImageCoords(state, im_w, im_h, w, h, zoomCenter); - - const float oldZoomFactor = state.zoomFactor; - const float newZoomFactor = state.zoomFactor - (deltaZoom/2000); - - if (newZoomFactor <= -1.0f) { - // MAX VALUE - return state; - } - - const float zoom = 1 + newZoomFactor; - - const float oldPanX = state.panX / (1 + oldZoomFactor); - const float oldPanY = state.panY / (1 + oldZoomFactor); - - // zoom with origin in (0/0) - state.panX = oldPanX * zoom; - state.panY = oldPanY * zoom; - state.zoomFactor = newZoomFactor; - - // As we do not want to zoom to (0/0) but rather keep the focus on the chosen - // image position (zoomCenter) we now have to "back-translate" to our initial - // position - const QPoint translatedZoomCenter = imageToScreenCoords(state, im_w, im_h, w, h, imPos); - const QPoint translate = translatedZoomCenter - zoomCenter; - state.panX += translate.x(); - state.panY += translate.y(); - state.isChanged = true; - return state; -} - -} -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/imagePreProcessor/IImageProcessor.h b/BioTracker/Utils/BioTrackerUtils/util/imagePreProcessor/IImageProcessor.h deleted file mode 100644 index 6845a963..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/imagePreProcessor/IImageProcessor.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -class Rectification; -class Settings; - - -class IImageProcessor { - public: - IImageProcessor(Rectification &rectification, Settings &settings) : - _rectification(rectification), - _settings(settings) { - } - - virtual ~IImageProcessor(void) {} - - /** - * This method processed the image and detects the found object. - * @param image, the image to process, - * @return void. - */ - virtual void process(cv::Mat image) = 0; - - protected: - const Rectification &_rectification; - Settings &_settings; -}; - diff --git a/BioTracker/Utils/BioTrackerUtils/util/imagePreProcessor/ImagePreProcessor.h b/BioTracker/Utils/BioTrackerUtils/util/imagePreProcessor/ImagePreProcessor.h deleted file mode 100644 index 25718b69..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/imagePreProcessor/ImagePreProcessor.h +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once - -#include - -#include "util/stdext.h" - -namespace BioTracker { -namespace Core { - -namespace PREPROCESSORPARAM { -// Parameter for the opencv BackgroundSubtractorMOG2 class -static const std::string BG_MOG2_HISTORY = - "TRACKERPARAM.BG_MOG2_HISTORY"; -static const std::string BG_MOG2_VAR_THRESHOLD = - "TRACKERPARAM.BG_MOG2_VAR_THRESHOLD"; -static const std::string BG_MOG2_SHADOW_DETECTION = - "TRACKERPARAM.BG_MOG2_SHADOW_DETECTION"; -static const std::string BG_MOG2_BACKGROUND_RATIO = - "TRACKERPARAM.BG_MOG2_BACKGROUND_RATIO"; - -// Parameters for enabling methods -static const std::string ENABLE_BG_SUBTRACTION = - "TRACKERPARAM.ENABLE_BG_SUBTRACTION"; -static const std::string ENABLE_BG_IMAGE = - "TRACKERPARAM.ENABLE_BG_IMAGE"; -static const std::string ENABLE_BINARIZING = - "TRACKERPARAM.ENABLE_BINARIZING"; -static const std::string ENABLE_ERODE = - "TRACKERPARAM.ENABLE_ERODE"; -static const std::string ENABLE_DILATE = - "TRACKERPARAM.ENABLE_DILATE"; -static const std::string IMAGE_VIEW_TYPE = - "TRACKERPARAM.IMAGE_VIEW_TYPE"; - -// Mapping issue -static const std::string MAX_MAPPED_DISTANCE_PX = - "TRACKERPARAM.MAX_MAPPED_DISTANCE_PX"; -static const std::string MAX_MAPPED_DISTANCE_CM = - "TRACKERPARAM.MAX_MAPPED_DISTANCE_CM"; - -// Blob dectection issue -static const std::string MAX_BLOB_SIZE = - "TRACKERPARAM.MAX_BLOB_SIZE"; -static const std::string MIN_BLOB_SIZE = - "TRACKERPARAM.MIN_BLOB_SIZE"; - -// Parameters for image pre-processing step -static const std::string SIZE_ERODE = "TRACKERPARAM.SIZE_ERODE"; -static const std::string SIZE_DILATE = - "TRACKERPARAM.SIZE_DILATE"; -static const std::string THRESHOLD_BINARIZING = - "TRACKERPARAM.THRESHOLD_BINARIZING"; - -// Image processing type -enum IMAGE_DISPLAY_TYPE { - IMAGE_OR = 0, - IMAGE_BI = 1, - IMAGE_ER = 2, - IMAGE_DI = 3, - IMAGE_FG = 4, - IMAGE_BG = 5, - IMAGE_PP = 6, -}; -} - -class Settings; - -class ImagePreProcessor { - public: - - /** - * The constructor with provided parameters. - * @param settings reference to the biotracker settings object - */ - ImagePreProcessor(Settings &settings); - - /** - * Init function. Sets the property for the imge pre-processing. - */ - void init(); - - /** - * A computer vision method to binarize an image. - * @param image image to binarize, - * @return a binarized image. - */ - cv::Mat binarize(cv::Mat image); - - /** - * Sets the threshold value for a parameter - * @param paramName the parameter name, - * @param threshValue threshold value, - */ - void setThreshold(std::string paramName, std::string threshValue); - - /** - * 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, - */ - void preProcess(cv::Mat image); - - /** - * The method updates the image background. - */ - void resetBackgroundImage(); - - /** - * Method to enable image pre-processing methods - * @param enableProcess specifies the process to enable or disable, - * @param enable true to enable, false to disable. - */ - void setEnable(std::string enableProcess, bool enable = true); - - /** - * Gets displayed image type for displaying it. - * @param imageDisplayType kind of image need to retrieve. - * Hint: IMAGE_BI, binarized image, - * IMAGE_ER, eroded image, - * IMAGE_DI, dilated image, - * IMAGE_FG, foreground mask image, - * IMAGE_BG, background image, - * IMAGE_PP, final proceedied image, - * @return type of image. - */ - cv::Mat imageDisplayType(PREPROCESSORPARAM::IMAGE_DISPLAY_TYPE - imageDisplayType); - - private: - // System properties - Settings &_settings; - - // variable of the various processing image - cv::Mat _original; - cv::Mat _proceededImage; - cv::Mat _fgMaskMOG; - cv::Mat _backgroundImage; - cv::Mat _binarizedImage; - cv::Mat _erodedImage; - cv::Mat _dilatedImage; - - // background subtraction - std::unique_ptr _pMOG; - - //parameters for image pre-processing - bool _backgroundSubtractionEnabled; - bool _backgroundEnabled; - bool _binarizeEnabled; - bool _erodeEnabled; - bool _dilateEnabled; -}; - -} -} - diff --git a/BioTracker/Utils/BioTrackerUtils/util/misc.cpp b/BioTracker/Utils/BioTrackerUtils/util/misc.cpp deleted file mode 100644 index 6fcf6deb..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/misc.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "util/misc.h" - -#include // QPoint -#include -#include - -int split(std::string &txt, std::vector &strs, char ch) -{ - 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)); - initialPos = pos + 1; - - pos = txt.find(ch, initialPos); - } - - // Add the last one - strs.push_back(txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1)); - - return strs.size(); -} - -std::string getTimeAndDate(std::string prefix, std::string suffix) -{ - // time_t timetitle; - // std::string timeInfo = prefix; - // time(&timetitle); - // std::string t = ctime(&timetitle); - // for (int i = 0; i < t.size(); i++) - // if (t[i] == ' ' || t[i] == ':') - // t[i] = '_'; - // timeInfo += t.substr(0, t.size() - 1); - // timeInfo += suffix; - // return timeInfo; - - - - - time_t rawtime; - struct tm * timeinfo; - - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - - char t[30]; - strftime(t, 30, "%Y-%m-%dT%H_%M_%S", timeinfo); // - - std::string out = prefix; - - std::string timeStampF(t); - - out += timeStampF; - out += suffix; - - return out; -} - -std::vector stringToCVPointVec(std::string arena) { - std::vector pts; - - QString qarena(arena.c_str()); - QStringList corners = qarena.split(";"); - for (int i = 0; i < corners.size(); i++) { - QString cur = corners.at(i); - QStringList p = cur.split(","); - pts.push_back(cv::Point(p.at(0).toInt(), p.at(1).toInt())); - } - return pts; -} - - -std::vector QVecToCvVec(std::vector q) { - std::vector v; - for (int i = 0; i < q.size(); i++) - v.push_back(cv::Point(q[i].x(), q[i].y())); - return v; -} -std::vector CvVecToQVec(std::vector q) { - std::vector v; - for (int i = 0; i < q.size(); i++) - v.push_back(QPoint(q[i].x, q[i].y)); - return v; -} - -std::string cvPointsToString(std::vector ac) { - - std::string arena = ""; - for (int i = 0; i < ac.size(); i++) - arena += (std::to_string(ac[i].x) + "," + std::to_string(ac[i].y) + ";"); - return arena.substr(0, arena.size() - 1); -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/misc.h b/BioTracker/Utils/BioTrackerUtils/util/misc.h deleted file mode 100644 index dc685031..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/misc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef MISC_H -#define MISC_H -#include -#include -#include -#include - -int split(std::string &txt, std::vector &strs, char ch); -std::string getTimeAndDate(std::string prefix, std::string suffix); -std::vector stringToCVPointVec(std::string arena); -std::vector QVecToCvVec(std::vector q); -std::string cvPointsToString(std::vector ac); -std::vector CvVecToQVec(std::vector q); -#endif \ No newline at end of file diff --git a/BioTracker/Utils/BioTrackerUtils/util/platform.h b/BioTracker/Utils/BioTrackerUtils/util/platform.h deleted file mode 100644 index 53dd43b0..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/platform.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -/* -This macro must be used to mark all symbols that should be exported to a DLL. -*/ -#ifdef _MSC_VER -#ifdef BUILD_BIOTRACKER_DLL -#define BIOTRACKER_DLLEXPORT __declspec(dllexport) -#define BIOTRACKER_EXPIMP_TEMPLATE -#else -#define BIOTRACKER_DLLEXPORT __declspec(dllimport) -#define BIOTRACKER_EXPIMP_TEMPLATE extern -#endif -#else -#define BIOTRACKER_DLLEXPORT -#endif diff --git a/BioTracker/Utils/BioTrackerUtils/util/singleton.h b/BioTracker/Utils/BioTrackerUtils/util/singleton.h deleted file mode 100644 index d171b6b9..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/singleton.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include -#include "settings/Settings.h" - -namespace BioTracker { -namespace Util { - -template -class Singleton { - - protected: - Singleton() {} - ~Singleton() {} - Singleton(const Singleton &) = delete; - Singleton &operator=(const Singleton &) = delete; - - public: - static T &getInstance(); - -}; - -template -T &Singleton::getInstance() { - static T instance; - return instance; -} - -/* - * Just like Singleton, but I want to have several different singleton instances of the same type which I can address by name. - * Example is the Settings class, which is also threadsafe by plastering it with mutexes. - * This way you can access everywhere in the application the current configuration from different threads without worries. - * Only recommendet, as performance is not relevant when accessing configuration. -*/ -template -class TypedSingleton { - -protected: - TypedSingleton() {} - ~TypedSingleton() {} - TypedSingleton(const TypedSingleton &) = delete; - TypedSingleton &operator=(const TypedSingleton &) = delete; - -public: - static T *getInstance(std::string s); - -}; - -template -T *TypedSingleton::getInstance(std::string s) { - static std::map instance; - if (instance.find(s) != instance.end()) { - return instance.find(s)->second; - } - else { - T* t = new T(s); - instance.insert(std::pair(s, t)); - return t; - } - return 0; -} - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/stdext.h b/BioTracker/Utils/BioTrackerUtils/util/stdext.h deleted file mode 100644 index ada7c5d7..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/stdext.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef STDEXT_H -#define STDEXT_H - -/* implementation of std::make_unique for c++<14 - * implementation according to N3656 - * see: http://isocpp.org/files/papers/N3656.txt - */ - -#include -#if (!defined(_MSC_VER) && __cplusplus <= 201103L) || (defined(_MSC_VER) && _MSC_VER < 1800) -#include -#include -#include - -namespace std { -template struct _Unique_if { - typedef unique_ptr _Single_object; -}; - -template struct _Unique_if { - typedef unique_ptr _Unknown_bound; -}; - -template struct _Unique_if { - typedef void _Known_bound; -}; - -template -typename _Unique_if::_Single_object -make_unique(Args &&... args) { - return unique_ptr(new T(std::forward(args)...)); -} - -template -typename _Unique_if::_Unknown_bound -make_unique(size_t n) { - typedef typename remove_extent::type U; - return unique_ptr(new U[n]()); -} - -template -typename _Unique_if::_Known_bound -make_unique(Args &&...) = delete; -} -#endif - -#endif diff --git a/BioTracker/Utils/BioTrackerUtils/util/stringTools.cpp b/BioTracker/Utils/BioTrackerUtils/util/stringTools.cpp deleted file mode 100644 index 6365a622..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/stringTools.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -#include // std::string -#include // std::invalid_argument - -#include "util/platform.h" - -namespace BioTracker { -namespace Util { - - -} -} diff --git a/BioTracker/Utils/BioTrackerUtils/util/stringTools.h b/BioTracker/Utils/BioTrackerUtils/util/stringTools.h deleted file mode 100644 index 2334a24d..00000000 --- a/BioTracker/Utils/BioTrackerUtils/util/stringTools.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include - -namespace BioTracker { -namespace Util { - -/** - * replaces every non-ASCII character in s with an escape sequence containing the hexadecimal representation of it's value. - * - * Additionally backslashes are escaped too, since this character is used to initiate an escape sequence. - * - * The value of a valid ASCII is [0, 127]. - * - * replacement map: - * ---------------- - * "\" --> "\\" - * non-ASCII --> "\x{2 digit hex value}" - * ASCII --> ASCII - * - */ -std::string escape_non_ascii(const std::string &s); - - -/** - * unescapes escaped (non-)ASCII characters. - * - * replacement map: - * ---------------- - * "\\" --> "\" - * "\x{2 hex digits}" --> character - * ASCII --> ASCII - * everything else --> exception - * - * @see escape_non_ascii - * - */ -std::string unescape_non_ascii(const std::string &s); - -/** - * @brief stem_filename - * stems the filename from a path - */ -std::string stem_filename(const std::string &s); - -} -} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..61773d02 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.15) + +exec_program("git" ${CMAKE_CURRENT_SOURCE_DIR} ARGS "describe --dirty --always" OUTPUT_VARIABLE SOURCE_VERSION) + +project(BioTracker + LANGUAGES CXX +) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(HMNVLibDir "Not Found" CACHE FILEPATH "") + +if( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) + find_package(biotracker-utility REQUIRED) +endif() + +add_subdirectory(Src) diff --git a/README.md b/README.md index 4ab2352b..67bc021c 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,60 @@ # README -## Running Biotracker 3 from prebuild binaries: +[![Build Status](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/biotracker/badges/master/build.svg)](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/biotracker/pipelines) -Binaries are distributed via Github: https://github.com/BioroboticsLab/biotracker_core/releases +# README -## Build dependencies +## Using BioTracker + +See the [wiki](https://github.com/BioroboticsLab/biotracker_core/wiki). -Building the Biotracker 3 needs: -- opencv build (>3.0) -- QT build (>= 5.4) -- Boost build -- CMake GUI (any version should be OK, but boost detection may vary) +## Running BioTracker from prebuild binaries: -## Building Biotracker 3 (Windows x64) +The releases github page provides stable version. +Most recent binaries can be grabbed from the pipeline. +- [BioTracker core application](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/biotracker/pipelines) +- Some trackers. For example the [Background subtraction tracker](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/backgroundsubtraction_tracker/pipelines) -Following example will use Visual Studio 2015, OpenCv 3.2, QT 5.9 and boost_1_64, all x64. -You will need to tell CMake where to find the libraries. You can do this via GUI when asked or set enviromental variables. +## Building trackers against prebuild BioTracker -Set: -- QT_DIR_CMAKE64, E.g. E:\Software\Libraries\QT\5.9\msvc2015_64\lib\cmake\Qt5 -- CV_DIR_CMAKE64, E.g. E:\Software\Libraries\opencv\build -- BOOST_LIBRARYDIR, E.g. E:\Software\Libraries\boost_1_65_1\stage64\lib -- BOOST_ROOT, E.g. E:\Software\Libraries\boost_1_65_1 -Note that your path's and library version may differ. +This will enable you to only build your own plugin without having to care about the robotracker toolchaining/dependencies/etc.. +- Download [Interfaces](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/interfaces/pipelines) project and add it to your toolchain (e.g. cmake prefix path) +- Optional: Do the same for the [utility](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/utility/pipelines) project, if you need it +- Download and install the [BioTracker core application](https://git.imp.fu-berlin.de/bioroboticslab/biotracker/biotracker/pipelines) +- It might be helpful to use some basic tracker as a template: https://github.com/BioroboticsLab/biotracker_sampletracker +- Make sure to implement the IBehavior interface +- Build +- Put your artifact in the Plugins section +- Run and Enjoy + +## Build dependencies -Building with NVEnc is comming soon. Meanwhile ignore "HMNVLibDir=Not Found", it will build with CPU encoding only. +Building the BioTracker needs: +- opencv (> 3.0) +- QT (>= 5.4) +- Boost +- CMake (>= 3.13) +- Buildtools (Tested: MSVC buildtools or g++) +- recommendet: ninja -Now configure, generate, open and build for Debug/Release. The build is dynamically linked, which means you will need to supply the DLL's to your newly build binary. Qt offers the windeployqt utility. Usage sample, console: -C:\Users\Hauke>E:\Software\Libraries\QT\5.9\msvc2015_64\bin\windeployqt.exe E:\Development\Hauke\biotracker_core\BioTracker\CoreApp\BioTracker\Release\Biotracker_core.exe -OpenCv does not come with such a utility and you need to copy the DLL's manually from e.g.: -E:\Software\Libraries\opencv\build\bin\Release (or Debug, respectively) -Boost libraries are not needed to be copied. +## Building BioTracker (Windows x64) -Congratulations! You build the Biotracker 3! +The [dockerfile](https://git.imp.fu-berlin.de/bioroboticslab/robofish/docker) documents the dependency installation: (includes dependencies for all projects, e.g. BioTracker, interfaces, ...) + +Install and configure those dependencies. A shorthand to the dockerfile is using [vcpkg](https://git.imp.fu-berlin.de/bioroboticslab/robofish/vcpkg) +Get the boost and opencv packages: +` vcpkg install boost-property-tree:x64-windows-14.16 boost-bimap:x64-windows-14.16 boost-assign:x64-windows-14.16 boost-system:x64-windows-14.16 boost-filesystem:x64-windows-14.16 boost-chrono:x64-windows-14.16 boost-timer:x64-windows-14.16 boost-program-options:x64-windows-14.16 ` +`vcpkg install openblas:x64-windows-14.16 opencv[opengl,ffmpeg,ximea,cuda]:x64-windows-14.16 ` +... and Qt systemwide using Qt5_dir +Now call cmake with some switches to include vcpkg: `-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-14.16` +... and build. +Proceed withe the build steps as in the linux section. -## Building Biotracker 3 (Linux) +## Building BioTracker (Linux) -Having set all the library paths you can build it just like any cmake project: -git clone https://github.com/BioroboticsLab/biotracker_core.git -cd biotracker_core -mkdir build -cd build -cmake ../BioTracker -make +The [dockerfile](https://git.imp.fu-berlin.de/bioroboticslab/robofish/docker) documents the dependency installation: (includes dependencies for all projects, e.g. BioTracker, interfaces, ...) +Having set all the library paths you can build it just like any cmake project. It's split into a few repositories for modularization. Clone, build and install them in order: [Interfaces](https://github.com/BioroboticsLab/biotracker_interfaces), [Utility](https://github.com/BioroboticsLab/biotracker_utility), [Behavior loader](https://github.com/BioroboticsLab/behavior_loader), the [BioTracker](https://github.com/BioroboticsLab/biotracker_core) itself and any tracking plugin of your liking, eg. the [Background subtraction tracker](https://github.com/BioroboticsLab/biotracker_backgroundsubtraction_tracker). -## Building Biotracker 3 (OSX) +## Building BioTracker (OSX) -Technically the Biotracker should build using the CMake toolchain and run on OSX. This is not officially supported, though. \ No newline at end of file +Technically the BioTracker should build using the CMake toolchain and run on OSX. This is not officially supported, though. diff --git a/Src/BioTracker.desktop b/Src/BioTracker.desktop new file mode 100644 index 00000000..53eb90c6 --- /dev/null +++ b/Src/BioTracker.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=BioTracker +Exec=BioTracker +Icon=BT3-big +Comment=Tracking application +Terminal=true +Categories=Science; \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/BioTracker3App.cpp b/Src/BioTracker3App.cpp similarity index 51% rename from BioTracker/CoreApp/BioTracker/BioTracker3App.cpp rename to Src/BioTracker3App.cpp index 852751be..57f18f62 100644 --- a/BioTracker/CoreApp/BioTracker/BioTracker3App.cpp +++ b/Src/BioTracker3App.cpp @@ -1,8 +1,8 @@ #include "BioTracker3App.h" -BioTracker3App::BioTracker3App(QObject *parent) : QObject(parent) +BioTracker3App::BioTracker3App(QObject* parent) +: QObject(parent) { - } void BioTracker3App::runBioTracker() @@ -10,12 +10,12 @@ void BioTracker3App::runBioTracker() m_BioTrackerContext->createApplication(); } -void BioTracker3App::setBioTrackerContext(IBioTrackerContext *context) +void BioTracker3App::setBioTrackerContext(IBioTrackerContext* context) { m_BioTrackerContext = context; } -IBioTrackerContext *BioTracker3App::getBioTrackerContext() +IBioTrackerContext* BioTracker3App::getBioTrackerContext() { return m_BioTrackerContext; } diff --git a/BioTracker/CoreApp/BioTracker/BioTracker3App.h b/Src/BioTracker3App.h similarity index 51% rename from BioTracker/CoreApp/BioTracker/BioTracker3App.h rename to Src/BioTracker3App.h index 1ac86a27..c833500d 100644 --- a/BioTracker/CoreApp/BioTracker/BioTracker3App.h +++ b/Src/BioTracker3App.h @@ -6,24 +6,22 @@ #include "Interfaces/IBioTrackerContext.h" #include "QPointer" - class BioTracker3App : public QObject { Q_OBJECT public: - explicit BioTracker3App(QObject *parent = 0); + explicit BioTracker3App(QObject* parent = 0); - void runBioTracker(); - void setBioTrackerContext(IBioTrackerContext *context); - IBioTrackerContext *getBioTrackerContext(); + void runBioTracker(); + void setBioTrackerContext(IBioTrackerContext* context); + IBioTrackerContext* getBioTrackerContext(); Q_SIGNALS: public Q_SLOTS: private: - QPointer< IBioTrackerContext > m_BioTrackerContext; - + QPointer m_BioTrackerContext; }; #endif // BIOTRACKER3APP_H diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt new file mode 100644 index 00000000..1aecb453 --- /dev/null +++ b/Src/CMakeLists.txt @@ -0,0 +1,245 @@ +############################################################## +#### BioTracker Core +############################################################## + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") +endif() + +set(target BioTracker) +add_executable (${target}) +set_target_properties(${target} PROPERTIES OUTPUT_NAME BioTracker) + +target_compile_definitions(${target} PRIVATE SOURCE_VERSION="${SOURCE_VERSION}") + +target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) + +target_link_libraries (${target} biotracker-utility) + +find_package(Qt5 REQUIRED COMPONENTS Core Gui Xml Network Widgets Multimedia MultimediaWidgets OpenGL) +target_link_libraries (${target} Qt5::Core Qt5::Gui Qt5::Xml Qt5::Network Qt5::Widgets Qt5::Multimedia Qt5::MultimediaWidgets Qt5::OpenGL) + +find_package(Boost REQUIRED COMPONENTS system filesystem program_options) +target_link_libraries(${target} Boost::headers Boost::system Boost::filesystem Boost::program_options) + +option(WITH_PYLON "Support Pylon cameras" $ENV{WITH_PYLON}) +if(WITH_PYLON) + list(APPEND FEATURES pylon) + find_package(Pylon5 REQUIRED) + target_compile_definitions(${target} PRIVATE HAS_PYLON=1) + target_link_libraries(${target} Pylon5::Base Pylon5::Utility Pylon5::GenAPI Pylon5::GCBase) +endif() + +string(JOIN "," VARIANT ${FEATURES}) + +IF("${HMNVLibDir}" MATCHES "Not Found") +ELSE() + target_link_libraries(${target} ${HMNVLibDir}/lib/NvEncInterace.lib) + target_compile_definitions(${target} PRIVATE WITH_CUDA=1) +ENDIF() + +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_link_libraries(${target} stdc++fs) +endif() + +message(STATUS "Configured CV version=${OpenCV_VERSION}") +message(STATUS "Configured QT version=${Qt5Core_VERSION}") +message(STATUS "Configured Boost version=${Boost_LIB_VERSION}") +add_definitions( -DMyQT_VERSION="${Qt5Core_VERSION}" ) +add_definitions( -DMyCV_VERSION="${OpenCV_VERSION}" ) +add_definitions( -DMyBT_VERSION="${Boost_LIB_VERSION}" ) + +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + target_compile_definitions(${target} PRIVATE NOMINMAX) + target_compile_definitions(${target} PRIVATE _CRT_SECURE_NO_WARNINGS) +endif() + +option(INSTALL_SYSTEM_LIBRARIES "Install system libraries" OFF) + +include(Locate) +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + install(TARGETS ${target} DESTINATION .) + + if(INSTALL_SYSTEM_LIBRARIES) + set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .) + include(InstallRequiredSystemLibraries) + endif() + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio") + include(WinDeployQt5) + deploy_qt5(${target} DESTINATION .) + endif() + + set(INSTALL_CUDA_COMPONENTS "" CACHE STRING "CUDA components to install") + locate_cuda(shared_libraries COMPONENTS ${INSTALL_CUDA_COMPONENTS}) + + set(INSTALL_OPENCV_COMPONENTS "" CACHE STRING "OpenCV components to install") + locate_opencv(shared_libraries COMPONENTS ${INSTALL_OPENCV_COMPONENTS}) + + set(INSTALL_SHARED_LIBRARIES "" CACHE STRING "Additional shared libraries to install") + locate_shared_library(shared_libraries ${INSTALL_SHARED_LIBRARIES}) + + locate_shared_library(shared_libraries biotracker-interfaces) + + install(FILES ${shared_libraries} DESTINATION .) +endif() + +set(CPACK_PACKAGE_NAME "${target}") +set(CPACK_PACKAGE_VENDOR "Biorobotics Lab / FU Berlin") +set(CPACK_PACKAGE_VERSION ${SOURCE_VERSION}) + +set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}") +if(NOT "${VARIANT}" STREQUAL "") + string(APPEND CPACK_PACKAGE_FILE_NAME "[${VARIANT}]") +endif() +string(APPEND CPACK_PACKAGE_FILE_NAME "-${CPACK_PACKAGE_VERSION}") + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + option(PACKAGE_MSI "Create MSI package" OFF) + if(PACKAGE_MSI) + set(CPACK_GENERATOR "WIX") + set(CPACK_WIX_UPGRADE_GUID "e47473db-3d71-4c42-8a58-d3eac87aa0bd") + set(CPACK_WIX_PRODUCT_VERSION "0.0.0") + + set(CPACK_PACKAGE_INSTALL_DIRECTORY "BioTracker/BioTracker") + + set(CPACK_WIX_PROGRAM_MENU_FOLDER "BioTracker") + + set_property(INSTALL "$" + PROPERTY CPACK_START_MENU_SHORTCUTS "${target}" + ) + + set_property(INSTALL "$" + PROPERTY CPACK_DESKTOP_SHORTCUTS "${target}" + ) + + set(CPACK_WIX_LICENSE_RTF ${CMAKE_SOURCE_DIR}/Src/cmake/WIX/licence.rtf) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WIX/WIX.template.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake/WIX/WIX.template") + set(CPACK_WIX_TEMPLATE "${CMAKE_CURRENT_BINARY_DIR}/cmake/WIX/WIX.template") + endif() +endif() + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + include(GNUInstallDirs) + + install(TARGETS ${target} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/BioTracker.desktop DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/logo/BT3-big.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256") + + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") + + if(WITH_PYLON) + install(DIRECTORY "${Pylon5_LIBRARY_DIR}/" DESTINATION "${CMAKE_INSTALL_LIBDIR}") + endif() + + get_target_property(shared_library biotracker-interfaces LOCATION) + install(FILES "${shared_library}" DESTINATION "${CMAKE_INSTALL_LIBDIR}") + + option(PACKAGE_APPIMAGE "Create AppImage package" OFF) + + if(PACKAGE_APPIMAGE) + find_program(LINUXDEPLOYQT_EXECUTABLE linuxdeployqt) + if(NOT LINUXDEPLOYQT_EXECUTABLE) + message(FATAL_ERROR "AppImage packaging tool \"linuxdeployqt\" not found") + endif() + set(CPACK_GENERATOR "External;${CPACK_GENERATOR}") + set(APPIMAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPackLinuxDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake" @ONLY) + set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake") + set(CPACK_EXTERNAL_ENABLE_STAGING ON) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH_USE_LINK_PATH ON) + endif() +endif() + +if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + string(APPEND CPACK_PACKAGE_FILE_NAME "-${CMAKE_SYSTEM_NAME}") +endif() + +include(CPack) + +target_sources(${target} +PRIVATE + "BioTracker3App.cpp" + "GuiContext.cpp" + "PluginLoader.cpp" + "main.cpp" + "guiresources.qrc" + "Controller/IControllerCfg.cpp" + "Controller/ControllerAnnotations.cpp" + "Controller/ControllerAreaDescriptor.cpp" + "Controller/ControllerCommands.cpp" + "Controller/ControllerCoreParameter.cpp" + "Controller/ControllerDataExporter.cpp" + "Controller/ControllerGraphicScene.cpp" + "Controller/ControllerMainWindow.cpp" + "Controller/ControllerNotifications.cpp" + "Controller/ControllerPlayer.cpp" + "Controller/ControllerPlugin.cpp" + "Controller/ControllerTextureObject.cpp" + "Controller/ControllerTrackedComponentCore.cpp" + "Controller/null_Controller.cpp" + "IStates/IPlayerState.cpp" + "Model/AreaDescriptor/AreaInfo.cpp" + "Model/AreaDescriptor/AreaInfoElement.cpp" + "Model/AreaDescriptor/AreaMemory.cpp" + "Model/AreaDescriptor/Rectification.cpp" + "Model/DataExporters/DataExporterCSV.cpp" + "Model/DataExporters/DataExporterGeneric.cpp" + "Model/DataExporters/DataExporterJson.cpp" + "Model/DataExporters/DataExporterSerialize.cpp" + "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp" + "Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp" + "Model/UndoCommands/TrackCommands.cpp" + "Model/Annotations.cpp" + "Model/BioTracker3ProxyMat.cpp" + "Model/CoreParameter.cpp" + "Model/ImageStream.cpp" + "Model/MediaPlayer.cpp" + "Model/null_Model.cpp" + "Model/TextureObject.cpp" + "util/CLIcommands.cpp" + "util/VideoCoder.cpp" + "util/Config.cpp" + "View/AreaDesciptor/AreaDescriptor.cpp" + "View/AreaDesciptor/EllipseDescriptor.cpp" + "View/AreaDesciptor/RectDescriptor.cpp" + "View/AnnotationsView.cpp" + "View/CameraDevice.cpp" + "View/ComponentShape.cpp" + "View/CoreParameterView.cpp" + "View/GLVideoView.cpp" + "View/GraphicsScene.cpp" + "View/GraphicsView.cpp" + "View/MainWindow.cpp" + "View/NotificationLogBrowser.cpp" + "View/SettingsWindow.cpp" + "View/TextureObjectView.cpp" + "View/TrackedComponentView.cpp" + "View/TrackedImageView.cpp" + "View/VideoControllWidget.cpp" + "View/Utility/RotationHandle.cpp" + "View/Utility/SwitchButton.cpp" + "View/Utility/Tracer.cpp" +) + +if(WITH_PYLON) + target_sources(${target} + PRIVATE + "util/camera/pylon.cpp" + ) +endif() + + + diff --git a/Src/Controller/ControllerAnnotations.cpp b/Src/Controller/ControllerAnnotations.cpp new file mode 100644 index 00000000..4e06efb9 --- /dev/null +++ b/Src/Controller/ControllerAnnotations.cpp @@ -0,0 +1,362 @@ +#include "ControllerAnnotations.h" +#include "View/MainWindow.h" +#include "Controller/ControllerGraphicScene.h" +#include "Controller/ControllerPlayer.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" +#include "Model/Annotations.h" +#include "View/AnnotationsView.h" +#include "Model/MediaPlayerStateMachine/PlayerParameters.h" + +#include + +#include +#include +#include + +ControllerAnnotations::~ControllerAnnotations() +{ + delete getModel(); + delete getView(); +} + +void ControllerAnnotations::cleanup() +{ + // Delete the model to trigger serialization + delete getModel(); +} + +void ControllerAnnotations::reset(std::string filepath) +{ + // Replace the model with a fresh one. + delete getModel(); + createModel(filepath); + connectModelToController(); +} + +ControllerAnnotations::ControllerAnnotations(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +void ControllerAnnotations::connectControllerToController() +{ + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + auto viewController = qobject_cast(ctr); + auto view = dynamic_cast(viewController->getView()); + view->addGraphicsItem(static_cast(getView())); + + QObject::connect(view, + &GraphicsView::onMousePressEvent, + this, + &ControllerAnnotations::mousePressEvent, + Qt::DirectConnection); + QObject::connect(view, + &GraphicsView::onMouseReleaseEvent, + this, + &ControllerAnnotations::mouseReleaseEvent, + Qt::DirectConnection); + QObject::connect(view, + &GraphicsView::onMouseMoveEvent, + this, + &ControllerAnnotations::mouseMoveEvent, + Qt::DirectConnection); + // QObject::connect(view, &GraphicsView::onKeyReleaseEvent, this, + // &ControllerAnnotations::keyReleaseEvent, Qt::DirectConnection); + QObject::connect(view, + &GraphicsView::onKeyPressEvent, + this, + &ControllerAnnotations::keyPressEvent, + Qt::DirectConnection); + + QWidget* viewport = view->viewport(); + QObject::connect(this, + SIGNAL(onRepaintRequired()), + viewport, + SLOT(repaint())); + } + + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + auto mediaPlayerController = dynamic_cast(ctr); + assert(mediaPlayerController); + MediaPlayer* player = dynamic_cast( + mediaPlayerController->getModel()); + assert(player); + QObject::connect(player, + &MediaPlayer::fwdPlayerParameters, + this, + &ControllerAnnotations::setPlayerParameters); + } +} + +void ControllerAnnotations::createModel(std::string filepath) +{ + m_Model = new Annotations(filepath); +} + +void ControllerAnnotations::createView() +{ + assert(m_Model); + m_View = new AnnotationsView(this, m_Model); +} + +void ControllerAnnotations::connectModelToController() +{ + auto model = static_cast(getModel()); + auto view = static_cast(getView()); + view->setNewModel(model); +} + +void ControllerAnnotations::updateView() +{ + auto view = static_cast(getView()); + view->prepareUpdate(); + emit(onRepaintRequired()); +} + +void ControllerAnnotations::keyPressEvent(QKeyEvent* event) +{ + auto model = static_cast(getModel()); + actionQueued = ActionQueued::None; + bool handled = true; + if (event->modifiers() & Qt::AltModifier) { + switch (event->key()) { + case Qt::Key::Key_A: + actionQueued = ActionQueued::CreateArrow; + break; + case Qt::Key::Key_L: + actionQueued = ActionQueued::CreateLabel; + break; + case Qt::Key::Key_R: + actionQueued = ActionQueued::CreateRect; + break; + case Qt::Key::Key_E: + actionQueued = ActionQueued::CreateEllipse; + break; + case Qt::Key::Key_H: + model->toggleHideAnnotations(); + handled = true; + break; + case Qt::Key::Key_Delete: // Fallthrough. + case Qt::Key::Key_Backspace: + // Remove existing selected annotation at current frame. + if (model->removeSelection()) { + updateView(); + } else + handled = false; + break; + case Qt::Key::Key_Q: + if (!model->updateSelectionStartFrame()) + handled = false; + break; + case Qt::Key::Key_W: + if (!model->updateSelectionEndFrame()) + handled = false; + break; + default: + handled = false; + break; + } + } + + if (handled) { + updateView(); + event->accept(); + } +} + +void ControllerAnnotations::mousePressEvent(QMouseEvent* event, + const QPoint& pos) +{ + // left-click: add annotation in pos or try start dragging annotation + if (event->button() == Qt::LeftButton) { + auto model = static_cast(getModel()); + bool handled = true; + + switch (actionQueued) { + case ActionQueued::CreateArrow: + model->startArrow(pos, model->getCurrentFrame()); + break; + case ActionQueued::CreateLabel: + model->startLabel(pos, model->getCurrentFrame()); + break; + case ActionQueued::CreateRect: + model->startRect(pos, model->getCurrentFrame()); + break; + case ActionQueued::CreateEllipse: + model->startEllipse(pos, model->getCurrentFrame()); + break; + default: + if (model->tryStartDragging(pos)) { + updateView(); + } else { + handled = false; + } + updateView(); + break; + } + if (handled) + event->accept(); + actionQueued = ActionQueued::None; + } + + // right-click: set text for annotation in pos + else if (event->button() == Qt::RightButton) { + auto model = static_cast(getModel()); + bool handled = true; + + if (model->trySetText(pos)) { + updateView(); + model->serialize(); + } else { + handled = false; + } + if (handled) { + event->accept(); + } + } +} + +Annotations::TrackedPoint ControllerAnnotations::snapToTrajectory( + const QPoint& originalPoint) +{ + auto model = static_cast(getModel()); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + auto trackedComponentCoreController = + qobject_cast(ctr); + auto trackedTrajectoryModel = dynamic_cast( + trackedComponentCoreController->getModel()); + + if (trackedTrajectoryModel && + QGuiApplication::queryKeyboardModifiers().testFlag( + Qt::ControlModifier)) { + auto minDistance = std::numeric_limits::infinity(); + QPoint closestPoint{0, 0}; + int closestTrackID{0}; + auto allChildren = trackedTrajectoryModel->getChildNodes(); + + for (const auto& childNode : allChildren) { + // Top level nodes are likely trajectories. + const auto childTrajectory = + dynamic_cast(childNode); + // Not a trajectory? Don't know how to handle. + if (childTrajectory == nullptr) + continue; + + for (size_t i = 0; i < childTrajectory->size(); ++i) { + if (i != model->getCurrentFrame()) + continue; + const auto& childComponent = childTrajectory->getChild( + static_cast(i)); + const auto point = dynamic_cast( + childComponent); + if (point == nullptr) + continue; + float distance = std::sqrt( + std::pow(point->getXpx() - originalPoint.x(), 2) + + std::pow(point->getYpx() - originalPoint.y(), 2)); + if (distance < minDistance) { + minDistance = distance; + closestPoint = QPoint(static_cast(point->getXpx()), + static_cast(point->getYpx())); + closestTrackID = childTrajectory->getId(); + } + } + } + + if (minDistance < 100.0f) { + return Annotations::TrackedPoint(closestPoint, closestTrackID); + } + } + return Annotations::TrackedPoint(originalPoint); +} + +void ControllerAnnotations::mouseReleaseEvent(QMouseEvent* event, + const QPoint& pos) +{ + auto model = static_cast(getModel()); + const bool isAltModifierActive = + QGuiApplication::queryKeyboardModifiers().testFlag(Qt::AltModifier); + + Annotations::TrackedPoint trackedPoint = snapToTrajectory(pos); + + if ((event->button() == Qt::LeftButton) && !isAltModifierActive && + (model->endAnnotation(trackedPoint) || + model->updateAnnotation(trackedPoint))) { + updateView(); + event->accept(); + } +} + +void ControllerAnnotations::mouseMoveEvent(QMouseEvent* event, + const QPoint& pos) +{ + auto model = static_cast(getModel()); + const bool isAltModifierActive = + QGuiApplication::queryKeyboardModifiers().testFlag(Qt::AltModifier); + + Annotations::TrackedPoint trackedPoint = snapToTrajectory(pos); + + if ((event->buttons() & Qt::LeftButton) && !isAltModifierActive && + model->updateAnnotation(trackedPoint)) { + updateView(); + event->accept(); + } +} + +void ControllerAnnotations::setPlayerParameters( + std::shared_ptr parameters) +{ + auto model = static_cast(getModel()); + model->setCurrentFrame(parameters->m_CurrentFrameNumber); + + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + auto trackedComponentCoreController = + qobject_cast(ctr); + auto trackedTrajectoryModel = dynamic_cast( + trackedComponentCoreController->getModel()); + if (trackedTrajectoryModel != nullptr) + model->updateTrackedAnnotations( + trackedTrajectoryModel->getChildNodes()); + updateView(); +} + +void ControllerAnnotations::receiveAddLabelAnnotation() +{ + actionQueued = ActionQueued::CreateLabel; +} +void ControllerAnnotations::receiveAddRectAnnotation() +{ + actionQueued = ActionQueued::CreateRect; +} +void ControllerAnnotations::receiveAddArrowAnnotation() +{ + actionQueued = ActionQueued::CreateArrow; +} +void ControllerAnnotations::receiveAddEllipseAnnotation() +{ + actionQueued = ActionQueued::CreateEllipse; +} +void ControllerAnnotations::receiveDeleteSelectedAnnotation() +{ + auto model = static_cast(getModel()); + if (model->removeSelection()) { + updateView(); + } +} + +void ControllerAnnotations::receiveSetAnnotationColor(QColor color) +{ + AnnotationsView* view = dynamic_cast(m_View); + if (view) { + view->setColor(color); + } +} diff --git a/Src/Controller/ControllerAnnotations.h b/Src/Controller/ControllerAnnotations.h new file mode 100644 index 00000000..f151e8a6 --- /dev/null +++ b/Src/Controller/ControllerAnnotations.h @@ -0,0 +1,74 @@ +#pragma once + +#include "Model/Annotations.h" +#include "IControllerCfg.h" +#include "QString" +#include +#include +#include + +struct playerParameters; + +/** + * The ControllerAnnotations inherits IController + * It is the management unit of the annotation component. + * It controls user input -> creates new annotations in model, forwards moves + * and deletes them + */ +class ControllerAnnotations : public IControllerCfg +{ + Q_OBJECT +public: + ControllerAnnotations( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::ANNOTATIONS); + virtual ~ControllerAnnotations(); + void cleanup(); + + // IController interface +public: + void connectControllerToController() override; + +public Q_SLOTS: + + /// + void reset(std::string filepath); + void mousePressEvent(QMouseEvent* event, const QPoint& pos); + void mouseReleaseEvent(QMouseEvent* event, const QPoint& pos); + void mouseMoveEvent(QMouseEvent* event, const QPoint& pos); + void keyPressEvent(QKeyEvent* event); + void setPlayerParameters( + std::shared_ptr parameters); + + // annotation receivers + void receiveAddLabelAnnotation(); + void receiveAddRectAnnotation(); + void receiveAddArrowAnnotation(); + void receiveAddEllipseAnnotation(); + void receiveDeleteSelectedAnnotation(); + void receiveSetAnnotationColor(QColor color); + +protected: + void createModel(std::string filepath = ""); + void createModel() override + { + createModel(""); + } + void createView() override; + void connectModelToController() override; + + enum class ActionQueued + { + None, + CreateArrow, + CreateLabel, + CreateRect, + CreateEllipse, + }; + ActionQueued actionQueued{ActionQueued::None}; + void updateView(); + Annotations::TrackedPoint snapToTrajectory(const QPoint& point); +Q_SIGNALS: + void onRepaintRequired(); +}; diff --git a/Src/Controller/ControllerAreaDescriptor.cpp b/Src/Controller/ControllerAreaDescriptor.cpp new file mode 100644 index 00000000..ae0ff9e8 --- /dev/null +++ b/Src/Controller/ControllerAreaDescriptor.cpp @@ -0,0 +1,361 @@ +#include "ControllerAreaDescriptor.h" + +#include "Model/AreaDescriptor/AreaInfo.h" +#include "View/AreaDesciptor/AreaDescriptor.h" +#include "View/AreaDesciptor/RectDescriptor.h" +#include "View/AreaDesciptor/EllipseDescriptor.h" +#include "util/types.h" + +#include "ControllerGraphicScene.h" +#include "View/GraphicsView.h" +#include "Model/AreaDescriptor/Rectification.h" +#include "Controller/ControllerPlayer.h" +#include "Controller/ControllerCoreParameter.h" + +#include + +#include "Model/AreaDescriptor/AreaMemory.h" +using namespace AreaMemory; + +ControllerAreaDescriptor::ControllerAreaDescriptor(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ + _watchingVertice = -1; + _watchingVerticeType = BiotrackerTypes::AreaType::NONE; + m_ViewApperture = nullptr; +} + +void ControllerAreaDescriptor::triggerUpdateAreaDescriptor() +{ + + IModelAreaDescriptor* area = dynamic_cast( + getModel()); + Q_EMIT updateAreaDescriptor(area); +} + +void ControllerAreaDescriptor::createView() +{ + assert(m_Model); + AreaInfo* mInf = dynamic_cast(getModel()); + RectDescriptor* view = new RectDescriptor(this, mInf->_rect.get()); + m_View = view; + QObject::connect(this, + &ControllerAreaDescriptor::currentVectorDrag, + view, + &RectDescriptor::receiveDragUpdate); + + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + auto viewController = qobject_cast(ctr); + auto gview = dynamic_cast(viewController->getView()); + gview->addGraphicsItem(view); + + AreaInfo* area = dynamic_cast(getModel()); + + int v = _cfg->AppertureType; + trackingAreaType(v); +} + +void ControllerAreaDescriptor::connectModelToController() +{ +} + +void ControllerAreaDescriptor::trackingAreaType(int v) +{ + + IController* ctr1 = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + auto viewController = qobject_cast(ctr1); + auto gview = dynamic_cast(viewController->getView()); + + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMPONENT); + RectDescriptor* view = dynamic_cast(m_View); + AreaInfo* area = dynamic_cast(getModel()); + if (m_ViewApperture) { + gview->removeGraphicsItem( + static_cast(m_ViewApperture)); + delete m_ViewApperture; + } + + if (v == 0) { + m_ViewApperture = new RectDescriptor(this, area->_apperture.get()); + area->_apperture->setType(0); + static_cast(m_ViewApperture) + ->setBrush(QBrush(Qt::red)); + QObject::connect(this, + &ControllerAreaDescriptor::currentVectorDrag, + static_cast(m_ViewApperture), + &RectDescriptor::receiveDragUpdate); + _cfg->AppertureType = 0; + } else if (v > 0) { + m_ViewApperture = new EllipseDescriptor(this, area->_apperture.get()); + area->_apperture->setType(1); + static_cast(m_ViewApperture) + ->setBrush(QBrush(Qt::red)); + static_cast(m_ViewApperture) + ->setDimensions(_w, _h); + QObject::connect(this, + &ControllerAreaDescriptor::currentVectorDrag, + static_cast(m_ViewApperture), + &EllipseDescriptor::receiveDragUpdate); + _cfg->AppertureType = 1; + } + + if (!_visibleApperture) + static_cast(m_ViewApperture)->hide(); + if (!_visibleRectification) + static_cast(m_View)->hide(); + + gview->addGraphicsItem(static_cast(m_ViewApperture)); +} + +void ControllerAreaDescriptor::rcvPlayerParameters( + std::shared_ptr parameters) +{ + // Best effort to save performance... + // File has changed + if (_currentFilename != parameters->m_CurrentFilename) { + _currentFilename = parameters->m_CurrentFilename; + + // Set area descriptor dimensions + auto ad = static_cast(m_ViewApperture); + auto m = parameters->m_CurrentFrame; + if (ad && m) { + _w = m->size().width; + _h = m->size().height; + ad->setDimensions(_w, _h); + } + QVector v = getVertices(_currentFilename, + _cfg->AreaDefinitions); + if (!v.empty()) { + changeAreaDescriptorType(v[2]); + } + } +} + +void ControllerAreaDescriptor::connectControllerToController() +{ + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + auto viewController = qobject_cast(ctr); + auto view = dynamic_cast(viewController->getView()); + + QObject::connect(view, + &GraphicsView::onMousePressEvent, + this, + &ControllerAreaDescriptor::mousePressEvent, + Qt::DirectConnection); + QObject::connect(view, + &GraphicsView::onMouseReleaseEvent, + this, + &ControllerAreaDescriptor::mouseReleaseEvent, + Qt::DirectConnection); + QObject::connect(view, + &GraphicsView::onMouseMoveEvent, + this, + &ControllerAreaDescriptor::mouseMoveEvent, + Qt::DirectConnection); + QObject::connect(view, + &GraphicsView::onKeyReleaseEvent, + this, + &ControllerAreaDescriptor::keyReleaseEvent, + Qt::DirectConnection); + + // Area info model needs to know video dimensions + auto model = static_cast(getModel()); + IController* ctrPl = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + auto mediaPlayerController = static_cast(ctrPl); + MediaPlayer* player = static_cast( + mediaPlayerController->getModel()); + QObject::connect(player, + &MediaPlayer::fwdPlayerParameters, + model, + &AreaInfo::rcvPlayerParameters, + Qt::DirectConnection); + QObject::connect(player, + &MediaPlayer::fwdPlayerParameters, + this, + &ControllerAreaDescriptor::rcvPlayerParameters, + Qt::DirectConnection); + + IController* ctrParms = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + auto parmsController = qobject_cast( + ctrParms); + QObject::connect(this, + &ControllerAreaDescriptor::changeAreaDescriptorType, + parmsController, + &ControllerCoreParameter::changeAreaDescriptorType, + Qt::DirectConnection); + + AreaInfo* area = dynamic_cast(getModel()); + QObject::connect(area->_rect.get(), + SIGNAL(updatedVertices()), + this, + SLOT(updateView())); + QObject::connect(area->_apperture.get(), + SIGNAL(updatedVertices()), + this, + SLOT(updateView())); + } + { + // View stuff from the parameter view + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + auto viewController = qobject_cast(ctr); + } + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + ControllerCoreParameter* cctr = static_cast( + ctr); + cctr->triggerUpdate(); + } +} + +void ControllerAreaDescriptor::createModel() +{ + m_Model = new AreaInfo(this); +} + +void ControllerAreaDescriptor::updateView() +{ + + AreaInfo* area = static_cast(getModel()); + RectDescriptor* rd = static_cast(getView()); + rd->updateRect(); + AreaDescriptor* ad = static_cast(m_ViewApperture); + ad->updateRect(); + area->updateRectification(); + area->updateApperture(); +} + +void ControllerAreaDescriptor::keyReleaseEvent(QKeyEvent* event) +{ +} + +void ControllerAreaDescriptor::mousePressEvent(QMouseEvent* event, + const QPoint& pos) +{ + auto model = static_cast(getModel()); + + // check if rectification vertice is grabbed and visible + RectDescriptor* rd = static_cast(getView()); + int verticeRect = -1; + if (rd->isVisible()) { + verticeRect = model->_rect->getVerticeAtLocation(pos); + if (verticeRect >= 0) { + _watchingVertice = verticeRect; + _watchingVerticeType = BiotrackerTypes::AreaType::RECT; + event->accept(); + } + } + + // check if apperture vertice is grabbed and visible + AreaDescriptor* ad = static_cast(m_ViewApperture); + int verticeApp = -1; + if (ad->isVisible()) { + verticeApp = model->_apperture->getVerticeAtLocation(pos); + if (verticeApp >= 0) { + _watchingVertice = verticeApp; + _watchingVerticeType = BiotrackerTypes::AreaType::APPERTURE; + event->accept(); + } + } + + // else none is grabbed + if (verticeRect < 0 && verticeApp < 0) { + _watchingVertice = -1; + _watchingVerticeType = BiotrackerTypes::AreaType::NONE; + } + + // disable use entire screen when one vertice is grabbed + if (verticeRect > 0 || verticeApp > 0) { + AreaInfo* area = static_cast(getModel()); + area->setUseEntireScreen(false); + } + + Q_EMIT currentVectorDrag(_watchingVerticeType, + _watchingVertice, + pos.x(), + pos.y()); +} + +void ControllerAreaDescriptor::mouseReleaseEvent(QMouseEvent* event, + const QPoint& pos) +{ + auto model = static_cast(getModel()); + + if (_watchingVertice >= 0 && + _watchingVerticeType == BiotrackerTypes::AreaType::RECT) { + model->_rect->setVerticeAtLocation(pos, _watchingVertice); + event->accept(); + triggerUpdateAreaDescriptor(); + } + + if (_watchingVertice >= 0 && + _watchingVerticeType == BiotrackerTypes::AreaType::APPERTURE) { + model->_apperture->setVerticeAtLocation(pos, _watchingVertice); + event->accept(); + triggerUpdateAreaDescriptor(); + } + + _watchingVerticeType = BiotrackerTypes::AreaType::NONE; + _watchingVertice = -1; + Q_EMIT currentVectorDrag(_watchingVerticeType, + _watchingVertice, + pos.x(), + pos.y()); +} + +void ControllerAreaDescriptor::mouseMoveEvent(QMouseEvent* event, + const QPoint& pos) +{ + Q_EMIT currentVectorDrag(_watchingVerticeType, + _watchingVertice, + pos.x(), + pos.y()); +} + +void ControllerAreaDescriptor::setRectificationDimensions(double w, double h) +{ + + _cfg->RectificationHeight = h; + _cfg->RectificationWidth = w; + + AreaInfo* area = static_cast(getModel()); + area->setRectificationDimensions(w, h); + triggerUpdateAreaDescriptor(); + + RectDescriptor* rd = static_cast(getView()); + rd->updateRect(); +} + +void ControllerAreaDescriptor::setDisplayRectificationDefinition(bool b) +{ + _visibleRectification = b; + RectDescriptor* rd = static_cast(getView()); + rd->setVisible(b); +} + +void ControllerAreaDescriptor::setDisplayTrackingAreaDefinition(bool b) +{ + _visibleApperture = b; + AreaDescriptor* ad = static_cast(m_ViewApperture); + ad->setVisible(b); +} + +void ControllerAreaDescriptor::setTrackingAreaAsEllipse(bool b) +{ + // Not passing b as a parameter for clarification reasons + if (b) { + trackingAreaType(1); + } else { + trackingAreaType(0); + } +} diff --git a/Src/Controller/ControllerAreaDescriptor.h b/Src/Controller/ControllerAreaDescriptor.h new file mode 100644 index 00000000..975012ae --- /dev/null +++ b/Src/Controller/ControllerAreaDescriptor.h @@ -0,0 +1,63 @@ +#pragma once + +#include "IControllerCfg.h" +#include "Interfaces/IModel/IModelAreaDescriptor.h" +#include +#include +#include "util/types.h" +#include "Model/MediaPlayerStateMachine/PlayerParameters.h" + +class ControllerAreaDescriptor : public IControllerCfg +{ + Q_OBJECT +public: + ControllerAreaDescriptor( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); + + void triggerUpdateAreaDescriptor(); + +signals: + void updateAreaDescriptor(IModelAreaDescriptor* ad); + void currentVectorDrag(BiotrackerTypes::AreaType vectorType, + int id, + double x, + double y); + void changeAreaDescriptorType(QString type); + +public slots: + void setRectificationDimensions(double w, double h); + void setDisplayRectificationDefinition(bool b); + void setDisplayTrackingAreaDefinition(bool b); + void setTrackingAreaAsEllipse(bool b); + void rcvPlayerParameters( + std::shared_ptr parameters); + +private slots: + void trackingAreaType(int v); + + void mousePressEvent(QMouseEvent* event, const QPoint& pos); + void mouseReleaseEvent(QMouseEvent* event, const QPoint& pos); + void mouseMoveEvent(QMouseEvent* event, const QPoint& pos); + void keyReleaseEvent(QKeyEvent* event); + void updateView(); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + +private: + int _watchingVertice; + BiotrackerTypes::AreaType _watchingVerticeType; + + IView* m_ViewApperture; + int _w = 1; + int _h = 1; + bool _visibleApperture = false; + bool _visibleRectification = false; + QString _currentFilename = "No Media"; +}; diff --git a/Src/Controller/ControllerCommands.cpp b/Src/Controller/ControllerCommands.cpp new file mode 100644 index 00000000..4e1c3202 --- /dev/null +++ b/Src/Controller/ControllerCommands.cpp @@ -0,0 +1,169 @@ +#include "Controller/ControllerCommands.h" +#include "QDebug" + +ControllerCommands::ControllerCommands(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +ControllerCommands::~ControllerCommands() +{ +} + +void ControllerCommands::receiveAddTrackCommand(QPoint pos, int id) +{ + AddTrackCommand* addCmd = new AddTrackCommand(id, pos); + QObject::connect(addCmd, + &AddTrackCommand::emitAddTrajectory, + this, + &ControllerCommands::emitAddTrajectory); + QObject::connect(addCmd, + &AddTrackCommand::emitValidateTrajectory, + this, + &ControllerCommands::emitValidateTrajectory); + QObject::connect(addCmd, + &AddTrackCommand::emitRemoveTrajectoryId, + this, + &ControllerCommands::emitRemoveTrajectoryId); + + _undoStack->push(addCmd); +} + +void ControllerCommands::receiveRemoveTrackCommand( + IModelTrackedTrajectory* traj) +{ + RemoveTrackCommand* rmtCmd = new RemoveTrackCommand(traj); + QObject::connect(rmtCmd, + &RemoveTrackCommand::emitValidateTrajectory, + this, + &ControllerCommands::emitValidateTrajectory); + QObject::connect(rmtCmd, + &RemoveTrackCommand::emitRemoveTrajectory, + this, + &ControllerCommands::emitRemoveTrajectory); + + _undoStack->push(rmtCmd); +} + +void ControllerCommands::receiveRemoveTrackEntityCommand( + IModelTrackedTrajectory* traj, + uint frameNumber) +{ + RemoveElementCommand* rmeCmd = new RemoveElementCommand(traj, frameNumber); + QObject::connect(rmeCmd, + &RemoveElementCommand::emitValidateEntity, + this, + &ControllerCommands::emitValidateEntity); + QObject::connect(rmeCmd, + &RemoveElementCommand::emitRemoveElement, + this, + &ControllerCommands::emitRemoveTrackEntity); + + _undoStack->push(rmeCmd); +} + +void ControllerCommands::receiveMoveElementCommand( + IModelTrackedTrajectory* traj, + QPoint oldPos, + QPoint newPos, + uint frameNumber, + int toMove) +{ + MoveElementCommand* mvCmd = + new MoveElementCommand(traj, frameNumber, oldPos, newPos, toMove); + QObject::connect(mvCmd, + &MoveElementCommand::emitMoveElement, + this, + &ControllerCommands::emitMoveElement); + + _undoStack->push(mvCmd); +} + +void ControllerCommands::receiveSwapIdCommand(IModelTrackedTrajectory* traj0, + IModelTrackedTrajectory* traj1) +{ + SwapTrackIdCommand* swapCmd = new SwapTrackIdCommand(traj0, traj1); + QObject::connect(swapCmd, + &SwapTrackIdCommand::emitSwapIds, + this, + &ControllerCommands::emitSwapIds); + + _undoStack->push(swapCmd); +} + +void ControllerCommands::receiveFixTrackCommand(IModelTrackedTrajectory* traj, + bool toggle) +{ + FixTrackCommand* fixCmd = new FixTrackCommand(traj, toggle); + QObject::connect(fixCmd, + &FixTrackCommand::emitFixTrack, + this, + &ControllerCommands::emitToggleFixTrack); + + _undoStack->push(fixCmd); +} + +void ControllerCommands::receiveEntityRotation(IModelTrackedTrajectory* traj, + double oldAngleDeg, + double newAngleDeg, + uint frameNumber) +{ + RotateEntityCommand* rotCmd = + new RotateEntityCommand(traj, oldAngleDeg, newAngleDeg, frameNumber); + QObject::connect(rotCmd, + &RotateEntityCommand::emitEntityRotation, + this, + &ControllerCommands::emitEntityRotation); + + _undoStack->push(rotCmd); +} + +void ControllerCommands::receiveUndo() +{ + if (_undoStack->canUndo()) { + _undoStack->undo(); + } else { + qDebug() << "CORE: Cannot undo the last command!"; + } +} + +void ControllerCommands::receiveRedo() +{ + if (_undoStack->canRedo()) { + _undoStack->redo(); + } else { + qDebug() << "CORE: Csannot redo the next command!"; + } +} + +void ControllerCommands::receiveClear() +{ + _undoStack->clear(); +} + +void ControllerCommands::receiveShowActionList() +{ + _undoView->show(); +} + +void ControllerCommands::connectControllerToController() +{ +} + +void ControllerCommands::createModel() +{ + _undoStack = new QUndoStack(this); +} + +void ControllerCommands::createView() +{ + _undoView = new QUndoView(_undoStack); + _undoView->setWindowTitle("Command List"); + _undoView->setAttribute(Qt::WA_QuitOnClose, false); +} + +void ControllerCommands::connectModelToController() +{ +} diff --git a/Src/Controller/ControllerCommands.h b/Src/Controller/ControllerCommands.h new file mode 100644 index 00000000..a95d5729 --- /dev/null +++ b/Src/Controller/ControllerCommands.h @@ -0,0 +1,96 @@ +#ifndef CONTROLLERCOMMANDS_H +#define CONTROLLERCOMMANDS_H + +#pragma once +#include "IControllerCfg.h" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "Model/UndoCommands/TrackCommands.h" +#include "QUndoStack" +#include "QUndoView" + +/** + * This class inherits from IController. + * http://doc.qt.io/qt-5/qundo.html + * The commands component controls the commands on an undo/redo stack (model) + * and the undo view + */ +class ControllerCommands : public IControllerCfg +{ + Q_OBJECT +public: + ControllerCommands( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + virtual ~ControllerCommands(); + +signals: + // signal to ctrPlugin to remove trajectory + void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); + + void emitRemoveTrajectoryId(int id); + + // signal to ctrPlugin to remove track entity + void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + + // signal to ctrPlugin to add trajectory + void emitAddTrajectory(QPoint pos); + + void emitValidateTrajectory(int id); + + void emitValidateEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + + void emitMoveElement(IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint pos, + int toMove); + + void emitSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + + void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); + + void emitEntityRotation(IModelTrackedTrajectory* trajectory, + double angleDeg, + uint frameNumber); + +public slots: + void receiveAddTrackCommand(QPoint pos, int id); + void receiveRemoveTrackCommand(IModelTrackedTrajectory* traj); + void receiveRemoveTrackEntityCommand(IModelTrackedTrajectory* traj, + uint frameNumber); + void receiveMoveElementCommand(IModelTrackedTrajectory* traj, + QPoint oldPos, + QPoint newPos, + uint frameNumber, + int toMove); + void receiveSwapIdCommand(IModelTrackedTrajectory* traj0, + IModelTrackedTrajectory* traj1); + void receiveFixTrackCommand(IModelTrackedTrajectory* traj, bool toggle); + void receiveEntityRotation(IModelTrackedTrajectory* traj, + double oldAngleDeg, + double newAngleDeg, + uint frameNumber); + + void receiveUndo(); + void receiveRedo(); + void receiveClear(); + void receiveShowActionList(); + + // IController interface +public: + void connectControllerToController() override; + +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + // member +private: + QUndoStack* _undoStack; + QUndoView* _undoView; +}; + +#endif // CONTROLLERCOMMANDS_H \ No newline at end of file diff --git a/Src/Controller/ControllerCoreParameter.cpp b/Src/Controller/ControllerCoreParameter.cpp new file mode 100644 index 00000000..89c0b729 --- /dev/null +++ b/Src/Controller/ControllerCoreParameter.cpp @@ -0,0 +1,340 @@ +#include "ControllerCoreParameter.h" +#include "ControllerTrackedComponentCore.h" +#include "ControllerAreaDescriptor.h" +#include "ControllerDataExporter.h" +#include "ControllerGraphicScene.h" +#include "ControllerPlayer.h" +#include "ControllerMainWindow.h" +#include "ControllerAnnotations.h" +#include "View/CoreParameterView.h" +#include "View/TrackedComponentView.h" +#include "Model/CoreParameter.h" + +ControllerCoreParameter::ControllerCoreParameter(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +void ControllerCoreParameter::createView() +{ + assert(m_Model); + m_View = new CoreParameterView(0, this, m_Model); +} + +void ControllerCoreParameter::connectModelToController() +{ +} + +void ControllerCoreParameter::connectControllerToController() +{ + CoreParameterView* view = static_cast(m_View); + view->triggerUpdate(); + // Connections to the trackedComponentCore + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + ControllerTrackedComponentCore* tccController = + dynamic_cast(ctr); + IView* vv = tccController->getView(); + TrackedComponentView* tcview = static_cast(vv); + + IController* ctr2 = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + ControllerGraphicScene* ctrGrphScn = + dynamic_cast(ctr2); + + QObject::connect(view, + &CoreParameterView::emitViewSwitch, + tcview, + &TrackedComponentView::receiveViewSwitch, + Qt::DirectConnection); + // Tracks + // QObject::connect(view, &CoreParameterView::emitSelectAll, tcview, + // &TrackedComponentView::receiveSelectAll, Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitAddTrack, + tcview, + &TrackedComponentView::addTrajectory, + Qt::DirectConnection); + + // Track dimensions + QObject::connect(view, + &CoreParameterView::emitTrackOrientationLine, + tcview, + &TrackedComponentView::receiveTrackOrientationLine, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTrackShowId, + tcview, + &TrackedComponentView::receiveTrackShowId, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTrackDimensionsAll, + tcview, + &TrackedComponentView::receiveTrackDimensionsAll, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTrackDimensionsSelected, + tcview, + &TrackedComponentView::receiveTrackDimensionsSelected, + Qt::DirectConnection); + QObject::connect( + view, + &CoreParameterView::emitTrackDimensionsSetDefault, + tcview, + &TrackedComponentView::receiveTrackDimensionsSetDefault, + Qt::DirectConnection); + + // Track ignore zoom + QObject::connect(view, + &CoreParameterView::emitIgnoreZoom, + tcview, + &TrackedComponentView::receiveIgnoreZoom, + Qt::DirectConnection); + + // Track color + QObject::connect(view, + &CoreParameterView::emitColorChangeBorderAll, + tcview, + &TrackedComponentView::receiveColorChangeBorderAll, + Qt::DirectConnection); + QObject::connect( + view, + &CoreParameterView::emitColorChangeBorderSelected, + tcview, + &TrackedComponentView::receiveColorChangeBorderSelected, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitColorChangeBrushAll, + tcview, + &TrackedComponentView::receiveColorChangeBrushAll, + Qt::DirectConnection); + QObject::connect( + view, + &CoreParameterView::emitColorChangeBrushSelected, + tcview, + &TrackedComponentView::receiveColorChangeBrushSelected, + Qt::DirectConnection); + // Tracing + QObject::connect(view, + &CoreParameterView::emitTracingHistoryLength, + tcview, + &TrackedComponentView::receiveTracingHistoryLength, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTracingStyle, + tcview, + &TrackedComponentView::receiveTracingStyle, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTracingSteps, + tcview, + &TrackedComponentView::receiveTracingSteps, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTracingTimeDegradation, + tcview, + &TrackedComponentView::receiveTracingTimeDegradation, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTracerFrameNumber, + tcview, + &TrackedComponentView::receiveTracerFrameNumber, + Qt::DirectConnection); + // Tracing dimensions + QObject::connect(view, + &CoreParameterView::emitTracerProportions, + tcview, + &TrackedComponentView::receiveTracerProportions, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTracerOrientationLine, + tcview, + &TrackedComponentView::receiveTracerOrientationLine, + Qt::DirectConnection); + // Misc + QObject::connect( + view, + &CoreParameterView::emitToggleAntialiasingEntities, + tcview, + &TrackedComponentView::receiveToggleAntialiasingEntities, + Qt::DirectConnection); + QObject::connect( + view, + &CoreParameterView::emitToggleAntialiasingFull, + ctrGrphScn, + &ControllerGraphicScene::receiveToggleAntialiasingFull, + Qt::DirectConnection); + } + // Connections to the AreaDescriptor + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); + ControllerAreaDescriptor* adController = + static_cast(ctr); + QObject::connect(view, + &CoreParameterView::emitRectDimensions, + adController, + &ControllerAreaDescriptor::setRectificationDimensions, + Qt::DirectConnection); + QObject::connect( + view, + &CoreParameterView::emitDisplayTrackingArea, + adController, + &ControllerAreaDescriptor::setDisplayTrackingAreaDefinition, + Qt::DirectConnection); + QObject::connect( + view, + &CoreParameterView::emitDisplayRectification, + adController, + &ControllerAreaDescriptor::setDisplayRectificationDefinition, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTrackingAreaAsEllipse, + adController, + &ControllerAreaDescriptor::setTrackingAreaAsEllipse, + Qt::DirectConnection); + } + + // Connections to the Annotations + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::ANNOTATIONS); + ControllerAnnotations* annoController = + static_cast(ctr); + QObject::connect(view, + &CoreParameterView::emitSetAnnoColor, + annoController, + &ControllerAnnotations::receiveSetAnnotationColor, + Qt::DirectConnection); + } + + // Connections to the DataExporter + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + ControllerDataExporter* deController = + static_cast(ctr); + QObject::connect(view, + &CoreParameterView::emitFinalizeExperiment, + deController, + &ControllerDataExporter::receiveFinalizeExperiment, + Qt::DirectConnection); + QObject::connect(view, + &CoreParameterView::emitTrialStarted, + deController, + &ControllerDataExporter::receiveTrialStarted, + Qt::DirectConnection); + } + // Media Player + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + ControllerPlayer* mpc = static_cast(ctr); + MediaPlayer* mp = static_cast(mpc->getModel()); + QObject::connect(mp, + &MediaPlayer::fwdPlayerParameters, + view, + &CoreParameterView::rcvPlayerParameters); + QObject::connect(view, + &CoreParameterView::emitStartPlayback, + mpc, + &ControllerPlayer::play); + QObject::connect(view, + &CoreParameterView::emitStopPlayback, + mpc, + &ControllerPlayer::stop); + QObject::connect(view, + &CoreParameterView::emitPausePlayback, + mpc, + &ControllerPlayer::pause); + } + // Main Window + { + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + ControllerMainWindow* mwc = static_cast(ctr); + QObject::connect(view, + &CoreParameterView::emitEnableTracking, + mwc, + &ControllerMainWindow::activeTracking); + QObject::connect(view, + &CoreParameterView::emitDisableTracking, + mwc, + &ControllerMainWindow::deactiveTrackring); + QObject::connect(view, + &CoreParameterView::emitActivateTrackingSwitch, + mwc, + &ControllerMainWindow::activeTrackingCheckBox); + QObject::connect(view, + &CoreParameterView::emitDeactivateTrackingSwitch, + mwc, + &ControllerMainWindow::deactiveTrackingCheckBox); + QObject::connect(view, + &CoreParameterView::emitSaveDataToFile, + mwc, + &ControllerMainWindow::receiveSaveTrajData); + } + + view->triggerUpdate(); +} + +void ControllerCoreParameter::changeAreaDescriptorType(QString type) +{ + if (dynamic_cast(m_View)) + dynamic_cast(m_View)->areaDescriptorTypeChanged( + type); +} + +void ControllerCoreParameter::receiveResetTrial() +{ + CoreParameterView* view = static_cast(m_View); + view->resetTrial(); +} + +void ControllerCoreParameter::triggerUpdate() +{ + + CoreParameterView* view = static_cast(m_View); + view->triggerUpdate(); +} + +void ControllerCoreParameter::receiveTrackNumber(int number) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + if (coreParams) { + coreParams->setTrackNumber(number); + } +} + +void ControllerCoreParameter::createModel() +{ + + m_Model = new CoreParameter(this); +} + +void ControllerCoreParameter::updateView() +{ +} + +void ControllerCoreParameter::setCorePermission( + std::pair permission) +{ + if (dynamic_cast(m_View)) { + dynamic_cast(m_View)->setPermission(permission); + } else { + // qDebug() << "no view yet"; + // This should never happen, actually + assert(false); + } +} + +int ControllerCoreParameter::getTrialNumber() +{ + return (static_cast( + m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT))) + ->getNumber(true); +} diff --git a/Src/Controller/ControllerCoreParameter.h b/Src/Controller/ControllerCoreParameter.h new file mode 100644 index 00000000..4b2e0747 --- /dev/null +++ b/Src/Controller/ControllerCoreParameter.h @@ -0,0 +1,46 @@ +#pragma once + +#include "IControllerCfg.h" +#include "Interfaces/IModel/IModelAreaDescriptor.h" +#include +#include + +class ControllerCoreParameter : public IControllerCfg +{ + Q_OBJECT +public: + ControllerCoreParameter( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COREPARAMETER); + + // Triggers the view to re-send gui parameters + void triggerUpdate(); + +signals: + //... + +private slots: + //... + void updateView(); + // update track number + void receiveTrackNumber(int number); + +public slots: + void setCorePermission(std::pair permission); + void changeAreaDescriptorType(QString type); + void receiveResetTrial(); + + // Forwarded from data exporter + int getTrialNumber(); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + +private: + //... +}; diff --git a/Src/Controller/ControllerDataExporter.cpp b/Src/Controller/ControllerDataExporter.cpp new file mode 100644 index 00000000..e3d281f4 --- /dev/null +++ b/Src/Controller/ControllerDataExporter.cpp @@ -0,0 +1,253 @@ +#include "ControllerDataExporter.h" +#include "Controller/ControllerCommands.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "Controller/ControllerPlayer.h" +#include "Model/DataExporters/DataExporterCSV.h" +#include "Model/DataExporters/DataExporterSerialize.h" +#include "Model/DataExporters/DataExporterJson.h" +#include "util/types.h" +#include +#include "QDesktopServices" + +using namespace BioTrackerUtilsMisc; // split + +ControllerDataExporter::ControllerDataExporter(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +ControllerDataExporter::~ControllerDataExporter() +{ +} + +void ControllerDataExporter::cleanup() +{ + if (m_Model) + qobject_cast(m_Model)->finalize(); +} + +void ControllerDataExporter::connectControllerToController() +{ + // connect to controller commands + IController* ictrcmd = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMMANDS); + ControllerCommands* ctrcmd = static_cast(ictrcmd); + + QObject::connect(this, + &ControllerDataExporter::emitResetUndoStack, + ctrcmd, + &ControllerCommands::receiveClear, + Qt::DirectConnection); + + // connect to view controller + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + ControllerTrackedComponentCore* tccController = + dynamic_cast(ctr); + + QObject::connect(this, + &ControllerDataExporter::emitViewUpdate, + tccController, + &ControllerTrackedComponentCore::receiveUpdateView, + Qt::DirectConnection); + + // ControllerPlayer* cPl = + // dynamic_cast(m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::PLAYER)); + // QObject::connect(cPl, &ControllerPlayer::emitNextMediaInBatch, this, + // &ControllerDataExporter::receiveReset, Qt::DirectConnection); +} + +void ControllerDataExporter::createModel() +{ + m_Model = nullptr; +} + +SourceVideoMetadata ControllerDataExporter::getSourceMetadata() +{ + IController* ctrM = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + MediaPlayer* mplay = dynamic_cast(ctrM->getModel()); + SourceVideoMetadata d; + d.name = mplay->getCurrentFileName().toStdString(); + d.fps = std::to_string(mplay->getFpsOfSourceFile()); + d.fps = d.fps.erase(d.fps.find_last_not_of('0') + 1, std::string::npos); + return d; +} + +void ControllerDataExporter::loadFile(std::string file) +{ + if (_factory) { + qobject_cast(m_Model)->loadFile(file); + } else { + std::cout << "Can not load tracks for this plugin as it does not " + "provide a factory." + << std::endl; + } +} + +void ControllerDataExporter::saveFile(std::string file) +{ + if (_factory) { + qobject_cast(m_Model)->writeAll(file); + } else { + std::cout << "Can not save tracks for this plugin as it does not " + "provide a factory." + << std::endl; + } +} + +void ControllerDataExporter::createView() +{ + + m_View = 0; +} + +void ControllerDataExporter::setDataStructure(IModel* exp) +{ + if (getModel()) + delete getModel(); + + // Grab the codec from config file + std::string exporter = exporterList[_cfg->DataExporter]; + if (exporter == "CSV") + m_Model = new DataExporterCSV(this); + else if (exporter == "Serialize") + m_Model = new DataExporterSerialize(this); + else if (exporter == "Json") + m_Model = new DataExporterJson(this); + else + m_Model = nullptr; + + qobject_cast(m_Model)->open( + static_cast(exp)); + + IModelDataExporter* model; + if ((model = dynamic_cast(getModel())) != nullptr) { + QObject::connect(model, + &IModelDataExporter::fileWritten, + this, + &ControllerDataExporter::receiveFileWritten); + } +} + +void ControllerDataExporter::setComponentFactory( + IModelTrackedComponentFactory* exp) +{ + _factory = exp; +} + +void ControllerDataExporter::receiveTrackingDone(uint frame) +{ + if (getModel()) { + dynamic_cast(getModel())->write(frame); + } +} + +void ControllerDataExporter::receiveFinalizeExperiment() +{ + if (getModel()) { + emitResetUndoStack(); + dynamic_cast(getModel())->finalizeAndReInit(); + emitViewUpdate(); + } +} + +void ControllerDataExporter::receiveReset() +{ + if (getModel()) { + emitResetUndoStack(); + dynamic_cast(getModel())->finalizeAndReInit(); + dynamic_cast(getModel())->close(); + emitViewUpdate(); + } + + createModel(); +} + +void ControllerDataExporter::connectModelToController() +{ + IController* ctrM = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + MediaPlayer* mplay = dynamic_cast(ctrM->getModel()); + + QObject::connect(mplay, + &MediaPlayer::fwdPlayerParameters, + this, + &ControllerDataExporter::rcvPlayerParameters); +} + +void ControllerDataExporter::rcvPlayerParameters( + std::shared_ptr parameters) +{ + if (qobject_cast(m_Model) != nullptr) { + qobject_cast(m_Model)->setFps( + parameters->m_fpsSourceVideo); + qobject_cast(m_Model)->setTitle( + parameters->m_CurrentTitle); + } +} + +int ControllerDataExporter::getNumber(bool trial) +{ + // Get all existing files of trial or track directory and parse highest + // export number + QString basePath = trial ? _cfg->DirTrials : _cfg->DirTracks; + QStringList allFiles = QDir(basePath).entryList(QDir::NoDotAndDotDot | + QDir::Files); + + int maxVal = 0; + foreach (QString s, allFiles) { + int val; + if (sscanf(s.toStdString().c_str(), "Export_%d_*", &val) != EOF) { + maxVal = std::max(maxVal, val); + } + } + return maxVal; +} + +QString ControllerDataExporter::generateBasename(bool temporaryFile) +{ + + QString resultPath = (_trialStarted ? _cfg->DirTrials : _cfg->DirTracks); + + QString path = (temporaryFile ? _cfg->DirTemp : resultPath); + int maxVal = getNumber(_trialStarted ? true : false); + std::string current = "Export_" + std::to_string(maxVal + 1) + "_"; + + return QString(getTimeAndDate(path.toStdString() + current, "").c_str()); +} + +void ControllerDataExporter::receiveFileWritten(QFileInfo fname) +{ + + QString str = "Exported file:\n"; + str += fname.absoluteFilePath(); + + QMessageBox msgBox; + msgBox.setText("File saved!"); + msgBox.setInformativeText(str); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + QPushButton* goToFileDirButton = msgBox.addButton(tr("Show in folder"), + QMessageBox::ActionRole); + QPushButton* openFileButton = msgBox.addButton(tr("Open file"), + QMessageBox::ActionRole); + + msgBox.setIcon(QMessageBox::Information); + msgBox.exec(); + + if (msgBox.clickedButton() == goToFileDirButton) { + QUrl fileDirUrl = QUrl::fromLocalFile(fname.absolutePath()); + QDesktopServices::openUrl(fileDirUrl); + } else if (msgBox.clickedButton() == openFileButton) { + QUrl fileUrl = QUrl::fromLocalFile(fname.absoluteFilePath()); + QDesktopServices::openUrl(fileUrl); + } +} + +void ControllerDataExporter::receiveTrialStarted(bool started) +{ + _trialStarted = started; +} diff --git a/Src/Controller/ControllerDataExporter.h b/Src/Controller/ControllerDataExporter.h new file mode 100644 index 00000000..ab8499af --- /dev/null +++ b/Src/Controller/ControllerDataExporter.h @@ -0,0 +1,67 @@ +#pragma once + +#include "IControllerCfg.h" +#include "Interfaces/IBioTrackerPlugin.h" +#include "Interfaces/IModel/IModelTrackedComponentFactory.h" +#include "QPointer" +#include "QThread" +#include "Model/MediaPlayer.h" + +// POD class to bundle some infos +struct SourceVideoMetadata +{ + std::string name; + std::string fps; +}; + +class ControllerDataExporter : public IControllerCfg +{ + Q_OBJECT +public: + ControllerDataExporter( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + ~ControllerDataExporter(); + void cleanup(); + + // IController interface +public: + void connectControllerToController() override; + void setDataStructure(IModel* exp); + void setComponentFactory(IModelTrackedComponentFactory* exp); + IModelTrackedComponentFactory* getComponentFactory() + { + return _factory; + }; + SourceVideoMetadata getSourceMetadata(); + int getNumber(bool trial); + QString generateBasename(bool temporaryFile); + + void loadFile(std::string file); + void saveFile(std::string file); + +Q_SIGNALS: + void emitResetUndoStack(); + void emitViewUpdate(); + +public Q_SLOTS: + void receiveReset(); + void receiveTrackingDone(uint frame); + void receiveFinalizeExperiment(); + void receiveFileWritten(QFileInfo fname); + void receiveTrialStarted(bool started); + +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + +private Q_SLOTS: + void rcvPlayerParameters( + std::shared_ptr parameters); + +private: + IModelTrackedComponentFactory* _factory; + bool _trialStarted = false; +}; diff --git a/Src/Controller/ControllerGraphicScene.cpp b/Src/Controller/ControllerGraphicScene.cpp new file mode 100644 index 00000000..720956ea --- /dev/null +++ b/Src/Controller/ControllerGraphicScene.cpp @@ -0,0 +1,57 @@ +#include "ControllerGraphicScene.h" +//#include "Model/TrackedComponents/TrackedElement.h" +#include "View/GraphicsView.h" +#include "Model/null_Model.h" +#include "View/MainWindow.h" + +ControllerGraphicScene::ControllerGraphicScene(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ + m_Element = NULL; + m_GraphicsView = NULL; +} + +void ControllerGraphicScene::addGraphicsItem(QGraphicsItem* item) +{ + GraphicsView* gview = dynamic_cast(m_View); + gview->addGraphicsItem(item); +} + +void ControllerGraphicScene::addTextureObject(QGraphicsItem* item) +{ + GraphicsView* gview = dynamic_cast(m_View); + gview->addPixmapItem(item); +} + +void ControllerGraphicScene::createModel() +{ + m_NullModel = new null_Model(); +} + +void ControllerGraphicScene::createView() +{ + m_View = new GraphicsView(0, this, m_NullModel); +} + +void ControllerGraphicScene::connectModelToController() +{ + QObject::connect(this, + &ControllerGraphicScene::signalToggleAntialiasingFull, + dynamic_cast(m_View), + &GraphicsView::receiveToggleAntialiasingFull); +} + +void ControllerGraphicScene::connectControllerToController() +{ + IController* ctrM = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer mainWin = dynamic_cast(ctrM->getView()); + mainWin->addVideoView(m_View); +} + +void ControllerGraphicScene::receiveToggleAntialiasingFull(bool toggle) +{ + signalToggleAntialiasingFull(toggle); +} \ No newline at end of file diff --git a/Src/Controller/ControllerGraphicScene.h b/Src/Controller/ControllerGraphicScene.h new file mode 100644 index 00000000..c0f2816a --- /dev/null +++ b/Src/Controller/ControllerGraphicScene.h @@ -0,0 +1,66 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef CONTROLLERGRAPHICSCENE_H +#define CONTROLLERGRAPHICSCENE_H + +#include "IControllerCfg.h" +#include "QGraphicsObject" +#include "QPointer" + +/** + * The ControllerGraphicScene class controlls the component for rendering + * TextureObjects and TrackedComponents on a GraphhicsView. Each PixmapItem + * represents a cv::Mat. The cv::Mat comes from the TextureObjects-Component of + * BioTracker. The GraphicsItem represents the compositum structure of + * IViewTrackedComponent classes. These structure comes from the + * ControllerTrackedComponentCore or the Plugin and handed over by the + * PluginController of the MainApplication. + * + */ +class ControllerGraphicScene : public IControllerCfg +{ + Q_OBJECT +public: + ControllerGraphicScene( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + + /** + * This methode add a the root node of the compositum structure of + * IViewTrackedComponent classes to the GraphicsView canvas. All child + * nodes will be rendered on a GraphicsView canvas as well. + */ + void addGraphicsItem(QGraphicsItem* item); + /** + * This methode adds a IViewGraphicsPixmapItem to the GraphicsView canvas + * for rendering. + */ + void addTextureObject(QGraphicsItem* item); + +signals: + void signalToggleAntialiasingFull(bool toggle); + +public slots: + void receiveToggleAntialiasingFull(bool toggle); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + +private: + IView* m_GraphicsView; + + IModel* m_Element; + QPointer m_NullModel; +}; + +#endif // CONTROLLERGRAPHICSCENE_H diff --git a/Src/Controller/ControllerMainWindow.cpp b/Src/Controller/ControllerMainWindow.cpp new file mode 100644 index 00000000..6aa581da --- /dev/null +++ b/Src/Controller/ControllerMainWindow.cpp @@ -0,0 +1,407 @@ +#include "ControllerMainWindow.h" +#include "View/MainWindow.h" +#include "View/GraphicsView.h" +#include "Model/null_Model.h" +#include "Model/Annotations.h" + +#include "Controller/ControllerPlayer.h" +#include "Controller/ControllerPlugin.h" +#include "Controller/ControllerAnnotations.h" +#include "Controller/ControllerDataExporter.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "Controller/ControllerCommands.h" +#include "Controller/ControllerGraphicScene.h" +#include "Controller/ControllerCoreParameter.h" +#include "GuiContext.h" + +#include "QPluginLoader" + +#include +#include + +ControllerMainWindow::ControllerMainWindow(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +void ControllerMainWindow::loadVideo( + std::vector files) +{ + + Q_EMIT emitOnLoadMedia(files.front().string()); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + qobject_cast(ctr)->loadVideoStream(files); + Q_EMIT emitMediaLoaded(files.front().string()); + + dynamic_cast(m_View)->checkMediaGroupBox(); +} + +void ControllerMainWindow::loadTracker(QString plugin) +{ + Q_EMIT emitOnLoadPlugin(plugin.toStdString()); + dynamic_cast(m_View)->resetTrackerViews(); + qobject_cast(m_BioTrackerContext) + ->loadBioTrackerPlugin(plugin); + dynamic_cast(m_View)->checkTrackerGroupBox(); + activeTrackingCheckBox(); + Q_EMIT emitPluginLoaded(plugin.toStdString()); +} + +void ControllerMainWindow::loadPictures( + std::vector files) +{ + std::string str = files.empty() ? "" : files.front().string(); + + Q_EMIT emitOnLoadMedia(str); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + qobject_cast(ctr)->loadPictures(files); + Q_EMIT emitMediaLoaded(str); + + dynamic_cast(m_View)->checkMediaGroupBox(); +} + +void ControllerMainWindow::loadCameraDevice(CameraConfiguration conf) +{ + Q_EMIT emitOnLoadMedia("::Camera"); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + qobject_cast(ctr)->loadCameraDevice(conf); + Q_EMIT emitMediaLoaded("::Camera"); + + dynamic_cast(m_View)->checkMediaGroupBox(); +} + +void ControllerMainWindow::activeTracking() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + qobject_cast(ctr)->setTrackingActivated(); + dynamic_cast(m_View)->activateTracking(); +} + +void ControllerMainWindow::deactiveTrackring() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + qobject_cast(ctr)->setTrackingDeactivated(); + dynamic_cast(m_View)->deactivateTracking(); +} + +void ControllerMainWindow::setTrackerList(QStringListModel* trackerList, + QString current) +{ + dynamic_cast(m_View)->setTrackerList(trackerList, current); +} + +void ControllerMainWindow::setTrackerParamterWidget(IView* widget) +{ + dynamic_cast(m_View)->addTrackerParameterView(widget); +} + +void ControllerMainWindow::setTrackerElementsWidget(IView* widget) +{ + dynamic_cast(m_View)->addTrackerElementsView(widget); +} + +void ControllerMainWindow::setCoreElementsWidget(IView* widget) +{ + dynamic_cast(m_View)->addCoreElementsView(widget); +} + +void ControllerMainWindow::setNotificationBrowserWidget(IView* widget) +{ + dynamic_cast(m_View)->addNotificationBrowser(widget); +} + +void ControllerMainWindow::loadTrajectoryFile(std::string file) +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + static_cast(ctr)->loadFile(file); + Q_EMIT emitTrackLoaded(file); +} + +void ControllerMainWindow::saveTrajectoryFile(std::string file) +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + static_cast(ctr)->saveFile(file); +} + +void ControllerMainWindow::deactiveTrackingCheckBox() +{ + dynamic_cast(m_View)->deactivateTrackingCheckBox(); +} + +void ControllerMainWindow::activeTrackingCheckBox() +{ + dynamic_cast(m_View)->activeTrackingCheckBox(); +} + +void ControllerMainWindow::receiveSaveTrajData() +{ + dynamic_cast(m_View)->saveDataToFile(); +} + +void ControllerMainWindow::createModel() +{ + // no model for MainWindow + m_Model = new null_Model(); +} + +void ControllerMainWindow::createView() +{ + m_View = dynamic_cast(new MainWindow(0, this, m_Model)); + static_cast(m_View)->show(); +} + +void ControllerMainWindow::connectModelToController() +{ + + MainWindow* mw = dynamic_cast(m_View); + QObject::connect(mw, + &MainWindow::selectPlugin, + this, + &ControllerMainWindow::rcvSelectPlugin); + + // Prepare annotations and serialize existing ones. + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::ANNOTATIONS); + ControllerAnnotations* annotationController = + static_cast(ctr); + QObject::connect(this, + &ControllerMainWindow::emitMediaLoaded, + annotationController, + &ControllerAnnotations::reset, + Qt::DirectConnection); + + // Write previously written data structure and reset it + IController* ctr2 = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + ControllerDataExporter* contrl = static_cast( + ctr2); + QObject::connect(this, + &ControllerMainWindow::emitOnLoadMedia, + contrl, + &ControllerDataExporter::receiveFinalizeExperiment, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitOnLoadPlugin, + contrl, + &ControllerDataExporter::receiveReset, + Qt::DirectConnection); +} + +void ControllerMainWindow::connectControllerToController() +{ + // + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + IView* v = ctr->getView(); + dynamic_cast(m_View)->addCoreParameterView(v); + + // connect to controller commands + IController* ictrcmd = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMMANDS); + ControllerCommands* ctrcmd = static_cast(ictrcmd); + + QObject::connect(this, + &ControllerMainWindow::emitUndoCommand, + ctrcmd, + &ControllerCommands::receiveUndo, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitRedoCommand, + ctrcmd, + &ControllerCommands::receiveRedo, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitOnLoadMedia, + ctrcmd, + &ControllerCommands::receiveClear, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitOnLoadPlugin, + ctrcmd, + &ControllerCommands::receiveClear, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitShowActionListCommand, + ctrcmd, + &ControllerCommands::receiveShowActionList, + Qt::DirectConnection); + + // connect to ControllerGraphicScene + IController* ictrgrv = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + ControllerGraphicScene* ctrgrv = static_cast( + ictrgrv); + GraphicsView* grv = static_cast(ctrgrv->getView()); + + QObject::connect(grv, + &GraphicsView::emitCursorPosition, + this, + &ControllerMainWindow::receiveCursorPosition, + Qt::QueuedConnection); + + // connect to ControllerTrackedComponentCore + IController* ictrtrcc = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + ControllerTrackedComponentCore* ctrtrcc = + static_cast(ictrtrcc); + + QObject::connect(this, + &ControllerMainWindow::emitAddTrack, + ctrtrcc, + &ControllerTrackedComponentCore::emitAddTrack, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitDeleteSelectedTracks, + ctrtrcc, + &ControllerTrackedComponentCore::emitDeleteSelectedTracks, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitSelectAll, + ctrtrcc, + &ControllerTrackedComponentCore::emitSelectAll, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitSwapIds, + ctrtrcc, + &ControllerTrackedComponentCore::emitSwapIdsToView, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitChangeColorBorder, + ctrtrcc, + &ControllerTrackedComponentCore::emitChangeColorBorder, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitChangeColorFill, + ctrtrcc, + &ControllerTrackedComponentCore::emitChangeColorFill, + Qt::DirectConnection); + + // connect to ControllerAnnotations + IController* ictrann = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::ANNOTATIONS); + ControllerAnnotations* ctrann = static_cast( + ictrann); + + QObject::connect(this, + &ControllerMainWindow::emitAddLabelAnno, + ctrann, + &ControllerAnnotations::receiveAddLabelAnnotation, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitAddRectAnno, + ctrann, + &ControllerAnnotations::receiveAddRectAnnotation, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitAddArrAnno, + ctrann, + &ControllerAnnotations::receiveAddArrowAnnotation, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitAddEllAnno, + ctrann, + &ControllerAnnotations::receiveAddEllipseAnnotation, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitDelSelAnno, + ctrann, + &ControllerAnnotations::receiveDeleteSelectedAnnotation, + Qt::DirectConnection); + + // connect to ControllerDataExporter + IController* ictrde = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + ControllerDataExporter* deController = + static_cast(ictrde); + QObject::connect(this, + &ControllerMainWindow::emitFinalizeExperiment, + deController, + &ControllerDataExporter::receiveFinalizeExperiment, + Qt::DirectConnection); + + // reset trials + IController* ictrcpv = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + ControllerCoreParameter* ctrcpv = static_cast( + ictrcpv); + QObject::connect(this, + &ControllerMainWindow::emitOnLoadMedia, + ctrcpv, + &ControllerCoreParameter::receiveResetTrial, + Qt::DirectConnection); + QObject::connect(this, + &ControllerMainWindow::emitOnLoadPlugin, + ctrcpv, + &ControllerCoreParameter::receiveResetTrial, + Qt::DirectConnection); + + // batch media signals + IController* ctr3 = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + ControllerPlayer* cont3 = static_cast(ctr3); + QObject::connect(cont3, + &ControllerPlayer::emitNextMediaInBatch, + this, + &ControllerMainWindow::emitOnLoadMedia, + Qt::DirectConnection); + QObject::connect(cont3, + &ControllerPlayer::emitNextMediaInBatchLoaded, + this, + &ControllerMainWindow::emitMediaLoaded, + Qt::DirectConnection); + + // Load video as per CLI + if (!_cfg->LoadVideo.isEmpty()) + loadVideo({_cfg->LoadVideo.toStdString().c_str()}); +} + +void ControllerMainWindow::receiveCursorPosition(QPoint pos) +{ + // qDebug() << pos; + dynamic_cast(m_View)->setCursorPositionLabel(pos); +} + +void ControllerMainWindow::setCorePermission( + std::pair permission) +{ + if (dynamic_cast(m_View)) { + dynamic_cast(m_View)->setCorePermission(permission); + } else { + assert(false); + } +} + +void ControllerMainWindow::rcvSelectPlugin(QString plugin) +{ + Q_EMIT emitOnLoadPlugin(plugin.toStdString()); + dynamic_cast(m_View)->resetTrackerViews(); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLUGIN); + qobject_cast(ctr)->selectPlugin(plugin); + // dynamic_cast(m_View)->activeTrackingCheckBox(); + activeTrackingCheckBox(); + Q_EMIT emitPluginLoaded(plugin.toStdString()); +} + +void ControllerMainWindow::onNewMediumLoaded(const std::string path) +{ + Q_EMIT emitMediaLoaded(path); +} + +void ControllerMainWindow::exit() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + ControllerPlayer* pc = static_cast(ctr); + pc->stop(); + delete m_BioTrackerContext; +} diff --git a/Src/Controller/ControllerMainWindow.h b/Src/Controller/ControllerMainWindow.h new file mode 100644 index 00000000..4f998170 --- /dev/null +++ b/Src/Controller/ControllerMainWindow.h @@ -0,0 +1,155 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef CONTROLLERMAINWINDOW_H +#define CONTROLLERMAINWINDOW_H + +#include "IControllerCfg.h" +#include "QPointer" +#include "QStringListModel" +#include "boost/filesystem.hpp" +#include +#include "util/types.h" +#include "util/camera/base.h" + +/** + * The ControllerMainWindow class controlls the IView class MainWindow. + * All user interactions done through the MainWindow class are delegated to the + * controllers of the component that concerns them. Other components can place + * their IView Widgets on the MainWindow. + */ +class ControllerMainWindow : public IControllerCfg +{ + Q_OBJECT +public: + ControllerMainWindow( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + + /** + * Receives the a string containing the video file path from the MainWindow + * class. The string is then given to the ControllerPlayer class of the + * MediaPlayer-Component. + */ + void loadVideo(std::vector files); + /** + * Receives the a string containing the Plugin file path from the + * MainWindow class. The string is then given to the BioTrackerContext + * class which will hand it over to the ControllerPlugin class. + */ + void loadTracker(QString str); + /** + * Receives the a string containing the pictures file path from the + * MainWindow class. The string is then given to the ControllerPlayer class + * of the MediaPlayer-Component. + */ + void loadPictures(std::vector files); + /** + * Receives the a string containing the camera device number from the + * MainWindow class. The string is then given to the ControllerPlayer class + * of the MediaPlayer-Component. + */ + void loadCameraDevice(CameraConfiguration conf); + /** + * Receives a QStringListModel with the names of all currently loades + * BioTracker Plugins from the ControllerPlugin class. + */ + void setTrackerList(QStringListModel* trackerList, QString current); + /** + * Embeds the Parameter Widget devined in the BioTracker Plugins into the + * MainWindow Widget. + */ + void setTrackerParamterWidget(IView* widget); + /** + * Embeds the view for visualization of tracking data devined in the + * BioTracker Plugins into the MainWindow Widget. + */ + void setTrackerElementsWidget(IView* widget); + /** + * Embeds the view for visualization of tracking data from the core app + * into the MainWindow Widget. + */ + void setCoreElementsWidget(IView* widget); + /** + * Embeds the the notification view of the core app into the MainWindow + * Widget. + */ + void setNotificationBrowserWidget(IView* widget); + + void loadTrajectoryFile(std::string file); + void saveTrajectoryFile(std::string file); + + void deactiveTrackingCheckBox(); + void activeTrackingCheckBox(); + + // Passes exit command to the GUI context + void exit(); + +public: +signals: + void emitFinalizeExperiment(); + + void emitOnLoadPlugin(const std::string path); + void emitOnLoadMedia(const std::string path); + + void emitPluginLoaded(const std::string path); + void emitMediaLoaded(const std::string path); + void emitTrackLoaded(const std::string path); + + void emitUndoCommand(); + void emitRedoCommand(); + void emitClearUndoStack(); + void emitShowActionListCommand(); + + // view toolbar actions + void emitAddTrack(); + void emitDeleteSelectedTracks(); + void emitSwapIds(); + void emitSelectAll(); + void emitChangeColorBorder(); + void emitChangeColorFill(); + void emitAddLabelAnno(); + void emitAddRectAnno(); + void emitAddArrAnno(); + void emitAddEllAnno(); + void emitDelSelAnno(); + +public slots: + void setCorePermission(std::pair permission); + /** + * Receives the command for activating the Tracking in a BioTracker Plugin + * from the MainWindow class. This command is given to the ControllerPlayer + * class of the MediaPlayer-component. + */ + void activeTracking(); + /** + * Receives the command for deactivating the Tracking in a BioTracker + * Plugin from the MainWindow class. This command is given to the + * ControllerPlayer class of the MediaPlayer-component. + */ + void deactiveTrackring(); + + void receiveSaveTrajData(); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + +private slots: + void rcvSelectPlugin(QString plugin); + void receiveCursorPosition(QPoint pos); + +private: + // Internal cleanup callback when a new video or imagestream is loaded. + void onNewMediumLoaded(const std::string path = ""); +}; + +#endif // CONTROLLERMAINWINDOW_H diff --git a/Src/Controller/ControllerNotifications.cpp b/Src/Controller/ControllerNotifications.cpp new file mode 100644 index 00000000..bb3cd6d3 --- /dev/null +++ b/Src/Controller/ControllerNotifications.cpp @@ -0,0 +1,59 @@ +#include "ControllerNotifications.h" +#include "View/NotificationLogBrowser.h" +#include "ControllerMainWindow.h" +#include "qdebug.h" + +IView* view; + +ControllerNotifications::ControllerNotifications(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +ControllerNotifications::~ControllerNotifications() +{ + qInstallMessageHandler(0); +} + +void ControllerNotifications::cleanup() +{ + qInstallMessageHandler(0); +} + +void ControllerNotifications::createModel() +{ +} + +void ControllerNotifications::createView() +{ + m_View = new NotificationLogBrowser(); + view = m_View; + qInstallMessageHandler(messageHandler); +} + +void ControllerNotifications::connectModelToController() +{ +} + +void ControllerNotifications::connectControllerToController() +{ + // Add notification browser to Main Window + IController* ctrA = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer ctrMainWindow = + qobject_cast(ctrA); + + ctrMainWindow->setNotificationBrowserWidget(m_View); +} + +void messageHandler(QtMsgType type, + const QMessageLogContext& context, + const QString& msg) +{ + NotificationLogBrowser* log = dynamic_cast(view); + if (log) { + log->outputMessage(type, msg); + } +} diff --git a/Src/Controller/ControllerNotifications.h b/Src/Controller/ControllerNotifications.h new file mode 100644 index 00000000..0a66a520 --- /dev/null +++ b/Src/Controller/ControllerNotifications.h @@ -0,0 +1,38 @@ +#pragma once + +#ifndef CONTROLLERNOTIFICATIONS_H + #define CONTROLLERNOTIFICATIONS_H + + #include "IControllerCfg.h" + +/** + * This class inherits from IController. + * The notifications component includes the notifications view. + * This controller uses qInstallMessageHandler(messageHandler) to + * intercept all qDebug messages and display them in a text browser (the view). + * This text browser is displayed in the 'Notifications' tab in the GUI. + * QDebug reference: http://doc.qt.io/qt-5/qdebug.html + */ +class ControllerNotifications : public IControllerCfg +{ + Q_OBJECT +public: + ControllerNotifications( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + ~ControllerNotifications(); + void cleanup() override; + +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; +}; + +void messageHandler(QtMsgType type, + const QMessageLogContext& context, + const QString& msg); + +#endif // CONTROLLERNOTIFICATIONS_H \ No newline at end of file diff --git a/Src/Controller/ControllerPlayer.cpp b/Src/Controller/ControllerPlayer.cpp new file mode 100644 index 00000000..664c2b56 --- /dev/null +++ b/Src/Controller/ControllerPlayer.cpp @@ -0,0 +1,273 @@ +#include "ControllerPlayer.h" +#include "View/VideoControllWidget.h" +#include "View/MainWindow.h" +#include "Controller/ControllerTextureObject.h" +#include "Controller/ControllerPlugin.h" +#include "Controller/ControllerGraphicScene.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "Controller/ControllerCoreParameter.h" + +#include +#include + +ControllerPlayer::ControllerPlayer(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ +} + +ControllerPlayer::~ControllerPlayer() +{ +} + +void ControllerPlayer::loadVideoStream( + std::vector files) +{ + qobject_cast(m_Model)->loadVideoStream(files); + emitPauseState(true); +} + +void ControllerPlayer::loadPictures(std::vector files) +{ + qobject_cast(m_Model)->loadPictures(files); + emitPauseState(true); +} + +void ControllerPlayer::loadCameraDevice(CameraConfiguration conf) +{ + qobject_cast(m_Model)->loadCameraDevice(conf); + emitPauseState(true); +} + +void ControllerPlayer::nextFrame() +{ + qobject_cast(m_Model)->nextFrameCommand(); +} + +void ControllerPlayer::prevFrame() +{ + qobject_cast(m_Model)->prevFrameCommand(); +} + +void ControllerPlayer::play() +{ + qobject_cast(m_Model)->playCommand(); + emitPauseState(false); +} + +void ControllerPlayer::stop() +{ + qobject_cast(m_Model)->stopCommand(); + emitPauseState(true); +} + +void ControllerPlayer::pause() +{ + qobject_cast(m_Model)->pauseCommand(); + emitPauseState(true); +} + +void ControllerPlayer::setGoToFrame(int frame) +{ + qobject_cast(m_Model)->goToFrame(frame); +} + +void ControllerPlayer::receiveRenderImage(cv::Mat img, QString name) +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); + QPointer ctrTextureObject = + qobject_cast(ctr); + + ctrTextureObject->updateTexture(name, img); +} + +void ControllerPlayer::receiveImageToTracker(cv::Mat mat, uint number) +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLUGIN); + QPointer ctrPlugin = qobject_cast( + ctr); + + ctrPlugin->sendCurrentFrameToPlugin(mat, number); +} + +void ControllerPlayer::changeImageView(QString str) +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); + QPointer ctrTextureObject = + qobject_cast(ctr); + + ctrTextureObject->changeTextureModel(str); +} + +int ControllerPlayer::recordOutput() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + QPointer ctrTextureObject = + qobject_cast(ctr); + + return qobject_cast(m_Model)->toggleRecordGraphicsScenes( + dynamic_cast(ctrTextureObject->getView())); +} + +int ControllerPlayer::recordInput() +{ + return qobject_cast(m_Model)->toggleRecordImageStream(); +} + +void ControllerPlayer::setTargetFps(double fps) +{ + return qobject_cast(m_Model)->setTargetFPS(fps); +} + +QString ControllerPlayer::takeScreenshot() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + QPointer ctrTextureObject = + qobject_cast(ctr); + return qobject_cast(m_Model)->takeScreenshot( + dynamic_cast(ctrTextureObject->getView())); +} + +void ControllerPlayer::setTrackingActivated() +{ + qobject_cast(m_Model)->setTrackingActive(); +} + +void ControllerPlayer::setTrackingDeactivated() +{ + qobject_cast(m_Model)->setTrackingDeactive(); +} + +void ControllerPlayer::connectControllerToController() +{ + // connect to mainwindow + IController* ctrM = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer mainWin = dynamic_cast(ctrM->getView()); + mainWin->addVideoControllWidget(m_View); + VideoControllWidget* vControl = static_cast(m_View); + vControl->setupVideoToolbar(); + + ////connect to coreparameterview + // IController* ictrCpv = + // m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COREPARAMETER); + // QPointer< ControllerCoreParameter > ctrCpv = + // dynamic_cast(ictrCpv); + + // QObject::connect(this, &ControllerPlayer::emitPauseState, ctrCpv, + // &ControllercoreParameter) +} + +void ControllerPlayer::createModel() +{ + m_Model = new MediaPlayer(this); +} + +void ControllerPlayer::createView() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer mainWindow = dynamic_cast( + ctr->getView()); + + m_View = new VideoControllWidget(mainWindow, this, m_Model); +} + +void ControllerPlayer::connectModelToController() +{ + + QObject::connect(qobject_cast(m_Model), + &MediaPlayer::renderCurrentImage, + this, + &ControllerPlayer::receiveRenderImage); + QObject::connect(qobject_cast(m_Model), + &MediaPlayer::trackCurrentImage, + this, + &ControllerPlayer::receiveImageToTracker); + QObject::connect(this, + &ControllerPlayer::emitPauseState, + qobject_cast(m_Model), + &MediaPlayer::rcvPauseState); + QObject::connect(qobject_cast(m_Model), + &MediaPlayer::signalVisualizeCurrentModel, + this, + &ControllerPlayer::receiveVisualizeCurrentModel); + QObject::connect(qobject_cast(m_Model), + &MediaPlayer::signalCurrentFrameNumberToPlugin, + this, + &ControllerPlayer::receiveCurrentFrameNumberToPlugin); + + QObject::connect(qobject_cast(m_Model), + &MediaPlayer::emitNextMediaInBatch, + this, + &ControllerPlayer::receiveNextMediaInBatch, + Qt::DirectConnection); + QObject::connect(qobject_cast(m_Model), + &MediaPlayer::emitNextMediaInBatchLoaded, + this, + &ControllerPlayer::receiveNextMediaInBatchLoaded, + Qt::DirectConnection); + + IController* ctrTRCC = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + QPointer trCC = + qobject_cast(ctrTRCC); + + QObject::connect(trCC, + &ControllerTrackedComponentCore::emitTrackNumber, + this, + &ControllerPlayer::receiveTrackCount, + Qt::DirectConnection); +} + +void ControllerPlayer::receiveNextMediaInBatch(const std::string path) +{ + _trackCountEndOfBatch = _trackCount; + Q_EMIT emitNextMediaInBatch(path); +} + +void ControllerPlayer::receiveNextMediaInBatchLoaded(const std::string path) +{ + Q_EMIT emitNextMediaInBatchLoaded(path); + + IController* ctrTRCC = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + QPointer trCC = + qobject_cast(ctrTRCC); + for (int i = 0; i < _trackCountEndOfBatch; i++) { + trCC->emitAddTrack(); + } +} + +void ControllerPlayer::receiveTrackCount(int trackNo) +{ + _trackCount = trackNo; +} + +void ControllerPlayer::receiveVisualizeCurrentModel(uint frameNumber) +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + QPointer ctrTrCompCore = + qobject_cast(ctr); + + ctrTrCompCore->receiveVisualizeTrackingModel(frameNumber); +} + +void ControllerPlayer::receiveChangeDisplayImage(QString str) +{ + + VideoControllWidget* w = dynamic_cast(m_View); + w->setSelectedView(str); +} + +void ControllerPlayer::receiveCurrentFrameNumberToPlugin(uint frameNumber) +{ + Q_EMIT signalCurrentFrameNumberToPlugin(frameNumber); +} diff --git a/Src/Controller/ControllerPlayer.h b/Src/Controller/ControllerPlayer.h new file mode 100644 index 00000000..dc5da90f --- /dev/null +++ b/Src/Controller/ControllerPlayer.h @@ -0,0 +1,145 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ +#ifndef CONTROLLERPLAYER_H +#define CONTROLLERPLAYER_H + +#include "IControllerCfg.h" +#include "Model/MediaPlayer.h" +#include "QPointer" +#include "util/types.h" + +/** + * The ControllerPlayer class it the controller of the MediaPlayer-Component. + * This controller creates and controlls the IModel class MediaPlayer and the + * IView class VideoControllWidget. + */ +class ControllerPlayer : public IControllerCfg +{ + Q_OBJECT +public: + ControllerPlayer( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + ~ControllerPlayer(); + + /** + * Hands over the file path of a video to the IModel class MediaPlayer. + */ + void loadVideoStream(std::vector files); + /** + * Hands over the file path of pictures to the IModel class MediaPlayer. + */ + void loadPictures(std::vector files); + /** + * Hands over the camera device number to the IModel class MediaPlayer. + */ + void loadCameraDevice(CameraConfiguration conf); + + /** + * Tells the MediaPlayer-Component to hand over the current cv::Mat and the + * current frame number to the BioTracker Plugin. + */ + void setTrackingActivated(); + /** + * Tells the MediaPlayer-Component not to hand over the current cv::Mat and + * the current frame number to the BioTracker Plugin. + */ + void setTrackingDeactivated(); + + /** + * Tells the IModel class MediaPlayer to display the next image frame of + * the ImageStream. + */ + void nextFrame(); + /** + * Tells the IModel class MediaPlayer to display the previous image frame + * of the ImageStream. + */ + void prevFrame(); + /** + * Tells the IModel class MediaPlayer to start playing the ImageStream. + */ + void play(); + /** + * Tells the IModel class MediaPlayer to stop playing the ImageStream. + */ + void stop(); + /** + * Tells the IModel class MediaPlayer to pause playing the ImageStream. + */ + void pause(); + /** + * If the user changes the ImageView in the comboBox represented in the + * VideoControllWidget it passes the selected ImageView name to the + * ControllerTextureObject class of the TextureObject-Component. + */ + void changeImageView(QString str); + + /** + * User clicked record -> record "what the user sees" + */ + int recordOutput(); + + int recordInput(); + + void setTargetFps(double fps); + + QString takeScreenshot(); + + // IController interface +public: + void connectControllerToController() override; + +signals: + void emitPauseState(bool state); + void signalCurrentFrameNumberToPlugin(uint frameNumber); + void emitNextMediaInBatch(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path); + +public Q_SLOTS: + /** + * This SLOT receives a cv::Mat and a name for the cv::Mat from the + * MediaPlayer class and hands it over to the ControllerTextureObject for + * rendering. + */ + void receiveRenderImage(cv::Mat mat, QString name); + /** + * This SLOT receives a cv::Mat and its frame number and hands it over to + * the ControllerPlugin for Tracking in the BioTracker Plugin. + */ + void receiveImageToTracker(cv::Mat mat, uint number); + /** + * This SLOT receives a framenumber and hands it over to the + * ControllerTrackedComponentCore for visualizing in the main app. + */ + void receiveVisualizeCurrentModel(uint frameNumber); + + void receiveChangeDisplayImage(QString str); + + void receiveCurrentFrameNumberToPlugin(uint frameNumber); + /** + * Tells the IModel class MediaPlayer to jump directly to the specified + * image frame by the parameter frame. + */ + void setGoToFrame(int frame); + + void receiveNextMediaInBatch(const std::string path); + void receiveNextMediaInBatchLoaded(const std::string path); + void receiveTrackCount(int trackNo); + +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + +private: + int _trackCount = 0; + int _trackCountEndOfBatch = 0; +}; + +#endif // CONTROLLERPLAYER_H diff --git a/Src/Controller/ControllerPlugin.cpp b/Src/Controller/ControllerPlugin.cpp new file mode 100644 index 00000000..6b5f0293 --- /dev/null +++ b/Src/Controller/ControllerPlugin.cpp @@ -0,0 +1,669 @@ +#include "ControllerPlugin.h" + +#include "Controller/ControllerPlayer.h" +#include "Controller/ControllerTextureObject.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "ControllerMainWindow.h" +#include "QDebug" +#include "util/types.h" +#include "ControllerDataExporter.h" +#include "ControllerAreaDescriptor.h" +#include "Controller/ControllerCoreParameter.h" +#include "Controller/ControllerCommands.h" + +#define REGISTRY_PATH "SOFTWARE\\FUBioroboticsLab\\BioTracker\\Plugins" +#define TRACKER_SUFFIX ".bio_tracker" + +ControllerPlugin::ControllerPlugin(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ + m_BioTrackerPlugin = NULL; + + m_TrackingThread = new QThread(this); + m_TrackingThread->setObjectName("TrackingThread"); + m_TrackingThread->start(); +} + +ControllerPlugin::~ControllerPlugin() +{ + + // They might not exist (no plugins available!) + if (m_BioTrackerPlugin) + delete m_BioTrackerPlugin; + if (pluginLoader) + delete pluginLoader; + + m_TrackingThread->quit(); + m_TrackingThread->wait(); +} + +void ControllerPlugin::addToPluginList(QString str) +{ + + std::string s = str.toStdString(); + pluginLoader->addToPluginList(str, TRACKER_SUFFIX); + + // Add Plugin name to Main Window + IController* ctrA = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer ctrMainWindow = + qobject_cast(ctrA); + + ctrMainWindow->setTrackerList(pluginLoader->getPluginList(), + pluginLoader->getCurrentPluginName()); +} + +void ControllerPlugin::loadPluginFromFileName(QString str) +{ + + if (pluginLoader->loadPluginFromFilename(str)) { + m_BioTrackerPlugin = qobject_cast( + pluginLoader->getPluginInstance()); + initPlugin(); + + // Add Plugin name to Main Window + IController* ctrA = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer ctrMainWindow = + qobject_cast(ctrA); + + ctrMainWindow->setTrackerList(pluginLoader->getPluginList(), + pluginLoader->getCurrentPluginName()); + + // Add Tracker Parameter to Main Window + IView* parms = m_BioTrackerPlugin->getTrackerParameterWidget(); + ctrMainWindow->setTrackerParamterWidget(parms); + + // Add Tracker tracked components (Elements) to Main Window + IView* elems = m_BioTrackerPlugin->getTrackerElementsWidget(); + ctrMainWindow->setTrackerElementsWidget(elems); + + IController* ctrB = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + QPointer ctrTrackedComponentCore = + qobject_cast(ctrB); + + // Add Tracker tracked components model to + // ControllerTrackedComponentCore + ctrTrackedComponentCore->addModel( + m_BioTrackerPlugin->getTrackerComponentModel()); + // Add tracked component view to main window + ctrMainWindow->setCoreElementsWidget( + ctrTrackedComponentCore->getTrackingElementsWidgetCore()); + + IController* ctrDE = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + QPointer ctrDataExp = + qobject_cast(ctrDE); + ctrDataExp->setDataStructure( + m_BioTrackerPlugin->getTrackerComponentModel()); + ctrDataExp->setComponentFactory( + m_BioTrackerPlugin->getComponentFactory()); + + m_BioTrackerPlugin->sendCorePermissions(); + } else { + qWarning() << "Failed to load plugin from filename!"; + } +} + +void ControllerPlugin::selectPlugin(QString str) +{ + if (str.isEmpty()) + return; + + if (pluginLoader->getCurrentPluginName() != str) + loadPluginFromFileName(pluginLoader->getPluginMap().find(str)->second); +} + +void ControllerPlugin::createModel() +{ + m_Model = nullptr; + pluginLoader = new PluginLoader(this); +} + +void ControllerPlugin::createView() +{ +} + +void ControllerPlugin::connectModelToController() +{ +} + +void ControllerPlugin::loadPluginsFromPluginSubfolder() +{ + + ////////////// + QDir d(_cfg->DirPlugins); + d.setFilter(QDir::Filter::Files); + QStringList nameFilter; + QFileInfoList fl = d.entryInfoList(nameFilter, QDir::Filter::Files); + + // Grab list of behaviors from config & registry + std::vector list = _cfg->UseRegistryLocations == 1 + ? PluginLoader::queryRegistryBehaviors( + REGISTRY_PATH) + : std::vector(); + // Search directories + std::vector filesFromFolders = + PluginLoader::searchDirectoriesForPlugins(list, TRACKER_SUFFIX); + for (auto x : filesFromFolders) + addToPluginList(x.c_str()); + + foreach (QFileInfo fi, fl) { + QString s = fi.absoluteFilePath(); + addToPluginList(s); + } + + // Load plugins as per CLI + if (!_cfg->UsePlugins.isEmpty()) { + addToPluginList(_cfg->UsePlugins.toStdString().c_str()); + } +} + +void ControllerPlugin::connectControllerToController() +{ + + // Add Plugin name to Main Window + IController* ctrA = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer ctrMainWindow = + qobject_cast(ctrA); + + ctrMainWindow->deactiveTrackingCheckBox(); + + loadPluginsFromPluginSubfolder(); + + // connect ControllerTrackedComponentView + IController* ctrB = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + QPointer ctrTrackedComponentCore = + qobject_cast(ctrB); + + QObject::connect(this, + SIGNAL(emitUpdateView()), + ctrTrackedComponentCore, + SLOT(receiveUpdateView())); + + // connect ControllerCommands + IController* ctrD = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMMANDS); + QPointer ctrCommands = + qobject_cast(ctrD); + + QObject::connect(ctrCommands, + SIGNAL(emitAddTrajectory(QPoint)), + this, + SLOT(receiveAddTrajectory(QPoint)), + Qt::DirectConnection); + QObject::connect(ctrCommands, + SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), + this, + SLOT(receiveRemoveTrajectory(IModelTrackedTrajectory*)), + Qt::DirectConnection); + QObject::connect(ctrCommands, + SIGNAL(emitRemoveTrajectoryId(int)), + this, + SLOT(receiveRemoveTrajectoryId(int)), + Qt::DirectConnection); + QObject::connect( + ctrCommands, + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), + this, + SLOT(receiveRemoveTrackEntity(IModelTrackedTrajectory*, uint)), + Qt::DirectConnection); + QObject::connect(ctrCommands, + SIGNAL(emitValidateTrajectory(int)), + this, + SLOT(receiveValidateTrajectory(int)), + Qt::DirectConnection); + QObject::connect( + ctrCommands, + SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), + this, + SLOT(receiveValidateEntity(IModelTrackedTrajectory*, uint)), + Qt::DirectConnection); + QObject::connect( + ctrCommands, + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint, int)), + this, + SLOT(receiveMoveElement(IModelTrackedTrajectory*, uint, QPoint, int)), + Qt::DirectConnection); + QObject::connect(ctrCommands, + SIGNAL(emitSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*)), + this, + SLOT(receiveSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*)), + Qt::DirectConnection); + QObject::connect( + ctrCommands, + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), + this, + SLOT(receiveToggleFixTrack(IModelTrackedTrajectory*, bool)), + Qt::DirectConnection); + QObject::connect( + ctrCommands, + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), + this, + SLOT(receiveEntityRotation(IModelTrackedTrajectory*, double, uint)), + Qt::DirectConnection); + + // connect ControllerPlayer + IController* ctrC = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + QPointer ctrPlayer = qobject_cast( + ctrC); + QObject::connect(ctrPlayer, + SIGNAL(emitPauseState(bool)), + this, + SLOT(receivePauseState(bool)), + Qt::DirectConnection); + + QObject::connect(ctrPlayer, + SIGNAL(signalCurrentFrameNumberToPlugin(uint)), + this, + SLOT(receiveCurrentFrameNumberToPlugin(uint)), + Qt::DirectConnection); +} + +void ControllerPlugin::initPlugin() +{ + m_BioTrackerPlugin = qobject_cast( + pluginLoader->getPluginInstance()); + if (!m_BioTrackerPlugin) { + qFatal("Error at loading plugin."); + } + + connectPlugin(); + m_BioTrackerPlugin->init(); + + m_BioTrackerPlugin->moveToThread(m_TrackingThread); + + IController* ctrAreaDesc = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); + ControllerAreaDescriptor* ctAreaDesc = + qobject_cast(ctrAreaDesc); + ctAreaDesc->triggerUpdateAreaDescriptor(); + + Q_EMIT signalCurrentFrameNumberToPlugin(m_currentFrameNumber); +} + +void ControllerPlugin::connectPlugin() +{ + IController* ctrA = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + QPointer ctrPlayer = qobject_cast( + ctrA); + + IModel* model = ctrPlayer->getModel(); + + IController* ctrB = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); + ControllerTextureObject* ctrTexture = + qobject_cast(ctrB); + + IController* ctrAreaDesc = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); + ControllerAreaDescriptor* ctAreaDesc = + qobject_cast(ctrAreaDesc); + + IController* ctrData = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::DATAEXPORT); + ControllerDataExporter* ctDataEx = qobject_cast( + ctrData); + + IController* ctrC = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + ControllerTrackedComponentCore* ctrCompView = + qobject_cast(ctrC); + + IController* ctrD = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + ControllerCoreParameter* ctrCoreParam = + qobject_cast(ctrD); + + IController* ctrE = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer ctrMainWindow = + qobject_cast(ctrE); + + auto obj = dynamic_cast(m_BioTrackerPlugin); + + QObject::connect(obj, + SIGNAL(emitTrackingDone(uint)), + ctDataEx, + SLOT(receiveTrackingDone(uint))); + + QObject::connect(obj, + &IBioTrackerPlugin::trackingImageNamesChanged, + ctrTexture, + &ControllerTextureObject::setTextureNames); + QObject::connect(obj, + &IBioTrackerPlugin::trackingImagesChanged, + ctrTexture, + &ControllerTextureObject::updateTextures); + + QObject::connect(obj, + SIGNAL(emitTrackingDone(uint)), + ctrCompView, + SLOT(receiveVisualizeTrackingModel(uint))); + + QObject::connect(ctAreaDesc, + SIGNAL(updateAreaDescriptor(IModelAreaDescriptor*)), + obj, + SLOT(receiveAreaDescriptor(IModelAreaDescriptor*))); + + QObject::connect( + obj, + SIGNAL(emitCorePermission(std::pair)), + ctrCompView, + SLOT(setCorePermission(std::pair))); + + QObject::connect( + obj, + SIGNAL(emitCorePermission(std::pair)), + ctrCoreParam, + SLOT(setCorePermission(std::pair))); + + QObject::connect( + obj, + SIGNAL(emitCorePermission(std::pair)), + ctrMainWindow, + SLOT(setCorePermission(std::pair))); + + QObject::connect(obj, + SIGNAL(emitDimensionUpdate(int, int)), + ctrCompView, + SIGNAL(emitDimensionUpdate(int, int))); + + // data model actions + QObject::connect(this, + SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), + obj, + SLOT(receiveRemoveTrajectory(IModelTrackedTrajectory*))); + QObject::connect( + this, + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), + obj, + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint))); + QObject::connect(this, + SIGNAL(emitAddTrajectory(QPoint)), + obj, + SLOT(receiveAddTrajectory(QPoint))); + QObject::connect( + this, + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint)), + obj, + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, uint, QPoint))); + QObject::connect(this, + SIGNAL(emitSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*)), + obj, + SLOT(receiveSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*))); + QObject::connect( + this, + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), + obj, + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool))); + + QObject::connect(this, + SIGNAL(emitRemoveTrajectoryId(int)), + obj, + SIGNAL(emitRemoveTrajectoryId(int))); + QObject::connect(this, + SIGNAL(emitValidateTrajectory(int)), + obj, + SIGNAL(emitValidateTrajectory(int))); + QObject::connect( + this, + SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint)), + obj, + SIGNAL(emitValidateEntity(IModelTrackedTrajectory*, uint))); + QObject::connect( + this, + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint)), + obj, + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, double, uint))); + + connect(this, + &ControllerPlugin::frameRetrieved, + m_BioTrackerPlugin, + &IBioTrackerPlugin::receiveCurrentFrameFromMainApp); + QObject::connect(this, + SIGNAL(signalCurrentFrameNumberToPlugin(uint)), + obj, + SLOT(receiveCurrentFrameNumberFromMainApp(uint))); +} + +void ControllerPlugin::disconnectPlugin() +{ +} + +// first send all the commands currently in the command queue then the next +// image can be sent +void ControllerPlugin::sendCurrentFrameToPlugin(cv::Mat mat, uint number) +{ + m_currentFrameNumber = number; + + // Prevent calling the plugin if none is loaded + if (m_BioTrackerPlugin) { + while (!m_editQueue.isEmpty()) { + queueElement edit = m_editQueue.dequeue(); + + switch (edit.type) { + case EDIT::REMOVE_TRACK: + emitRemoveTrajectory(edit.trajectory0); + break; + case EDIT::REMOVE_TRACK_ID: + emitRemoveTrajectoryId(edit.id); + break; + case EDIT::REMOVE_ENTITY: + emitRemoveTrackEntity(edit.trajectory0, edit.frameNumber); + break; + case EDIT::ADD: + emitAddTrajectory(edit.pos); + break; + case EDIT::MOVE: + emitMoveElement(edit.trajectory0, edit.frameNumber, edit.pos); + break; + case EDIT::SWAP: + emitSwapIds(edit.trajectory0, edit.trajectory1); + break; + case EDIT::FIX: + emitToggleFixTrack(edit.trajectory0, edit.toggle); + break; + case EDIT::VALIDATE: + emitValidateTrajectory(edit.id); + break; + case EDIT::VALIDATE_ENTITY: + emitValidateEntity(edit.trajectory0, edit.frameNumber); + break; + case EDIT::ROTATE_ENTITY: + emitEntityRotation(edit.trajectory0, + edit.angle, + edit.frameNumber); + break; + } + } + emit frameRetrieved(mat, number); + } +} + +//############################SLOTS################################################## + +// receivers of commands + +void ControllerPlugin::receiveRemoveTrajectory( + IModelTrackedTrajectory* trajectory) +{ + if (m_paused) { + emitRemoveTrajectory(trajectory); + emitUpdateView(); + } else { + queueElement removeTrackEdit; + removeTrackEdit.type = EDIT::REMOVE_TRACK; + removeTrackEdit.trajectory0 = trajectory; + m_editQueue.enqueue(removeTrackEdit); + } +} + +void ControllerPlugin::receiveRemoveTrajectoryId(int id) +{ + if (m_paused) { + emitRemoveTrajectoryId(id); + emitUpdateView(); + } else { + queueElement removeTrackEdit; + removeTrackEdit.type = EDIT::REMOVE_TRACK_ID; + removeTrackEdit.id = id; + m_editQueue.enqueue(removeTrackEdit); + } +} + +void ControllerPlugin::receiveRemoveTrackEntity( + IModelTrackedTrajectory* trajectory, + uint frameNumber) +{ + if (m_paused) { + emitRemoveTrackEntity(trajectory, frameNumber); + emitUpdateView(); + } else { + queueElement removeEntityEdit; + removeEntityEdit.type = EDIT::REMOVE_ENTITY; + removeEntityEdit.trajectory0 = trajectory; + removeEntityEdit.frameNumber = frameNumber; + m_editQueue.enqueue(removeEntityEdit); + } +} + +void ControllerPlugin::receiveAddTrajectory(QPoint pos) +{ + if (m_paused) { + emitAddTrajectory(pos); + emitUpdateView(); + } else { + queueElement addEdit; + addEdit.type = EDIT::ADD; + addEdit.pos = pos; + m_editQueue.enqueue(addEdit); + } +} + +void ControllerPlugin::receiveMoveElement(IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint pos, + int toMove) +{ + if (m_paused) { + emitMoveElement(trajectory, frameNumber, pos); + // only emit the update after the last move is processed + if (toMove == 1) { + emitUpdateView(); + } + } else { + queueElement moveEdit; + moveEdit.type = EDIT::MOVE; + moveEdit.trajectory0 = trajectory; + moveEdit.pos = pos; + moveEdit.frameNumber = frameNumber; + m_editQueue.enqueue(moveEdit); + } +} + +void ControllerPlugin::receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1) +{ + if (m_paused) { + emitSwapIds(trajectory0, trajectory1); + emitUpdateView(); + } else { + queueElement swapEdit; + swapEdit.type = EDIT::SWAP; + swapEdit.trajectory0 = trajectory0; + swapEdit.trajectory1 = trajectory1; + m_editQueue.enqueue(swapEdit); + } +} + +void ControllerPlugin::receiveValidateTrajectory(int id) +{ + if (m_paused) { + emitValidateTrajectory(id); + emitUpdateView(); + } else { + queueElement validateEdit; + validateEdit.type = EDIT::VALIDATE; + validateEdit.id = id; + m_editQueue.enqueue(validateEdit); + } +} + +void ControllerPlugin::receiveValidateEntity( + IModelTrackedTrajectory* trajectory, + uint frameNumber) +{ + if (m_paused) { + emitValidateEntity(trajectory, frameNumber); + emitUpdateView(); + } else { + queueElement validateEntityEdit; + validateEntityEdit.type = EDIT::VALIDATE_ENTITY; + validateEntityEdit.trajectory0 = trajectory; + validateEntityEdit.frameNumber = frameNumber; + m_editQueue.enqueue(validateEntityEdit); + } +} + +void ControllerPlugin::receiveToggleFixTrack( + IModelTrackedTrajectory* trajectory, + bool toggle) +{ + if (m_paused) { + emitToggleFixTrack(trajectory, toggle); + emitUpdateView(); + } else { + queueElement fixEdit; + fixEdit.type = EDIT::FIX; + fixEdit.trajectory0 = trajectory; + fixEdit.toggle = toggle; + m_editQueue.enqueue(fixEdit); + } +} + +void ControllerPlugin::receiveEntityRotation( + IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber) +{ + if (m_paused) { + emitEntityRotation(trajectory, angle, frameNumber); + emitUpdateView(); + } else { + queueElement rotEdit; + rotEdit.type = EDIT::ROTATE_ENTITY; + rotEdit.trajectory0 = trajectory; + rotEdit.angle = angle; + rotEdit.frameNumber = frameNumber; + m_editQueue.enqueue(rotEdit); + } +} + +//********************************************************************* + +void ControllerPlugin::receivePauseState(bool state) +{ + m_paused = state; +} + +void ControllerPlugin::receiveCurrentFrameNumberToPlugin(uint frameNumber) +{ + m_currentFrameNumber = frameNumber; + Q_EMIT signalCurrentFrameNumberToPlugin(frameNumber); +} + +void ControllerPlugin::receiveTrackingDone() +{ +} diff --git a/Src/Controller/ControllerPlugin.h b/Src/Controller/ControllerPlugin.h new file mode 100644 index 00000000..9789554c --- /dev/null +++ b/Src/Controller/ControllerPlugin.h @@ -0,0 +1,215 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** edited by Jonas Piotrowski + ** + ****************************************************************************/ + +#ifndef CONTROLLERPLUGIN_H +#define CONTROLLERPLUGIN_H +#include "IControllerCfg.h" +#include "Interfaces/IBioTrackerPlugin.h" +#include "PluginLoader.h" +#include "QThread" +#include "QQueue" +#include "QPoint" + +/// ENUM for the command queue in the controllerplugin +enum EDIT +{ + REMOVE_TRACK, + REMOVE_TRACK_ID, + REMOVE_ENTITY, + ADD, + MOVE, + SWAP, + FIX, + VALIDATE, + VALIDATE_ENTITY, + ROTATE_ENTITY +}; + +/// struct for the command queue in the controllerplugin +struct queueElement +{ + EDIT type; + QPoint pos; + IModelTrackedTrajectory* trajectory0; + IModelTrackedTrajectory* trajectory1; + IModelTrackedComponent* element; + bool toggle; + int id; + double angle; + uint frameNumber; +}; + +/** + * This is the controller class of the Plugin Loader Component. This component + * is responsible for loading and managing BioTracker Plugins The + * ControllerPlugin class is responsible for loading and connecting to + * BioTracker Plugins. It also manages tracking data modification commands. It + * queues up the commands and forwards them to the trakcing plugin if either + * the tracking is paused or the tracker is done with tracking the previous + * frame. The plgin then sends the commands first and afterward the next image + * to track. This avoids a race condition. + */ +class ControllerPlugin : public IControllerCfg +{ + Q_OBJECT +public: + ControllerPlugin( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + ~ControllerPlugin(); + + void addToPluginList(QString str); + + /** + * (This function + * This function delivers a file path of a Plugin to the IModel class + * PluginLoader. If the Plugin could be loaded, the functions additionally + * requests the name of the Plugin and sets it as an entry into an IView + * widget in the MainWindow. + */ + void loadPluginFromFileName(QString str); + + /** + * This function hands the received cv::Mat pointer and the current frame + * number to the PluginLoader. + */ + void sendCurrentFrameToPlugin(cv::Mat mat, uint number); + + void selectPlugin(QString str); + +signals: + void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void emitRemoveTrajectoryId(int id); + void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void emitValidateTrajectory(int id); + void emitValidateEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void emitAddTrajectory(QPoint pos); + void emitMoveElement(IModelTrackedTrajectory* element, + uint frameNumber, + QPoint pos); + void emitSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + void emitToggleFixTrack(IModelTrackedTrajectory* trajectory0, bool toggle); + void emitEntityRotation(IModelTrackedTrajectory* trajectory0, + double angle, + uint frameNumber); + + void emitUpdateView(); + void frameRetrieved(cv::Mat mat, uint frameNumber); + void signalCurrentFrameNumberToPlugin(uint frameNumber); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + + void connectPlugin(); + void initPlugin(); + void disconnectPlugin(); + +private Q_SLOTS: + /** + * + * If Tracking is active and the tracking process was finished, the Plugin + * is able to emit a Signal that triggers this SLOT. + */ + void receiveTrackingDone(); + /** + * + * Receive command to remove a trajectory and put it in edit queue + */ + void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); + /** + * + * Receive command to remove a trajectory by id and put it in edit queue + */ + void receiveRemoveTrajectoryId(int id); + /** + * + * Receive command to remove a track entity and put it in edit queue + */ + void receiveRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + /** + * + * Receive command to add a trajectory and put it in edit queue + */ + void receiveAddTrajectory(QPoint pos); + /** + * + * Receive command to move a element in a trajectory and put it in edit + * queue + */ + void receiveMoveElement(IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint pos, + int toMove); + /** + * + * Receive command to swap two ID's and put it in edit queue + */ + void receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + /** + * + * Receive command to revalidate a traj by id + */ + void receiveValidateTrajectory(int id); + /** + * + * Receive command to revalidate a entity + */ + void receiveValidateEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + /** + * + * Receive command to fix a traj, so the tracker should not change it's + * data + */ + void receiveToggleFixTrack(IModelTrackedTrajectory* trajectory, + bool toggle); + /** + * + * Receive command to rotate an entity + */ + void receiveEntityRotation(IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber); + /** + * + * Receive current state of medium (pause or play) + */ + void receivePauseState(bool state); + /** + * + * Receive current frame number from media play to send it to the plugin + */ + void receiveCurrentFrameNumberToPlugin(uint frameNumber); + +private: + void loadPluginsFromPluginSubfolder(); + + IBioTrackerPlugin* m_BioTrackerPlugin; + + QQueue m_editQueue; + + QPointer m_TrackingThread; + + PluginLoader* pluginLoader; + + bool m_paused = true; + + uint m_currentFrameNumber = 0; +}; + +#endif // CONTROLLERPLUGIN_H diff --git a/Src/Controller/ControllerTextureObject.cpp b/Src/Controller/ControllerTextureObject.cpp new file mode 100644 index 00000000..41dd5921 --- /dev/null +++ b/Src/Controller/ControllerTextureObject.cpp @@ -0,0 +1,146 @@ +#include "ControllerTextureObject.h" +#include "View/GLVideoView.h" +#include "View/MainWindow.h" +#include "Controller/ControllerGraphicScene.h" +#include "Controller/ControllerPlayer.h" +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" +#include "View/TextureObjectView.h" + +#include + +ControllerTextureObject::ControllerTextureObject(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ + m_TextureViewNamesModel = new QStringListModel(); + createNewTextureObjectModel("Original"); +} + +void ControllerTextureObject::changeTextureModel(QString name) +{ + if (!hasTexture(name)) { + qCritical().noquote() + << QString("Invalid texture name '%1'").arg(name); + return; + } + + m_Model = m_TextureObjects.value(name); + + changeTextureView(m_Model); +} + +void ControllerTextureObject::connectControllerToController() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + QPointer ctrPlayer = qobject_cast( + ctr); + + QPointer videoView = + dynamic_cast(ctrPlayer->getView()); + videoView->setVideoViewComboboxModel(m_TextureViewNamesModel); + + IController* ctrG = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + QPointer ctrGraphics = + qobject_cast(ctrG); + QGraphicsPixmapItem* item = dynamic_cast(m_View); + + ctrGraphics->addTextureObject(item); +} + +void ControllerTextureObject::setTextureNames(QVector names) +{ + changeTextureModel("Original"); + + for (auto name : m_TextureViewNamesModel->stringList()) { + if (name != "Original") { + m_TextureObjects.remove(name); + } + } + + m_TextureViewNamesModel->setStringList({"Original"}); + + for (auto name : names) { + createNewTextureObjectModel(name); + } +} + +void ControllerTextureObject::updateTexture(QString name, cv::Mat img) +{ + if (name.isEmpty() || !hasTexture(name)) { + qCritical().noquote() + << QString("Invalid texture name '%1'").arg(name); + return; + } + + if (!hasTexture(name)) { + createNewTextureObjectModel(name); + } + + m_TextureObjects.value(name)->set(img); +} + +void ControllerTextureObject::updateTextures(QMap textures) +{ + for (const auto name : textures.keys()) { + updateTexture(name, textures[name]); + } +} + +void ControllerTextureObject::createModel() +{ + createNewTextureObjectModel(m_DefaultTextureName); + + m_Model = m_TextureObjects.value(m_DefaultTextureName); +} + +void ControllerTextureObject::createView() +{ + m_View = new TextureObjectView(this, this, m_Model); +} + +void ControllerTextureObject::connectModelToController() +{ +} + +bool ControllerTextureObject::hasTexture(QString name) +{ + if (name.isEmpty()) { + return false; + } + + for (int i = 0; i < m_TextureViewNamesModel->rowCount(); ++i) { + if (m_TextureViewNamesModel->data(m_TextureViewNamesModel->index(i)) + .toString() == name) { + return true; + } + } + + return false; +} + +void ControllerTextureObject::createNewTextureObjectModel(QString name) +{ + m_TextureObjects.insert(name, new TextureObject(this, name)); + + if (m_TextureViewNamesModel->insertRow( + m_TextureViewNamesModel->rowCount())) { + auto index = m_TextureViewNamesModel->index( + m_TextureViewNamesModel->rowCount() - 1); + m_TextureViewNamesModel->setData(index, name); + } else { + qFatal("Failed to add new texture model"); + } +} + +void ControllerTextureObject::changeTextureView(IModel* model) +{ + m_View->setNewModel(model); +} + +QAbstractListModel* ControllerTextureObject::textureNamesModel() +{ + return m_TextureViewNamesModel; +} diff --git a/Src/Controller/ControllerTextureObject.h b/Src/Controller/ControllerTextureObject.h new file mode 100644 index 00000000..d3aeae0b --- /dev/null +++ b/Src/Controller/ControllerTextureObject.h @@ -0,0 +1,80 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef CONTROLLERTEXTUREOBJECT_H +#define CONTROLLERTEXTUREOBJECT_H + +#include "IControllerCfg.h" +#include "opencv2/core/core.hpp" +#include "QString" +#include "Model/TextureObject.h" + +#include +#include "QStringList" +#include "QStringListModel" +#include "QPointer" + + +/** + * This is the Controller class of the software component TextureObject. This + * component is responsible for rendering cv::Mats on a disply canvas. Other + * components can trigger the SLOT receiveCvMat(std::shard_ptr mat, + * QString name) in order to render their images. Usually this would be the + * component MediaPlayer which will send the original cv::Mat from an + * ImageStream to controller class ControllerTextureObject. An other component + * is the BioTracker Plugin. If a cv::Mat is manipulated by a Tracking + * Algorithm the Plugin is able to send that cv::Mat to this component. The + * Parameter name will be listed in the combobox widget on the MainWindow + * widget. The ControllerTextureObject class controlls the of the + * TrextureObject Component. + */ +class ControllerTextureObject : public IControllerCfg +{ + Q_OBJECT +public: + ControllerTextureObject( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + + /** + * If the user changes the combobox widget for the rendered cv::Mat in the + * MainWindow this methode will change the corresponding IModel class + * TextureObject. + */ + void changeTextureModel(QString name); + + // IController interface +public: + void connectControllerToController() override; + + QAbstractListModel* textureNamesModel(); + bool hasTexture(QString name); + +public Q_SLOTS: + void setTextureNames(QVector names); + void updateTexture(QString name, cv::Mat img); + void updateTextures(QMap textures); + +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + +private: + void createNewTextureObjectModel(QString name); + void changeTextureView(IModel* model); + +private: + QMap> m_TextureObjects; + + QString m_DefaultTextureName = "Original"; + + QPointer m_TextureViewNamesModel; +}; + +#endif // CONTROLLERTEXTUREOBJECT_H diff --git a/Src/Controller/ControllerTrackedComponentCore.cpp b/Src/Controller/ControllerTrackedComponentCore.cpp new file mode 100644 index 00000000..5a95e4f7 --- /dev/null +++ b/Src/Controller/ControllerTrackedComponentCore.cpp @@ -0,0 +1,243 @@ +#include "ControllerTrackedComponentCore.h" +#include "ControllerMainWindow.h" +#include "ControllerCoreParameter.h" +#include "ControllerPlayer.h" +#include "Model/null_Model.h" +#include "Model/CoreParameter.h" +#include "View/TrackedComponentView.h" +#include "View/CoreParameterView.h" +#include "util/types.h" +#include "qdebug.h" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "Interfaces/IView/IViewTrackedComponent.h" +#include "Controller/ControllerCommands.h" + +ControllerTrackedComponentCore::ControllerTrackedComponentCore( + QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IControllerCfg(parent, context, ctr) +{ + m_View = nullptr; + m_Model = nullptr; +} + +void ControllerTrackedComponentCore::createView() +{ + // This occurs when there has been a previous plugin to visualize + if (m_View != nullptr) + delete m_View; + + m_View = new TrackedComponentView(0, this, m_Model); +} + +void ControllerTrackedComponentCore::connectModelToController() +{ +} + +void ControllerTrackedComponentCore::connectControllerToController() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer ctrMainWindow = + qobject_cast(ctr); + + // connect to view + TrackedComponentView* view = static_cast(m_View); + QObject::connect(view, + SIGNAL(emitAddTrajectory(QPoint, int)), + this, + SIGNAL(emitAddTrajectory(QPoint, int))); + QObject::connect(view, + SIGNAL(emitSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*)), + this, + SIGNAL(emitSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*))); + QObject::connect(this, + SIGNAL(emitDimensionUpdate(int, int)), + view, + SLOT(rcvDimensionUpdate(int, int))); + + QObject::connect(this, + SIGNAL(emitAddTrack()), + view, + SLOT(addTrajectory())); + QObject::connect(this, + SIGNAL(emitDeleteSelectedTracks()), + view, + SLOT(removeTrajectories())); + QObject::connect(this, + SIGNAL(emitSelectAll()), + view, + SLOT(receiveSelectAll())); + QObject::connect(this, SIGNAL(emitSwapIdsToView()), view, SLOT(swapIds())); + QObject::connect(this, + SIGNAL(emitChangeColorBorder()), + view, + SLOT(receiveColorChangeBorderSelected())); + QObject::connect(this, + SIGNAL(emitChangeColorFill()), + view, + SLOT(receiveColorChangeBrushSelected())); + + // connect to update track number in core params + IController* ctrICP = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + QPointer ctrCP = + qobject_cast(ctrICP); + QObject::connect(this, + SIGNAL(emitTrackNumber(int)), + ctrCP, + SLOT(receiveTrackNumber(int))); + + // connect to commandcontroller + IController* ctrICC = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMMANDS); + QPointer ctrCC = qobject_cast( + ctrICC); + QObject::connect(this, + SIGNAL(emitAddTrajectory(QPoint, int)), + ctrCC, + SLOT(receiveAddTrackCommand(QPoint, int))); + QObject::connect( + this, + SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), + ctrCC, + SLOT(receiveRemoveTrackCommand(IModelTrackedTrajectory*))); + QObject::connect( + this, + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), + ctrCC, + SLOT(receiveRemoveTrackEntityCommand(IModelTrackedTrajectory*, uint))); + QObject::connect(this, + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, + QPoint, + QPoint, + uint, + int)), + ctrCC, + SLOT(receiveMoveElementCommand(IModelTrackedTrajectory*, + QPoint, + QPoint, + uint, + int))); + QObject::connect(this, + SIGNAL(emitSwapIds(IModelTrackedTrajectory*, + IModelTrackedTrajectory*)), + ctrCC, + SLOT(receiveSwapIdCommand(IModelTrackedTrajectory*, + IModelTrackedTrajectory*))); + QObject::connect( + this, + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), + ctrCC, + SLOT(receiveFixTrackCommand(IModelTrackedTrajectory*, bool))); + QObject::connect(this, + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, + double, + double, + uint)), + ctrCC, + SLOT(receiveEntityRotation(IModelTrackedTrajectory*, + double, + double, + uint))); + + // connect to controllerPlayer + IController* ctrIP = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::PLAYER); + QPointer ctrP = qobject_cast(ctrIP); + QObject::connect(this, + &ControllerTrackedComponentCore::emitGoToFrame, + ctrP, + &ControllerPlayer::setGoToFrame); + + // Tell the Visualization to reset upon loading a new plugin + QObject::connect(ctrMainWindow, + &ControllerMainWindow::emitTrackLoaded, + this, + &ControllerTrackedComponentCore::receiveOnPluginLoaded); +} + +void ControllerTrackedComponentCore::receiveOnPluginLoaded() +{ + receiveUpdateView(); +} + +void ControllerTrackedComponentCore::setCorePermission( + std::pair permission) +{ + if (dynamic_cast(m_View)) { + dynamic_cast(m_View)->setPermission(permission); + } else { + // qDebug() << "no view yet"; + // This should never happen, actually + assert(false); + } +} + +void ControllerTrackedComponentCore::receiveUpdateView() +{ + TrackedComponentView* compView = dynamic_cast( + m_View); + compView->getNotified(); + // signal the core parameter controller to update the track number + IModelTrackedTrajectory* model = dynamic_cast( + getModel()); + int trackNumber = model->validCount(); + emitTrackNumber(trackNumber); +} + +void ControllerTrackedComponentCore::createModel() +{ + // This controller gets his model (via addModel()) from the corresponding + // tracked-component-controller when a plugin is loaded + m_Model = new null_Model(); +} + +IView* ControllerTrackedComponentCore::getTrackingElementsWidgetCore() +{ + return m_View; +} + +IModel* ControllerTrackedComponentCore::getCoreParameter() +{ + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COREPARAMETER); + QPointer ctrCP = + qobject_cast(ctr); + return ctrCP->getModel(); +} + +void ControllerTrackedComponentCore::addModel(IModel* model) +{ + m_Model = model; + m_View->setNewModel(m_Model); + + TrackedComponentView* view = dynamic_cast(m_View); + + // signal initial track number to core params + IModelTrackedTrajectory* iModel = dynamic_cast( + getModel()); + if (iModel) { + int trackNumber = iModel->validCount(); + emitTrackNumber(trackNumber); + } +} + +void ControllerTrackedComponentCore::receiveVisualizeTrackingModel( + uint framenumber) +{ + // signal the view to update track entities + TrackedComponentView* compView = dynamic_cast( + m_View); + compView->updateShapes(framenumber); + // signal the core parameter controller to update the track number + IModelTrackedTrajectory* model = dynamic_cast( + getModel()); + if (model) { + int trackNumber = model->validCount(); + emitTrackNumber(trackNumber); + } +} diff --git a/Src/Controller/ControllerTrackedComponentCore.h b/Src/Controller/ControllerTrackedComponentCore.h new file mode 100644 index 00000000..44428c16 --- /dev/null +++ b/Src/Controller/ControllerTrackedComponentCore.h @@ -0,0 +1,123 @@ +#ifndef CONTROLLERTRACKEDCOMPONENTCORE_H +#define CONTROLLERTRACKEDCOMPONENTCORE_H + +#include "IControllerCfg.h" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" + +/** + * The ControllerTrackedComponentCore class controls the component for + * visualizing TrackedComponents. It is basically a forwarder for permissions, + * user interaction signals (including tracking data manipulation). + */ + +class ControllerTrackedComponentCore : public IControllerCfg +{ + Q_OBJECT +public: + ControllerTrackedComponentCore( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + + /** + * Hook for the view to put in in the mainwindow's media panel each time a + * plugin is loaded + */ + IView* getTrackingElementsWidgetCore(); + + /** + * The model is actually the tracking data from the tracking plugin. This + * component only reads this data. Is called when a new tracking plugin is + * loaded. + */ + void addModel(IModel* model); + + /** + * Hook for the view to get the core parameters to set up new + * componentshapes with default settings + */ + IModel* getCoreParameter(); + + /* + * SIGNALS + */ +signals: + /// signal to ctrcommands to remove trajectory + void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); + + /// signal to ctrcommands to remove entity + void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + + /// signal to ctrcommands to add trajectory + void emitAddTrajectory(QPoint pos, int id); + + /// signal to ctrcommands to move entity + void emitMoveElement(IModelTrackedTrajectory* trajectory, + QPoint oldPos, + QPoint newPos, + uint frameNumber, + int toMove); + + /// signal to ctrcommands to swap track id's + void emitSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + + /// signal to ctrcommands fix or unfix a traj + void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); + + /// signal to ctrcommands rotate entity + void emitEntityRotation(IModelTrackedTrajectory*, + double oldAngleDeg, + double newAngleDeg, + uint frameNumber); + + /// signal to ctrCoreParameter to show number of valid trrajectories + + void emitTrackNumber(int number); + + /// signal to view to update its dimensions + void emitDimensionUpdate(int x, int y); + + // forward left-toolbar actions to view + void emitAddTrack(); + void emitDeleteSelectedTracks(); + void emitSwapIdsToView(); + void emitSelectAll(); + void emitChangeColorBorder(); + void emitChangeColorFill(); + void emitGoToFrame(int frame); + + /* + * SLOTS + */ +public Q_SLOTS: + + /// A (different) plugin has been loaded. Here, the controller needs to + /// inform the view + void receiveOnPluginLoaded(); + + /// this slot gets triggered when the core-view needs to update with the + /// current frame + void receiveVisualizeTrackingModel(uint framenumber); + + /// gets triggered when plugin sends permissions and forwards it to the + /// view + void setCorePermission(std::pair permission); + + /// gets triggered when a the view needs an update + void receiveUpdateView(); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + + // IView* m_parameterView; + // IModel* m_coreParameterModel; +}; + +#endif // CONTROLLERTRACKEDCOMPONENTCORE_H diff --git a/Src/Controller/IControllerCfg.cpp b/Src/Controller/IControllerCfg.cpp new file mode 100644 index 00000000..90af64a4 --- /dev/null +++ b/Src/Controller/IControllerCfg.cpp @@ -0,0 +1,18 @@ +#include "IControllerCfg.h" + +IControllerCfg::IControllerCfg(QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IController(parent, context, ctr) +{ +} + +void IControllerCfg::setConfig(Config* cfg) +{ + _cfg = cfg; +} + +Config* IControllerCfg::getConfig() +{ + return _cfg; +} \ No newline at end of file diff --git a/Src/Controller/IControllerCfg.h b/Src/Controller/IControllerCfg.h new file mode 100644 index 00000000..d4f32df9 --- /dev/null +++ b/Src/Controller/IControllerCfg.h @@ -0,0 +1,35 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef NULL_CONTROLLER_H +#define NULL_CONTROLLER_H + +#include "Interfaces/IController/IController.h" +#include "Interfaces/ENUMS.h" +#include "util/Config.h" + +/** + * The null_Controller class is for initialisation of IController classes + * instead of using Null Pointers. + */ +class IControllerCfg : public IController +{ + +public: + IControllerCfg(QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + + void setConfig(Config* cfg); + + Config* getConfig(); + +protected: + Config* _cfg; +}; + +#endif // NULL_CONTROLLER_H diff --git a/BioTracker/CoreApp/BioTracker/Controller/null_Controller.cpp b/Src/Controller/null_Controller.cpp similarity index 98% rename from BioTracker/CoreApp/BioTracker/Controller/null_Controller.cpp rename to Src/Controller/null_Controller.cpp index 612c02f3..194a4683 100644 --- a/BioTracker/CoreApp/BioTracker/Controller/null_Controller.cpp +++ b/Src/Controller/null_Controller.cpp @@ -2,25 +2,20 @@ 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 new file mode 100644 index 00000000..0c5d8207 --- /dev/null +++ b/Src/Controller/null_Controller.h @@ -0,0 +1,26 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ +#pragma once + +#include "IControllerCfg.h" + +/** + * The null_Controller class is for initialisation of IController classes + * instead of using Null Pointers. + */ +class null_Controller : public IControllerCfg +{ +public: + null_Controller(); + + // IController interface +protected: + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; +}; diff --git a/Src/GuiContext.cpp b/Src/GuiContext.cpp new file mode 100644 index 00000000..df986c07 --- /dev/null +++ b/Src/GuiContext.cpp @@ -0,0 +1,137 @@ +#include "GuiContext.h" +#include "Controller/ControllerMainWindow.h" +#include "Controller/ControllerPlayer.h" +#include "Controller/ControllerTextureObject.h" +#include "Controller/ControllerPlugin.h" +#include "Controller/ControllerAnnotations.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" +#include "Controller/ControllerGraphicScene.h" +#include "Controller/ControllerDataExporter.h" +#include "Controller/ControllerAreaDescriptor.h" +#include "Controller/ControllerCoreParameter.h" +#include "Controller/ControllerCommands.h" +#include "Controller/ControllerNotifications.h" +#include "QPointer" + +#include "QDebug" + +GuiContext::GuiContext(QObject* parent, Config* cfg) +: IBioTrackerContext(parent) +{ + _cfg = cfg; + QPointer MainWindowController = new ControllerMainWindow( + this, + this, + ENUMS::CONTROLLERTYPE::MAINWINDOW); + QPointer PlayerController = + new ControllerPlayer(this, this, ENUMS::CONTROLLERTYPE::PLAYER); + QPointer TextureObjectController = + new ControllerTextureObject(this, + this, + ENUMS::CONTROLLERTYPE::TEXTUREOBJECT); + QPointer GraphicsViewController = new ControllerGraphicScene( + this, + this, + ENUMS::CONTROLLERTYPE::GRAPHICSVIEW); + QPointer TrackedComponentCoreController = + new ControllerTrackedComponentCore( + this, + this, + ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE); + QPointer DataExportController = new ControllerDataExporter( + this, + this, + ENUMS::CONTROLLERTYPE::DATAEXPORT); + QPointer PluginController = + new ControllerPlugin(this, this, ENUMS::CONTROLLERTYPE::PLUGIN); + QPointer AnnotationsController = new ControllerAnnotations( + this, + this, + ENUMS::CONTROLLERTYPE::ANNOTATIONS); + QPointer AreaDescriptorController = + new ControllerAreaDescriptor(this, + this, + ENUMS::CONTROLLERTYPE::AREADESCRIPTOR); + QPointer CoreParameterController = + new ControllerCoreParameter(this, + this, + ENUMS::CONTROLLERTYPE::COREPARAMETER); + QPointer CommandsController = + new ControllerCommands(this, this, ENUMS::CONTROLLERTYPE::COMMANDS); + QPointer NotificationController = new ControllerNotifications( + this, + this, + ENUMS::CONTROLLERTYPE::NOTIFICATION); + + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::MAINWINDOW, + MainWindowController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::PLAYER, PlayerController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TEXTUREOBJECT, + TextureObjectController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::GRAPHICSVIEW, + GraphicsViewController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKEDCOMPONENTCORE, + TrackedComponentCoreController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::DATAEXPORT, + DataExportController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::PLUGIN, PluginController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::ANNOTATIONS, + AnnotationsController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::AREADESCRIPTOR, + AreaDescriptorController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COREPARAMETER, + CoreParameterController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMMANDS, + CommandsController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::NOTIFICATION, + NotificationController); + + for (auto x : m_ControllersMap) { + auto c = static_cast(x); + c->setConfig(_cfg); + } +} + +void GuiContext::loadBioTrackerPlugin(QString str) +{ + qobject_cast( + m_ControllersMap.value(ENUMS::CONTROLLERTYPE::PLUGIN)) + ->loadPluginFromFileName(str); +} + +void GuiContext::createAppController() +{ + QMap::iterator i; + for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) { + i.value()->createComponents(); + } +} + +void GuiContext::connectController() +{ + QMap::iterator i; + for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) { + i.value()->connectComponents(); + } +} + +void GuiContext::exit() +{ + + QString cfgLoc = _cfg->CfgCustomLocation.isEmpty() + ? Config::configLocation + : _cfg->CfgCustomLocation; + _cfg->save(cfgLoc, "config.ini"); + QMap::iterator i; + for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) { + i.value()->cleanup(); + } + + for (auto&& i : m_ControllersMap) { + delete i; + } + + qApp->exit(); + std::exit(0); +} diff --git a/BioTracker/CoreApp/BioTracker/GuiContext.h b/Src/GuiContext.h similarity index 56% rename from BioTracker/CoreApp/BioTracker/GuiContext.h rename to Src/GuiContext.h index 93fc3b68..78a3f118 100644 --- a/BioTracker/CoreApp/BioTracker/GuiContext.h +++ b/Src/GuiContext.h @@ -3,28 +3,28 @@ #include "Interfaces/IBioTrackerContext.h" #include "Interfaces/IController/IController.h" - - - +#include "util/Config.h" class GuiContext : public IBioTrackerContext { Q_OBJECT public: - GuiContext(QObject *parent = 0); - ~GuiContext() { - exit(); - } + GuiContext(QObject* parent = 0, Config* cfg = nullptr); + ~GuiContext() + { + exit(); + } void loadBioTrackerPlugin(QString str); - void exit(); + void exit(); // IBioTrackerContext interface protected: - void createAppController() override; - void connectController() override; + void createAppController() override; + void connectController() override; + Config* _cfg; }; #endif // GUICONTEXT_H diff --git a/Src/IStates/IPlayerState.cpp b/Src/IStates/IPlayerState.cpp new file mode 100644 index 00000000..2e6ede49 --- /dev/null +++ b/Src/IStates/IPlayerState.cpp @@ -0,0 +1,41 @@ +#include "IPlayerState.h" + +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" + +#include "opencv2/core/core.hpp" + +IPlayerState::IPlayerState( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: m_Player(player) +, m_ImageStream(imageStream) +{ + m_FrameNumber = 0; +} + +cv::Mat IPlayerState::getCurrentFrame() +{ + return m_Mat; +} + +size_t IPlayerState::getCurrentFrameNumber() +{ + return m_FrameNumber; +} + +void IPlayerState::changeImageStream( + std::shared_ptr imageStream) +{ + m_ImageStream.reset(); + m_ImageStream = imageStream; +} + +stateParameters IPlayerState::getStateParameters() +{ + return m_StateParameters; +} + +QString IPlayerState::getCurrentFileName() +{ + return QString::fromStdString(m_ImageStream->currentFilename()); +} diff --git a/Src/IStates/IPlayerState.h b/Src/IStates/IPlayerState.h new file mode 100644 index 00000000..66be3b42 --- /dev/null +++ b/Src/IStates/IPlayerState.h @@ -0,0 +1,135 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef IPLAYERSTATE_H +#define IPLAYERSTATE_H + +#include +#include + +#include "Interfaces/IModel/IModel.h" +#include "Model/ImageStream.h" +#include "QPointer" + +/** + * The stateParameters struct represents the possible stats for the + * VideoControll buttons in the MainWindow widget. If a value is true, the + * button will be available to the user. If a value is false, the button is + * deactivated in the MainWindow. + */ +struct stateParameters +{ + bool m_Play; + bool m_Forw; + bool m_Back; + bool m_Stop; + bool m_Paus; + bool m_RecI; + bool m_RecO; +}; + +class MediaPlayerStateMachine; +/** + * The IPlayerState class is the interface for all states of the + * MediaPlayerStateMachine. This class is responsible for manipulating + * ImageStreams with its method operate(). If new states are required simply + * create them and add a name for the state to the ENUMERATION PLAYER_STATES. + * + * Any State class is able to set its following state in the + * MediaPlayerStateMachine. + * + */ +class IPlayerState : public IModel +{ + Q_OBJECT + +public: + explicit IPlayerState( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + enum PLAYER_STATES + { + STATE_INITIAL, + STATE_INITIAL_STREAM, + STATE_PLAY, + STATE_STEP_FORW, + STATE_STEP_BACK, + STATE_PAUSE, + STATE_WAIT, + STATE_GOTOFRAME + }; + Q_ENUM(PLAYER_STATES) + +public: + /** + * If the user changes the Image Source all states will be informed + * throught this method. + */ + void changeImageStream( + std::shared_ptr imageStream); + + /** + * Must be implemented by any state. Implement here the ImageStream + * manipulation. + */ + virtual void operate() = 0; + + /** + * Returns the State Parameters for the ImageStream controlls in the + * VideoViewWidget. + */ + stateParameters getStateParameters(); + + /** + * Returns the current filename of the ImageStream. + */ + QString getCurrentFileName(); + + /** + * Returns the current title of the ImageStream. + */ + std::string getCurrentTitle() + { + return m_ImageStream->getTitle(); + }; + + std::vector getBatchItems() + { + return m_ImageStream->getBatchItems(); + }; + + /** + * Returns the current cv::Mat of the ImageStream. + */ + cv::Mat getCurrentFrame(); + + /** + * Returns the current frame number of the ImageStream. + */ + size_t getCurrentFrameNumber(); + + // TODO: The Media player does not hold a valid imagestream. Hence use the + // current state's stream to grab details + std::shared_ptr m_ImageStream; + +Q_SIGNALS: + void emitNextMediaInBatch(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path); + +protected: + MediaPlayerStateMachine* m_Player; + + stateParameters m_StateParameters; + + cv::Mat m_Mat; + size_t m_FrameNumber; + std::fstream fs; + + QString m_currentFileName; +}; + +#endif // IPLAYERSTATE_H diff --git a/Src/Model/Annotations.cpp b/Src/Model/Annotations.cpp new file mode 100644 index 00000000..461f7c7b --- /dev/null +++ b/Src/Model/Annotations.cpp @@ -0,0 +1,502 @@ +#include "Annotations.h" +#include "Interfaces/IModel/IModelTrackedComponent.h" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +Annotations::~Annotations() +{ + serialize(); +} + +std::string Annotations::getFilename() const +{ + return filepath + ".annotations.json"; +} + +void Annotations::serialize() const +{ + if (!dirty || filepath.empty()) + return; + + QJsonArray serializedAnnotations; + for (auto& annotation : annotations) { + serializedAnnotations.append( + QJsonObject::fromVariantMap(annotation->serializeToMap())); + } + QJsonDocument jsonDocument(serializedAnnotations); + QFile outfile{QString::fromStdString(getFilename())}; + if (!outfile.open(QFile::WriteOnly)) + return; + outfile.write(jsonDocument.toJson()); + + dirty = false; +} + +void Annotations::deserialize() +{ + if (filepath.empty()) + return; + QFile infile{QString::fromStdString(getFilename())}; + if (!infile.open(QFile::ReadOnly)) + return; + const QJsonDocument jsonDocument{ + QJsonDocument::fromJson(infile.readAll())}; + const QJsonArray jsonArray(jsonDocument.array()); + + for (const auto& serializedAnnotation : jsonArray) { + const auto jsonObject{serializedAnnotation.toObject()}; + const QString type{jsonObject["type"].toString()}; + + std::shared_ptr annotation; + if (type == "arrow") + annotation = std::make_shared(); + else if (type == "label") + annotation = std::make_shared(); + else if (type == "rect") + annotation = std::make_shared(); + else if (type == "ellipse") + annotation = std::make_shared(); + if (annotation) { + annotation->deserializeFrom(jsonObject.toVariantMap()); + annotations.push_back(annotation); + } + } + + dirty = false; +} + +void Annotations::updateTrackedAnnotations( + const QList& trackedComponents) +{ + for (auto& annotation : annotations) { + annotation->updateTrackedPositions(static_cast(getCurrentFrame()), + trackedComponents); + } +} + +void Annotations::TrackedPoint::update( + int currentFrameID, + const QList& trackedComponents) +{ + if (!isLinkedToTrack) + return; + + for (const auto& trackedComponent : trackedComponents) { + const auto trackedTrajectory = dynamic_cast( + trackedComponent); + if (trackedTrajectory == nullptr) + continue; + if (trackedTrajectory->getId() != trackID) + continue; + + const auto& childComponent = trackedTrajectory->getChild( + currentFrameID); + const auto point = dynamic_cast( + childComponent); + if (point == nullptr) + return; + + position = QPoint(static_cast(point->getXpx()), + static_cast(point->getYpx())); + return; + } +} + +void Annotations::Annotation::drawHandleLocation(QPainter* painter, + QPoint pos, + QString text) +{ + QPen original{painter->pen()}; + QPen dotted{original}; + dotted.setStyle(Qt::PenStyle::DotLine); + dotted.setWidthF(dotted.widthF() / 4.0); + painter->setPen(dotted); + const int radius = 20; + painter->drawEllipse(pos, radius, radius); + + // text slighy other color --> hue + 20 + // so text can be read when annotation is also contrasting with the + // background + QPen textPen{original}; + QColor textColor{dotted.color()}; + textColor.setHsv(textColor.hsvHue() + 20, + textColor.hsvSaturation(), + textColor.value()); + textPen.setColor(textColor); + painter->setPen(textPen); + + // font + QFont font = painter->font(); + font.setPointSize(15); + painter->setFont(font); + + // calculate text width to position variably + QFontMetrics fm(font); + int width = fm.width(text); + int height = fm.height(); + + // text position under origin handle + QPoint textPos = pos + QPoint(-width / 2, 20 + height); + + // draw text + painter->drawText(textPos, text); + + painter->setPen(original); +} + +bool Annotations::Annotation::isHandleAtPosition(const QPoint& handle, + const QPoint& pos) +{ + QPoint diff = handle - pos; + const float euclidian = std::sqrt((diff.x() * diff.x()) + + (diff.y() * diff.y())); + return euclidian <= 20.0; +} + +void Annotations::Annotation::deserializeFrom( + const QMap& map) +{ + text = map.value("comment", text).toString(); + startFrame = + map.value("start_frame", static_cast(startFrame)).toInt(); + endFrame = map.value("end_frame", static_cast(endFrame)).toInt(); + origin.position.setX(map.value("origin_x", origin.x()).toInt()); + origin.position.setY(map.value("origin_y", origin.y()).toInt()); + if (map.contains("origin_track_id")) { + origin.isLinkedToTrack = true; + origin.trackID = map.value("origin_track_id").toInt(); + } +} + +QMap Annotations::Annotation::serializeToMap() const +{ + QMap map; + map["type"] = QString::fromStdString(name()); + map["comment"] = text; + map["start_frame"] = static_cast(startFrame); + map["end_frame"] = static_cast(endFrame); + + if (origin.isLinkedToTrack) { + map["origin_track_id"] = origin.trackID; + } else { + map["origin_x"] = origin.x(); + map["origin_y"] = origin.y(); + } + return map; +} + +void Annotations::AnnotationLabel::paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const +{ + QPen original{painter->pen()}; + QPen thin{original}; + thin.setWidthF(1.0); + painter->setPen(thin); + const int len = 20; + painter->drawLine(*this->origin + QPoint(-len, -len), + *this->origin + QPoint(+len, +len)); + painter->drawLine(*this->origin + QPoint(-len, len), + *this->origin + QPoint(+len, -len)); + + painter->setPen(original); + + Annotation::drawHandleLocation(painter, origin, text); +} + +void Annotations::AnnotationArrow::deserializeFrom( + const QMap& map) +{ + Annotation::deserializeFrom(map); + arrowHead.position.setX(map.value("end_x", arrowHead.x()).toInt()); + arrowHead.position.setY(map.value("end_y", arrowHead.y()).toInt()); + if (map.contains("end_track_id")) { + arrowHead.isLinkedToTrack = true; + arrowHead.trackID = map.value("end_track_id").toInt(); + } +} + +QMap Annotations::AnnotationArrow::serializeToMap() const +{ + auto base = Annotations::Annotation::serializeToMap(); + if (arrowHead.isLinkedToTrack) { + base["end_track_id"] = arrowHead.trackID; + } else { + base["end_x"] = arrowHead.x(); + base["end_y"] = arrowHead.y(); + } + return base; +} + +void Annotations::AnnotationArrow::paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const +{ + painter->drawLine(this->origin.getPoint(), this->arrowHead.getPoint()); + // Draw the origin slightly bigger. + { + painter->save(); + QPen thick{painter->pen()}; + thick.setWidthF(thick.widthF() * 2.5f); + painter->setPen(thick); + painter->drawPoint(this->origin.getPoint()); + painter->restore(); + } + // Draw the arrowhead slightly thinner. + { + painter->save(); + QPen thin{painter->pen()}; + thin.setWidthF(thin.widthF() * 0.5f); + painter->setPen(thin); + painter->drawPoint(this->arrowHead.getPoint()); + painter->restore(); + } + Annotation::drawHandleLocation(painter, origin, text); + Annotation::drawHandleLocation(painter, arrowHead, ""); +} + +Annotations::TrackedPoint* Annotations::AnnotationArrow::getHandleForPosition( + const QPoint& pos) +{ + if (isHandleAtPosition(arrowHead, pos)) + return &arrowHead; + return Annotation::getHandleForPosition(pos); +} + +void Annotations::AnnotationArrow::updateTrackedPositions( + int currentFrameID, + const QList& trackedComponents) +{ + Annotation::updateTrackedPositions(currentFrameID, trackedComponents); + arrowHead.update(currentFrameID, trackedComponents); +} + +void Annotations::AnnotationRect::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const +{ + QRect rect{origin.getPoint(), arrowHead.getPoint()}; + painter->drawRect(rect); + // Draw the origin slightly bigger. + { + painter->save(); + QPen thick{painter->pen()}; + thick.setWidthF(thick.widthF() * 2.5f); + painter->setPen(thick); + painter->drawPoint(origin.getPoint()); + painter->restore(); + } + // Draw the bottom right point slightly thinner. + { + painter->save(); + QPen thin{painter->pen()}; + thin.setWidthF(thin.widthF() * 0.5f); + painter->setPen(thin); + painter->drawPoint(arrowHead.getPoint()); + painter->restore(); + } + Annotation::drawHandleLocation(painter, origin, text); + Annotation::drawHandleLocation(painter, arrowHead, ""); +} + +void Annotations::AnnotationEllipse::paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const +{ + QRect rect{origin.getPoint(), arrowHead.getPoint()}; + painter->drawEllipse(rect); + // Draw the origin slightly bigger. + { + painter->save(); + QPen thick{painter->pen()}; + thick.setWidthF(thick.widthF() * 2.5f); + painter->setPen(thick); + painter->drawPoint(origin.getPoint()); + painter->restore(); + } + // Draw the bottom right point slightly thinner. + { + painter->save(); + QPen thin{painter->pen()}; + thin.setWidthF(thin.widthF() * 0.5f); + painter->setPen(thin); + painter->drawPoint(arrowHead.getPoint()); + painter->restore(); + } + Annotation::drawHandleLocation(painter, origin, text); + Annotation::drawHandleLocation(painter, arrowHead, ""); +} + +void Annotations::startArrow(QPoint origin, size_t currentFrame) +{ + currentAnnotation = std::make_shared(origin, + currentFrame); +} + +void Annotations::startLabel(QPoint origin, size_t currentFrame) +{ + currentAnnotation = std::make_shared(origin, + currentFrame); +} + +void Annotations::startRect(QPoint origin, size_t currentFrame) +{ + currentAnnotation = std::make_shared(origin, currentFrame); +} + +void Annotations::startEllipse(QPoint origin, size_t currentFrame) +{ + currentAnnotation = std::make_shared(origin, + currentFrame); +} + +bool Annotations::updateAnnotation(TrackedPoint cursor) +{ + if (currentAnnotation) { + currentAnnotation->onEndAnnotation(cursor); + dirty = true; + return true; + } + if (selection) { + *selection.handle = cursor; + dirty = true; + return true; + } + return false; +} + +bool Annotations::tryStartDragging(QPoint cursor) +{ + selection.reset(); + float currentDistance = std::numeric_limits::max(); + bool annotationFound = false; + for (auto& annotation : annotations) { + if (annotation->isHidden()) + continue; + auto handle = annotation->getHandleForPosition(cursor); + if (!handle) // Nothing found? + continue; + const float distance = QVector2D{handle->getPoint() - cursor}.length(); + if (distance >= currentDistance) // Point is farther? + continue; + // New best point found! + currentDistance = distance; + selection.handle = handle; + selection.annotation = annotation; + annotationFound = true; + } + return annotationFound; +} + +bool Annotations::trySetText(QPoint cursor) +{ + selection.reset(); + for (auto& annotation : annotations) { + if (annotation->isHidden()) + continue; + if (!(selection.handle = annotation->getHandleForPosition(cursor))) { + continue; + } + selection.annotation = annotation; + + bool ok; + QString annoText = QInputDialog::getText(Q_NULLPTR, + tr("Set annotation text"), + tr("Annotation text:"), + QLineEdit::Normal, + annotation->getText(), + &ok); + if (ok) { + annotation->setText(annoText); + dirty = true; + } + return true; + } + return false; +} + +bool Annotations::endAnnotation(TrackedPoint cursor) +{ + if (currentAnnotation) { + const bool isValid = currentAnnotation->onEndAnnotation(cursor); + if (!isValid) + return false; + + annotations.push_back(currentAnnotation); + currentAnnotation.reset(); + dirty = true; + return true; + } + + return false; +} + +bool Annotations::removeSelection() +{ + if (!selection) + return false; + Annotation* selectedAnnotation{selection.annotation.lock().get()}; + + for (auto iter = annotations.begin(); iter != annotations.end();) { + const auto annotation = *iter; + if (annotation.get() == selectedAnnotation) { + iter = annotations.erase(iter); + dirty = true; + } else + ++iter; + } + return true; +} + +bool Annotations::updateSelectionStartFrame() +{ + if (!selection) + return false; + Annotation* selectedAnnotation{selection.annotation.lock().get()}; + selectedAnnotation->startFrame = getCurrentFrame(); + if (selectedAnnotation->endFrame < selectedAnnotation->startFrame) + selectedAnnotation->endFrame = selectedAnnotation->startFrame; + dirty = true; + return true; +} + +bool Annotations::updateSelectionEndFrame() +{ + if (!selection) + return false; + Annotation* selectedAnnotation{selection.annotation.lock().get()}; + selectedAnnotation->endFrame = getCurrentFrame(); + if (selectedAnnotation->startFrame > selectedAnnotation->endFrame) + selectedAnnotation->startFrame = selectedAnnotation->endFrame; + dirty = true; + return true; +} + +void Annotations::toggleHideAnnotations() +{ + bool allWereHidden = true; + for (auto& annotation : annotations) { + if (!annotation->isHidden()) { + allWereHidden = false; + annotation->setHidden(true); + } + } + + if (allWereHidden) { + for (auto& annotation : annotations) + annotation->setHidden(false); + } +} \ No newline at end of file diff --git a/Src/Model/Annotations.h b/Src/Model/Annotations.h new file mode 100644 index 00000000..3e0aee90 --- /dev/null +++ b/Src/Model/Annotations.h @@ -0,0 +1,340 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg and BioTracker in version 2. + ** + ** + ****************************************************************************/ + +#pragma once + +#include "Interfaces/IModel/IModel.h" + +#include +#include "QString" +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class IModelTrackedComponent; + +/** + Model to handle annotations, including serialization. + Annotations will be drawn on top of the video. Their position is defined in + image coordinates. +*/ +class Annotations : public IModel +{ + Q_OBJECT +public: + Annotations(std::string filepath = "") + : filepath(filepath) + { + deserialize(); + } + virtual ~Annotations(); + + /* + A 2d point that can be linked to a tracked component ID. + */ + struct TrackedPoint + { + TrackedPoint(const QPoint& pos) + : position(pos) + { + } + TrackedPoint(int x, int y) + : TrackedPoint(QPoint(x, y)) + { + } + TrackedPoint(const QPoint& pos, int trackID) + : TrackedPoint(pos) + { + this->trackID = trackID; + isLinkedToTrack = true; + } + TrackedPoint() + { + } + QPoint position{0, 0}; + int trackID{0}; + bool isLinkedToTrack{0}; + + // Retrieve the current position. + QPoint getPoint() const + { + return position; + } + const QPoint& operator*() const + { + return position; + } + int x() const + { + return position.x(); + } + int y() const + { + return position.y(); + } + // Update the current position to the corresponding track position IIF + // isLinkedToTrack. + void update(int currentFrameID, + const QList& trackedComponents); + }; + /* + Base annotation class. + Children must at least support serialization and drawing. + */ + struct Annotation + { + Annotation(QPoint origin = {0, 0}, size_t startFrame = 0) + : origin(origin) + , startFrame(startFrame) + { + } + virtual ~Annotation() = default; + // Position in pixels. + TrackedPoint origin{0, 0}; + size_t startFrame{0}, endFrame{0}; + // Possible text for each annotation + QString text{""}; + /// Name that identifies this type of annotation and is used for + /// serialization. + virtual std::string name() const = 0; + virtual void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const = 0; + // Saving requires writing/reading properties to/from maps. + virtual QMap serializeToMap() const; + virtual void deserializeFrom(const QMap& map); + // Set text. Called when right clicking. + virtual void setText(QString newText) + { + text = newText; + } + // Get text. Called when right clicking. + virtual QString getText() + { + return text; + } + // Called either during dragging or when the mouse is released. + // Needs to update positional data. + virtual bool onEndAnnotation(TrackedPoint currentPosition) + { + origin = currentPosition; + return true; + } + virtual QRectF boundingRect() const + { + return QRect(*origin, *origin).marginsAdded({20, 20, 20, 20}); + } + // Used for mouse-click events. + // Returns the handle that has been clicked. + virtual TrackedPoint* getHandleForPosition(const QPoint& pos) + { + if (isHandleAtPosition(origin, pos)) + return &origin; + return nullptr; + } + // Static, so that the view can use it to draw special handles. + static void drawHandleLocation(QPainter* painter, + QPoint pos, + QString text); + static void drawHandleLocation(QPainter* painter, + const TrackedPoint& pos, + QString text) + { + drawHandleLocation(painter, *pos, text); + } + virtual void updateTrackedPositions( + int currentFrameID, + const QList& trackedComponents) + { + origin.update(currentFrameID, trackedComponents); + } + // Visually disable annotations and interactions with them. + // This will not be serialized. + void setHidden(bool hidden = true) + { + this->hidden = hidden; + } + bool isHidden() const + { + return hidden; + } + + protected: + bool isHandleAtPosition(const QPoint& handle, const QPoint& pos); + bool isHandleAtPosition(const TrackedPoint& handle, const QPoint& pos) + { + return isHandleAtPosition(*handle, pos); + } + + private: + bool hidden{false}; + }; + + /// A label marks a position. + struct AnnotationLabel : public Annotation + { + using Annotation::Annotation; + virtual ~AnnotationLabel() = default; + + virtual std::string name() const override + { + return "label"; + } + virtual void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const override; + }; + + /// An arrow defines a vector between two positions. + struct AnnotationArrow : public Annotation + { + using Annotation::Annotation; + virtual ~AnnotationArrow() = default; + + virtual std::string name() const override + { + return "arrow"; + } + virtual QMap serializeToMap() const override; + virtual void deserializeFrom( + const QMap& map) override; + virtual bool onEndAnnotation(TrackedPoint currentPosition) override + { + arrowHead = currentPosition; + return true; + } + virtual void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const override; + virtual QRectF boundingRect() const + { + return QRect(*origin, *arrowHead).marginsAdded({20, 20, 20, 20}); + } + virtual TrackedPoint* getHandleForPosition(const QPoint& pos) override; + virtual void updateTrackedPositions( + int currentFrameID, + const QList& trackedComponents) override; + + TrackedPoint arrowHead; + }; + + // A rectangle defined by two points (top-left and bottom-right) + struct AnnotationRect : public AnnotationArrow + { + using AnnotationArrow::AnnotationArrow; + virtual ~AnnotationRect() = default; + + virtual std::string name() const override + { + return "rect"; + } + virtual void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const override; + }; + // An ellipse defined by two points (top-left and bottom-right) + struct AnnotationEllipse : public AnnotationArrow + { + using AnnotationArrow::AnnotationArrow; + virtual ~AnnotationEllipse() = default; + + virtual std::string name() const override + { + return "ellipse"; + } + virtual void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) const override; + }; + + void serialize() const; + void deserialize(); + /// Called by the controller to begin a new annotation. + void startArrow(QPoint origin, size_t currentFrame); + void startLabel(QPoint origin, size_t currentFrame); + void startRect(QPoint origin, size_t currentFrame); + void startEllipse(QPoint origin, size_t currentFrame); + /// Called by the controller on left mouse-clicks. + bool tryStartDragging(QPoint cursor); + /// Called by the controller on left mouse-clicks. + bool trySetText(QPoint cursor); + // Called by the controller during mouse-drags to update the current + // annotation. + bool updateAnnotation(TrackedPoint cursor); + // Called on mouse-release. + bool endAnnotation(TrackedPoint cursor); + // Removes the currently selected (through tryStartDragging) annotation. + bool removeSelection(); + // Sets the start frame of the current selection to the current frame. + bool updateSelectionStartFrame(); + // Sets the end frame of the current selection to the current frame. + bool updateSelectionEndFrame(); + // The current frame is required for the view to highlight annotations. + void setCurrentFrame(size_t currentFrame) + { + this->currentFrame = currentFrame; + } + size_t getCurrentFrame() const + { + return currentFrame; + } + // Called when trajectories or displayed frames have changed. + void updateTrackedAnnotations( + const QList& trackedComponents); + // Used to hide existing annotations, or if all are hidden, unhide them. + void toggleHideAnnotations(); + +private: + size_t currentFrame{0}; /**< The current frame is required by the view. */ + + std::string filepath; /**< filepath of the original source image. */ + + std::string getFilename() const; /**< The resulting filename will add a + suffix to the original source path. */ + + mutable bool dirty{ + false}; /**< Whether the annotations need to be serialized on exit. */ + + std::vector> + annotations; /**< vector of all annotations */ + + std::shared_ptr + currentAnnotation; /**< Held temporarily during events - not yet + 'created'. */ + + /// Valid during drag & drop or after mouse selection. + struct SelectionData + { + // Annotation from the annotations vector above. Defines validity of + // the whole struct. + std::weak_ptr annotation; + TrackedPoint* handle{nullptr}; + explicit operator bool() const + { + return !annotation.expired(); + } + // This is likely not thread-safe. + Annotation* operator->() + { + return annotation.lock().get(); + } + void reset() + { + return annotation.reset(); + } + } selection; + + friend class AnnotationsView; +}; diff --git a/Src/Model/AreaDescriptor/AreaInfo.cpp b/Src/Model/AreaDescriptor/AreaInfo.cpp new file mode 100644 index 00000000..61cc0466 --- /dev/null +++ b/Src/Model/AreaDescriptor/AreaInfo.cpp @@ -0,0 +1,194 @@ +#include "AreaInfo.h" + +#include "Rectification.h" + +#include "Utility/misc.h" +#include +#include "AreaMemory.h" + +using namespace AreaMemory; +using namespace BioTrackerUtilsMisc; + +AreaInfo::AreaInfo(QObject* parent) +: IModelAreaDescriptor(parent) +{ + _parms = nullptr; + _areaInfoCache = + static_cast(parent)->getConfig()->AreaDefinitions; + _rect = std::make_shared(); + _rect->setShowNumbers(true); + _rect->setAreaType(BiotrackerTypes::AreaType::RECT); + _apperture = std::make_shared(); + _apperture->setAreaType(BiotrackerTypes::AreaType::APPERTURE); + _useEntireScreen = true; + loadAreas(); + updateRectification(); +} + +QString AreaInfo::myType() +{ + if (_apperture != nullptr) { + return QString::number(_apperture->getType()); + } + return "0"; +} + +void AreaInfo::reset(int w, int h) +{ + _useEntireScreen = true; + _rectInitialized = false; + _vdimX = w; + _vdimY = h; + + QVector vertices = _parms != nullptr + ? getVertices(_parms->m_CurrentFilename, + _areaInfoCache) + : QVector(); + + if (vertices == DEFAULT_PAIR // couldn't find entry + || vertices.empty()) // biotracker just started + { + std::vector v{cv::Point(0, 0), + cv::Point(0, _vdimY), + cv::Point(_vdimX, _vdimY), + cv::Point(_vdimX, 0)}; + _apperture->setVertices(v); + _rect->setVertices(v); + } else { + std::vector pts = toQPointVector(vertices[0]); + std::vector pts2 = toQPointVector(vertices[1]); + _apperture->setVertices(QVecToCvVec(pts2)); + _rect->setVertices(QVecToCvVec(pts)); + } +} + +void AreaInfo::loadAreas() +{ + + QVector pair = getVertices(_parms ? _parms->m_CurrentFilename + : "", + _areaInfoCache, + true); + + if (pair[1] == QString(DEFAULT_RECT)) { + if (_parms) { + auto m = _parms->m_CurrentFrame; + reset(m->size().width, m->size().height); + } else { + reset(100, 100); + } + } + + std::vector p = stringToCVPointVec(pair[0].toStdString()); + _rect->setVertices(p); + + p = stringToCVPointVec(pair[1].toStdString()); + ; + _apperture->setVertices(p); +} + +void AreaInfo::rcvPlayerParameters( + std::shared_ptr parameters) +{ + if (_parms == nullptr || + _parms->m_CurrentFilename != parameters->m_CurrentFilename) { + _rectInitialized = false; + } + if (!parameters->m_CurrentFrame) { + return; + } + + _parms = parameters; + auto m = *parameters->m_CurrentFrame; + if ((m.size().width != _vdimX || m.size().height != _vdimY) && + _useEntireScreen) { // TODO: _useEntireScreen? if we do not update + // stuff in the very beginning, tracking + // rectification will break + reset(m.size().width, m.size().height); + loadAreas(); + updateRectification(); + } +} + +void AreaInfo::updateRectification() +{ + if (_parms) { + if (!_rectInitialized) { + QVector vertices = getVertices(_parms->m_CurrentFilename, + _areaInfoCache); + std::vector pts = toQPointVector(vertices[0]); + Rectification::instance().setArea(pts); + Rectification::instance().setupRecitification(100, + 100, + _vdimX, + _vdimY); + _rectInitialized = true; + } else { + QVector vertices = getVertices(_parms->m_CurrentFilename, + _areaInfoCache); + Rectification::instance().setArea(_rect->getQVertices()); + Rectification::instance().setupRecitification(100, + 100, + _vdimX, + _vdimY); + + setVertices( + _parms->m_CurrentFilename, + QVector{ + cvPointsToString(_rect->getVertices()).c_str(), + cvPointsToString(_apperture->getVertices()).c_str(), + QString(myType()), + QString(vertices[3])}, + _areaInfoCache); + + setVertices( + "Last", + QVector{ + cvPointsToString(_rect->getVertices()).c_str(), + cvPointsToString(_apperture->getVertices()).c_str(), + QString(myType()), + QString(vertices[3])}, + _areaInfoCache); + } + } else { + // TODO: What's to do here? + } +} + +void AreaInfo::setRectificationDimensions(double w, double h) +{ + Rectification::instance().setDimension(w, h); +} + +void AreaInfo::updateApperture() +{ + + if (_parms && _rectInitialized) { + QVector vertices = getVertices(_parms->m_CurrentFilename, + _areaInfoCache); + std::vector p = _apperture->getVertices(); + + setVertices( + _parms->m_CurrentFilename, + QVector{cvPointsToString(_rect->getVertices()).c_str(), + cvPointsToString(p).c_str(), + QString(myType()), + QString(vertices[3])}, + _areaInfoCache); // TODO + } +} + +bool AreaInfo::inTrackingArea(cv::Point2f point_cm) +{ + return _apperture->insideElement(point_cm); +} + +cv::Point2f AreaInfo::pxToCm(cv::Point point_px) +{ + return Rectification::instance().pxToCm(point_px); +} + +cv::Point2f AreaInfo::cmToPx(cv::Point2f point_cm) +{ + return Rectification::instance().cmToPx(point_cm); +} diff --git a/Src/Model/AreaDescriptor/AreaInfo.h b/Src/Model/AreaDescriptor/AreaInfo.h new file mode 100644 index 00000000..79cd0ae0 --- /dev/null +++ b/Src/Model/AreaDescriptor/AreaInfo.h @@ -0,0 +1,71 @@ +#pragma once +#include "Interfaces/IModel/IModelAreaDescriptor.h" +#include "Interfaces/IModel/IModel.h" +#include "Controller/IControllerCfg.h" +#include "AreaInfoElement.h" +#include "util/types.h" +#include "Model/MediaPlayerStateMachine/PlayerParameters.h" + +class AreaInfo : public IModelAreaDescriptor +{ + Q_OBJECT +public: + AreaInfo() = delete; + AreaInfo(QObject* parent = 0); + + // TODO PORT + bool inTrackingArea(cv::Point2f point_cm) override; + + /** + * Transform the provided pixel coordinates into world coordinates and + * return world coordinates. + * @param: pixelCoords, a list of points. + * @return: world coordinates in as a list. + */ + cv::Point2f pxToCm(cv::Point point_px) override; + + /** + * Transform the provided pixel point into world coordinates and return + * world point. + * @param: point, a pixel point, used opencv point + * @return: world point. + */ + cv::Point2f cmToPx(cv::Point2f point_cm) override; + + void updateApperture(); + + void updateRectification(); + + void setRectificationDimensions(double w, double h); + + void reset(int w, int h); + void loadAreas(); + void setUseEntireScreen(bool b) + { + _useEntireScreen = b; + }; + bool getUseEntireScreen() + { + return _useEntireScreen; + }; + + std::shared_ptr _rect; + std::shared_ptr _apperture; + +private: + // If the user never changed the area, use the whole screen. Indicate by + // this switch + bool _useEntireScreen = false; + int _vdimX = 1; + int _vdimY = 1; + std::shared_ptr _parms; + bool _rectInitialized = false; + QString _areaInfoCache; + +public Q_SLOTS: + void rcvPlayerParameters( + std::shared_ptr parameters); + +private: + QString myType(); +}; diff --git a/Src/Model/AreaDescriptor/AreaInfoElement.cpp b/Src/Model/AreaDescriptor/AreaInfoElement.cpp new file mode 100644 index 00000000..2326f069 --- /dev/null +++ b/Src/Model/AreaDescriptor/AreaInfoElement.cpp @@ -0,0 +1,81 @@ +#include "AreaInfoElement.h" + +#include +#include + +AreaInfoElement::AreaInfoElement(int type) +: _areaType(BiotrackerTypes::AreaType::NONE) +, _type(type) +, _showNumbers(false) +{ +} + +AreaInfoElement::~AreaInfoElement() +{ +} + +bool AreaInfoElement::insideElement(cv::Point p) +{ + + if (_type == 0) { + + return cv::pointPolygonTest(_v, p, true) > 0; + } else if (_type == 1) { + float rx = std::abs(_v[1].x - _v[0].x) / 2; + float ry = std::abs(_v[1].y - _v[0].y) / 2; + float h = _v[0].x + rx; + float k = _v[0].y + ry; + float x = p.x; + float y = p.y; + + float xh = std::pow(x - h, 2); + float yk = std::pow(y - k, 2); + float val = (xh / (rx * rx)) + (yk / (ry * ry)); + bool inShape = val <= 1; + + return inShape; + } + return false; +} + +int AreaInfoElement::getVerticeAtLocation(const QPoint& pos) +{ + if (_type == 0) { + for (int i = 0; i < 4; i++) { + if (isHandleAtPosition(_v[i], pos)) + return i; + } + } else if (_type == 1) { + for (int i = 0; i < 2; i++) { + if (isHandleAtPosition(_v[i], pos)) + return i; + } + } + + return -1; +} + +void AreaInfoElement::setVerticeAtLocation(const QPoint& pos, int vertice) +{ + if (_type == 0 && vertice >= 0 && vertice < 4) { + _v[vertice] = cv::Point2f(pos.x(), pos.y()); + } else if (_type > 0 && vertice >= 0 && vertice < 2) { + _v[vertice] = cv::Point2f(pos.x(), pos.y()); + } + + Q_EMIT updatedVertices(); +} + +bool AreaInfoElement::isHandleAtPosition(const cv::Point2f& handle, + const QPoint& pos) +{ + return isHandleAtPosition(QPoint(handle.x, handle.y), pos); +} +bool AreaInfoElement::isHandleAtPosition(const QPoint& handle, + const QPoint& pos) +{ + QPoint diff = handle - pos; + const float euclidian = std::sqrt((diff.x() * diff.x()) + + (diff.y() * diff.y())); + return euclidian <= 20.0; +} diff --git a/Src/Model/AreaDescriptor/AreaInfoElement.h b/Src/Model/AreaDescriptor/AreaInfoElement.h new file mode 100644 index 00000000..63168be4 --- /dev/null +++ b/Src/Model/AreaDescriptor/AreaInfoElement.h @@ -0,0 +1,96 @@ +#pragma once +#include "Interfaces/IModel/IModel.h" +#include +#include +#include "util/types.h" + +class AreaInfoElement : public IModel +{ + Q_OBJECT + +public: + AreaInfoElement(int type = 0); + ~AreaInfoElement(); + + bool insideElement(cv::Point p); + + void setVertices(std::vector p) + { + _v = p; + Q_EMIT updatedVertices(); + }; + + std::vector _v; + + std::vector getVertices() + { + return _v; + }; + + // TODO: change everything to QPoints? + std::vector getQVertices() + { + std::vector v; + for (int i = 0; i < _v.size(); i++) { + v.push_back(QPoint(_v[i].x, _v[i].y)); + } + return v; + }; + + int getType() + { + return _type; + }; + void setType(int t) + { + _type = t; + }; + + void setVerticeAtLocation(const QPoint& pos, int vertice); + int getVerticeAtLocation(const QPoint& pos); + + virtual QPoint* getHandleForPosition(const QPoint& pos) + { + if (isHandleAtPosition(_origin, pos)) + return &_origin; + return nullptr; + } + + void setShowNumbers(bool b) + { + _showNumbers = b; + } + + bool getShowNumbers() + { + return _showNumbers; + } + + BiotrackerTypes::AreaType getAreaType() + { + return _areaType; + } + void setAreaType(BiotrackerTypes::AreaType t) + { + _areaType = t; + } + +protected: + bool isHandleAtPosition(const cv::Point2f& handle, const QPoint& pos); + bool isHandleAtPosition(const QPoint& handle, const QPoint& pos); + +signals: + void updatedVertices(); + +private: + // Position in pixels. + QPoint _origin{0, 0}; + + bool _showNumbers; + + // Rect or Ellipse? + int _type; + + // Rectification, tracking area or both? + BiotrackerTypes::AreaType _areaType; +}; diff --git a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaMemory.cpp b/Src/Model/AreaDescriptor/AreaMemory.cpp similarity index 70% rename from BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaMemory.cpp rename to Src/Model/AreaDescriptor/AreaMemory.cpp index 48df3267..ce486ba0 100644 --- a/BioTracker/CoreApp/BioTracker/Model/AreaDescriptor/AreaMemory.cpp +++ b/Src/Model/AreaDescriptor/AreaMemory.cpp @@ -1,6 +1,6 @@ #include "AreaMemory.h" -#include "util/misc.h" +#include "Utility/misc.h" #include #include @@ -12,14 +12,18 @@ TODO: This is still rather prototype'ish. */ #include -namespace AreaMemory{ + +using namespace BioTrackerUtilsMisc; // split +namespace AreaMemory +{ QMap> map; - QVector getVertices(QString file, bool useLast) { + QVector getVertices(QString file, QString areaFile, bool useLast) + { if (map.size() == 0) { std::ifstream o; - o.open(CFG_AREA_DEFINITIONS, std::ifstream::in); + o.open(areaFile.toStdString(), std::ifstream::in); if (o.is_open()) { while (!o.eof()) { std::string line = ""; @@ -31,7 +35,7 @@ namespace AreaMemory{ strs[1].c_str(), strs[2].c_str(), strs[3].c_str(), - strs[4].c_str() }; + strs[4].c_str()}; } } } @@ -43,36 +47,38 @@ namespace AreaMemory{ else { if (useLast && map.contains("Last")) { return map.value("Last"); - }else + } else return DEFAULT_PAIR; } } - void setVertices(QString file, QVector values) { + void setVertices(QString file, QVector values, QString areaFile) + { if (file.size() <= 1) { return; } map[file] = values; std::ofstream o; - o.open(CFG_AREA_DEFINITIONS, std::ofstream::out); + o.open(areaFile.toStdString(), std::ofstream::out); if (o.is_open()) { QMapIterator> i(map); while (i.hasNext()) { i.next(); o << i.key().toStdString() << "#" << i.value()[0].toStdString() - << "#" << i.value()[1].toStdString() - << "#" << i.value()[2].toStdString() - << "#" << i.value()[3].toStdString() << std::endl; + << "#" << i.value()[1].toStdString() << "#" + << i.value()[2].toStdString() << "#" + << i.value()[3].toStdString() << std::endl; } } } - std::vector toQPointVector(QString vertices) { + std::vector toQPointVector(QString vertices) + { std::vector strs; - std::vector points; - std::string s = vertices.toStdString(); + std::vector points; + std::string s = vertices.toStdString(); split(s, strs, ';'); for (int i = 0; i < strs.size(); i++) { std::vector pt; diff --git a/Src/Model/AreaDescriptor/AreaMemory.h b/Src/Model/AreaDescriptor/AreaMemory.h new file mode 100644 index 00000000..cedd9e07 --- /dev/null +++ b/Src/Model/AreaDescriptor/AreaMemory.h @@ -0,0 +1,23 @@ +#pragma once +#include "Interfaces/IModel/IModelAreaDescriptor.h" +#include "Interfaces/IModel/IModel.h" +#include "AreaInfoElement.h" +#include "util/types.h" +#include "Model/MediaPlayerStateMachine/PlayerParameters.h" + +namespace AreaMemory +{ +#define DEFAULT_RECT "15,15;15,105;105,105;105,15" +#define DEFAULT_AREA "10,10;10,100;100,100;100,10" +#define DEFAULT_PAIR \ + QVector \ + { \ + DEFAULT_AREA, DEFAULT_RECT, "0", "0" \ + } + + QVector getVertices(QString file, + QString areaFile, + bool useLast = false); + void setVertices(QString file, QVector values, QString areaFile); + std::vector toQPointVector(QString vertices); +}; diff --git a/Src/Model/AreaDescriptor/Rectification.cpp b/Src/Model/AreaDescriptor/Rectification.cpp new file mode 100644 index 00000000..6613f75b --- /dev/null +++ b/Src/Model/AreaDescriptor/Rectification.cpp @@ -0,0 +1,364 @@ +#include "Rectification.h" +#include +#include + +#include +#include "Utility/misc.h" +#include "util/types.h" +#include "util/Config.h" + +using namespace BioTrackerUtilsMisc; // split + +Rectification::Rectification(float w, float h) +{ + initRecitification(w, h); + setupRecitification(0, 0, 0, 0); +} + +void Rectification::init(double areaHeight_cm, + double areaWidth_cm, + std::vector areaCoordinates, + int camCaptureWidth_px, + int camCaptureHeight_px, + int frameDisplayWidthPx, + int frameDisplayHeightPx) +{ + _q = cv::Mat(3, 1, CV_32F); + _camCaptureWidth_px = camCaptureWidth_px; + _camCaptureHeight_px = camCaptureHeight_px; + _areaHeight_cm = areaHeight_cm; + _areaWidth_cm = areaWidth_cm; + _areaCoordinates = areaCoordinates; + _frameDisplayWidthPx = frameDisplayWidthPx; + _frameDisplayHeightPx = frameDisplayHeightPx; + + setupRecitification(frameDisplayWidthPx, + frameDisplayHeightPx, + camCaptureWidth_px, + camCaptureHeight_px); +} + +void Rectification::initRecitification(double areaHeight_cm, + double areaWidth_cm) +{ + setArea(); + setDimension(areaWidth_cm, areaHeight_cm); +} + +void Rectification::setArea(std::vector areaCoordinates) +{ + _areaCoordinates = areaCoordinates; + // BioTracker::Core::Settings *_settings = + // BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); + //_settings->setParam(AREADESCRIPTOR::CN_ARENA, + // cvPointsToString(areaCoordinates).c_str()); +} + +void Rectification::setArea(std::vector areaCoordinates) +{ + std::vector cvAreaCoordinates; + for (int i = 0; i < areaCoordinates.size(); i++) { + cvAreaCoordinates.push_back( + cv::Point(areaCoordinates[i].x(), areaCoordinates[i].y())); + } + setArea(cvAreaCoordinates); +} + +std::vector Rectification::getDefaultArena() +{ + std::string s = (Config::DefaultArena).toStdString(); + return stringToCVPointVec(s); +} + +void Rectification::setArea() +{ + setArea(getDefaultArena()); +} + +void Rectification::setDimension(double areaWidth_cm, double areaHeight_cm) +{ + _areaWidth_cm = areaWidth_cm; + _areaHeight_cm = areaHeight_cm; + setupRecitification(_frameDisplayWidthPx, + _frameDisplayHeightPx, + _camCaptureWidth_px, + _camCaptureHeight_px); +} + +void Rectification::setupRecitification(int frameDisplayWidthPx, + int frameDisplayHeightPx, + int camImageWidth, + int camImageHeight) +{ + _frameDisplayWidthPx = frameDisplayWidthPx; + _frameDisplayHeightPx = frameDisplayHeightPx; + + _camCaptureWidth_px = frameDisplayWidthPx; + _camCaptureHeight_px = frameDisplayHeightPx; + + if (_rectifiedAreaCoordinates.size() > 0) { + _rectifiedAreaCoordinates.clear(); + } + + _rectifiedAreaCoordinates.push_back(cv::Point2f(0.0, 0.0)); // Top left + _rectifiedAreaCoordinates.push_back( + cv::Point2f(0.0, _areaHeight_cm)); // botton left + _rectifiedAreaCoordinates.push_back( + cv::Point2f(_areaWidth_cm, _areaHeight_cm)); // bottom right + _rectifiedAreaCoordinates.push_back( + cv::Point2f(_areaWidth_cm, 0.0)); // top right + + std::vector areaCoordinates_2f; + + assert(_areaCoordinates.size() == 4); + + cv::Mat coordinateMatrix(getSortedPoints()); + + if (cv::sum(coordinateMatrix)[0] > 0.0f) + coordinateMatrix.copyTo(areaCoordinates_2f); + else + areaCoordinates_2f = _rectifiedAreaCoordinates; + + _H = cv::findHomography(areaCoordinates_2f, _rectifiedAreaCoordinates); + _H_inv = _H.inv(); + _isSetup = true; +} + +void Rectification::resetAreaCoordinates() +{ + std::vector areaCoordinates; + + double rationHeight = double(_frameDisplayHeightPx) / + double(_camCaptureHeight_px); + double rationWidth = double(_frameDisplayWidthPx) / + double(_camCaptureWidth_px); + + for (cv::Point p : _areaCoordinates) { + + int newP_x = p.x / rationWidth; + int newP_y = p.y / rationHeight; + + areaCoordinates.push_back(cv::Point(newP_x, newP_y)); + } + + if (checkValidCoordinates(areaCoordinates, + _camCaptureHeight_px, + _camCaptureWidth_px)) { + _areaCoordinates.clear(); + _areaCoordinates = areaCoordinates; + + setupRecitification(_frameDisplayWidthPx, + _frameDisplayHeightPx, + _camCaptureWidth_px, + _camCaptureHeight_px); + } +} + +bool Rectification::checkValidCoordinates( + std::vector areaCoordinates, + int camCaptureHeight_px, + int camCaptureWidth_px) +{ + for (cv::Point p : areaCoordinates) { + if (p.y > camCaptureHeight_px) + return false; + if (p.x > camCaptureWidth_px) + return false; + } + + return true; +} + +cv::Point2f Rectification::pxToCm(cv::Point point_px) const +{ + cv::Mat_ v = (cv::Mat_(3, 1) << point_px.x, point_px.y, 1); + cv::gemm(_H, v, 1, 0, 0, _q); + double* qx = _q.ptr(0); + double* qy = _q.ptr(1); + double* qz = _q.ptr(2); + + cv::Point2f cm((*qx / *qz), (*qy / *qz)); + return cm; +} + +cv::Point2f Rectification::pxToCm(QPoint point_px) const +{ + return pxToCm(cv::Point(point_px.x(), point_px.y())); +} + +cv::Point2f Rectification::cmToPx(cv::Point2f point_cm) const +{ + cv::Mat_ v = (cv::Mat_(3, 1) << point_cm.x, point_cm.y, 1); + cv::gemm(_H_inv, v, 1, 0, 0, _q); + double* qx = _q.ptr(0); + double* qy = _q.ptr(1); + double* qz = _q.ptr(2); + + return cv::Point2f((*qx / *qz), (*qy / *qz)); +} + +bool Rectification::inArea(cv::Point2f point_cm) const +{ + bool flag = (point_cm.x >= 0 && point_cm.y >= 0 && + point_cm.x <= _areaWidth_cm && point_cm.y <= _areaHeight_cm); + return flag; +} + +int Rectification::minXPx() +{ + int minX = _camCaptureWidth_px; + for (int i = 0; i < _areaCoordinates.size(); i++) { + if (_areaCoordinates.at(i).x < minX) + minX = _areaCoordinates.at(i).x; + } + return minX; +} + +int Rectification::maxXPx() +{ + int maxX = -1; + for (int i = 0; i < _areaCoordinates.size(); i++) { + if (_areaCoordinates.at(i).x > maxX) + maxX = _areaCoordinates.at(i).x; + } + return maxX; +} + +int Rectification::minYPx() +{ + int minY = _camCaptureHeight_px; + for (int i = 0; i < _areaCoordinates.size(); i++) { + if (_areaCoordinates.at(i).y < minY) + minY = _areaCoordinates.at(i).y; + } + return minY; +} + +int Rectification::maxYPx() +{ + int maxY = -1; + for (int i = 0; i < _areaCoordinates.size(); i++) { + if (_areaCoordinates.at(i).y > maxY) + maxY = _areaCoordinates.at(i).y; + } + return maxY; +} + +cv::Point Rectification::getTopLeft() +{ + assert(_areaCoordinates.size() == 4); + + std::vector ac(_areaCoordinates); + + std::sort(ac.begin(), + ac.end(), + [](const cv::Point& a, const cv::Point& b) -> bool { + return (a.x <= b.x) && (a.y <= b.y); + }); + + return ac[0]; +} + +cv::Point Rectification::getBottomLeft() +{ + assert(_areaCoordinates.size() == 4); + + std::vector ac(_areaCoordinates); + + std::sort(ac.begin(), + ac.end(), + [](const cv::Point& a, const cv::Point& b) -> bool { + return (a.x <= b.x) && (a.y >= b.y); + }); + + return ac[0]; +} + +cv::Point Rectification::getBottomRight() +{ + assert(_areaCoordinates.size() == 4); + + std::vector ac(_areaCoordinates); + + std::sort(ac.begin(), + ac.end(), + [](const cv::Point& a, const cv::Point& b) -> bool { + return (a.x >= b.x) && (a.y >= b.y); + }); + + return ac[0]; +} + +cv::Point Rectification::getTopRight() +{ + assert(_areaCoordinates.size() == 4); + + std::vector ac(_areaCoordinates); + + std::sort(ac.begin(), + ac.end(), + [](const cv::Point& a, const cv::Point& b) -> bool { + return (a.x >= b.x) && (a.y <= b.y); + }); + + return ac[0]; +} + +cv::Mat Rectification::getSortedPoints() +{ + assert(_areaCoordinates.size() == 4); + return cv::Mat(_areaCoordinates); +} + +cv::Point Rectification::getCorrectedResolutionPoint(QPoint pos) +{ + return getCorrectedResolutionPoint(cv::Point(pos.x(), pos.y())); +} + +cv::Point Rectification::getCorrectedResolutionPoint(cv::Point pos) +{ + + int heightScaled = _frameDisplayHeightPx; + int widthScaled = _frameDisplayWidthPx; + + float scaleFactor = 1.0f; + + if (_camCaptureWidth_px > _frameDisplayWidthPx || + _camCaptureHeight_px > _frameDisplayHeightPx) { + scaleFactor = float(_camCaptureWidth_px) / float(_frameDisplayWidthPx); + + heightScaled = _camCaptureHeight_px / scaleFactor; + + if (_camCaptureWidth_px == _camCaptureHeight_px) { + if (heightScaled > _frameDisplayHeightPx) { + scaleFactor = float(_camCaptureHeight_px) / + float(_frameDisplayHeightPx); + + widthScaled = _camCaptureWidth_px / scaleFactor; + + assert(widthScaled <= _frameDisplayWidthPx); + } else { + if (heightScaled > _frameDisplayWidthPx) { + scaleFactor = float(_camCaptureHeight_px) / + float(_frameDisplayWidthPx); + + widthScaled = _camCaptureWidth_px / scaleFactor; + + assert(widthScaled <= _frameDisplayWidthPx); + } + } + } else { + if (heightScaled > _frameDisplayWidthPx) { + scaleFactor = float(_camCaptureHeight_px) / + float(_frameDisplayWidthPx); + + widthScaled = _camCaptureWidth_px / scaleFactor; + + assert(widthScaled <= _frameDisplayWidthPx); + } + } + } + + return cv::Point(int(float(pos.x) * scaleFactor), + int(float(pos.y) * scaleFactor)); +} \ No newline at end of file diff --git a/Src/Model/AreaDescriptor/Rectification.h b/Src/Model/AreaDescriptor/Rectification.h new file mode 100644 index 00000000..9c1949dc --- /dev/null +++ b/Src/Model/AreaDescriptor/Rectification.h @@ -0,0 +1,164 @@ +#pragma once + +#include +#include + +#include + +/** + * Rectification class normalizing the tracking image + */ +class Rectification +{ +public: + static Rectification& instance() + { + static Rectification _instance(100, + 100); // Guaranteed to be destroyed. + // Instantiated on first use. + return _instance; + } + + ~Rectification() + { + } + +private: + /** + * The standard constructor. + */ + Rectification(float w, float h); + + Rectification( + const Rectification&); /* verhindert, dass eine weitere Instanz via + Kopier-Konstruktor erstellt werden kann */ + + Rectification& operator=( + const Rectification&); // Verhindert weitere Instanz durch Kopie + +public: + void init(double areaHeight_cm, + double areaWidth_cm, + std::vector areaCoordinates, + int camCaptureWidth_px, + int camCaptureHeight_px, + int frameDisplayWidthPx, + int frameDisplayHeightPx); + + bool isSetup() + { + return _isSetup; + }; + + double areaWidth_cm() const + { + return _areaWidth_cm; + } + double areaHeight_cm() const + { + return _areaHeight_cm; + } + int captureWidth_px() const + { + return _camCaptureWidth_px; + } + int captureHeight_px() const + { + return _camCaptureHeight_px; + } + + bool inArea(cv::Point2f point_cm) const; + + /** + * Transform the provided pixel coordinates into world coordinates and + * return world coordinates. + * @param: pixelCoords, a list of points. + * @return: world coordinates in as a list. + */ + cv::Point2f pxToCm(cv::Point point_px) const; + cv::Point2f pxToCm(QPoint point_px) const; + + /** + * Transform the provided pixel point into world coordinates and return + * world point. + * @param: point, a pixel point, used opencv point + * @return: world point. + */ + cv::Point2f cmToPx(cv::Point2f point_cm) const; + + /** + * Sets the tank coordinates. + * @param: areaCoordinates, the coordinate list of the considered area. + * @return: void. + */ + void setArea(std::vector areaCoordinates); + void setArea(std::vector areaCoordinates); + + // infers the area coordinates from the data model + void setArea(); + std::vector getDefaultArena(); + void resetAreaCoordinates(); + + /** + * Sets the real world dimension the tank. + * @param: areaWidth_cm, width of the tank in cm, + * @param: areaHeight_cm, height of the tank in cm, + * @return: void. + */ + void setDimension(double areaWidth_cm, double areaHeight_cm); + + void setCamImageSize(cv::Size size) + { + _camCaptureWidth_px = size.width; + _camCaptureHeight_px = size.height; + } + + void initRecitification(double areaHeight_cm, double areaWidth_cm); + void setupRecitification(int frameDisplayWidthPx, + int frameDisplayHeightPx, + int camImageWidth, + int camImageHeight); + + std::vector area() const + { + return _areaCoordinates; + } + + int minXPx(); + int maxXPx(); + int minYPx(); + int maxYPx(); + + cv::Point getTopLeft(); + cv::Point getBottomLeft(); + cv::Point getBottomRight(); + cv::Point getTopRight(); + cv::Point getCorrectedResolutionPoint(QPoint pos); + cv::Point getCorrectedResolutionPoint(cv::Point pos); + cv::Mat getSortedPoints(); + +private: + std::vector _areaCoordinates; + std::vector _rectifiedAreaCoordinates; + + // Homography + cv::Mat_ _H; + cv::Mat_ _H_inv; + // some vector 3x1. Might be zero? TODO + mutable cv::Mat_ _q; + + int _camCaptureWidth_px; + int _camCaptureHeight_px; + + int _frameDisplayWidthPx; + int _frameDisplayHeightPx; + + double _areaWidth_cm; + double _areaHeight_cm; + + bool _isSetup; + + bool checkValidCoordinates(std::vector areaCoordinates, + int camCaptureHeight_px, + int camCaptureWidth_px); +}; diff --git a/BioTracker/CoreApp/BioTracker/Model/BioTracker3ProxyMat.cpp b/Src/Model/BioTracker3ProxyMat.cpp similarity index 97% rename from BioTracker/CoreApp/BioTracker/Model/BioTracker3ProxyMat.cpp rename to Src/Model/BioTracker3ProxyMat.cpp index 3b17de71..43480dc9 100644 --- a/BioTracker/CoreApp/BioTracker/Model/BioTracker3ProxyMat.cpp +++ b/Src/Model/BioTracker3ProxyMat.cpp @@ -1,2 +1 @@ #include "BioTracker3ProxyMat.h" - diff --git a/BioTracker/CoreApp/BioTracker/Model/BioTracker3ProxyMat.h b/Src/Model/BioTracker3ProxyMat.h similarity index 63% rename from BioTracker/CoreApp/BioTracker/Model/BioTracker3ProxyMat.h rename to Src/Model/BioTracker3ProxyMat.h index 6b96a336..1faf68c7 100644 --- a/BioTracker/CoreApp/BioTracker/Model/BioTracker3ProxyMat.h +++ b/Src/Model/BioTracker3ProxyMat.h @@ -1,10 +1,9 @@ /**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** Origin of this class is BioTracker in version 2. - ** - ****************************************************************************/ - + ** + ** This file is part of the BioTracker Framework + ** Origin of this class is BioTracker in version 2. + ** + ****************************************************************************/ #ifndef BIOTRACKER3PROXYMAT_H #define BIOTRACKER3PROXYMAT_H @@ -16,34 +15,40 @@ #include /** - * The BioTracker3ProxyMat class is currently not used in BioTracker. It is an old class of the BioTracker in version 2. + * The BioTracker3ProxyMat class is currently not used in BioTracker. It is an + * old class of the BioTracker in version 2. */ -class BioTracker3ProxyMat { - public: +class BioTracker3ProxyMat +{ +public: BioTracker3ProxyMat(cv::Mat const& mat) - : m_originalMat(mat) { + : m_originalMat(mat) + { } BioTracker3ProxyMat(const BioTracker3ProxyMat&) = delete; BioTracker3ProxyMat& operator=(const BioTracker3ProxyMat&) = delete; - cv::Mat& getMat() { + cv::Mat& getMat() + { if (!isModified()) { m_modifiedMat = m_originalMat.clone(); } return m_modifiedMat.get(); } - void setMat(cv::Mat mat) { + void setMat(cv::Mat mat) + { m_modifiedMat = mat; } - bool isModified() const { + bool isModified() const + { return m_modifiedMat.is_initialized(); } - private: - cv::Mat const& m_originalMat; +private: + cv::Mat const& m_originalMat; boost::optional m_modifiedMat; }; diff --git a/Src/Model/CoreParameter.cpp b/Src/Model/CoreParameter.cpp new file mode 100644 index 00000000..6f362538 --- /dev/null +++ b/Src/Model/CoreParameter.cpp @@ -0,0 +1,17 @@ +#include "CoreParameter.h" + +CoreParameter::CoreParameter(QObject* parent) +: IModel(parent) +{ + //_settings = + // BioTracker::Util::TypedSingleton::getInstance(CONFIGPARAM::CONFIG_INI_FILE); + //_settings = new BioTracker::Core::Settings(CONFIGPARAM::CONFIG_INI_FILE); + + Q_EMIT notifyView(); +} + +void CoreParameter::setTrackNumber(int number) +{ + m_trackNumber = number; + notifyView(); +} diff --git a/Src/Model/CoreParameter.h b/Src/Model/CoreParameter.h new file mode 100644 index 00000000..a6599e37 --- /dev/null +++ b/Src/Model/CoreParameter.h @@ -0,0 +1,65 @@ +#ifndef COREPARAMETER_H +#define COREPARAMETER_H + +#include "Interfaces/IModel/IModel.h" +#include "qcolor.h" + +/** + * This model includes the default visualization options the + * TrackedcomponentView uses to create its ComponentsShapes. Other shared + * paramters can also be added. It is a runtime shared storage. + */ +class CoreParameter : public IModel +{ + Q_OBJECT +public: + CoreParameter(QObject* parent = 0); + + // void setAll( + // bool viewSwitch, + // QString tracingStyle, + // int tracingHistory, + // int tracingSteps, + // QColor* colorBorder, + // QColor* colorBrush) + //{ + // m_viewSwitch = viewSwitch; + // m_tracingStyle = tracingStyle; + // m_tracingHistory = tracingHistory; + // m_tracingSteps = tracingSteps; + // m_colorBorder = colorBorder; + // m_colorBrush = colorBrush; + + // Q_EMIT notifyView(); + //}; + void setTrackNumber(int number); + +public: + bool m_viewSwitch = true; + bool m_antialiasingEntities = false; + bool m_antialiasingFull = false; + + // Tracing + QString m_tracingStyle = "No tracing"; + int m_tracingHistory = 20; + int m_tracingSteps = 1; + QString m_tracingTimeDegradation = "None"; + double m_tracerProportions = 0.5; + bool m_tracerOrientationLine = false; + bool m_tracerFrameNumber = false; + // Track dimensions + int m_trackWidth = 30; + int m_trackHeight = 20; + // Track misc + bool m_trackOrientationLine = true; + bool m_trackShowId = false; + // Track color + QColor* m_colorBorder = new QColor(Qt::black); + QColor* m_colorBrush = new QColor(Qt::green); + // Track count + int m_trackNumber = 0; + // Ignore zooming + bool m_ignoreZoom = false; +}; + +#endif // COREPARAMETER_H diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterCSV.cpp b/Src/Model/DataExporters/DataExporterCSV.cpp similarity index 52% rename from BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterCSV.cpp rename to Src/Model/DataExporters/DataExporterCSV.cpp index d116e1c5..c0796d99 100644 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterCSV.cpp +++ b/Src/Model/DataExporters/DataExporterCSV.cpp @@ -1,29 +1,28 @@ #include "DataExporterCSV.h" -#include "Controller/ControllerDataExporter.h" #include "util/types.h" -#include "util/misc.h" +#include "Utility/misc.h" #include #include #include -DataExporterCSV::DataExporterCSV(QObject *parent) : - DataExporterGeneric(parent) +using namespace BioTrackerUtilsMisc; // split + +DataExporterCSV::DataExporterCSV(QObject* parent) +: DataExporterGeneric(parent) { - _root = 0; - BioTracker::Core::Settings *settings = BioTracker::Util::TypedSingleton::getInstance(CORE_CONFIGURATION); - _separator = settings->getValueOrDefault(CFG_SER_CSVSEP, CFG_SER_CSVSEP_VAL); + _root = nullptr; + _separator = _cfg->CsvSeperator.toStdString(); } - DataExporterCSV::~DataExporterCSV() { } -//https://codereview.stackexchange.com/questions/29611/finding-the-number-of-occurrences-of-a-string-in-another-string +// https://codereview.stackexchange.com/questions/29611/finding-the-number-of-occurrences-of-a-string-in-another-string int DataExporterCSV::key_search(const std::string& s, const std::string& key) { - int count = 0; - size_t pos = 0; + int count = 0; + size_t pos = 0; while ((pos = s.find(key, pos)) != std::string::npos) { ++count; ++pos; @@ -31,14 +30,13 @@ int DataExporterCSV::key_search(const std::string& s, const std::string& key) return count; } - -std::vector DataExporterCSV::getHeaderElements(IModelTrackedComponent *comp) { +std::vector DataExporterCSV::getHeaderElements( + IModelTrackedComponent* comp) +{ std::vector ret; - for (int i = 0; imetaObject()->propertyCount(); ++i) - { - if (comp->metaObject()->property(i).isStored(comp)) - { + for (int i = 0; i < comp->metaObject()->propertyCount(); ++i) { + if (comp->metaObject()->property(i).isStored(comp)) { if (!comp->metaObject()->property(i).isStored()) { continue; } @@ -49,15 +47,14 @@ std::vector DataExporterCSV::getHeaderElements(IModelTrackedCompone return ret; } -std::string DataExporterCSV::getHeader(IModelTrackedComponent *comp, int cnt) { +std::string DataExporterCSV::getHeader(IModelTrackedComponent* comp, int cnt) +{ std::stringstream ss; ss << "FRAME" << _separator << "MillisecsByFPS"; for (int c = 0; c < cnt; c++) { - for (int i = 0; imetaObject()->propertyCount(); ++i) - { - if (comp->metaObject()->property(i).isStored(comp)) - { + for (int i = 0; i < comp->metaObject()->propertyCount(); ++i) { + if (comp->metaObject()->property(i).isStored(comp)) { if (!comp->metaObject()->property(i).isStored()) { continue; } @@ -71,14 +68,14 @@ std::string DataExporterCSV::getHeader(IModelTrackedComponent *comp, int cnt) { } /* Writes a tracked component to string -*/ -std::string DataExporterCSV::writeComponentCSV(IModelTrackedComponent* comp, int tid) { + */ +std::string DataExporterCSV::writeComponentCSV(IModelTrackedComponent* comp, + int tid) +{ std::stringstream ss; - for (int i = 0; imetaObject()->propertyCount(); ++i) - { - if (comp->metaObject()->property(i).isStored(comp)) - { + for (int i = 0; i < comp->metaObject()->propertyCount(); ++i) { + if (comp->metaObject()->property(i).isStored(comp)) { if (!comp->metaObject()->property(i).isStored()) { continue; } @@ -87,9 +84,9 @@ std::string DataExporterCSV::writeComponentCSV(IModelTrackedComponent* comp, int continue; } std::string str = comp->metaObject()->property(i).name(); - QVariant v = comp->metaObject()->property(i).read(comp); + QVariant v = comp->metaObject()->property(i).read(comp); std::string val = v.toString().toStdString(); - val = (val == "" ? "0" : val); + val = (val == "" ? "0" : val); ss << _separator << val; } } @@ -97,26 +94,33 @@ std::string DataExporterCSV::writeComponentCSV(IModelTrackedComponent* comp, int return ss.str(); } -void DataExporterCSV::setProperty(IModelTrackedComponent* comp, std::string key, std::string val) { - QString qval = QString(val.c_str()); +void DataExporterCSV::setProperty(IModelTrackedComponent* comp, + std::string key, + std::string val) +{ + QString qval = QString(val.c_str()); QVariant v(qval); comp->setProperty(key.c_str(), v); } -void DataExporterCSV::addChildOfChild(IModelTrackedTrajectory *root, IModelTrackedComponent* child, IModelTrackedComponentFactory* factory, int idx) { - IModelTrackedTrajectory *traj = dynamic_cast(root->getChild(child->getId())); +void DataExporterCSV::addChildOfChild(IModelTrackedTrajectory* root, + IModelTrackedComponent* child, + IModelTrackedComponentFactory* factory, + int idx) +{ + IModelTrackedTrajectory* traj = dynamic_cast( + root->getChild(child->getId())); if (traj) { traj->add(child, idx); - } - else - { - traj = static_cast(factory->getNewTrackedTrajectory("0")); + } else { + traj = static_cast( + factory->getNewTrackedTrajectory("0")); traj->setValid(false); traj->add(child, idx); root->add(traj, child->getId()); } - + traj->setValid(child->getValid()); } @@ -129,21 +133,24 @@ void DataExporterCSV::loadFile(std::string file) getline(ifs, line); } - //parse header - ControllerDataExporter *ctr = dynamic_cast(_parent); - IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() : nullptr; + // parse header + ControllerDataExporter* ctr = dynamic_cast( + _parent); + IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() + : nullptr; if (!factory) { return; } - IModelTrackedComponent* dummy = static_cast(factory->getNewTrackedElement("0")); + IModelTrackedComponent* dummy = static_cast( + factory->getNewTrackedElement("0")); std::vector headerElsStr = getHeaderElements(dummy); - int headerEls = headerElsStr.size(); + int headerEls = static_cast(headerElsStr.size()); std::vector strs; split(line, strs, _separator[0]); - int idcnt = (strs.size() - 2) / headerEls; + int idcnt = (static_cast(strs.size()) - 2) / headerEls; - //Add data lines + // Add data lines while (!ifs.eof()) { getline(ifs, line); @@ -152,13 +159,15 @@ void DataExporterCSV::loadFile(std::string file) if (strs.size() < 2) continue; - //First two entries are the "global header" (trajectory info, same for all at current timeslice) - int frame = atoi(strs[0].c_str()); + // First two entries are the "global header" (trajectory info, same for + // all at current timeslice) + int frame = atoi(strs[0].c_str()); float frameById = atof(strs[1].c_str()); - //the current trajectory/element pair - int curTrajCnt = 0; - IModelTrackedComponent* comp = static_cast(factory->getNewTrackedElement("0")); + // the current trajectory/element pair + int curTrajCnt = 0; + IModelTrackedComponent* comp = static_cast( + factory->getNewTrackedElement("0")); for (int x = 2; x < strs.size(); x++) { setProperty(comp, headerElsStr[curTrajCnt], strs[x].c_str()); @@ -167,30 +176,34 @@ void DataExporterCSV::loadFile(std::string file) if (curTrajCnt >= headerEls) { curTrajCnt = 0; addChildOfChild(_root, comp, factory, frame); - comp = static_cast(factory->getNewTrackedElement("0")); + comp = static_cast( + factory->getNewTrackedElement("0")); } } - //addChildOfChild(_root, comp, factory, frame); + // addChildOfChild(_root, comp, factory, frame); } } -void DataExporterCSV::write(int idx) { +void DataExporterCSV::write(int idx) +{ if (!_root) { qDebug() << "CORE: No output opened!"; return; } - //TODO there is some duplicated code here + // TODO there is some duplicated code here _ofs << std::to_string(idx) - << _separator + std::to_string((long long)((((double)idx) / _fps) * 1000)); + << _separator + + std::to_string((long long) ((((double) idx) / _fps) * 1000)); - //Write single trajectory + // Write single trajectory int trajNumber = 0; for (int i = 0; i < _root->size(); i++) { - IModelTrackedTrajectory *t = dynamic_cast(_root->getChild(i)); + IModelTrackedTrajectory* t = dynamic_cast( + _root->getChild(i)); if (t) { - IModelTrackedPoint *e; + IModelTrackedPoint* e; if (idx == -1) e = dynamic_cast(t->getLastChild()); else @@ -204,16 +217,18 @@ void DataExporterCSV::write(int idx) { _ofs << std::endl; } -void DataExporterCSV::finalizeAndReInit() { +void DataExporterCSV::finalizeAndReInit() +{ - close(); //Not needed, but... + close(); // Not needed, but... writeAll(); cleanup(); open(_root); } -void DataExporterCSV::writeAll(std::string f) { - //Sanity +void DataExporterCSV::writeAll(std::string f) +{ + // Sanity if (!_root) { qDebug() << "CORE: No output opened!"; return; @@ -222,12 +237,11 @@ void DataExporterCSV::writeAll(std::string f) { _ofs.close(); } - //Find max length of all tracks + // Find max length of all tracks int max = getMaxLinecount(); - //There is nothing to write - if (max <= 0) - { + // There is nothing to write + if (max <= 0) { cleanup(); return; } @@ -239,47 +253,51 @@ void DataExporterCSV::writeAll(std::string f) { if (target.substr(target.size() - 4) != ".csv") target += ".csv"; - //Create final file - std::ofstream o; + // Create final file + std::ofstream o; o.open(target, std::ofstream::out); - //write metadata - ControllerDataExporter *ctr = dynamic_cast(_parent); + // write metadata + ControllerDataExporter* ctr = dynamic_cast( + _parent); SourceVideoMetadata d = ctr->getSourceMetadata(); o << "# Source name: " << d.name << std::endl; o << "# Source FPS: " << d.fps << std::endl; QVariant vv(QDateTime::currentDateTime()); o << "# Generation time: " << vv.toString().toStdString() << std::endl; - //write header - int vcount = _root->validCount(); - IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() : nullptr; - int headerCount = 0; + // write header + int vcount = _root->validCount(); + IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() + : nullptr; + int headerCount = 0; if (factory != nullptr) { - IModelTrackedComponent *ptraj = static_cast(factory->getNewTrackedElement("0")); + IModelTrackedComponent* ptraj = static_cast( + factory->getNewTrackedElement("0")); std::string header = getHeader(ptraj, vcount); - headerCount = getHeaderElements(ptraj).size(); + headerCount = static_cast(getHeaderElements(ptraj).size()); o << header << "\n"; delete ptraj; } - - //Write out everything to a new file + // Write out everything to a new file int trajNumber = 0; - //idx is the frame number + // idx is the frame number for (int idx = 0; idx < max; idx++) { o << std::to_string(idx) - << _separator + std::to_string((((float)idx) / _fps) * 1000); + << _separator + std::to_string((((float) idx) / _fps) * 1000); int linecnt = 0; - //i is the track number + // i is the track number for (int i = 0; i < _root->size(); i++) { - IModelTrackedTrajectory *t = dynamic_cast(_root->getChild(i)); + IModelTrackedTrajectory* t = + dynamic_cast(_root->getChild(i)); if (t && t->validCount() > 0) { - IModelTrackedPoint *e = dynamic_cast(t->getChild(idx)); + IModelTrackedPoint* e = dynamic_cast( + t->getChild(idx)); if (e) { std::string line = writeComponentCSV(e, trajNumber); o << line; @@ -290,7 +308,7 @@ void DataExporterCSV::writeAll(std::string f) { } int count = _root->validCount(); while (linecnt < count) { - for (int i = 0; isize() == 0) { - //Remove temporary file - QFile file(_tmpFile.c_str()); - file.remove(); - } + // Remove temporary file + QFile file(_tmpFile.c_str()); + file.remove(); } diff --git a/Src/Model/DataExporters/DataExporterCSV.h b/Src/Model/DataExporters/DataExporterCSV.h new file mode 100644 index 00000000..215bc737 --- /dev/null +++ b/Src/Model/DataExporters/DataExporterCSV.h @@ -0,0 +1,82 @@ +#pragma once +#include "DataExporterGeneric.h" + +class DataExporterCSV : public DataExporterGeneric +{ + Q_OBJECT +public: + DataExporterCSV(QObject* parent = 0); + ~DataExporterCSV(); + + /** + * Add a single frame index to the output file + * @param Index to write or -1 for latest + */ + void write(int idx = -1) override; + + /** + * Re-Serialize the entire structure in a clean fashion + */ + void writeAll(std::string f = "") override; + + /** + * Close the file + */ + void close() override; + + void loadFile(std::string file) override; + + /** + * Effectively a writeAll, close and open. + */ + void finalizeAndReInit() override; + + QString getSuffix() + { + return ".csv"; + }; + +private: + /** + * helper function to generate a part of an output line + */ + std::string writeTrackpoint(IModelTrackedPoint* e, int trajNumber); + + std::string _separator; + + /* finding the number of occurrences of a string in another strin + * + * https://codereview.stackexchange.com/questions/29611/finding-the-number-of-occurrences-of-a-string-in-another-string + */ + int key_search(const std::string& s, const std::string& key); + + /* Get's the names of all stored properties. + * + * Useful for corresponding them with CSV headers. order relevant. + * returns Individual1 + */ + std::vector getHeaderElements(IModelTrackedComponent* comp); + + /* Get's the header as one connected string + * + * Similar getHeaderElements, but for all components and having all + * elements of the return vector concatenated returns + * GlobalHeaders,Individual1,Indiviual2,... + */ + std::string getHeader(IModelTrackedComponent* comp, int cnt); + + /* Sets sets a property to a components. + */ + void setProperty(IModelTrackedComponent* comp, + std::string key, + std::string val); + + /* Writes a tracked component to string + */ + std::string writeComponentCSV(IModelTrackedComponent* comp, int tid); + + void addChildOfChild(IModelTrackedTrajectory* root, + IModelTrackedComponent* child, + IModelTrackedComponentFactory* factory, + int idx); +}; diff --git a/Src/Model/DataExporters/DataExporterGeneric.cpp b/Src/Model/DataExporters/DataExporterGeneric.cpp new file mode 100644 index 00000000..ce5f0d20 --- /dev/null +++ b/Src/Model/DataExporters/DataExporterGeneric.cpp @@ -0,0 +1,67 @@ +#include "DataExporterGeneric.h" +#include "util/types.h" +#include "Utility/misc.h" +#include +#include +#include + +DataExporterGeneric::DataExporterGeneric(QObject* parent) +: IModelDataExporter(parent) +{ + _parent = static_cast(parent); + _cfg = static_cast(parent)->getConfig(); + _root = 0; +} + +void DataExporterGeneric::open(IModelTrackedTrajectory* root) +{ + _root = root; + + _tmpFile = _parent->generateBasename(true).toStdString() + ".tmp" + + getSuffix().toStdString(); + _finalFile = _parent->generateBasename(false).toStdString() + + getSuffix().toStdString(); + _ofs.open(_tmpFile, std::ofstream::out); +} + +int DataExporterGeneric::getMaxLinecount() +{ + if (_root == nullptr) + return 0; + + int max = 0; + for (int i = 0; i < _root->size(); i++) { + IModelTrackedTrajectory* t = dynamic_cast( + _root->getChild(i)); + if (t) + max = std::max(t->size(), max); + } + + return max; +} + +void DataExporterGeneric::cleanup() +{ + int s = _root->size(); + + // Erase all tracking data from the tracking structure! + _root->clear(); + + // Remove temporary file + QFile file(_tmpFile.c_str()); + file.remove(); + + if (s > 0) { + // Tell the controller about the written file + QFileInfo fi(_finalFile.c_str()); + fileWritten(fi); + } + return; +} + +void DataExporterGeneric::finalize() +{ + close(); + writeAll(""); + cleanup(); +}; diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterGeneric.h b/Src/Model/DataExporters/DataExporterGeneric.h similarity index 61% rename from BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterGeneric.h rename to Src/Model/DataExporters/DataExporterGeneric.h index 34e9627a..9507d139 100644 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterGeneric.h +++ b/Src/Model/DataExporters/DataExporterGeneric.h @@ -3,39 +3,40 @@ #include "Interfaces/IModel/IModelTrackedTrajectory.h" #include "Interfaces/IModel/IModelTrackedComponent.h" #include "Interfaces/IModel/IModelTrackedComponentFactory.h" +#include "Controller/ControllerDataExporter.h" +#include "util/Config.h" #include #include class DataExporterGeneric : public IModelDataExporter { - Q_OBJECT + Q_OBJECT public: - DataExporterGeneric(QObject *parent = 0); + DataExporterGeneric(QObject* parent = 0); - /** + /** * Opens a file for writing the passed tracking structure * @param root Pointer to the tracking structure - */ - void open(IModelTrackedTrajectory *root) override; + */ + void open(IModelTrackedTrajectory* root) override; void finalize() override; protected: - int getMaxLinecount(); void cleanup(); - QObject *_parent = nullptr; + ControllerDataExporter* _parent = nullptr; + Config* _cfg; std::ofstream _ofs; - //Name of the temporary file to write to + // Name of the temporary file to write to std::string _tmpFile; - //Name of the final file, holding a clean representation of the structure. + // Name of the final file, holding a clean representation of the structure. std::string _finalFile; -private: +private: }; - diff --git a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterJson.cpp b/Src/Model/DataExporters/DataExporterJson.cpp similarity index 53% rename from BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterJson.cpp rename to Src/Model/DataExporters/DataExporterJson.cpp index 0a3337ed..c055655b 100644 --- a/BioTracker/CoreApp/BioTracker/Model/DataExporters/DataExporterJson.cpp +++ b/Src/Model/DataExporters/DataExporterJson.cpp @@ -1,12 +1,11 @@ #include "DataExporterJson.h" #include "util/types.h" -#include "util/misc.h" +#include "Utility/misc.h" #include #include #include "Controller/ControllerDataExporter.h" - #include #include #include @@ -15,36 +14,39 @@ #include #include #include +#include +#include - - -namespace DataExporterJsonUtil { +namespace DataExporterJsonUtil +{ template - static T preprocess_value(T &¶mValue) { + static T preprocess_value(T&& paramValue) + { return std::forward(paramValue); } /* Writes a tracked component to a property tree for json serialization - */ - void writeComponentJson(IModelTrackedComponent* comp, boost::property_tree::ptree *pt) { + */ + void writeComponentJson(IModelTrackedComponent* comp, + boost::property_tree::ptree* pt) + { - for (int i = 0; imetaObject()->propertyCount(); ++i) - { - if (comp->metaObject()->property(i).isStored(comp)) - { + for (int i = 0; i < comp->metaObject()->propertyCount(); ++i) { + if (comp->metaObject()->property(i).isStored(comp)) { if (!comp->metaObject()->property(i).isStored()) { continue; } std::string str = comp->metaObject()->property(i).name(); - QVariant v = comp->metaObject()->property(i).read(comp); + QVariant v = comp->metaObject()->property(i).read(comp); pt->put(str, v.toString().toStdString()); } } } /* Helper function to extract a suffix number from a string - */ - int getId(std::string fst, std::string prefix) { + */ + int getId(std::string fst, std::string prefix) + { if (fst.size() < prefix.size()) return -1; @@ -58,78 +60,87 @@ namespace DataExporterJsonUtil { } /* Helper function to set elements - */ - void setElemProperty(boost::property_tree::ptree *tree, std::string key, IModelTrackedComponent* comp) { - QString val = QString(tree->data().c_str()); + */ + void setElemProperty(boost::property_tree::ptree* tree, + std::string key, + IModelTrackedComponent* comp) + { + QString val = QString(tree->data().c_str()); std::string check = val.toStdString(); - QVariant v(val); + QVariant v(val); comp->setProperty(key.c_str(), v); } /* Recursion to write the tracked component tree into a boost property tree - */ + */ void populateLevel( IModelTrackedComponent* comp, - boost::property_tree::basic_ptree> *pt, + boost::property_tree:: + basic_ptree>* pt, IModelTrackedComponentFactory* factory, - std::deque prefixes) + std::deque prefixes) { - //Check the prefixes (are the children leafs or nodes?) + // Check the prefixes (are the children leafs or nodes?) std::string prefix = ""; if (prefixes.size() > 0) { prefix = prefixes.front(); prefixes.pop_front(); } - //Iterate children + // Iterate children for (auto it : *pt) { - //Get ID if any + // Get ID if any int id = getId(it.first, prefix); - //Check if there is a subtree + // Check if there is a subtree if (it.second.size() > 0) { - //This is a valid subtree + // This is a valid subtree if (prefixes.size() > 0) { - IModelTrackedTrajectory *child = static_cast(factory->getNewTrackedTrajectory("0")); + IModelTrackedTrajectory* child = + static_cast( + factory->getNewTrackedTrajectory("0")); populateLevel(child, &(it.second), factory, prefixes); - static_cast(comp)->add(child, id); + static_cast(comp)->add(child, + id); } - //This is a leaf node with only properties beneath + // This is a leaf node with only properties beneath else { - IModelTrackedComponent *node = static_cast(factory->getNewTrackedElement("0")); + IModelTrackedComponent* node = + static_cast( + factory->getNewTrackedElement("0")); populateLevel(node, &(it.second), factory, prefixes); static_cast(comp)->add(node, id); } } - //Found a property and assigning it + // Found a property and assigning it else { setElemProperty(&(it.second), it.first, comp); } } - } } -DataExporterJson::DataExporterJson(QObject *parent) : - DataExporterGeneric(parent) +DataExporterJson::DataExporterJson(QObject* parent) +: DataExporterGeneric(parent) { _root = 0; } - DataExporterJson::~DataExporterJson() { - //delete _root; + // delete _root; } -std::string DataExporterJson::writeTrackpoint(IModelTrackedPoint *e, int trajNumber) { +std::string DataExporterJson::writeTrackpoint(IModelTrackedPoint* e, + int trajNumber) +{ std::stringstream ss; - return ss.str(); } -void DataExporterJson::write(int idx) { +void DataExporterJson::write(int idx) +{ if (!_root) { qDebug() << "CORE: No output opened!"; return; @@ -138,36 +149,36 @@ void DataExporterJson::write(int idx) { _ofs << std::endl; } -void DataExporterJson::finalizeAndReInit() { - close(); //Not needed, but... +void DataExporterJson::finalizeAndReInit() +{ + close(); // Not needed, but... writeAll(); cleanup(); open(_root); } -void DataExporterJson::loadFile(std::string file) { +void DataExporterJson::loadFile(std::string file) +{ boost::property_tree::ptree ptRoot; boost::property_tree::read_json(file, ptRoot); - ControllerDataExporter *ctr = dynamic_cast(_parent); - IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() : nullptr; + ControllerDataExporter* ctr = _parent; + IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() + : nullptr; if (!factory) { return; } - //ID's of entities are managed via prefix+enumeration - std::deque prefixes = { "Trajectory_", "Element_" }; + // ID's of entities are managed via prefix+enumeration + std::deque prefixes = {"Trajectory_", "Element_"}; - //Recursively reads the json - DataExporterJsonUtil::populateLevel( - _root, - &ptRoot, - factory, - prefixes); + // Recursively reads the json + DataExporterJsonUtil::populateLevel(_root, &ptRoot, factory, prefixes); }; -void DataExporterJson::writeAll(std::string f) { - //Sanity +void DataExporterJson::writeAll(std::string f) +{ + // Sanity if (!_root) { qDebug() << "CORE: No output opened!"; return; @@ -188,38 +199,41 @@ void DataExporterJson::writeAll(std::string f) { if (target.substr(target.size() - 4) != ".json") target += ".json"; - boost::property_tree::ptree ptRoot; + boost::property_tree::ptree ptRoot; DataExporterJsonUtil::writeComponentJson(_root, &ptRoot); - - //go through all trajectories - for (int i = 0; i < _root->size(); i++) { - IModelTrackedTrajectory *t = static_cast(_root->getChild(i)); + + // go through all trajectories + for (int i = 0; i < _root->size(); i++) { + IModelTrackedTrajectory* t = static_cast( + _root->getChild(i)); boost::property_tree::ptree ptt; DataExporterJsonUtil::writeComponentJson(t, &ptt); ////i is the track number for (int idx = 0; idx < t->size(); idx++) { - IModelTrackedComponent *e = static_cast(t->getChild(idx)); + IModelTrackedComponent* e = static_cast( + t->getChild(idx)); - //If the node exists (i.e. not NULL) then it to the property tree + // If the node exists (i.e. not NULL) then it to the property tree if (e) { boost::property_tree::ptree pte; DataExporterJsonUtil::writeComponentJson(e, &pte); - ptt.put_child("Element_"+std::to_string(idx), pte); + ptt.put_child("Element_" + std::to_string(idx), pte); } } - //Insert the trajectory into the tree + // Insert the trajectory into the tree ptRoot.put_child("Trajectory_" + std::to_string(i), ptt); - } + } write_json(target, ptRoot); } -void DataExporterJson::close() { +void DataExporterJson::close() +{ _ofs.close(); - if ((!_root || _root->size() == 0) &&_tmpFile!="" ) { - //Remove temporary file + if ((!_root || _root->size() == 0) && _tmpFile != "") { + // Remove temporary file QFile file(_tmpFile.c_str()); file.remove(); } diff --git a/Src/Model/DataExporters/DataExporterJson.h b/Src/Model/DataExporters/DataExporterJson.h new file mode 100644 index 00000000..f0decebb --- /dev/null +++ b/Src/Model/DataExporters/DataExporterJson.h @@ -0,0 +1,45 @@ +#pragma once + +#include "DataExporterGeneric.h" + +class DataExporterJson : public DataExporterGeneric +{ + Q_OBJECT +public: + DataExporterJson(QObject* parent = 0); + ~DataExporterJson(); + + /** + * Add a single frame index to the output file + * @param Index to write or -1 for latest + */ + void write(int idx = -1) override; + + /** + * Re-Serialize the entire structure in a clean fashion + */ + void writeAll(std::string f = "") override; + + /** + * Close the file + */ + void close() override; + + void loadFile(std::string file) override; + + /** + * Effectively a writeAll, close and open. + */ + void finalizeAndReInit() override; + + QString getSuffix() + { + return ".json"; + }; + +private: + /** + * helper function to generate a part of an output line + */ + std::string writeTrackpoint(IModelTrackedPoint* e, int trajNumber); +}; diff --git a/Src/Model/DataExporters/DataExporterSerialize.cpp b/Src/Model/DataExporters/DataExporterSerialize.cpp new file mode 100644 index 00000000..aa973424 --- /dev/null +++ b/Src/Model/DataExporters/DataExporterSerialize.cpp @@ -0,0 +1,172 @@ +#include "DataExporterSerialize.h" +#include "util/types.h" +#include "Utility/misc.h" +#include +#include + +#include +#include +#include +#include + +#include "Controller/ControllerDataExporter.h" + +DataExporterSerialize::DataExporterSerialize(QObject* parent) +: DataExporterGeneric(parent) +{ + _root = 0; +} + +DataExporterSerialize::~DataExporterSerialize() +{ +} + +std::string DataExporterSerialize::writeTrackpoint(IModelTrackedPoint* e, + int trajNumber) +{ + std::stringstream ss; + + return ss.str(); +} + +void DataExporterSerialize::write(int idx) +{ + if (!_root) { + qDebug() << "CORE: No output opened!"; + return; + } + + _ofs << std::endl; +} + +void DataExporterSerialize::finalizeAndReInit() +{ + close(); // Not needed, but... + writeAll(); + cleanup(); + open(_root); +} + +void DataExporterSerialize::loadFile(std::string file) +{ + + ControllerDataExporter* ctr = _parent; + IModelTrackedComponentFactory* factory = ctr ? ctr->getComponentFactory() + : nullptr; + if (!factory) { + return; + } + + QFile f(file.c_str()); + f.open(QIODevice::ReadOnly); + QDataStream in(&f); + + IModelTrackedTrajectory* root = _root; + in >> *root; + int children = -1; + in >> children; + + std::vector childids; + for (int i = 0; i < children; i++) { + IModelTrackedTrajectory* child = static_cast( + factory->getNewTrackedTrajectory("0")); + in >> *child; + childids.push_back(child->getId()); + root->add(child, child->getId()); + } + + // i is the track number + for (int i = 0; i < childids.size(); i++) { + IModelTrackedTrajectory* curTraj = + static_cast(root->getChild(childids[i])); + int trajSize = -1; + in >> trajSize; + // idx is the frame number + for (int idx = 0; idx < trajSize; idx++) { + IModelTrackedComponent* e = factory->getNewTrackedElement("0"); + int cid = 0; + in >> cid; + in >> *e; + curTraj->add(e, cid); + } + } +}; + +void DataExporterSerialize::writeAll(std::string f) +{ + // Sanity + if (!_root) { + qDebug() << "CORE: No output opened!"; + return; + } + if (_ofs.is_open()) { + _ofs.close(); + } + + if (getMaxLinecount() <= 1) { + cleanup(); + return; + } + + std::string target = f; + if (target.size() <= 1) { + target = _finalFile; + } + if (target.substr(target.size() - 4) != ".dat") + target += ".dat"; + + // Create final file + QFile file(target.c_str()); + file.open(QIODevice::WriteOnly); + QDataStream out(&file); + + // serialize tree nodes (!= leafs) + out << *_root; + out << _root->size(); + for (int i = 0; i < _root->size(); i++) { + IModelTrackedTrajectory* t = dynamic_cast( + _root->getChild(i)); + out << *t; + } + + // i is the track number + for (int i = 0; i < _root->size(); i++) { + IModelTrackedTrajectory* t = dynamic_cast( + _root->getChild(i)); + + int cnt = 0; + for (int idx = 0; idx < t->size(); idx++) { + if (t) { + IModelTrackedComponent* e = + dynamic_cast(t->getChild(idx)); + if (e) { + cnt++; + } + } + } + out << cnt; + + // idx is the frame number + for (int idx = 0; idx < t->size(); idx++) { + if (t) { + IModelTrackedComponent* e = + dynamic_cast(t->getChild(idx)); + if (e) { + out << idx; + out << *e; + } + } + } + } +} + +void DataExporterSerialize::close() +{ + _ofs.close(); + + if ((!_root || _root->size() == 0) && _tmpFile != "") { + // Remove temporary file + QFile file(_tmpFile.c_str()); + file.remove(); + } +} diff --git a/Src/Model/DataExporters/DataExporterSerialize.h b/Src/Model/DataExporters/DataExporterSerialize.h new file mode 100644 index 00000000..09eb27b8 --- /dev/null +++ b/Src/Model/DataExporters/DataExporterSerialize.h @@ -0,0 +1,45 @@ +#pragma once + +#include "DataExporterGeneric.h" + +class DataExporterSerialize : public DataExporterGeneric +{ + Q_OBJECT +public: + DataExporterSerialize(QObject* parent = 0); + ~DataExporterSerialize(); + + /** + * Add a single frame index to the output file + * @param Index to write or -1 for latest + */ + void write(int idx = -1) override; + + /** + * Re-Serialize the entire structure in a clean fashion + */ + void writeAll(std::string f = "") override; + + /** + * Close the file + */ + void close() override; + + void loadFile(std::string file) override; + + /** + * Effectively a writeAll, close and open. + */ + void finalizeAndReInit() override; + + QString getSuffix() + { + return ".dat"; + }; + +private: + /** + * helper function to generate a part of an output line + */ + std::string writeTrackpoint(IModelTrackedPoint* e, int trajNumber); +}; diff --git a/Src/Model/ImageStream.cpp b/Src/Model/ImageStream.cpp new file mode 100644 index 00000000..52fb04cb --- /dev/null +++ b/Src/Model/ImageStream.cpp @@ -0,0 +1,771 @@ +#include "ImageStream.h" + +#include "util/stdext.h" +#include // assert +#include // std::invalid_argument +#include +#include +#include +#include + +#include + +#include "util/Exceptions.h" +#include "QSharedPointer" +#include "Utility/misc.h" +#include "View/CameraDevice.h" +#include "util/VideoCoder.h" + +#include "Controller/IControllerCfg.h" + +#if HAS_PYLON + #include "util/camera/pylon.h" + #include +#endif +#include + +namespace BioTracker +{ + namespace Core + { + + ImageStream::ImageStream(QObject* parent, Config* cfg) + : QObject(parent) + , m_current_frame(cv::Mat(cv::Size(0, 0), CV_8UC3)) + , m_current_frame_number(0) + { + _cfg = cfg; + if (cfg) + m_frame_stride = cfg->FrameStride; + } + + size_t ImageStream::currentFrameNumber() const + { + return m_current_frame_number; + } + + cv::Mat ImageStream::currentFrame() const + { + return m_current_frame; + } + + bool ImageStream::setFrameNumber(size_t frame_number) + { + // valid new frame number + if (frame_number < this->numFrames()) { + // skip update if frame number doesn't change + if (frame_number == this->currentFrameNumber()) { + return true; + } else { + const bool success = this->setFrameNumber_impl( + frame_number); + m_current_frame_number = frame_number; + return success; + } + } + // invalid new frame number + else { + this->clearImage(); + return false; + } + } + + bool ImageStream::lastFrame() const + { + return this->currentFrameNumber() + 1 == this->numFrames(); + } + + bool ImageStream::end() const + { + return (this->currentFrameNumber() >= this->numFrames() && + this->numFrames() >= 0); + } + + bool ImageStream::currentFrameIsEmpty() const + { + return this->currentFrame().empty(); + } + + bool ImageStream::nextFrame() + { + const size_t new_frame_number = this->currentFrameNumber() + + m_frame_stride; + if (new_frame_number < this->numFrames()) { + const bool success = this->nextFrame_impl(); + m_current_frame_number = new_frame_number; + return success; + } else { + this->clearImage(); + return false; + } + } + + bool ImageStream::previousFrame() + { + if (this->currentFrameNumber() > 0) { + const size_t new_frame_numer = this->currentFrameNumber() - 1; + const bool success = this->previousFrame_impl(); + m_current_frame_number = new_frame_numer; + return success; + } else { + this->clearImage(); + return false; + } + } + + void ImageStream::set_current_frame(cv::Mat img) + { + m_current_frame = img; + } + + void ImageStream::clearImage() + { + m_current_frame = cv::Mat(cv::Size(0, 0), CV_8UC3); + m_current_frame_number = this->numFrames(); + } + + bool ImageStream::nextFrame_impl() + { + assert(this->currentFrameNumber() + 1 < this->numFrames()); + const size_t new_frame_number = this->currentFrameNumber() + 1; + return this->setFrameNumber_impl(new_frame_number); + } + + bool ImageStream::previousFrame_impl() + { + assert(this->currentFrameNumber() > 0); + const size_t new_frame_number = this->currentFrameNumber() - 1; + return this->setFrameNumber_impl(new_frame_number); + } + + bool ImageStream::hasNextInBatch() + { + return false; + } + + void ImageStream::stepToNextInBatch() + { + } + + std::vector ImageStream::getBatchItems() + { + return {}; + } + + ImageStream::~ImageStream() = default; + + /*********************************************************/ + + class ImageStream3NoMedia : public ImageStream + { + public: + explicit ImageStream3NoMedia() = default; + virtual GuiParam::MediaType type() const override + { + return GuiParam::MediaType::NoMedia; + } + virtual size_t numFrames() const override + { + return 0; + } + virtual bool toggleRecord() override + { + return false; + } + virtual double fps() const override + { + return 1.0; + } + virtual std::string currentFilename() const override + { + return "No Media"; // TODO make this nicer.. + } + + private: + virtual bool setFrameNumber_impl(size_t) override + { + return false; + } + }; + + /*********************************************************/ + + class ImageStream3Pictures : public ImageStream + { + public: + explicit ImageStream3Pictures( + Config* cfg, + std::vector picture_files) + : ImageStream(0, cfg) + , m_picture_files(std::move(picture_files)) + , m_currentFrame(0) + { + + // Grab the codec from config file + double fps = _cfg->RecordFPS; + if (fps > 0) { + m_fps = fps; + } else { + m_fps = 1; + } + + // load first image + if (this->numFrames() > 0) { + this->setFrameNumber_impl(0); + auto filename = m_picture_files[0].string(); + auto new_frame = cv::imread(filename); + m_w = new_frame.size().width; + m_h = new_frame.size().height; + m_recording = false; + vCoder = std::make_shared(m_fps, _cfg); + } + } + virtual GuiParam::MediaType type() const override + { + return GuiParam::MediaType::Images; + } + virtual size_t numFrames() const override + { + return m_picture_files.size(); + } + virtual bool toggleRecord() override + { + if (this->numFrames() <= 0) { + return false; + } + m_recording = vCoder->toggle(m_w, m_h, m_fps); + + return m_recording; + } + virtual double fps() const override + { + return m_fps; + } + virtual std::string currentFilename() const override + { + assert(currentFrameNumber() < m_picture_files.size()); + return m_picture_files[currentFrameNumber()].string(); + } + + private: + virtual bool nextFrame_impl() override + { + m_currentFrame += static_cast(m_frame_stride); + if (this->numFrames() > m_currentFrame) { + + auto filename = m_picture_files[m_currentFrame].string(); + auto new_frame = cv::imread(filename); + this->set_current_frame(new_frame); + if (m_recording) { + if (vCoder) + vCoder->add(new_frame); + } + return true; + } + return false; + } + + virtual bool setFrameNumber_impl(size_t frame_number) override + { + auto filename = m_picture_files[frame_number].string(); + auto new_frame = cv::imread(filename); + this->set_current_frame(new_frame); + m_currentFrame = static_cast(frame_number); + if (m_recording) { + if (vCoder) + vCoder->add(new_frame); + } + return !new_frame.empty(); + } + std::vector m_picture_files; + std::shared_ptr vCoder; + double m_w; + double m_h; + bool m_recording; + int m_currentFrame; + double m_fps; + }; + + /*********************************************************/ + + class ImageStream3Video : public ImageStream + { + public: + /** + * @throw file_not_found when the file does not exists + * @throw video_open_error when there is an error with the video + * @brief ImageStreamVideo + * @param filename path to the file + */ + explicit ImageStream3Video( + Config* cfg, + const std::vector& files) + : ImageStream(0, cfg) + { + openMedia(files); + } + virtual GuiParam::MediaType type() const override + { + return GuiParam::MediaType::Video; + } + virtual size_t numFrames() const override + { + return m_num_frames; + } + virtual bool toggleRecord() override + { + if (!m_capture.isOpened()) { + return false; + } + m_recording = vCoder->toggle(m_w, m_h, m_fps); + + return m_recording; + } + virtual double fps() const override + { + return m_fps; + } + virtual std::string currentFilename() const override + { + return m_fileName; + } + + virtual bool hasNextInBatch() override + { + return !(m_batch.empty()); + } + + virtual void stepToNextInBatch() override + { + if (m_batch.empty()) { + throw video_open_error("batch is empty"); + } + openMedia(m_batch); + } + + virtual std::vector getBatchItems() override + { + std::vector batchItems; + for (auto x : m_batch) { + batchItems.push_back(x.string()); + } + return batchItems; + } + + private: + void openMedia(std::vector files) + { + + m_capture.open(files.front().string()); + m_num_frames = static_cast( + m_capture.get(cv::CAP_PROP_FRAME_COUNT)); + m_fps = m_capture.get(cv::CAP_PROP_FPS); + m_fileName = files.front().string(); + + if (!boost::filesystem::exists(files.front())) { + throw file_not_found("Could not find file " + + files.front().string()); + } + if (!m_capture.isOpened()) { + throw video_open_error(":("); + } + + m_batch = files; + m_batch.erase(m_batch.begin(), m_batch.begin() + 1); + + // Grab the fps from config file + double fps = _cfg->RecordFPS; + if (fps != -1) { + m_fps = fps; + } + + m_w = m_capture.get(cv::CAP_PROP_FRAME_WIDTH); + m_h = m_capture.get(cv::CAP_PROP_FRAME_HEIGHT); + m_recording = false; + vCoder = std::make_shared(m_fps, _cfg); + + // load first image + if (this->numFrames() > 0) { + this->nextFrame_impl(); + } + + m_current_frame_number = 0; + } + + virtual bool nextFrame_impl() override + { + cv::Mat new_frame; + for (int i = 0; i < m_frame_stride; i++) + m_capture >> new_frame; + this->set_current_frame(new_frame); + if (m_recording) { + if (vCoder) + vCoder->add(new_frame); + } + return !new_frame.empty(); + } + + virtual bool setFrameNumber_impl(size_t frame_number) override + { + // new frame is next frame --> use next frame function + if (this->currentFrameNumber() + 1 == frame_number) { + return this->nextFrame_impl(); + } else { + // adjust frame position ("0-based index of the frame to be + // decoded/captured next.") + m_capture.set(cv::CAP_PROP_POS_FRAMES, + static_cast(frame_number)); + return this->nextFrame_impl(); + } + } + + cv::VideoCapture m_capture; + size_t m_num_frames; + std::string m_fileName; + std::shared_ptr vCoder; + std::vector m_batch; + double m_fps; + double m_w; + double m_h; + bool m_recording; + }; + + /*********************************************************/ + class ImageStream3OpenCVCamera : public ImageStream + { + public: + /** + * @throw file_not_found when device does not exists + * @throw device_open_error when there is an error with the device + * @brief ImageStreamCamera + * @param device_id according to the VideoCapture class of OpenCV + */ + explicit ImageStream3OpenCVCamera(Config* cfg, + CameraConfiguration conf) + : ImageStream(0, cfg) + , m_capture(conf._selector.name) + , m_fps(m_capture.get(cv::CAP_PROP_FPS)) + { + // Give the camera some extra time to get ready: + // Somehow opening it on first try sometimes does not succeed. + // Workaround: + // http://stackoverflow.com/questions/22019064/unable-to-read-frames-from-videocapture-from-secondary-webcam-with-opencv?rq=1 + // So, stubbornly try it a few times until it works. + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + qDebug() << "\nStarting to record on camera no. " + << conf._selector.index; + m_w = conf._width == -1 ? _cfg->CameraWidth : conf._width; + m_h = conf._height == -1 ? _cfg->CameraHeight : conf._height; + m_fps = conf._fps == -1 ? _cfg->RecordFPS : conf._fps; + m_recording = false; + vCoder = std::make_shared(m_fps, _cfg); + + int fails = 0; + while (!m_capture.isOpened() && fails < 5) { + m_capture.open(conf._selector.index); + std::this_thread::sleep_for( + std::chrono::milliseconds(1000)); + fails++; + } + + if (!m_capture.isOpened()) { + qWarning() << "Unable to open camera!"; + throw device_open_error(":("); + } + + if (m_w != -1) + m_capture.set(cv::CAP_PROP_FRAME_WIDTH, m_w); + if (m_h != -1) + m_capture.set(cv::CAP_PROP_FRAME_HEIGHT, m_h); + if (m_fps != -1) + m_capture.set(cv::CAP_PROP_FPS, m_fps); + + m_w = m_capture.get(cv::CAP_PROP_FRAME_WIDTH); + m_h = m_capture.get(cv::CAP_PROP_FRAME_HEIGHT); + m_fps = m_capture.get(cv::CAP_PROP_FPS); + qDebug() << "Cam open: " << m_capture.isOpened() + << " w/h:" << m_w << "/" << m_h << " fps:" << m_fps; + // load first image + if (this->numFrames() > 0) { + this->nextFrame_impl(); + } + } + virtual GuiParam::MediaType type() const override + { + return GuiParam::MediaType::Camera; + } + virtual size_t numFrames() const override + { + return -1; // TODO + } + virtual bool toggleRecord() override + { + if (!m_capture.isOpened()) { + return false; + } + m_recording = vCoder->toggle(m_w, m_h, m_fps); + + return m_recording; + } + virtual double fps() const override + { + return m_fps; + } + virtual std::string currentFilename() const override + { + return "Camera"; // TODO be more specific! + } + + private: + virtual bool nextFrame_impl() override + { + cv::Mat new_frame; + + for (int i = 0; i < m_frame_stride; i++) { + m_capture >> new_frame; + } + + this->set_current_frame(new_frame); + if (m_recording) { + if (vCoder) + vCoder->add(new_frame); + } + return !new_frame.empty(); + } + + virtual bool setFrameNumber_impl(size_t) override + { + // throw std::runtime_error("setFrameNumber not + // available for ImageStreamCamera"); + this->nextFrame_impl(); + return true; + } + + std::shared_ptr vCoder; + cv::VideoCapture m_capture; + double m_fps; + double m_w; + double m_h; + bool m_recording; + }; + +#if HAS_PYLON + /*********************************************************/ + class ImageStream3PylonCamera : public ImageStream + { + private: + Pylon::CGrabResultPtr m_grabbed; + + public: + explicit ImageStream3PylonCamera(Config* cfg, + CameraConfiguration conf) + : ImageStream(0, cfg) + , m_camera(getPylonDevice(conf._selector.index), + Pylon::Cleanup_Delete) + { + m_fps = conf._fps == -1 ? _cfg->RecordFPS : conf._fps; + + m_camera.Open(); + + if (!m_camera.IsOpen()) { + qWarning() << "Unable to open camera!"; + throw device_open_error("Error loading camera"); + } + + m_imageSize = {[&]() -> int { + if (conf._width != -1) + return conf._width; + if (_cfg->CameraWidth != -1) + return _cfg->CameraWidth; + return GenApi::CIntegerPtr( + m_camera.GetNodeMap().GetNode( + "SensorWidth")) + ->GetValue(); + }(), + [&]() -> int { + if (conf._height != -1) + return conf._height; + if (_cfg->CameraHeight != -1) + return _cfg->CameraHeight; + return GenApi::CIntegerPtr( + m_camera.GetNodeMap().GetNode( + "SensorHeight")) + ->GetValue(); + }()}; + + GenApi::CBooleanPtr(m_camera.GetNodeMap().GetNode( + "AcquisitionFrameRateEnable")) + ->SetValue(1); + + if (m_fps == -1) { + m_fps = getFrameRate(); + } else { + setFrameRate(m_fps); + auto const actual_fps = getFrameRate(); + qInfo() << "Actual framerate:" << actual_fps; + if (std::abs(actual_fps - m_fps) > 0.1) { + throw device_open_error("Error setting framerate"); + } + m_fps = actual_fps; + } + + qDebug() << "\nStarting to record on camera " + << m_camera.GetDeviceInfo().GetFriendlyName(); + m_camera.StartGrabbing(Pylon::GrabStrategy_LatestImages, + Pylon::GrabLoop_ProvidedByUser); + nextFrame_impl(); + + m_recording = false; + m_encoder = std::make_unique(m_fps, _cfg); + } + + GuiParam::MediaType type() const override + { + return GuiParam::MediaType::Camera; + } + + std::size_t numFrames() const override + { + return std::numeric_limits::max(); + } + + bool toggleRecord() override + { + if (!m_camera.IsOpen()) { + return false; + } + m_recording = m_encoder->toggle(m_imageSize.width, + m_imageSize.height, + m_fps); + + return m_recording; + } + + double fps() const override + { + return m_fps; + } + + std::string currentFilename() const override + { + return std::string(m_camera.GetDeviceInfo().GetFriendlyName()); + } + + private: + bool nextFrame_impl() override + { + for (std::size_t i = 1; i < m_frame_stride; ++i) { + if (!m_camera.RetrieveResult( + 2000, + m_grabbed, + Pylon::TimeoutHandling_Return)) { + return false; + } + } + + if (!m_camera.RetrieveResult(2000, + m_grabbed, + Pylon::TimeoutHandling_Return)) { + return false; + } + + auto view = toOpenCV(m_grabbed); + auto scaled = view.clone(); + cv::resize(scaled, scaled, m_imageSize); + set_current_frame(scaled); + if (m_recording && m_encoder) + m_encoder->add(scaled); + + return !scaled.empty(); + } + + bool setFrameNumber_impl(size_t) override + { + return false; + } + + double getFrameRate() + { + if (m_camera.IsUsb()) { + return GenApi::CFloatPtr(m_camera.GetNodeMap().GetNode( + "AcquisitionFrameRate")) + ->GetValue(); + } + + throw std::logic_error("Unsupported device class"); + } + + void setFrameRate(double value) + { + if (m_camera.IsUsb()) { + GenApi::CFloatPtr( + m_camera.GetNodeMap().GetNode("AcquisitionFrameRate")) + ->SetValue(value); + } else { + throw std::logic_error("Unsupported camera type"); + } + } + + Pylon::PylonAutoInitTerm m_pylon; + Pylon::CInstantCamera m_camera; + double m_fps; + cv::Size m_imageSize; + bool m_recording; + + std::unique_ptr m_encoder; + }; +#endif + + /*********************************************************/ + + std::shared_ptr make_ImageStream3NoMedia() + { + return std::make_shared(); + } + + std::shared_ptr make_ImageStream3Pictures( + Config* cfg, + std::vector filenames) + { + return std::make_shared( + cfg, + std::move(filenames)); + } + + std::shared_ptr make_ImageStream3Video( + Config* cfg, + const std::vector& files) + { + try { + return std::make_shared(cfg, files); + } catch (const video_open_error&) { + return make_ImageStream3NoMedia(); + } + } + + std::shared_ptr make_ImageStream3Camera( + Config* cfg, + CameraConfiguration conf) + { + try { + switch (conf._selector.type) { + case CameraType::OpenCV: + return std::make_shared(cfg, + conf); +#if HAS_PYLON + case CameraType::Pylon: + return std::make_shared(cfg, + conf); +#endif + default: + throw std::logic_error( + "Missing image stream implementation"); + } + } catch (const device_open_error&) { + return make_ImageStream3NoMedia(); + } + } + + } +} diff --git a/Src/Model/ImageStream.h b/Src/Model/ImageStream.h new file mode 100644 index 00000000..313d4cd5 --- /dev/null +++ b/Src/Model/ImageStream.h @@ -0,0 +1,207 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** Origin of this class is BioTracker in version 2. + ** + ****************************************************************************/ + +#ifndef BIOTRACKER3IMAGESTREAM_H +#define BIOTRACKER3IMAGESTREAM_H + +#include // std::unique_ptr +#include // cv::Mat +#include // std::vector +#include // std::string +#include +#include +#include "QSharedPointer" + +#include "util/ParamNames.h" // GUIPARAM::MediaType +#include "util/types.h" +#include "util/camera/base.h" +#include "util/Config.h" + +namespace BioTracker +{ + namespace Core + { + + /** + * The ImageStream class was part of BioTracker version 2. It is + * responsible for generation ImageStreams from files or camera + * devices. + */ + class ImageStream : public QObject + { + Q_OBJECT + public: + explicit ImageStream(QObject* parent = 0, Config* cfg = nullptr); + + /** + * @return the stream's MediaType i.e. "Video", "Images", "NoMedia" + */ + virtual GuiParam::MediaType type() const = 0; + + /** + * @return the total number of frames + */ + virtual size_t numFrames() const = 0; + + virtual bool toggleRecord() = 0; + + /** + * @return the current frame number + */ + size_t currentFrameNumber() const; + + /** + * @return true, if the current frame is the last frame + */ + bool lastFrame() const; + + /** + * @return true, if the stream's end is reached; i.e. current frame + * points behind it's last frame + */ + bool end() const; + + /** + * @return true, if currentFrame().empty(); + */ + bool currentFrameIsEmpty() const; + + /** + * @return the media's fps rate + */ + virtual double fps() const = 0; + + /** + * @return the filename of the current file defined through the + * frameNumber + */ + virtual std::string currentFilename() const = 0; + + /** + * returns the current frame. + * - if the current frame position is invalid or an error occurred, + * an empty image is returned. + */ + cv::Mat currentFrame() const; + + /** + * sets the current frame number and updates the current frame. + * - if frame_number is invalid, the current frame is invalidated. + * @return true if the operation was successful, i.e. the frame + * number is valid and no error occurred. + */ + bool setFrameNumber(size_t frame_number); + + /** + * advances the current frame frame. + * - if this function is called on the media's last frame, the + * current frame is invalidated. + * @return true if the operation was successful, i.e. the current + * frame isn't the last frame and no error occurred. + */ + bool nextFrame(); + + /** + * sets the current frame position to the previous frame. + * - if this function is called on the media's first frame, the + * current frame is invalidated. + * @return true if the operation was successful, i.e. the current + * frame isn't the first one and no error occurred. + */ + bool previousFrame(); + + /** + * Gets the title of the current image stream. + * A title should represent the identity of a source stream as a + *string. E.g. a video "MyTracking.mkv" should yield a name like + *"MyTracking". Streams from Camera No. 1 should yiel "Camera_1" or + *the like. Naming conventions are up to the stream + *implementations. + */ + std::string getTitle(); + + virtual bool hasNextInBatch(); + + virtual void stepToNextInBatch(); + + virtual std::vector getBatchItems(); + + virtual ~ImageStream(); + + protected: + /** + * sets the image returned by this->currentFrame(); + */ + void set_current_frame(cv::Mat img); + + /** + * Sets the title of the current image stream. + * A title should represent the identity of a source stream as a + *string. E.g. a video "MyTracking.mkv" should yield a name like + *"MyTracking". Streams from Camera No. 1 should yiel "Camera_1" or + *the like. Naming conventions are up to the stream + *implementations. The title is set by the stream itself and may + *not be modified from the outside. + */ + void setTitle(std::string title); + + /** + * The stride of the image stream. Think of it as "use only every + * n'th frame". + */ + size_t m_frame_stride; + + cv::Mat m_current_frame; + size_t m_current_frame_number; + std::string m_title; + Config* _cfg; + + private: + /** + * empties m_current_frame & sets m_current_frame_number to + * this->numFrames(); + */ + void clearImage(); + /** + * - called by ImageStreamImpl::setFrameNumber + * if frame_number < numFrames() && frame_number != + * this->currentFrameNumber(); + * - m_current_frame_number is updated afterwards + */ + virtual bool setFrameNumber_impl(size_t frame_number) = 0; + /** + * - called by ImageStreamImpl::nextFrame() + * if currentFrameNumber() + 1 < numFrames(); + * - m_current_frame_number is updated afterwards + */ + virtual bool nextFrame_impl(); + /** + * - called by ImageStreamImpl::previousFrame() + * if currentFrameNumber() > 0; + * - m_current_frame_number is updated afterwards + */ + virtual bool previousFrame_impl(); + }; + + std::shared_ptr make_ImageStream3NoMedia(); + + std::shared_ptr make_ImageStream3Pictures( + Config* cfg, + std::vector filenames); + + std::shared_ptr make_ImageStream3Video( + Config* cfg, + const std::vector& filename); + + std::shared_ptr make_ImageStream3Camera( + Config* cfg, + CameraConfiguration conf); + + } +} + +#endif // BIOTRACKER3IMAGESTREAM_H diff --git a/Src/Model/MediaPlayer.cpp b/Src/Model/MediaPlayer.cpp new file mode 100644 index 00000000..dc719dbe --- /dev/null +++ b/Src/Model/MediaPlayer.cpp @@ -0,0 +1,424 @@ +#include "MediaPlayer.h" +#include "Utility/misc.h" + +// Settings related +#include "util/types.h" +#include "Controller/IControllerCfg.h" + +using namespace BioTrackerUtilsMisc; // getTimeAndDate + +MediaPlayer::MediaPlayer(QObject* parent) +: IModel(parent) +{ + _cfg = static_cast(parent)->getConfig(); + m_currentFPS = 0; + m_fpsOfSourceFile = 0; + _imagew = 0; + _imageh = 0; + m_useCuda = false; + m_RecI = false; + m_RecO = false; + m_videoc = std::make_shared(_cfg->RecordFPS, _cfg); + m_NameOfCvMat = "Original"; + + m_TrackingIsActive = false; + m_recd = false; + m_recordScaled = false; + // Initialize PlayerStateMachine and a Thread for the Player + // // Do not set a Parent for MediaPlayerStateMachine in order to run + // the Player in the QThread! + + m_PlayerThread = new QThread(this); + m_PlayerThread->setObjectName("PlayerThread"); + m_Player = new MediaPlayerStateMachine(); + m_Player->setConfig(_cfg); + + // Connect MediaPlayer with PlayerStateMachine + + // Load ImageStreams in StateMachine + QObject::connect(this, + &MediaPlayer::loadVideoStream, + m_Player, + &MediaPlayerStateMachine::receiveLoadVideoCommand); + QObject::connect(this, + &MediaPlayer::loadCameraDevice, + m_Player, + &MediaPlayerStateMachine::receiveLoadCameraDevice); + QObject::connect(this, + &MediaPlayer::loadPictures, + m_Player, + &MediaPlayerStateMachine::receiveLoadPictures); + + // Controll the Player + QObject::connect(this, + &MediaPlayer::nextFrameCommand, + m_Player, + &MediaPlayerStateMachine::receiveNextFramCommand); + QObject::connect(this, + &MediaPlayer::pauseCommand, + m_Player, + &MediaPlayerStateMachine::receivePauseCommand); + QObject::connect(this, + &MediaPlayer::playCommand, + m_Player, + &MediaPlayerStateMachine::receivePlayCommand); + QObject::connect(this, + &MediaPlayer::prevFrameCommand, + m_Player, + &MediaPlayerStateMachine::receivePrevFrameCommand); + QObject::connect(this, + &MediaPlayer::stopCommand, + m_Player, + &MediaPlayerStateMachine::receiveStopCommand); + QObject::connect(this, + &MediaPlayer::goToFrame, + m_Player, + &MediaPlayerStateMachine::receiveGoToFrame); + + QObject::connect(this, + &MediaPlayer::pauseCommand, + this, + &MediaPlayer::receiveTrackingPaused); + QObject::connect(this, + &MediaPlayer::stopCommand, + this, + &MediaPlayer::receiveTrackingPaused); + + QObject::connect(this, + &MediaPlayer::toggleRecordImageStreamCommand, + m_Player, + &MediaPlayerStateMachine::receivetoggleRecordImageStream); + + // Handle PlayerStateMachine results + QObject::connect(m_Player, + &MediaPlayerStateMachine::emitPlayerParameters, + this, + &MediaPlayer::receivePlayerParameters); + QObject::connect(m_Player, + &MediaPlayerStateMachine::emitPlayerParameters, + this, + &MediaPlayer::fwdPlayerParameters); + + // Handle next state operation + QObject::connect(m_Player, + &MediaPlayerStateMachine::emitPlayerOperationDone, + this, + &MediaPlayer::receivePlayerOperationDone); + QObject::connect(this, + &MediaPlayer::runPlayerOperation, + m_Player, + &MediaPlayerStateMachine::receiveRunPlayerOperation); + + QObject::connect(m_Player, + &MediaPlayerStateMachine::emitNextMediaInBatch, + this, + &MediaPlayer::emitNextMediaInBatch, + Qt::DirectConnection); + QObject::connect(m_Player, + &MediaPlayerStateMachine::emitNextMediaInBatchLoaded, + this, + &MediaPlayer::emitNextMediaInBatchLoaded, + Qt::DirectConnection); + + // Move the PlayerStateMachine to the Thread + m_Player->moveToThread(m_PlayerThread); + + // Start the Thread + m_PlayerThread->start(); +} + +MediaPlayer::~MediaPlayer() +{ + stopCommand(); + m_PlayerThread->quit(); + if (!m_PlayerThread->wait(2000)) { + m_PlayerThread->terminate(); + m_PlayerThread->wait(); + } +} + +void MediaPlayer::setTrackingActive() +{ + m_TrackingIsActive = true; +} + +void MediaPlayer::setTrackingDeactive() +{ + m_TrackingIsActive = false; +} + +bool MediaPlayer::getPlayState() +{ + return m_Play; +} + +bool MediaPlayer::getForwardState() +{ + return m_Forw; +} + +bool MediaPlayer::getBackwardState() +{ + return m_Back; +} + +bool MediaPlayer::getStopState() +{ + return m_Stop; +} + +bool MediaPlayer::getPauseState() +{ + return m_Paus; +} + +bool MediaPlayer::getRecIState() +{ + return m_RecI; +} + +bool MediaPlayer::getRecOState() +{ + return m_RecO; +} + +bool MediaPlayer::getTrackingState() +{ + return m_TrackingIsActive; +} + +size_t MediaPlayer::getTotalNumberOfFrames() +{ + return m_TotalNumbFrames; +} + +size_t MediaPlayer::getCurrentFrameNumber() +{ + return m_CurrentFrameNumber; +} + +double MediaPlayer::getFpsOfSourceFile() +{ + return m_fpsOfSourceFile; +} + +double MediaPlayer::getCurrentFPS() +{ + return m_currentFPS; +} + +double MediaPlayer::getTargetFPS() +{ + return m_targetFPS; +} +void MediaPlayer::setTargetFPS(double fps) +{ + m_targetFPS = fps; + m_Player->receiveTargetFps(fps); +} + +QString MediaPlayer::getCurrentFileName() +{ + return m_CurrentFilename; +} + +cv::Mat MediaPlayer::getCurrentFrame() +{ + return m_CurrentFrame; +} + +int MediaPlayer::reopenVideoWriter() +{ + QRectF r = m_gv->sceneRect(); + + if (_imagew != r.width() || _imageh != r.height() || !m_recd) { + + if (m_useCuda) { +#ifdef WITH_CUDA + + _imagew = r.width(); + _imageh = r.height(); + m_videoc = std::make_shared(_cfg->RecordFPS, _cfg); + EncodeConfig* cfg = m_videoc->m_nvEncoder->getEncodeConfig(); + cfg->width = _imagew; + cfg->height = _imageh; + cfg->fps = 30; + cfg->codec = NV_ENC_H264; + cfg->inputFormat = + NV_ENC_BUFFER_FORMAT_NV12; // NV_ENC_BUFFER_FORMAT_YUV444 + // //NV_ENC_BUFFER_FORMAT_NV12 + const std::string f = getTimeAndDate("ViewCapture", ".avi"); + char* chr = strdup(f.c_str()); + m_videoc->start(); + free(chr); + m_recd = true; +#else + std::cout << "Error on recording: Asked to use cudacodec although " + "build is not cuda-enabled. Not recording." + << std::endl; +#endif + + } else { + if (m_videoWriter && m_videoWriter->isOpened()) + m_videoWriter->release(); + _imagew = r.width(); + _imageh = r.height(); + + int codec = cv::VideoWriter::fourcc('X', '2', '6', '4'); + m_videoWriter = std::make_shared( + getTimeAndDate("./ViewCapture", ".avi"), + codec, + 30, + cv::Size(r.width(), r.height()), + 1); + m_recd = m_videoWriter->isOpened(); + } + } + return m_recd; +} + +QString MediaPlayer::takeScreenshot(GraphicsView* gv) +{ + QRectF rscene = gv->sceneRect(); + QRectF rview = gv->rect(); + QSize size; + if (!m_recordScaled) + size = rscene.size().toSize(); + else + size = rview.size().toSize(); + auto image = QImage(size, QImage::Format_RGB32); + auto painter = QPainter(&image); + + if (!m_recordScaled) + gv->scene()->render(&painter); + else + gv->render(&painter); + + auto filePath = QString::fromStdString( + getTimeAndDate(_cfg->DirScreenshots.toStdString(), ".png")); + + image.save(filePath); + + return filePath; +} + +void MediaPlayer::receiveTrackingPaused() +{ +} + +void MediaPlayer::receivePlayerParameters( + std::shared_ptr param) +{ + + m_Back = param->m_Back; + m_Paus = param->m_Paus; + m_Play = param->m_Play; + m_Stop = param->m_Stop; + m_Forw = param->m_Forw; + m_RecI = param->m_RecI; + m_RecO = param->m_RecO; + + m_CurrentFilename = param->m_CurrentFilename; + m_CurrentFrameNumber = param->m_CurrentFrameNumber; + m_fpsOfSourceFile = param->m_fpsSourceVideo; + m_TotalNumbFrames = param->m_TotalNumbFrames; + + if (param->m_CurrentFrame && !param->m_CurrentFrame->empty()) { + m_CurrentFrame = *param->m_CurrentFrame; + + Q_EMIT renderCurrentImage(m_CurrentFrame, m_NameOfCvMat); + + if (m_TrackingIsActive) { + Q_EMIT trackCurrentImage(m_CurrentFrame, + static_cast(m_CurrentFrameNumber)); + } else { + Q_EMIT signalVisualizeCurrentModel( + static_cast(m_CurrentFrameNumber)); + Q_EMIT signalCurrentFrameNumberToPlugin( + static_cast(m_CurrentFrameNumber)); + } + + if (m_recd) { + QRectF rscene = m_gv->sceneRect(); + QRectF rview = m_gv->rect(); + QSize size; + if (!m_recordScaled) + size = rscene.size().toSize(); + else + size = rview.size().toSize(); + if (m_image.size() != size) { + m_image = QImage(size, QImage::Format_RGB32); + if (m_painter.isActive()) + m_painter.end(); + m_painter.begin(&m_image); + } + + if (!m_recordScaled) + m_gv->scene()->render(&m_painter); + else + m_gv->render(&m_painter); + + auto view = cv::Mat(m_image.height(), + m_image.width(), + CV_8UC(m_image.depth() / 8), + m_image.bits(), + m_image.bytesPerLine()); + + auto copy = view.clone(); + cv::cvtColor(copy, copy, cv::ColorConversionCodes::COLOR_BGR2RGB); + m_videoc->add(copy); + } + } else { + qWarning() + << "MediaPlayer: Received player parameters with invalid image."; + } + + Q_EMIT notifyView(); +} + +void MediaPlayer::rcvPauseState(bool state) +{ + _paused = state; + + if (!state) { + m_currentFPS = 0; + } +} + +void MediaPlayer::receivePlayerOperationDone() +{ + end = std::chrono::system_clock::now(); + long s = std::chrono::duration_cast(end - start) + .count(); + if (!_paused) { + m_currentFPS = floor(1.0 / (double(s) / 1000.0)); + } else { + m_currentFPS = 0; + } + + emit runPlayerOperation(); + + start = std::chrono::system_clock::now(); +} + +int MediaPlayer::toggleRecordImageStream() +{ + Q_EMIT toggleRecordImageStreamCommand(); + return 0; +} + +int MediaPlayer::toggleRecordGraphicsScenes(GraphicsView* gv) +{ + + m_gv = gv; + QRectF rscene = m_gv->sceneRect(); // 0us + QRectF rview = m_gv->rect(); // 0us + QSize s1 = rscene.size().toSize(); // 0us + QSize s2 = rview.size().toSize(); // 0us + m_recordScaled = _cfg->RecordScaledOutput; + if (!m_recordScaled) + m_recd = m_videoc->toggle(s1.width(), s1.height(), 30); + else + m_recd = m_videoc->toggle(s2.width(), s2.height(), 30); + return m_recd; +} diff --git a/Src/Model/MediaPlayer.h b/Src/Model/MediaPlayer.h new file mode 100644 index 00000000..f0e23614 --- /dev/null +++ b/Src/Model/MediaPlayer.h @@ -0,0 +1,233 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef MEDIAPLAYER_H +#define MEDIAPLAYER_H + +#include "Interfaces/IModel/IModel.h" +#include "QThread" +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" +#include "View/GraphicsView.h" + +#include +#include +#include "util/types.h" +#include "util/VideoCoder.h" +#include "util/Config.h" + +/** + * The MediaPlayer class is an IModel class an part of the MediaPlayer + * component. This class creats a MediaPlayerStateMachine object and moves it + * to a QThread. The MediaPlayer class controlls and represents the results of + * the MediaPlayerStateMachine. The communication between a MediaPlayer object + * and a MediaPlayerStateMachine object is done by Qts SIGNALS and SLOTS. This + * is due to the fact that SIGNALS and SLTOS are thread safe. A disadvantage is + * that SIGNALS and SLOTS are slower then normal function calls. + * + * The constructor of this class is responsible for connecting to the + * MediaPlayerStateMachine. + */ +class MediaPlayer : public IModel +{ + Q_OBJECT +public: + MediaPlayer(QObject* parent = 0); + ~MediaPlayer(); + +Q_SIGNALS: + /** + * Emit the path to a video stream. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void loadVideoStream(std::vector files); + /** + * Emit the path to pictures. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void loadPictures(std::vector files); + /** + * Emit the camera device number. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void loadCameraDevice(CameraConfiguration conf); + + /** + * Emit a frame number. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void goToFrame(int frame); + /** + * Emit the next frame command. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void nextFrameCommand(); + /** + * Emit previous frame command. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void prevFrameCommand(); + /** + * Emit the play command. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void playCommand(); + /** + * Emit stop command. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void stopCommand(); + /** + * Emit the pause command. This signal will be received by the + * MediaPlayerStateMachine which runns in a separate Thread. + */ + void pauseCommand(); + + /** + * This SIGNAL will be emmited if a state operation should be executed. + * This signal will be received by the MediaPlayerStateMachine which runns + * in a separate Thread. + */ + void runPlayerOperation(); + + /** + * This SIGNAL will send a cv::Mat and a name to the MediaPlayer controller + * class. This controller will give the data to the TextureObject + * component. + */ + void renderCurrentImage(cv::Mat mat, QString name); + /** + * This SIGNAL is only emmited if Tracking Is Active. The PluginLoader + * component will receive the cv::Mat and the current frame number. + */ + void trackCurrentImage(cv::Mat mat, uint number); + /** + * This SIGNAL is only emmited if Tracking Is inactive. The core + * visualization controller will receive the framenumber and will try to + * visualize the tracking model. + */ + void signalVisualizeCurrentModel(uint frameNumber); + + void signalCurrentFrameNumberToPlugin(uint frameNumber); + + void toggleRecordImageStreamCommand(); + + void fwdPlayerParameters( + std::shared_ptr parameters); + + void emitNextMediaInBatch(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path); + +public: + void setTrackingActive(); + void setTrackingDeactive(); + void setTargetFPS(double fps); + + bool getPlayState(); + bool getForwardState(); + bool getBackwardState(); + bool getStopState(); + bool getPauseState(); + bool getRecIState(); + bool getRecOState(); + + bool getTrackingState(); + + int toggleRecordGraphicsScenes(GraphicsView* gv); + int toggleRecordImageStream(); + + size_t getTotalNumberOfFrames(); + size_t getCurrentFrameNumber(); + double getFpsOfSourceFile(); + double getCurrentFPS(); + double getTargetFPS(); + QString getCurrentFileName(); + cv::Mat getCurrentFrame(); + + QString takeScreenshot(GraphicsView* gv); + +public Q_SLOTS: + /** + * MediaPlayer will receive the current playerParameters from the + * MediaPlayerStateMachine. + */ + void receivePlayerParameters( + std::shared_ptr param); + + /** + * If the MediaPlayerStateMachine is finished with executing the current + * state it will trigger this SLOT. + */ + void receivePlayerOperationDone(); + + /** + * + */ + void receiveTrackingPaused(); + + /** + * Catches the pause state from the controller. + * This will automatically wrap all cases of "stop" semantics. + * We do this although the info is basically passed implicitly via other + * commands, because it's easier + */ + void rcvPauseState(bool state); + +private: + // TODO Refactor members to _ instead of m_ + + /** + * helper function which opens a video. If video size has changed, a new + * video is opened. + */ + int reopenVideoWriter(); + int _imagew; + int _imageh; + Config* _cfg; + + QPointer m_PlayerThread; + QPointer m_Player; + + // IPlayerState* m_CurrentPlayerState; + // IPlayerState* m_NextPlayerState; + + QMap m_States; + + size_t m_TotalNumbFrames; + size_t m_CurrentFrameNumber; + double m_fpsOfSourceFile; + double m_currentFPS; + double m_targetFPS; + QString m_CurrentFilename; + cv::Mat m_CurrentFrame; + + bool m_Play; + bool m_Forw; + bool m_Back; + bool m_Stop; + bool m_Paus; + bool m_RecI; + bool m_RecO; + + bool m_recd; + bool m_recordScaled; + bool _paused = true; + + bool m_useCuda; + GraphicsView* m_gv; + QImage m_image; + QPainter m_painter; + std::shared_ptr m_videoWriter; + std::shared_ptr m_videoc; + + bool m_TrackingIsActive; + QString m_NameOfCvMat = "Original"; + + std::chrono::system_clock::time_point start; + std::chrono::system_clock::time_point end; +}; + +#endif // MEDIAPLAYER_H diff --git a/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp new file mode 100644 index 00000000..2a8b6a36 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.cpp @@ -0,0 +1,204 @@ +#include "MediaPlayerStateMachine.h" + +#include "Model/MediaPlayerStateMachine/PlayerParameters.h" +#include "PlayerStates/PStatePlay.h" +#include "PlayerStates/PStateInitialStream.h" +#include "PlayerStates/PStateStepForw.h" +#include "PlayerStates/PStateInitial.h" +#include "PlayerStates/PStatePause.h" +#include "PlayerStates/PStateStepBack.h" +#include "PlayerStates/PStateWait.h" +#include "PlayerStates/PStateGoToFrame.h" + +#include "util/types.h" +#include + +MediaPlayerStateMachine::MediaPlayerStateMachine(QObject* parent) +: IModel(parent) +, m_ImageStream(BioTracker::Core::make_ImageStream3NoMedia()) +{ + m_PlayerParameters = playerParameters(); + + m_States.insert(IPlayerState::PLAYER_STATES::STATE_INITIAL, + (new PStateInitial(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_INITIAL_STREAM, + (new PStateInitialStream(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_STEP_FORW, + (new PStateStepForw(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_PLAY, + (new PStatePlay(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_PAUSE, + (new PStatePause(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_STEP_BACK, + (new PStateStepBack(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_WAIT, + (new PStateWait(this, m_ImageStream))); + m_States.insert(IPlayerState::PLAYER_STATES::STATE_GOTOFRAME, + (new PStateGoToFrame(this, m_ImageStream))); + + QMap::iterator i; + for (i = m_States.begin(); i != m_States.end(); i++) { + QObject::connect(i.value(), + &IPlayerState::emitNextMediaInBatch, + this, + &MediaPlayerStateMachine::emitNextMediaInBatch); + QObject::connect(i.value(), + &IPlayerState::emitNextMediaInBatchLoaded, + this, + &MediaPlayerStateMachine::emitNextMediaInBatchLoaded); + } + + setNextState(IPlayerState::PLAYER_STATES::STATE_INITIAL); +} + +void MediaPlayerStateMachine::receiveRunPlayerOperation() +{ + + if (m_NextPlayerState != + m_States.value(IPlayerState::PLAYER_STATES::STATE_WAIT)) { + + m_CurrentPlayerState = m_NextPlayerState; + m_CurrentPlayerState->operate(); + + updatePlayerParameter(); + emitSignals(); + } +} + +void MediaPlayerStateMachine::receiveLoadVideoCommand( + std::vector files) +{ + + m_stream = BioTracker::Core::make_ImageStream3Video(_cfg, files); + + m_PlayerParameters.m_TotalNumbFrames = m_stream->numFrames(); + + for (auto x : m_States) { + x->changeImageStream(m_stream); + } + + setNextState(IPlayerState::STATE_INITIAL_STREAM); +} + +void MediaPlayerStateMachine::receiveLoadPictures( + std::vector files) +{ + m_stream = BioTracker::Core::make_ImageStream3Pictures(_cfg, files); + + m_PlayerParameters.m_TotalNumbFrames = m_stream->numFrames(); + + for (auto x : m_States) { + x->changeImageStream(m_stream); + } + + setNextState(IPlayerState::STATE_INITIAL_STREAM); +} + +void MediaPlayerStateMachine::receiveLoadCameraDevice(CameraConfiguration conf) +{ + m_stream.reset(); + for (auto x : m_States) { + x->changeImageStream(m_stream); + } + + m_stream = BioTracker::Core::make_ImageStream3Camera(_cfg, conf); + + m_PlayerParameters.m_TotalNumbFrames = m_stream->numFrames(); + + for (auto x : m_States) { + x->changeImageStream(m_stream); + } + + setNextState(IPlayerState::STATE_INITIAL_STREAM); +} + +void MediaPlayerStateMachine::receivePrevFrameCommand() +{ + setNextState(IPlayerState::STATE_STEP_BACK); +} + +void MediaPlayerStateMachine::receiveNextFramCommand() +{ + setNextState(IPlayerState::STATE_STEP_FORW); +} + +void MediaPlayerStateMachine::receivePauseCommand() +{ + setNextState(IPlayerState::STATE_PAUSE); +} + +void MediaPlayerStateMachine::receiveStopCommand() +{ + setNextState(IPlayerState::STATE_INITIAL_STREAM); +} + +void MediaPlayerStateMachine::receivePlayCommand() +{ + setNextState(IPlayerState::STATE_PLAY); +} + +void MediaPlayerStateMachine::receiveGoToFrame(int frame) +{ + PStateGoToFrame* state = dynamic_cast( + m_States.value(IPlayerState::PLAYER_STATES::STATE_GOTOFRAME)); + state->setFrameNumber(frame); + setNextState(IPlayerState::STATE_GOTOFRAME); +} + +void MediaPlayerStateMachine::receiveTargetFps(double fps) +{ + m_PlayerParameters.m_fpsTarget = fps; + static_cast(m_States.value(IPlayerState::STATE_PLAY)) + ->setFps(fps); +} + +void MediaPlayerStateMachine::receivetoggleRecordImageStream() +{ + if (m_stream) + m_PlayerParameters.m_RecI = m_stream->toggleRecord(); + else + m_PlayerParameters.m_RecI = false; + emitSignals(); + return; +} + +void MediaPlayerStateMachine::updatePlayerParameter() +{ + + stateParameters stateParam = m_CurrentPlayerState->getStateParameters(); + + m_PlayerParameters.m_Back = stateParam.m_Back; + m_PlayerParameters.m_Forw = stateParam.m_Forw; + m_PlayerParameters.m_Paus = stateParam.m_Paus; + m_PlayerParameters.m_Play = stateParam.m_Play; + m_PlayerParameters.m_Stop = stateParam.m_Stop; + + m_PlayerParameters.m_CurrentFilename = + m_CurrentPlayerState->getCurrentFileName(); + m_PlayerParameters.m_TotalNumbFrames = + m_CurrentPlayerState->m_ImageStream->numFrames(); + + m_PlayerParameters.m_CurrentFrame = + m_CurrentPlayerState->getCurrentFrame(); + m_PlayerParameters.m_CurrentFrameNumber = + m_CurrentPlayerState->getCurrentFrameNumber(); + m_PlayerParameters.m_fpsSourceVideo = + m_CurrentPlayerState->m_ImageStream->fps(); + m_PlayerParameters.m_batchItems = m_CurrentPlayerState->getBatchItems(); +} + +void MediaPlayerStateMachine::emitSignals() +{ + auto parametersCopy = std::make_shared( + m_PlayerParameters); + assert(parametersCopy->m_CurrentFrameNumber == + m_PlayerParameters.m_CurrentFrameNumber); + Q_EMIT emitPlayerParameters(parametersCopy); +} + +void MediaPlayerStateMachine::setNextState(IPlayerState::PLAYER_STATES state) +{ + m_NextPlayerState = m_States.value(state); + + Q_EMIT emitPlayerOperationDone(); +} diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h similarity index 51% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h rename to Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h index c9cb7462..001832ec 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h +++ b/Src/Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h @@ -1,10 +1,9 @@ /**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ - + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ #ifndef BIOTRACKER3PLAYER_H #define BIOTRACKER3PLAYER_H @@ -27,27 +26,36 @@ #include "PlayerParameters.h" #include "View/CameraDevice.h" +#include "util/Config.h" /** - * The MediaPlayerStateMachine class is an IModel class and is responsible for the executing and setting Player Stats. The instance of this class runns in a separate Thread. + * The MediaPlayerStateMachine class is an IModel class and is responsible for + * the executing and setting Player Stats. The instance of this class runns in + * a separate Thread. */ -class MediaPlayerStateMachine : public IModel { +class MediaPlayerStateMachine : public IModel +{ Q_OBJECT - public: +public: explicit MediaPlayerStateMachine(QObject* parent = 0); /** - * This method can be called by the MediaPlayer class and by any State which is part of the MediaPlayerStateMachine. + * This method can be called by the MediaPlayer class and by any State + * which is part of the MediaPlayerStateMachine. */ - void setNextState(IPlayerState::PLAYER_STATES state); + void setNextState(IPlayerState::PLAYER_STATES state); - IPlayerState::PLAYER_STATES getState(); + IPlayerState::PLAYER_STATES getState(); - //IPlayerState::PLAYER_STATES getState(); + void setConfig(Config* cfg) + { + _cfg = cfg; + }; - public Q_SLOTS: +public Q_SLOTS: /** - * This SLOT is called by the MediaPlayer class. If this slot is triggered the next state will be executed. + * This SLOT is called by the MediaPlayer class. If this slot is triggered + * the next state will be executed. */ void receiveRunPlayerOperation(); @@ -63,36 +71,39 @@ class MediaPlayerStateMachine : public IModel { void receiveGoToFrame(int frame); void receiveTargetFps(double fps); - void receivetoggleRecordImageStream(); + void receivetoggleRecordImageStream(); - Q_SIGNALS: +Q_SIGNALS: /** - * After each state execution this SIGNAL is emmited and received by the MediaPlayer class. The parameter playerParameters contains all information that was changed during the execution of the current state. + * After each state execution this SIGNAL is emmited and received by the + * MediaPlayer class. The parameter playerParameters contains all + * information that was changed during the execution of the current state. */ - void emitPlayerParameters(playerParameters* parameters); + void emitPlayerParameters( + std::shared_ptr parameters); /** - * When the state operation got finished, this SIGNAL is emmited and received by the MediaPlayer class. + * When the state operation got finished, this SIGNAL is emmited and + * received by the MediaPlayer class. */ void emitPlayerOperationDone(); - void emitNextMediaInBatch(); + void emitNextMediaInBatch(const std::string path); + void emitNextMediaInBatchLoaded(const std::string path); - private: +private: void updatePlayerParameter(); void emitSignals(); - - private: - IPlayerState* m_CurrentPlayerState; - IPlayerState* m_NextPlayerState; - QThread m_StateThread; +private: + IPlayerState* m_CurrentPlayerState; + IPlayerState* m_NextPlayerState; QMap m_States; - std::shared_ptr m_ImageStream; + std::shared_ptr m_ImageStream; - playerParameters* m_PlayerParameters; - std::shared_ptr m_stream; + playerParameters m_PlayerParameters; + std::shared_ptr m_stream; + Config* _cfg; }; - #endif // BIOTRACKER3PLAYER_H diff --git a/Src/Model/MediaPlayerStateMachine/PlayerParameters.h b/Src/Model/MediaPlayerStateMachine/PlayerParameters.h new file mode 100644 index 00000000..ef7f4b1f --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerParameters.h @@ -0,0 +1,40 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PLAYERPARAMETERS_H +#define PLAYERPARAMETERS_H + +#include + +/** + * The playerParameters struct holds all data types of the current MediaPlayer + * state. + */ +struct playerParameters +{ + + // PlayerStates + bool m_Play; + bool m_Forw; + bool m_Back; + bool m_Stop; + bool m_Paus; + bool m_RecI; + bool m_RecO; + + // The other information + size_t m_TotalNumbFrames; + QString m_CurrentFilename; + std::string m_CurrentTitle; + size_t m_CurrentFrameNumber; + std::optional m_CurrentFrame; + double m_fpsSourceVideo; + double m_fpsTarget; + std::vector m_batchItems; +}; + +#endif // PLAYERPARAMETERS_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp similarity index 69% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp index 10aa6f98..32c9218a 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.cpp @@ -1,38 +1,39 @@ #include "PStateGoToFrame.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" - -PStateGoToFrame::PStateGoToFrame(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStateGoToFrame::PStateGoToFrame( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; m_StateParameters.m_Paus = false; m_StateParameters.m_Play = false; - m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; + m_StateParameters.m_Stop = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; m_FrameNumber = 0; m_GoToFrameNumber = 0; operate(); - } -void PStateGoToFrame::setFrameNumber(int frame) { +void PStateGoToFrame::setFrameNumber(int frame) +{ m_GoToFrameNumber = frame; } -void PStateGoToFrame::operate() { +void PStateGoToFrame::operate() +{ m_StateParameters.m_Play = true; m_StateParameters.m_Stop = true; m_StateParameters.m_Paus = false; - if (m_ImageStream->setFrameNumber(m_GoToFrameNumber)) { - m_Mat = m_ImageStream->currentFrame(); + m_Mat = m_ImageStream->currentFrame(); m_FrameNumber = m_ImageStream->currentFrameNumber(); } @@ -53,5 +54,4 @@ void PStateGoToFrame::operate() { } m_Player->setNextState(IPlayerState::STATE_WAIT); - } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h new file mode 100644 index 00000000..aa435a85 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateGoToFrame.h @@ -0,0 +1,38 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATEGOTOFRAME_H +#define PSTATEGOTOFRAME_H + +#include "IStates/IPlayerState.h" + +/** + * This State is responsible for jumping to a spezific frame number in the + * ImageStream. The following state will be STATE_WAIT + */ +class PStateGoToFrame : public IPlayerState +{ +public: + PStateGoToFrame( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; + +public: + /** + * This function sets the next frame number. + */ + void setFrameNumber(int frame); + +private: + int m_GoToFrameNumber; +}; + +#endif // PSTATEGOTOFRAME_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp similarity index 66% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp index 7e232f41..5d2c62b1 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.cpp @@ -1,24 +1,27 @@ #include "PStateInitial.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -PStateInitial::PStateInitial(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStateInitial::PStateInitial( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; m_StateParameters.m_Paus = false; m_StateParameters.m_Play = false; m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; m_FrameNumber = 0; operate(); } -void PStateInitial::operate() { +void PStateInitial::operate() +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h new file mode 100644 index 00000000..2bf392ea --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitial.h @@ -0,0 +1,28 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATEINITIAL_H +#define PSTATEINITIAL_H + +#include "IStates/IPlayerState.h" + +/** + * This State is the first state when running BioTracker. It sets all + * parameters to false and sets as next state STATE_WAIT + */ +class PStateInitial : public IPlayerState +{ +public: + PStateInitial(MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; +}; + +#endif // PSTATEINITIAL_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp similarity index 65% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp index b57f1fdd..dab4531f 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.cpp @@ -1,9 +1,11 @@ #include "PStateInitialStream.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -PStateInitialStream::PStateInitialStream(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStateInitialStream::PStateInitialStream( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; @@ -12,10 +14,10 @@ PStateInitialStream::PStateInitialStream(MediaPlayerStateMachine* player, m_StateParameters.m_Stop = false; m_FrameNumber = 0; - } -void PStateInitialStream::operate() { +void PStateInitialStream::operate() +{ m_StateParameters.m_Play = true; m_StateParameters.m_Forw = true; @@ -24,10 +26,10 @@ void PStateInitialStream::operate() { m_StateParameters.m_Paus = false; bool xval = false; - xval = m_ImageStream->setFrameNumber(0); + xval = m_ImageStream->setFrameNumber(0); if (xval) { - m_Mat = m_ImageStream->currentFrame(); + m_Mat = m_ImageStream->currentFrame(); m_FrameNumber = m_ImageStream->currentFrameNumber(); } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h new file mode 100644 index 00000000..989c3175 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateInitialStream.h @@ -0,0 +1,29 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATEINITIALSTREAM_H +#define PSTATEINITIALSTREAM_H + +#include "IStates/IPlayerState.h" + +/** + * This State is active when a video or camera device was selected by the user. + * It sets as following state STATE_WAIT. + */ +class PStateInitialStream : public IPlayerState +{ +public: + PStateInitialStream( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; +}; + +#endif // INITIALVIDEOSTATE_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp similarity index 64% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp index 8b9cfe62..28dfe67a 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.cpp @@ -1,23 +1,25 @@ #include "PStatePause.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -PStatePause::PStatePause(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStatePause::PStatePause( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; m_StateParameters.m_Paus = false; m_StateParameters.m_Play = false; m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; m_FrameNumber = 0; - } -void PStatePause::operate() { +void PStatePause::operate() +{ m_StateParameters.m_Play = true; m_StateParameters.m_Forw = true; @@ -25,7 +27,7 @@ void PStatePause::operate() { m_StateParameters.m_Stop = true; m_StateParameters.m_Paus = false; - m_Mat = m_ImageStream->currentFrame(); + m_Mat = m_ImageStream->currentFrame(); m_FrameNumber = m_ImageStream->currentFrameNumber(); m_Player->setNextState(IPlayerState::STATE_WAIT); diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h new file mode 100644 index 00000000..05a90a2d --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePause.h @@ -0,0 +1,28 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATEPAUSE_H +#define PSTATEPAUSE_H + +#include "IStates/IPlayerState.h" + +/** + * This state is active when the user clicks on the Pause button in the GUI. + * The next state will be STATE_WAIT. + */ +class PStatePause : public IPlayerState +{ +public: + PStatePause(MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; +}; + +#endif // PSTATEPAUSE_H diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp new file mode 100644 index 00000000..d9e95613 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.cpp @@ -0,0 +1,70 @@ +#include "PStatePlay.h" +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" +#include "QTimer" + +#include +using namespace std::chrono; + +PStatePlay::PStatePlay( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ + + m_StateParameters.m_Back = false; + m_StateParameters.m_Forw = false; + m_StateParameters.m_Paus = false; + m_StateParameters.m_Play = false; + m_StateParameters.m_Stop = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; + + m_FrameNumber = 0; +} + +void PStatePlay::operate() +{ + + m_StateParameters.m_Play = true; + m_StateParameters.m_Forw = false; + m_StateParameters.m_Back = false; + m_StateParameters.m_Stop = true; + m_StateParameters.m_Paus = true; + + bool isLastFrame = m_ImageStream->lastFrame(); + IPlayerState::PLAYER_STATES nextState = IPlayerState::STATE_INITIAL; + + if (!isLastFrame) { + m_ImageStream->nextFrame(); + m_Mat = m_ImageStream->currentFrame(); + m_FrameNumber = m_ImageStream->currentFrameNumber(); + nextState = IPlayerState::STATE_PLAY; + } else if (m_ImageStream->hasNextInBatch()) { + Q_EMIT emitNextMediaInBatch("Samplestring"); + m_ImageStream->stepToNextInBatch(); + m_ImageStream->nextFrame(); + m_Mat = m_ImageStream->currentFrame(); + m_FrameNumber = m_ImageStream->currentFrameNumber(); + nextState = IPlayerState::STATE_PLAY; + Q_EMIT emitNextMediaInBatchLoaded("Samplestring"); + } else { + nextState = IPlayerState::STATE_INITIAL_STREAM; + } + + // If fps is limited, wait the neccessary time + end = std::chrono::system_clock::now(); + if (_targetFps > 0) { + long long dt = std::chrono::duration_cast( + end - start) + .count(); + long long targetFps = (1. / _targetFps) * 1000.; + + if (dt < targetFps) { + std::this_thread::sleep_for( + std::chrono::milliseconds(targetFps - dt)); + } + } + start = std::chrono::system_clock::now(); + + m_Player->setNextState(nextState); +} diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h new file mode 100644 index 00000000..e506d083 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStatePlay.h @@ -0,0 +1,40 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATEPLAY_H +#define PSTATEPLAY_H + +#include "IStates/IPlayerState.h" +#include + +/** + * This Stat is active when a video fiel is playing or a camera device is + * streaming. If the current frame is the last in the ImageStream this state + * will set STATE_INITIAL as next state. If the current frame is not the last + * frame in the ImageStream, the next state will be STATE_PLAY. + */ +class PStatePlay : public IPlayerState +{ +public: + PStatePlay(MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + void setFps(double fps) + { + _targetFps = fps; + } + + // IPlayerState interface +public Q_SLOTS: + void operate() override; + +private: + std::chrono::system_clock::time_point end, start; + double _targetFps = 0; +}; + +#endif // PSTATEPLAY_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp similarity index 69% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp index c924e4d3..d477909e 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.cpp @@ -1,32 +1,33 @@ #include "PStateStepBack.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -PStateStepBack::PStateStepBack(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStateStepBack::PStateStepBack( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; m_StateParameters.m_Paus = false; m_StateParameters.m_Play = false; m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; m_FrameNumber = 0; - } -void PStateStepBack::operate() { +void PStateStepBack::operate() +{ m_StateParameters.m_Play = true; m_StateParameters.m_Forw = true; m_StateParameters.m_Stop = true; m_StateParameters.m_Paus = false; - if (m_ImageStream->previousFrame()) { - m_Mat = m_ImageStream->currentFrame(); + m_Mat = m_ImageStream->currentFrame(); m_FrameNumber = m_ImageStream->currentFrameNumber(); } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h new file mode 100644 index 00000000..5c9abe51 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepBack.h @@ -0,0 +1,28 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATESTEPBACK_H +#define PSTATESTEPBACK_H + +#include "IStates/IPlayerState.h" + +/** + * This state will active if the user clicks on the Back button in the GUI. The + * following state will be STATE_WAIT. + */ +class PStateStepBack : public IPlayerState +{ +public: + PStateStepBack(MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; +}; + +#endif // PSTATESTEPBACK_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp similarity index 69% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp index fae818ab..e011bfa7 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.cpp @@ -1,32 +1,33 @@ #include "PStateStepForw.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" -PStateStepForw::PStateStepForw(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStateStepForw::PStateStepForw( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; m_StateParameters.m_Paus = false; m_StateParameters.m_Play = false; m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; m_FrameNumber = 0; - } -void PStateStepForw::operate() { +void PStateStepForw::operate() +{ m_StateParameters.m_Play = true; m_StateParameters.m_Back = true; m_StateParameters.m_Stop = true; m_StateParameters.m_Paus = false; - if (m_ImageStream->nextFrame()) { - m_Mat = m_ImageStream->currentFrame(); + m_Mat = m_ImageStream->currentFrame(); m_FrameNumber = m_ImageStream->currentFrameNumber(); } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h new file mode 100644 index 00000000..44b9bed4 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateStepForw.h @@ -0,0 +1,28 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATESTEPFORW_H +#define PSTATESTEPFORW_H + +#include "IStates/IPlayerState.h" + +/** + * This State is active if the user clicks the Forward button in the GUI. The + * next state will be STATE_WAIT. + */ +class PStateStepForw : public IPlayerState +{ +public: + PStateStepForw(MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; +}; + +#endif // PSTATESTEPFORW_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp similarity index 53% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp index c75d40b7..43da0dfb 100644 --- a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.cpp @@ -1,24 +1,25 @@ #include "PStateWait.h" #include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" - -PStateWait::PStateWait(MediaPlayerStateMachine* player, - std::shared_ptr imageStream) : - IPlayerState(player, imageStream) { +PStateWait::PStateWait( + MediaPlayerStateMachine* player, + std::shared_ptr imageStream) +: IPlayerState(player, imageStream) +{ m_StateParameters.m_Back = false; m_StateParameters.m_Forw = false; m_StateParameters.m_Paus = false; m_StateParameters.m_Play = false; m_StateParameters.m_Stop = false; - m_StateParameters.m_RecI = false; - m_StateParameters.m_RecO = false; + m_StateParameters.m_RecI = false; + m_StateParameters.m_RecO = false; m_FrameNumber = 0; - } -void PStateWait::operate() { +void PStateWait::operate() +{ // Just Wait } diff --git a/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h new file mode 100644 index 00000000..ca7f35a6 --- /dev/null +++ b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWait.h @@ -0,0 +1,27 @@ +/**************************************************************************** + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ + +#ifndef PSTATEWAIT_H +#define PSTATEWAIT_H + +#include "IStates/IPlayerState.h" + +/** + * This state dose nothing. There is also no next state set by this state. + */ +class PStateWait : public IPlayerState +{ +public: + PStateWait(MediaPlayerStateMachine* player, + std::shared_ptr imageStream); + + // IPlayerState interface +public Q_SLOTS: + void operate() override; +}; + +#endif // PSTATEWAIT_H diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.cpp.autosave b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.cpp.autosave similarity index 100% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.cpp.autosave rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.cpp.autosave diff --git a/BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.h.autosave b/Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.h.autosave similarity index 100% rename from BioTracker/CoreApp/BioTracker/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.h.autosave rename to Src/Model/MediaPlayerStateMachine/PlayerStates/PStateWaite.h.autosave diff --git a/BioTracker/CoreApp/BioTracker/Model/TextureObject.cpp b/Src/Model/TextureObject.cpp similarity index 53% rename from BioTracker/CoreApp/BioTracker/Model/TextureObject.cpp rename to Src/Model/TextureObject.cpp index 91a09ea0..8435d3d3 100644 --- a/BioTracker/CoreApp/BioTracker/Model/TextureObject.cpp +++ b/Src/Model/TextureObject.cpp @@ -1,21 +1,24 @@ #include "TextureObject.h" -TextureObject::TextureObject(QObject *parent, QString name) : - IModel(parent), - m_Name(name) +TextureObject::TextureObject(QObject* parent, QString name) +: IModel(parent) +, m_Name(name) { // OpenCV's coordinate system originates in the upper left corner. - // OpenGL originates in the lower left. Thus the image has to be flipped vertically + // OpenGL originates in the lower left. Thus the image has to be flipped + // vertically m_texture = QImage(1, 1, QImage::Format_RGB888); } -void TextureObject::set(const cv::Mat &img) { - //TODO Andi this cv::Mat is null sometimes when using the camera!? - if (&img == NULL) - return; +void TextureObject::set(cv::Mat img) +{ + if (img.empty()) { + return; + } + if (img.channels() == 3) { - img.convertTo(img, CV_8UC3); - cv::cvtColor(img, m_img, CV_BGR2RGB); + img.convertTo(m_img, CV_8UC3); + cv::cvtColor(m_img, m_img, cv::ColorConversionCodes::COLOR_BGR2RGB); } else if (img.channels() == 1) { // convert grayscale to "color" cv::Mat img8U; @@ -23,31 +26,33 @@ void TextureObject::set(const cv::Mat &img) { // we assume that the 1d image has more than 8bit per pixel // (usually 64F) so we need to map a [HUGE range] to -> [0 .. 255] double min, max; + // FIXME: This still sometimes crashes when accessing the img data. + // cv::Mat is reference counted, so all cv::Mat + // instances should be replaced with cv::Mat. cv::minMaxLoc(img, &min, &max); - if (min >= 0 && min < 255 && max > 0 && max <= 255) { + if (min >= 0 && min < 255 && max >= 0 && max <= 255) { // do not refit if the range is actually inbetween [0 ... 255] img.convertTo(img8U, CV_8U); } else if (max > min) { // otherwise: the range is outside of native [0 ... 255] so we // actually need to do some refitting - // mapping 1-step out from [0 .. 255] range 1-step in the [min .. max] range - const double sizeRatio = 256.0/abs(static_cast(max - min)); + // mapping 1-step out from [0 .. 255] range 1-step in the [min .. + // max] range + const double sizeRatio = 256.0 / abs(static_cast(max - min)); const double convertedMin = abs(static_cast(min * sizeRatio)); img.convertTo(img8U, CV_8U, sizeRatio, convertedMin); } - cv::cvtColor(img8U, m_img, CV_GRAY2RGB); + cv::cvtColor(img8U, m_img, cv::ColorConversionCodes::COLOR_GRAY2RGB); } else { - m_img = img; + img.copyTo(m_img); } - m_texture = QImage( - m_img.data, - m_img.cols, - m_img.rows, - static_cast(m_img.step), - QImage::Format_RGB888 - ); + m_texture = QImage(m_img.data, + m_img.cols, + m_img.rows, + static_cast(m_img.step), + QImage::Format_RGB888); Q_EMIT notifyView(); } diff --git a/BioTracker/CoreApp/BioTracker/Model/TextureObject.h b/Src/Model/TextureObject.h similarity index 53% rename from BioTracker/CoreApp/BioTracker/Model/TextureObject.h rename to Src/Model/TextureObject.h index f136f04e..f1d6e639 100644 --- a/BioTracker/CoreApp/BioTracker/Model/TextureObject.h +++ b/Src/Model/TextureObject.h @@ -1,10 +1,9 @@ /**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg and BioTracker in version 2. - ** - ****************************************************************************/ - + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg and BioTracker in version 2. + ** + ****************************************************************************/ #ifndef BIOTRACKER3TEXTUREOBJECT_H #define BIOTRACKER3TEXTUREOBJECT_H @@ -16,31 +15,37 @@ #include "QString" /** - * The TextureObject class in an IModel class. It is responsible for converting cv::Mats to QImages. These QImages are then displayed in the TextureObjectView. - * This class was adapted from the TextureObject class in BioTracker 2. + * The TextureObject class in an IModel class. It is responsible for converting + * cv::Mats to QImages. These QImages are then displayed in the + * TextureObjectView. This class was adapted from the TextureObject class in + * BioTracker 2. */ -class TextureObject : public IModel { +class TextureObject : public IModel +{ Q_OBJECT - public: +public: explicit TextureObject(QObject* parent = 0, QString name = "NoName"); - void set(cv::Mat const& img); + void set(cv::Mat img); QString getName(); - QImage const& get() const { + QImage const& get() const + { return m_texture; } - int width() const { + int width() const + { return m_texture.width(); } - int height() const { + int height() const + { return m_texture.height(); } - private: +private: QString m_Name; cv::Mat m_img; - QImage m_texture; + QImage m_texture; }; #endif // BIOTRACKER3TEXTUREOBJECT_H diff --git a/Src/Model/UndoCommands/TrackCommands.cpp b/Src/Model/UndoCommands/TrackCommands.cpp new file mode 100644 index 00000000..4304bdf8 --- /dev/null +++ b/Src/Model/UndoCommands/TrackCommands.cpp @@ -0,0 +1,188 @@ +#include "TrackCommands.h" + +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "QUndoCommand" +#include "QPoint" +#include "QDebug" + +AddTrackCommand::AddTrackCommand(int id, QPoint pos, QUndoCommand* parent) +: QUndoCommand(parent) +, _id(id) +, _pos(pos) +{ + _added = false; + setText(QString("Add trajectory ") + QString::number(id)); +} + +void AddTrackCommand::undo() +{ + emitRemoveTrajectoryId(_id); +} + +void AddTrackCommand::redo() +{ + if (!_added) { + Q_EMIT emitAddTrajectory(_pos); + _added = true; + } else { + emitValidateTrajectory(_id); + } +} + +RemoveTrackCommand::RemoveTrackCommand(IModelTrackedTrajectory* traj, + QUndoCommand* parent) +: QUndoCommand(parent) +, _traj(traj) +{ + setText(QString("Remove trajectory ") + QString::number(traj->getId())); +} + +void RemoveTrackCommand::undo() +{ + emitValidateTrajectory(_traj->getId()); +} + +void RemoveTrackCommand::redo() +{ + emitRemoveTrajectory(_traj); +} + +RemoveElementCommand::RemoveElementCommand(IModelTrackedTrajectory* traj, + uint frameNumber, + QUndoCommand* parent) +: QUndoCommand(parent) +, _traj(traj) +, _frameNumber(frameNumber) +{ + + setText("Remove entity " + QString::number(_frameNumber) + + " of trajectory " + QString::number(traj->getId())); +} + +void RemoveElementCommand::undo() +{ + emitValidateEntity(_traj, _frameNumber); +} + +void RemoveElementCommand::redo() +{ + emitRemoveElement(_traj, _frameNumber); +} + +MoveElementCommand::MoveElementCommand(IModelTrackedTrajectory* traj, + uint frameNumber, + QPoint oldPos, + QPoint newPos, + int toMove, + QUndoCommand* parent) +: QUndoCommand(parent) +, _traj(traj) +, _frameNumber(frameNumber) +, _oldPos(oldPos) +, _newPos(newPos) +, _toMove(toMove) +{ + setText("Move entity " + QString::number(_frameNumber) + + " of trajectory " + QString::number(traj->getId()) + " to " + + QString::number(_newPos.x()) + ", " + + QString::number(_newPos.y())); +} + +void MoveElementCommand::undo() +{ + emitMoveElement(_traj, _frameNumber, _oldPos, _toMove); +} + +void MoveElementCommand::redo() +{ + emitMoveElement(_traj, _frameNumber, _newPos, _toMove); + _toMove = 1; +} + +/*bool MoveElementCommand::mergeWith(const QUndoCommand * command) +//{ +// const MoveElementCommand *moveCommandToMerge = static_cast(command); +// IModelTrackedTrajectory* trajToMerge = moveCommandToMerge->_traj; +// uint frameNumberToMerge = moveCommandToMerge->_frameNumber; +// +// if ((_traj != trajToMerge) || (frameNumberToMerge != _frameNumber)) { +// return false; +// } +// +// _oldPos +// +}*/ + +SwapTrackIdCommand::SwapTrackIdCommand(IModelTrackedTrajectory* traj0, + IModelTrackedTrajectory* traj1, + QUndoCommand* parent) +: QUndoCommand(parent) +, _traj0(traj0) +, _traj1(traj1) +{ + setText("Swap id's of " + QString::number(_traj0->getId()) + " and " + + QString::number(_traj1->getId())); +} + +void SwapTrackIdCommand::undo() +{ + emitSwapIds(_traj1, _traj0); +} + +void SwapTrackIdCommand::redo() +{ + emitSwapIds(_traj0, _traj1); +} + +FixTrackCommand::FixTrackCommand(IModelTrackedTrajectory* traj, + bool isFixed, + QUndoCommand* parent) +: QUndoCommand(parent) +, _traj(traj) +, _isFixed(isFixed) +{ + if (_isFixed) { + setText("Fix tracking data of trajectory " + + QString::number(_traj->getId())); + } else { + setText("Unfix tracking data of trajectory " + + QString::number(_traj->getId())); + } +} + +void FixTrackCommand::undo() +{ + emitFixTrack(_traj, !_isFixed); +} + +void FixTrackCommand::redo() +{ + emitFixTrack(_traj, _isFixed); +} + +RotateEntityCommand::RotateEntityCommand(IModelTrackedTrajectory* traj, + double oldAngle, + double angle, + uint frameNumber, + QUndoCommand* parent) +: QUndoCommand(parent) +, _traj(traj) +, _newAngle(angle) +, _oldAngle(oldAngle) +, _frameNumber(frameNumber) +{ + setText("Rotate entity " + QString::number(_frameNumber) + + " of trajectory " + QString::number(_traj->getId()) + " to " + + QString::number(_newAngle)); +} + +void RotateEntityCommand::undo() +{ + emitEntityRotation(_traj, _oldAngle, _frameNumber); +} + +void RotateEntityCommand::redo() +{ + emitEntityRotation(_traj, _newAngle, _frameNumber); +} \ No newline at end of file diff --git a/Src/Model/UndoCommands/TrackCommands.h b/Src/Model/UndoCommands/TrackCommands.h new file mode 100644 index 00000000..b020c57d --- /dev/null +++ b/Src/Model/UndoCommands/TrackCommands.h @@ -0,0 +1,185 @@ +#ifndef TRACKCOMMANDS_H +#define TRACKCOMMANDS_H + +#pragma once + +#include "QUndoCommand" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "QPoint" + +// http://doc.qt.io/qt-5/qundo.html + +/** + * Add track command with data to do and undo: + * position, id, traj, added + */ +class AddTrackCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + AddTrackCommand(int id, QPoint pos, QUndoCommand* parent = 0); + void undo() override; + void redo() override; +signals: + void emitAddTrajectory(QPoint pos); + void emitValidateTrajectory(int id); + void emitRemoveTrajectoryId(int id); + +private: + IModelTrackedTrajectory* _traj; + int _id; + QPoint _pos; + bool _added; +}; + +/** + * Remove Track command with data to do and undo: + * traj + */ +class RemoveTrackCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + RemoveTrackCommand(IModelTrackedTrajectory* traj, + QUndoCommand* parent = 0); + + void undo() override; + void redo() override; +signals: + void emitValidateTrajectory(int id); + void emitRemoveTrajectory(IModelTrackedTrajectory* traj); + +private: + IModelTrackedTrajectory* _traj; +}; + +/** + * Remove Entity command with data to do and undo: + * traj, framenumber + */ +class RemoveElementCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + RemoveElementCommand(IModelTrackedTrajectory* traj, + uint frameNumber, + QUndoCommand* parent = 0); + + void undo() override; + void redo() override; +signals: + void emitValidateEntity(IModelTrackedTrajectory* traj, uint frameNumber); + void emitRemoveElement(IModelTrackedTrajectory* traj, uint frameNumber); + +private: + IModelTrackedTrajectory* _traj; + uint _frameNumber; +}; + +/** + * Move Entity command with data to do and undo: + * traj, oldPos, newPos, hwo many left to move (for a multimove), framenuber + */ +class MoveElementCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + MoveElementCommand(IModelTrackedTrajectory* traj, + uint frameNumber, + QPoint oldPos, + QPoint newPos, + int toMove, + QUndoCommand* parent = 0); + + void undo() override; + void redo() override; + // bool mergeWith(const QUndoCommand *command) override; +signals: + void emitMoveElement(IModelTrackedTrajectory* traj, + uint _frameNumber, + QPoint pos, + int toMove); + +private: + IModelTrackedTrajectory* _traj; + uint _frameNumber; + QPoint _oldPos; + QPoint _newPos; + int _toMove; +}; + +/** + * Swap Track Id command with data to do and undo: + * traj 0 and traj 1 + */ +class SwapTrackIdCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + SwapTrackIdCommand(IModelTrackedTrajectory* traj0, + IModelTrackedTrajectory* traj1, + QUndoCommand* parent = 0); + + void undo() override; + void redo() override; + +signals: + void emitSwapIds(IModelTrackedTrajectory* traj0, + IModelTrackedTrajectory* traj1); + +private: + IModelTrackedTrajectory* _traj0; + IModelTrackedTrajectory* _traj1; +}; + +/** + * Fix Track command with data to do and undo: + * fix toggle and traj + */ +class FixTrackCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + FixTrackCommand(IModelTrackedTrajectory* traj, + bool isFixed, + QUndoCommand* parent = 0); + + void undo() override; + void redo() override; +signals: + void emitFixTrack(IModelTrackedTrajectory* traj, bool toggle); + +private: + IModelTrackedTrajectory* _traj; + bool _isFixed; +}; + +/** + * Rotate Entity command with data to do and undo: + * traj, old angle, new angle, fraemenumber + */ +class RotateEntityCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + RotateEntityCommand(IModelTrackedTrajectory* traj, + double oldAngleDeg, + double newAngleDeg, + uint frameNumber, + QUndoCommand* parent = 0); + + void undo() override; + void redo() override; +signals: + void emitEntityRotation(IModelTrackedTrajectory* traj, + double angle, + uint frameNumber); + +private: + IModelTrackedTrajectory* _traj; + double _oldAngle; + double _newAngle; + uint _frameNumber; +}; + +#endif // TRACKCOMMANDS_H diff --git a/BioTracker/CoreApp/BioTracker/Model/null_Model.cpp b/Src/Model/null_Model.cpp similarity index 98% rename from BioTracker/CoreApp/BioTracker/Model/null_Model.cpp rename to Src/Model/null_Model.cpp index db2793d0..4328117f 100644 --- a/BioTracker/CoreApp/BioTracker/Model/null_Model.cpp +++ b/Src/Model/null_Model.cpp @@ -2,5 +2,4 @@ null_Model::null_Model() { - } diff --git a/BioTracker/CoreApp/BioTracker/Model/null_Model.h b/Src/Model/null_Model.h similarity index 58% rename from BioTracker/CoreApp/BioTracker/Model/null_Model.h rename to Src/Model/null_Model.h index c169409b..7c7ad8df 100644 --- a/BioTracker/CoreApp/BioTracker/Model/null_Model.h +++ b/Src/Model/null_Model.h @@ -1,9 +1,9 @@ /**************************************************************************** - ** - ** This file is part of the BioTracker Framework - ** by Andreas Jörg - ** - ****************************************************************************/ + ** + ** This file is part of the BioTracker Framework + ** by Andreas Jörg + ** + ****************************************************************************/ #ifndef NULL_MODEL_H #define NULL_MODEL_H @@ -13,9 +13,10 @@ /** * The null_Model class is only for initialization of IModel classes. */ -class null_Model : public IModel { +class null_Model : public IModel +{ Q_OBJECT - public: +public: null_Model(); }; diff --git a/Src/PluginLoader.cpp b/Src/PluginLoader.cpp new file mode 100644 index 00000000..5e41759b --- /dev/null +++ b/Src/PluginLoader.cpp @@ -0,0 +1,345 @@ +#include "PluginLoader.h" +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include + #include + #include + #include + #include + #define MAX_KEY_LENGTH 255 + #define MAX_VALUE_NAME 16383 + +std::vector QueryKey(HKEY hKey, std::string path) +{ + // See + // https://docs.microsoft.com/en-us/windows/desktop/sysinfo/enumerating-registry-subkeys + std::vector list; + TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name + DWORD cchClassName = MAX_PATH; // size of class string + DWORD cSubKeys = 0; // number of subkeys + DWORD cbMaxSubKey; // longest subkey size + DWORD cchMaxClass; // longest class string + DWORD cValues; // number of values for key + DWORD cchMaxValue; // longest value name + DWORD cbMaxValueData; // longest value data + DWORD cbSecurityDescriptor; // size of security descriptor + FILETIME ftLastWriteTime; // last write time + + DWORD i, retCode; + + TCHAR achValue[MAX_VALUE_NAME]; + DWORD cchValue = MAX_VALUE_NAME; + + // Get the class name and the value count. + retCode = RegQueryInfoKey(hKey, // key handle + achClass, // buffer for class name + &cchClassName, // size of class string + NULL, // reserved + &cSubKeys, // number of subkeys + &cbMaxSubKey, // longest subkey size + &cchMaxClass, // longest class string + &cValues, // number of values for this key + &cchMaxValue, // longest value name + &cbMaxValueData, // longest value data + &cbSecurityDescriptor, // security descriptor + &ftLastWriteTime); // last write time + + // Enumerate the key values. + if (cValues) { + // printf( "\nNumber of values: %d\n", cValues); + + for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++) { + cchValue = MAX_VALUE_NAME; + achValue[0] = '\0'; + retCode = RegEnumValue(hKey, + i, + achValue, + &cchValue, + NULL, + NULL, + NULL, + NULL); + + if (retCode == ERROR_SUCCESS) { + CRegKey regKey; + CHAR szBuffer[512]; + ULONG dwBufferSize = sizeof(szBuffer); + + if (auto error_code = regKey.Open(HKEY_LOCAL_MACHINE, + path.c_str(), + KEY_READ); + error_code != ERROR_SUCCESS) { + qWarning() << "Error opening windows registry path " + << path.c_str() << ": " << error_code; + regKey.Close(); + continue; + } + if (auto error_code = regKey.QueryStringValue(achValue, + szBuffer, + &dwBufferSize); + error_code != ERROR_SUCCESS) { + qWarning() << "Error opening windows registry value " + << achValue << ": " << error_code; + regKey.Close(); + continue; + } + + std::string fp = szBuffer; + std::replace(fp.begin(), fp.end(), '\\', '/'); + list.push_back(fp); + } + } + } + return list; +} +#endif + +std::vector PluginLoader::queryRegistryBehaviors(std::string path) +{ + std::vector list; + +#ifdef _WIN32 + HKEY hTestKey; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT(path.c_str()), + 0, + KEY_READ, + &hTestKey) == ERROR_SUCCESS) { + list = QueryKey(hTestKey, path); + } + + RegCloseKey(hTestKey); +#endif + + return list; +} + +#ifdef _WIN32 +const char* WinGetEnv(const char* name) +{ + const DWORD buffSize = 65535; + static char buffer[buffSize]; + if (GetEnvironmentVariableA(name, buffer, buffSize)) { + return buffer; + } else { + return 0; + } +} +bool WinSetEnv(const char* name, const char* toWhat) +{ + return SetEnvironmentVariableA(name, toWhat); +} +#endif + +bool is_shared_library(std::filesystem::path const& p) +{ + auto extension = p.extension(); + return extension == ".so" || extension == ".dylib" || extension == ".dll"; +} + +const char* PluginLoader::addDllPath(std::string f) +{ +// Get the directory of the DLL/*.so and add it to the PATH env variable. +// This way dependencies can be shipped in the same directory +#ifdef _WIN32 + QFileInfo finf(f.c_str()); + // rather than the buggy _getenv: + // https://docs.microsoft.com/de-de/windows/desktop/api/winbase/nf-winbase-getenvironmentvariable + auto old_path = WinGetEnv("PATH"); + auto path = std::ostringstream(); + if (old_path) { + path << old_path << ";" << finf.absolutePath().toStdString().c_str(); + WinSetEnv("PATH", path.str().c_str()); + } else { + qWarning() << "Failed to get and modify PATH enviromental variable."; + } + return old_path; +#endif + + return ""; +} + +void PluginLoader::delDllPath(const char* oldPath) +{ +// reset path. We don't want some weird cross-effects +#ifdef _WIN32 + if (oldPath) { + WinSetEnv("PATH", oldPath); + } +#endif +} + +bool endsWith(std::string value, std::string ending) +{ + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + std::transform(ending.begin(), ending.end(), ending.begin(), ::tolower); + if (ending.size() > value.size()) + return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + +bool validSuffix(std::string f, std::string suffix) +{ + return (endsWith(f, suffix + ".dll") || endsWith(f, suffix + ".so")); +} + +std::vector PluginLoader::searchDirectoriesForPlugins( + std::vector list, + std::string suffix) +{ + // Search directories + std::vector filesFromFolders; + + for (auto f : list) { + auto path = std::filesystem::path(f); + if (path.empty()) { + continue; + } + if (std::filesystem::is_directory(path)) { + try { + for (auto& e : std::filesystem::directory_iterator(path)) { + auto p = e.path(); + if (is_shared_library(p) && + p.replace_extension().extension() == suffix) { + filesFromFolders.push_back(e.path().string()); + } + } + } catch (std::filesystem::filesystem_error const& e) { + qWarning() << e.what(); + } + } else if (is_shared_library(path)) { + filesFromFolders.push_back(f); + } else { + qWarning() << "Neither a directory, nor a shared library:" + << f.data(); + } + } + + return filesFromFolders; +} + +PluginLoader::PluginLoader(QObject* parent) +{ + m_MetaData = nullptr; + m_PluginLoader = new QPluginLoader(this); + m_PluginListModel = new QStringListModel(); +} +PluginLoader::~PluginLoader() +{ + delete m_PluginLoader; + delete m_PluginListModel; +} + +bool PluginLoader::loadPluginFromFilename(QString const& filename) +{ + bool retval = false; + if (m_PluginLoader->isLoaded()) { + m_PluginLoader->unload(); + } + + bool isLib = QLibrary::isLibrary(filename); + + if (isLib) { + + auto oldPath = PluginLoader::addDllPath(filename.toStdString()); + m_PluginLoader->setFileName(filename); + + readMetaDataFromPlugin(); + + retval = m_PluginLoader->load(); + QString s = m_PluginLoader->errorString(); + std::string ss = s.toStdString(); + addPluginnameToLists(getCurrentPluginName(), filename); + + if (!m_PluginLoader->isLoaded()) { + qWarning() << ss.c_str(); + retval = false; + } + PluginLoader::delDllPath(oldPath); + } else { + retval = false; + } + + return retval; +} + +void PluginLoader::addPluginnameToLists(QString mstring, QString filename) +{ + if (!m_PluginList.contains(mstring)) + m_PluginList.append(mstring); + m_PluginListModel->setStringList(m_PluginList); + m_PluginMap.insert(std::pair(mstring, filename)); +} + +bool PluginLoader::loadPluginFromName(QString name) +{ + QString filename = m_PluginMap.find(name)->second; + return loadPluginFromFilename(filename); +} + +int PluginLoader::addToPluginList(QString filename, QString suffix) +{ + if (!validSuffix(filename.toStdString(), suffix.toStdString())) + return 1; + + bool isLib = QLibrary::isLibrary(filename); + + if (isLib) { + + QPluginLoader loader; + loader.setFileName(filename); + QJsonValue pluginMeda(loader.metaData().value("MetaData")); + QJsonObject metaObj = pluginMeda.toObject(); + QString mstring = metaObj.value("name").toString(); + addPluginnameToLists(mstring, filename); + } else { + return 2; + qWarning() << "Error reading plugin: " << filename; + } + return 0; +} + +QStringListModel* PluginLoader::getPluginList() +{ + return m_PluginListModel; +} + +QObject* PluginLoader::getPluginInstance() +{ + return (m_PluginLoader->instance()); +} + +QJsonObject PluginLoader::getPluginMetaData() const +{ + if (m_MetaData == nullptr) + qFatal("(getPluginMetaData) No plugin loaded"); + return *m_MetaData; +} + +void PluginLoader::readMetaDataFromPlugin() +{ + m_MetaData = std::make_shared( + m_PluginLoader->metaData().value("MetaData").toObject()); +} + +bool PluginLoader::getIsPluginLoaded() +{ + return m_isPluginLoaded; +} + +QString PluginLoader::getCurrentPluginName() +{ + if (m_MetaData == nullptr) + return "Error name"; + return m_MetaData->value("name").toString(); +} +const std::map& PluginLoader::getPluginMap() const +{ + return m_PluginMap; +} diff --git a/Src/PluginLoader.h b/Src/PluginLoader.h new file mode 100644 index 00000000..ea93edee --- /dev/null +++ b/Src/PluginLoader.h @@ -0,0 +1,110 @@ + +#ifndef PLUGINLOADER_H +#define PLUGINLOADER_H + +#include "QPluginLoader" +#include "QStringListModel" +#include "QPointer" +#include +#include + +/** + * \class PluginLoader + * This class loads Qt-Plugins, the related metadata and files the plugin + * depends on. \author Hauke Mönck, Gregor Barth + */ + +class PluginLoader : QObject +{ + Q_OBJECT +public: + explicit PluginLoader(QObject* parent = 0); + + ~PluginLoader(); + + /** + * Loads a file as a QT plugin and reads it's name from the metadata. + * It will then be added to the stringlist and is selectable via + * "loadPluginFromName". This function does not actually set the plugin + * instance. + */ + int addToPluginList(QString filename, QString suffix); + + /** + * Returns a QStrinListModel with the names of all seen Plugins. + */ + QStringListModel* getPluginList(); + + /** + * Loads a BioTracker Plugin from a file path. It returns true if the + * Plugin could be loaded, otherwise false. The loaded plugin acts as + * singleton! + */ + bool loadPluginFromFilename(QString const& filename); + + /** + * Loads a plugin from it's name (given in the metadata) instead of the + * filename. Only works if it is already known to the pluginloader, i.e. + * was loaded manually or automatically before or or has been added to the + * pluginlist via "addToPluginList" + */ + bool loadPluginFromName(QString name); + + QJsonObject getPluginMetaData() const; + + static std::vector queryRegistryBehaviors(std::string path); + + static std::vector searchDirectoriesForPlugins( + std::vector list, + std::string suffix); + + // return oldPath + static const char* addDllPath(std::string file); + + static void delDllPath(const char* oldPath); + + // Is a plugin loaded or not? + bool getIsPluginLoaded(); + + // Gets the name of the currently loaded plugin + QString getCurrentPluginName(); + + /** + * Returns the Instance of the BioTracker Plugin. + */ + QObject* getPluginInstance(); + + /** + * Returns a map containing the mapping "plugin name -> filename" + */ + std::map const& getPluginMap() const; + +private: + void addPluginnameToLists(QString name, QString filename); + + // a map containing the mapping "plugin name -> filename" + std::map m_PluginMap; + + /** + * Gets the metadata from the currently loaded plugin. + * Currently this is nothing but the advertised name of the plugin + */ + void readMetaDataFromPlugin(); + + // The QT object to actually load the plugins + QPluginLoader* m_PluginLoader; + + std::shared_ptr m_MetaData; + + // nomen est omen + bool m_isPluginLoaded; + + // List of all available plugins + QStringList m_PluginList; + + // Entire ListModel of the metadata (actually containing all metadata, not + // only name) + QStringListModel* m_PluginListModel; +}; + +#endif // PLUGINLOADER_H diff --git a/Src/View/AnnotationsView.cpp b/Src/View/AnnotationsView.cpp new file mode 100644 index 00000000..be252cca --- /dev/null +++ b/Src/View/AnnotationsView.cpp @@ -0,0 +1,78 @@ +#include "AnnotationsView.h" + +#include +#include +#include + +#include "Interfaces/IController/IController.h" + +#include "Model/Annotations.h" +#include "View/GraphicsView.h" + +AnnotationsView::~AnnotationsView() +{ +} + +void AnnotationsView::prepareUpdate() +{ + prepareGeometryChange(); +} + +void AnnotationsView::setColor(QColor color) +{ + _annoColor = color; +} + +QRectF AnnotationsView::boundingRect() const +{ + auto model = static_cast(getModel()); + + QRectF rect{}; + for (auto& annotation : model->annotations) { + rect = rect.united(annotation->boundingRect()); + } + + if (model->currentAnnotation) + rect = rect.united(model->currentAnnotation->boundingRect()); + return rect; +} + +void AnnotationsView::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + setZValue(-1); + auto model = static_cast(getModel()); + const auto currentFrame = model->getCurrentFrame(); + for (auto& annotation : model->annotations) { + if (annotation->isHidden()) + continue; + // Is the current frame in the annotation's range? + if ((currentFrame >= annotation->startFrame && + currentFrame <= annotation->endFrame) || + (currentFrame == annotation->startFrame && + annotation->startFrame > annotation->endFrame)) + painter->setPen(QPen(_annoColor, 3, Qt::SolidLine, Qt::RoundCap)); + else { + QColor transparentGray = Qt::gray; + transparentGray.setAlphaF(0.2); + painter->setPen( + QPen(transparentGray, 2.5, Qt::DashLine, Qt::RoundCap)); + } + annotation->paint(painter, option, widget); + } + + if (model->currentAnnotation) { + QColor transparentYellow = _annoColor; + transparentYellow.setAlphaF(0.5); + painter->setPen( + QPen(transparentYellow, 3, Qt::SolidLine, Qt::RoundCap)); + model->currentAnnotation->paint(painter, option, widget); + } + if (model->selection) { + painter->setPen(QPen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap)); + Annotations::Annotation::drawHandleLocation(painter, + *model->selection.handle, + ""); + } +} \ No newline at end of file diff --git a/Src/View/AnnotationsView.h b/Src/View/AnnotationsView.h new file mode 100644 index 00000000..bb7c654b --- /dev/null +++ b/Src/View/AnnotationsView.h @@ -0,0 +1,45 @@ +#pragma once + +#include "Interfaces/IView/IView.h" + +#include +#include +#include + +class GraphicsView; + +/** + * This view inherits from IView and QGraphicsItem. + * It is responsible for drawing the annotations. + * It is shown on to of the media panel. + */ +class AnnotationsView : public IView, public QGraphicsItem +{ +public: + using IView::IView; + AnnotationsView() = delete; + virtual ~AnnotationsView(); + +public: + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + void prepareUpdate(); + void setColor(QColor color); + +protected: + QRectF boundingRect() const; + + // IView interface +public: + void setNewModel(IModel* model) override + { + setModel(model); + }; + +protected: + void connectModelView() override{}; + + // members + QColor _annoColor = QColor(Qt::yellow); /**< color of all annotations */ +}; diff --git a/Src/View/AreaDesciptor/AreaDescriptor.cpp b/Src/View/AreaDesciptor/AreaDescriptor.cpp new file mode 100644 index 00000000..ec26cce6 --- /dev/null +++ b/Src/View/AreaDesciptor/AreaDescriptor.cpp @@ -0,0 +1,12 @@ +#include "AreaDescriptor.h" +#include "Controller/IControllerCfg.h" + +AreaDescriptor::AreaDescriptor(IController* controller, IModel* model) +: IView(controller, model) +{ + _cfg = static_cast(controller)->getConfig(); +}; + +AreaDescriptor::~AreaDescriptor() +{ +} diff --git a/Src/View/AreaDesciptor/AreaDescriptor.h b/Src/View/AreaDesciptor/AreaDescriptor.h new file mode 100644 index 00000000..261ad1ac --- /dev/null +++ b/Src/View/AreaDesciptor/AreaDescriptor.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Interfaces/IView/IViewTrackedComponent.h" +#include +#include "util/Config.h" + +class AreaDescriptor : public QObject, public IView, public QGraphicsItem +{ + Q_OBJECT + Q_INTERFACES(QGraphicsItem) +public: + AreaDescriptor(IController* controller, IModel* model); + ~AreaDescriptor(); + + virtual void setBrush(QBrush brush) = 0; + virtual void setRect(std::vector rect) = 0; + virtual std::vector getRect() = 0; + virtual void updateRect() = 0; + + void setDimensions(int x, int y) + { + _vdimX = x; + _vdimY = y; + } + +protected: + int _vdimX = 1; + int _vdimY = 1; + Config* _cfg; +}; diff --git a/Src/View/AreaDesciptor/EllipseDescriptor.cpp b/Src/View/AreaDesciptor/EllipseDescriptor.cpp new file mode 100644 index 00000000..4646aa3b --- /dev/null +++ b/Src/View/AreaDesciptor/EllipseDescriptor.cpp @@ -0,0 +1,186 @@ +#include "EllipseDescriptor.h" +#include "Model/AreaDescriptor/AreaInfoElement.h" +#include "Utility/misc.h" + +#include "QBrush" +#include "QPainter" +#include +#include + +EllipseDescriptor::EllipseDescriptor(IController* controller, IModel* model) +: AreaDescriptor(controller, model) +{ + setAcceptHoverEvents(true); + setAcceptedMouseButtons(Qt::MouseButtons::enum_type::LeftButton); + + _brush = QBrush(Qt::blue); + + _v = (dynamic_cast(getModel()))->getVertices(); + for (int i = 0; i < 4; i++) { + std::shared_ptr ri = + std::make_shared( + QRect(_v[i].x - 10, _v[i].y - 10, 20, 20), + this); + ri->setBrush(_brush); + } + + updateEllipse(); + + _isInit = false; +} + +void EllipseDescriptor::init() +{ + _rectificationMarkerOrig->setBrush(_brush); + _rectificationMarkerEnd->setBrush(_brush); +} + +void EllipseDescriptor::updateEllipse() +{ + + _v = (dynamic_cast(getModel()))->getVertices(); + _rectification = std::make_shared( + QRect(_v[0].x, _v[0].y, _v[1].x - _v[0].x, _v[1].y - _v[0].y), + this); + _rectificationMarkerOrig = std::make_shared( + QRect(_v[0].x, _v[0].y, 10, 10), + this); + _rectificationMarkerEnd = std::make_shared( + QRect(_v[1].x, _v[1].y, 10, 10), + this); + _rectificationMarkerOrig->setBrush(_brush); + _rectificationMarkerEnd->setBrush(_brush); +} + +EllipseDescriptor::~EllipseDescriptor() +{ +} + +void EllipseDescriptor::setBrush(QBrush brush) +{ + _brush = brush; + _rectificationMarkerOrig->setBrush(_brush); + _rectificationMarkerEnd->setBrush(_brush); +} + +void EllipseDescriptor::updateRect() +{ + setRect(getRect()); +} + +void EllipseDescriptor::setRect(std::vector rect) +{ + if (rect.size() >= 2) { + _v = (dynamic_cast(getModel()))->getVertices(); + updateEllipse(); + } +} + +void EllipseDescriptor::receiveDragUpdate(BiotrackerTypes::AreaType vectorType, + int id, + double x, + double y) +{ + int atype = (dynamic_cast(getModel()))->getAreaType(); + if (atype == vectorType) { + _dragVectorId = id; + _drag = QPoint(x, y); + } else { + _dragVectorId = -1; + } + update(); +} + +std::vector EllipseDescriptor::getRect() +{ + return (dynamic_cast(getModel()))->getVertices(); +} + +void EllipseDescriptor::getNotified() +{ +} + +QRectF EllipseDescriptor::boundingRect() const +{ + return QRect(10, 10, 10, 10); +} + +bool isInverted(int x1, int y1, int x2, int y2) +{ + if ((x1 > x2 && y1 < y2) || (x1 < x2 && y1 > y2)) { + return true; + } + return false; +} + +void EllipseDescriptor::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + if (!_isInit) + init(); + + // TODO remove hardcoding and code duplication + if (_dragVectorId >= 0) { + QColor transparentGray = Qt::gray; + transparentGray.setAlphaF(0.75); + painter->setPen(QPen(transparentGray, 1, Qt::SolidLine)); + painter->drawRect(_drag.x(), _drag.y(), 10, 10); + + auto fst = _dragVectorId != 0 ? _rectificationMarkerOrig + : _rectificationMarkerEnd; + bool inv = + isInverted(fst->rect().x(), fst->rect().y(), _drag.x(), _drag.y()); + int x = fst->rect().x() + (_drag.x() - fst->rect().x()) / 2.0; + int y = fst->rect().y() + (_drag.y() - fst->rect().y()) / 2.0; + + if (inv) { + // Create a canvas to draw on + QImage image(_vdimX, _vdimY, QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::transparent); + QPainter p(&image); + + // Create dark rect which spans the screen + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + QRectF r(0, 0, _vdimX, _vdimY); + QColor b; + b.setRgb(0, 0, 0, 200); + QBrush brush(b); + p.fillRect(r, brush); + p.drawRect(r); + + // Cut out the rectangle + p.setCompositionMode(QPainter::CompositionMode_DestinationOut); + b.setNamedColor("white"); + b.setAlpha(125); + QBrush bbb(b); + p.setBrush(bbb); + p.drawEllipse(QRect(fst->rect().x(), + fst->rect().y(), + _drag.x() - fst->rect().x(), + _drag.y() - fst->rect().y())); + + // Draw canvas onto the actual image + painter->setOpacity(0.5); // mixed with the previous alphas! + painter->drawImage(0, 0, image); + } else { + // This part is way simpler, as we only need to draw a somewhat + // transparent & filled ellipse + QColor b; + b.setNamedColor("black"); + b.setAlpha(125); + QBrush brush(b); + painter->setBrush(brush); + painter->setOpacity(0.5); + painter->drawEllipse(QRect(fst->rect().x(), + fst->rect().y(), + _drag.x() - fst->rect().x(), + _drag.y() - fst->rect().y())); + } + } +} + +bool EllipseDescriptor::sceneEventFilter(QGraphicsItem* watched, QEvent* event) +{ + return 1; +} diff --git a/Src/View/AreaDesciptor/EllipseDescriptor.h b/Src/View/AreaDesciptor/EllipseDescriptor.h new file mode 100644 index 00000000..89ead7a1 --- /dev/null +++ b/Src/View/AreaDesciptor/EllipseDescriptor.h @@ -0,0 +1,64 @@ +#pragma once + +#include "AreaDescriptor.h" +#include +#include "util/types.h" + +class EllipseDescriptor : public AreaDescriptor +{ + Q_OBJECT +public: + EllipseDescriptor(IController* controller = 0, IModel* model = 0); + ~EllipseDescriptor(); + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + + QRectF boundingRect() const override; + void setBrush(QBrush brush) override; + + void setRect(std::vector rect) override; + std::vector getRect() override; + + void updateRect() override; + + // IViewTrackedComponent interface +public Q_SLOTS: + void getNotified(); + void receiveDragUpdate(BiotrackerTypes::AreaType vectorType, + int id, + double x, + double y); + +protected: + bool sceneEventFilter(QGraphicsItem* watched, QEvent* event) override; + +private: + void init(); + void updateEllipse(); + bool _isInit; + + std::vector _v; + // float _ellipseRotation; + + QGraphicsItem* _watchingDrag; + QBrush _brush; + + // Rects + std::shared_ptr _rectification; + std::shared_ptr _rectificationMarkerOrig; + std::shared_ptr _rectificationMarkerEnd; + + int _dragVectorId; + QPoint _drag; + + // IView interface +public: + void setNewModel(IModel* model) override + { + setModel(model); + }; + +protected: + void connectModelView() override{}; +}; diff --git a/Src/View/AreaDesciptor/RectDescriptor.cpp b/Src/View/AreaDesciptor/RectDescriptor.cpp new file mode 100644 index 00000000..de793b33 --- /dev/null +++ b/Src/View/AreaDesciptor/RectDescriptor.cpp @@ -0,0 +1,212 @@ +#include "RectDescriptor.h" + +#include "QBrush" +#include "QPainter" +#include + +#include "Utility/misc.h" +#include "Model/AreaDescriptor/AreaInfoElement.h" +#include "Model/AreaDescriptor/AreaInfo.h" +#include + +double orientation(cv::Point2f p1, cv::Point2f p2) +{ + cv::Point2f diff = p1 - p2; + // need to check the origin of coorindiates + return std::atan2(p1.y - p2.y, p1.x - p2.x); +} + +RectDescriptor::RectDescriptor(IController* controller, IModel* model) +: AreaDescriptor(controller, model) +{ + _dragVectorId = -1; + _dragType = BiotrackerTypes::AreaType::NONE; + setAcceptHoverEvents(true); + + _brush = QBrush(Qt::blue); + + _v = (dynamic_cast(getModel()))->getVertices(); + setRect(_v); + + _isInit = false; +} + +void RectDescriptor::init() +{ + for (int i = 0; i < 4; i++) { + _rectification[i]->setAcceptHoverEvents(true); + _rectification[i]->installSceneEventFilter(this); + } +} + +void RectDescriptor::setBrush(QBrush brush) +{ + for (int i = 0; i < 4; i++) { + _rectification[i]->setBrush(brush); + } + _brush = brush; +} + +bool RectDescriptor::inShape(QPoint p) +{ + return false; +} + +void RectDescriptor::updateRect() +{ + setRect(getRect()); +} + +void RectDescriptor::setRect(std::vector rect) +{ + std::vector> rectification; + std::vector> rectificationLines; + std::vector> rectificationNumbers; + + _v = (dynamic_cast(getModel()))->getVertices(); + + for (int i = 0; i < 4; i++) { + std::shared_ptr ri = + std::make_shared( + QRect(rect[i].x - 10, rect[i].y - 10, 20, 20), + this); + ri->setBrush(_brush); + rectification.push_back(ri); + // Numbers at corners + if ((dynamic_cast(getModel()))->getShowNumbers()) { + std::shared_ptr ti = + std::make_shared(QString::number(i), + this); + ti->setPos(_v[i].x + 10, _v[i].y + 10); + ti->setFont(QFont("Arial", 20)); + rectificationNumbers.push_back(ti); + } + } + + for (int i = 0; i < 4; i++) { + + auto fst = rectification[i]; + auto snd = rectification[(i + 1) % 4]; + + std::shared_ptr ri = + std::make_shared(QLine(fst->rect().x() + 10, + fst->rect().y() + 10, + snd->rect().x() + 10, + snd->rect().y() + 10), + this); + + rectificationLines.push_back(ri); + if ((dynamic_cast(getModel()))->getShowNumbers()) { + std::string label = "???"; + if (i % 2 == 0) { + label = std::to_string(_cfg->RectificationHeight); + label.erase(label.find_last_not_of('0') + 1, + std::string::npos); + } else { + label = std::to_string(_cfg->RectificationWidth); + label.erase(label.find_last_not_of('0') + 1, + std::string::npos); + } + std::shared_ptr ti = + std::make_shared(label.c_str(), this); + cv::Point2f a(fst->rect().x() + 10, fst->rect().y() + 10); + cv::Point2f b(snd->rect().x() + 10, snd->rect().y() + 10); + double alpha = orientation(a, b) * 180 / CV_PI; + // Fix upside down text + alpha = alpha > 0 ? 180 - alpha : alpha; + cv::Point2f c = a + (b - a) * 0.5; + ti->setPos(c.x, c.y); + ti->setFont(QFont("Arial", 20)); + ti->setRotation(-1 * alpha); + rectificationNumbers.push_back(ti); + } + } + _rectification = rectification; + _rectificationLines = rectificationLines; + _rectificationNumbers = rectificationNumbers; +} + +std::vector RectDescriptor::getRect() +{ + return (dynamic_cast(getModel()))->getVertices(); +} + +void RectDescriptor::receiveDragUpdate(BiotrackerTypes::AreaType vectorType, + int id, + double x, + double y) +{ + _dragType = (dynamic_cast(getModel()))->getAreaType(); + if (_dragType == vectorType) { + _dragVectorId = id; + _drag = QPoint(x, y); + } else { + _dragVectorId = -1; + } + update(); +} + +RectDescriptor::~RectDescriptor() +{ +} + +void RectDescriptor::getNotified() +{ +} + +QRectF RectDescriptor::boundingRect() const +{ + return QRect(10, 10, 10, 10); +} + +void RectDescriptor::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + if (!_isInit) + init(); + + // We want smooth lines! + painter->setRenderHint(QPainter::Antialiasing); + + // TODO remove hardcoding and code duplication + if (_dragVectorId >= 0 && _dragType != BiotrackerTypes::AreaType::NONE) { + QColor transparentGray = Qt::gray; + transparentGray.setAlphaF(0.75); + painter->setPen(QPen(transparentGray, 1, Qt::SolidLine)); + painter->drawRect(_drag.x() - 10, _drag.y() - 10, 20, 20); + int fstId = (_dragVectorId - 1) % 4; + fstId = (fstId == -1 ? 3 : fstId); + auto fst = _rectification[fstId]; + auto snd = _rectification[(_dragVectorId + 1) % 4]; + painter->drawLine(QLine(fst->rect().x() + 10, + fst->rect().y() + 10, + _drag.x(), + _drag.y())); + painter->drawLine(QLine(snd->rect().x() + 10, + snd->rect().y() + 10, + _drag.x(), + _drag.y())); + } +} + +void RectDescriptor::updateLinePositions() +{ + + for (int i = 0; i < 4; i++) { + + auto fst = _rectification[i]; + auto snd = _rectification[(i + 1) % 4]; + auto ln = _rectificationLines[i]; + ln->setLine(QLine(fst->rect().x() + 10, + fst->rect().y() + 10, + snd->rect().x() + 10, + snd->rect().y() + 10)); + } +} + +bool RectDescriptor::sceneEventFilter(QGraphicsItem* watched, QEvent* event) +{ + + return 0; +} diff --git a/Src/View/AreaDesciptor/RectDescriptor.h b/Src/View/AreaDesciptor/RectDescriptor.h new file mode 100644 index 00000000..270fc7d6 --- /dev/null +++ b/Src/View/AreaDesciptor/RectDescriptor.h @@ -0,0 +1,72 @@ +#pragma once + +#include "AreaDescriptor.h" +#include +#include +#include "util/types.h" +#include + +class RectDescriptor : public AreaDescriptor +{ + Q_OBJECT +public: + RectDescriptor(IController* controller = 0, IModel* model = 0); + ~RectDescriptor(); + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + + QRectF boundingRect() const override; + + bool inShape(QPoint p); + + void setBrush(QBrush brush) override; + void setRect(std::vector rect) override; + std::vector getRect() override; + + void updateRect() override; + + // IViewTrackedComponent interface +public Q_SLOTS: + void getNotified(); + void receiveDragUpdate(BiotrackerTypes::AreaType vectorType, + int id, + double x, + double y); + +protected: + bool sceneEventFilter(QGraphicsItem* watched, QEvent* event) override; + void updateLinePositions(); + +private: + void init(); + bool _isInit; + + QGraphicsItem* _watchingDrag; + int _dragX; + int _dragY; + + std::vector _v; + + // Rects + std::vector> _rectification; + std::vector> _rectificationLines; + std::vector> + _rectificationNumbers; + + QBrush _brush; + + BiotrackerTypes::AreaType _dragType; + int _dragVectorId; + QPoint _drag; + + // IView interface +public: + void setNewModel(IModel* model) override + { + setModel(model); + }; + +protected: + void connectModelView() override{}; +}; diff --git a/Src/View/CameraDevice.cpp b/Src/View/CameraDevice.cpp new file mode 100644 index 00000000..648dc1c4 --- /dev/null +++ b/Src/View/CameraDevice.cpp @@ -0,0 +1,199 @@ +#include "CameraDevice.h" +#include "ui_CameraDevice.h" + +#include "QCameraInfo" +#include "util/types.h" +#include "util/camera/base.h" +#if HAS_PYLON + #include "util/camera/pylon.h" +#endif +#include +#include +#include "opencv2/highgui/highgui.hpp" + +CameraDevice::CameraDevice(QWidget* parent) +: QWidget(parent) +, ui(new Ui::CameraDevice) +{ + ui->setupUi(this); + m_ximeaId = -1; + + this->setAttribute(Qt::WA_DeleteOnClose); + + listAllCameras(); +} + +CameraDevice::~CameraDevice() +{ + delete ui; +} + +CameraConfiguration CameraDevice::grabUICameraConfiguration() +{ + auto camera_selector = ui->comboBox->currentData().value(); + + std::string sx = ui->lineEdit->text().toStdString(); + std::string sy = ui->lineEdit_2->text().toStdString(); + std::string sf = ui->lineEdit_3->text().toStdString(); + int x, y, f; + x = (sx == "Default" ? -1 : std::stoi(sx)); + y = (sy == "Default" ? -1 : std::stoi(sy)); + f = (sf == "Default" ? -1 : std::stoi(sf)); + + CameraConfiguration conf(camera_selector, x, y, f, false, ""); + return conf; +} + +void CameraDevice::on_buttonBox_accepted() +{ + CameraConfiguration conf = grabUICameraConfiguration(); + Q_EMIT emitSelectedCameraDevice(conf); + + this->close(); +} + +void CameraDevice::on_showPreviewButton_clicked() +{ + auto conf = grabUICameraConfiguration(); + + cv::Mat image; + switch (conf._selector.type) { + case CameraType::OpenCV: { + if (conf._selector.index == cv::CAP_XIAPI) { + m_capture.open(cv::CAP_XIAPI); + } else { + m_capture.open(conf._selector.name); + } + + for (auto num_tries = 0; !m_capture.isOpened() && num_tries < 50; + ++num_tries) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (conf._width != -1) + m_capture.set(cv::CAP_PROP_FRAME_WIDTH, conf._width); + if (conf._height != -1) + m_capture.set(cv::CAP_PROP_FRAME_HEIGHT, conf._height); + if (conf._fps != -1) + m_capture.set(cv::CAP_PROP_FPS, conf._fps); + + if (!m_capture.isOpened()) { + ui->label_NoImage->setText("Error loading camera"); + return; + } + + cv::Mat mat; + for (auto i = 0; i < 10; ++i) { + m_capture.grab(); + m_capture.retrieve(mat); + } + + auto height = conf._height != -1 ? conf._height + : ui->label_NoImage->height(); + auto ar = mat.rows ? static_cast(mat.cols) / mat.rows : 1; + auto width = conf._width != -1 ? conf._width + : static_cast(height * ar); + + cv::Mat scaled; + cv::resize(mat, scaled, cv::Size{width, height}); + if (scaled.type() == CV_8UC1) + cv::cvtColor(scaled, scaled, cv::COLOR_GRAY2RGB); + cv::cvtColor(scaled, scaled, cv::COLOR_BGR2RGB); + + ui->label_NoImage->setPixmap( + QPixmap::fromImage(QImage(scaled.data, + scaled.cols, + scaled.rows, + static_cast(scaled.step1()), + QImage::Format_RGB888))); + m_capture.release(); + break; + } +#if HAS_PYLON + case CameraType::Pylon: { + Pylon::PylonAutoInitTerm pylon; + auto camera = Pylon::CInstantCamera{ + getPylonDevice(conf._selector.index)}; + camera.Open(); + for (auto num_tries = 0; !camera.IsOpen() && num_tries < 50; + ++num_tries) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (!camera.IsOpen()) { + ui->label_NoImage->setText("Error loading camera"); + return; + } + + Pylon::CGrabResultPtr grab_result; + camera.GrabOne(5000, grab_result); + auto view = toOpenCV(grab_result); + + auto height = conf._height != -1 ? conf._height + : ui->label_NoImage->height(); + auto ar = view.rows ? static_cast(view.cols) / view.rows : 1; + auto width = conf._width != -1 ? conf._width + : static_cast(height * ar); + + cv::Mat scaled; + cv::resize(view, scaled, cv::Size{width, height}); + + ui->label_NoImage->setPixmap( + QPixmap::fromImage(QImage(scaled.data, + scaled.cols, + scaled.rows, + static_cast(scaled.step1()), + QImage::Format_RGB888))); + break; + } +#endif + default: + throw std::logic_error("Missing preview implementation"); + } +} + +void CameraDevice::on_comboBox_currentIndexChanged(int index) +{ +} + +void CameraDevice::listAllCameras() +{ + cameras = QCameraInfo::availableCameras(); + for (int index = 0; index < cameras.size(); ++index) { + ui->comboBox->addItem(cameras[index].description(), + QVariant::fromValue(CameraSelector{ + CameraType::OpenCV, + index, + cameras[index].deviceName().toStdString()})); + } + + { + cv::VideoCapture ximea_camera(cv::CAP_XIAPI); + if (ximea_camera.isOpened()) { + ui->comboBox->addItem( + "XIMEA default", + QVariant::fromValue( + CameraSelector{CameraType::OpenCV, cv::CAP_XIAPI, ""})); + } + } + +#if HAS_PYLON + { + Pylon::PylonAutoInitTerm pylon; + + auto& factory = Pylon::CTlFactory::GetInstance(); + Pylon::DeviceInfoList_t devices; + factory.EnumerateDevices(devices); + + for (int index = 0; index < devices.size(); ++index) { + ui->comboBox->addItem( + QString{devices[index].GetFriendlyName()}, + QVariant::fromValue( + CameraSelector{CameraType::Pylon, index, ""})); + } + } +#endif +} + +void CameraDevice::on_buttonBox_rejected() +{ + this->close(); +} diff --git a/BioTracker/CoreApp/BioTracker/View/CameraDevice.h b/Src/View/CameraDevice.h similarity index 54% rename from BioTracker/CoreApp/BioTracker/View/CameraDevice.h rename to Src/View/CameraDevice.h index 239360f3..894d8700 100644 --- a/BioTracker/CoreApp/BioTracker/View/CameraDevice.h +++ b/Src/View/CameraDevice.h @@ -7,10 +7,12 @@ #include "QCameraViewfinder" #include "QPointer" #include "util/types.h" +#include "util/camera/base.h" #include -namespace Ui { -class CameraDevice; +namespace Ui +{ + class CameraDevice; } class CameraDevice : public QWidget @@ -18,13 +20,13 @@ class CameraDevice : public QWidget Q_OBJECT public: - explicit CameraDevice(QWidget *parent = 0); + explicit CameraDevice(QWidget* parent = 0); ~CameraDevice(); private Q_SLOTS: void on_buttonBox_accepted(); - void on_pushButton_clicked(); + void on_showPreviewButton_clicked(); void on_comboBox_currentIndexChanged(int index); @@ -34,19 +36,19 @@ private Q_SLOTS: void emitSelectedCameraDevice(CameraConfiguration conf); private: - CameraConfiguration grabUICameraConfiguration(); - void listAllCameras(); + CameraConfiguration grabUICameraConfiguration(); + void listAllCameras(); private: - Ui::CameraDevice *ui; - cv::VideoCapture m_capture; + Ui::CameraDevice* ui; + cv::VideoCapture m_capture; - QPointer< QCamera > camera; - QPointer< QCameraViewfinder > viewfinder; + QPointer camera; + QPointer viewfinder; QList cameras; - int m_ximeaId; + int m_ximeaId; }; #endif // CAMERADEVICE_H diff --git a/Src/View/CameraDevice.ui b/Src/View/CameraDevice.ui new file mode 100644 index 00000000..b8555500 --- /dev/null +++ b/Src/View/CameraDevice.ui @@ -0,0 +1,168 @@ + + + CameraDevice + + + + 0 + 0 + 480 + 320 + + + + Open camera + + + + + + + + + + + 0 + 0 + + + + <No Image> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + Select Camera Device + + + + + + + + + + Preview + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + 0 + 0 + + + + Resolution: + + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + Default + + + + + + + + 0 + 0 + + + + x + + + + + + + + 100 + 16777215 + + + + Default + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + FPS: + + + + + + + Default + + + + + + + + + + + + diff --git a/Src/View/ComponentShape.cpp b/Src/View/ComponentShape.cpp new file mode 100644 index 00000000..df935d2e --- /dev/null +++ b/Src/View/ComponentShape.cpp @@ -0,0 +1,1515 @@ +#include "ComponentShape.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "View/Utility/Tracer.h" + +/* + * This is the cpp file of the ComponentShape class + * Collapse/Fold all methods to have a better overview. + */ + +ComponentShape::ComponentShape(QGraphicsObject* parent, + IModelTrackedTrajectory* trajectory, + int id) +: QGraphicsObject(parent) +, m_trajectory(trajectory) +, m_id(id) +, m_parent(parent) +{ + setData(0, m_id); + setData(1, "point"); + + m_polygons = QList(); + m_useDefaultDimensions = true; + m_penWidth = 2; + m_transparency = 255; + m_penStyle = Qt::SolidLine; + m_penStylePrev = Qt::SolidLine; + m_marked = false; + + // set default permissions + m_pMovable = true; + m_pRemovable = true; + m_pSwappable = true; + m_pRotatable = true; + + m_fixed = false; + m_currentFramenumber = 0; + m_rotation = 0; + // m_trajectoryWasActiveOnce = false; + + // create tracing layer + m_tracingLayer = new QGraphicsRectItem(); + m_tracingLayer->setZValue(3); + this->scene()->addItem(m_tracingLayer); + + // create orientation line + m_rotationLine = QLineF(); + + // set flags + setFlag(ItemIsMovable); + setFlag(ItemIsSelectable); + setAcceptedMouseButtons(Qt::LeftButton); + + setVisible(true); +} + +ComponentShape::~ComponentShape() +{ + delete m_tracingLayer; +} + +//*****************************QGraphicsItem +// interface*************************************** + +QRectF ComponentShape::boundingRect() const +{ + if (this->data(1) == "ellipse" || this->data(1) == "point" || + this->data(1) == "rectangle") { + return QRectF(0, 0, m_w, m_h); + } else if (this->data(1) == "polygon") { + // outer polygon bounding rect + return m_polygons[0].boundingRect(); + } else { + // Note: This log might not appear (on console) as the application dies + // of assert before the buffer is served + qDebug() << "Could not create a bounding rect for current track " + << m_id; + assert(0); + } +} + +QPainterPath ComponentShape::shape() const +{ + QPainterPath path; + if (this->data(1) == "ellipse") { + path.addEllipse(0, 0, m_w, m_h); + } else if (this->data(1) == "point") { + int dim = m_w <= m_h ? m_w : m_h; + // path.addEllipse(0, 0, dim , dim); + QRectF ellipse; + // ellipse = QRectF(0, m_h - m_w , m_w, m_w); + qreal origin_x = m_rotationLine.p1().x() - dim / 2; + qreal origin_y = m_rotationLine.p1().y() - dim / 2; + ellipse = QRectF(origin_x, origin_y, dim, dim); + + path.addEllipse(ellipse); + + } else if (this->data(1) == "rectangle") { + path.addRect(0, 0, m_w, m_h); + } else if (this->data(1) == "polygon") { + // outer polygon + path.addPolygon(m_polygons[0]); + } else { + qDebug() << "Could not create a interaction area for trajectory " + << m_id; + assert(0); + } + return path; +} + +void ComponentShape::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + if (m_currentFramenumber < 0) + return; + // Antialiasing + if (m_antialiasing) { + painter->setRenderHint(QPainter::Antialiasing); + } + + // check if scene is set + if (!(this->scene())) { + qDebug() << "componentscene is null\n"; + } + + QPen pen = QPen(m_penColor, m_penWidth, m_penStyle); + QBrush brush = QBrush(m_brushColor); + painter->setPen(pen); + painter->setBrush(brush); + + // draw orientation line + if (m_orientationLine && !m_rotationLine.isNull()) { + painter->drawLine(m_rotationLine); + } + + // TODO enums for types? + + // draw ellipse + if (this->data(1) == "ellipse") { + QRectF ellipse = QRectF(0, 0, m_w, m_h); + painter->drawEllipse(ellipse); + } + + // draw rectangle + if (this->data(1) == "rectangle") { + QRect rectangle = QRect(0, 0, m_w, m_h); + painter->drawRect(rectangle); + } + + // draw point + // take the smaller of width and height + // a point should always have the same height and width + if (this->data(1) == "point") { + QRectF ellipse; + if (m_w <= m_h) { + // ellipse = QRectF(0, m_h - m_w , m_w, m_w); + qreal origin_x = m_rotationLine.p1().x() - m_w / 2; + qreal origin_y = m_rotationLine.p1().y() - m_w / 2; + ellipse = QRectF(origin_x, origin_y, m_w, m_w); + } else { + qreal origin_x = m_rotationLine.p1().x() - m_h / 2; + qreal origin_y = m_rotationLine.p1().y() - m_h / 2; + ellipse = QRectF(origin_x, origin_y, m_h, m_h); + } + painter->drawEllipse(ellipse); + } + + // draw polygon + if (this->data(1) == "polygon") { + foreach (QPolygonF polygonF, m_polygons) { + painter->drawPolygon(polygonF); + } + } + + // draw id in center + if (m_showId) { + painter->drawText(this->boundingRect(), + Qt::AlignCenter, + QString::number(m_id)); + } +} + +bool ComponentShape::advance() +{ + return false; +} + +void ComponentShape::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ + m_mousePressTime = QTime::currentTime(); + m_mousePressTime.start(); + m_mousePressPos = pos().toPoint(); + + if (event->button() == Qt::LeftButton) { + // handle left mouse button here + setCursor(Qt::ClosedHandCursor); + update(); + } + // pass on + QGraphicsItem::mousePressEvent(event); +} + +void ComponentShape::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) { + setCursor(Qt::ArrowCursor); + + QPoint currentPos = this->pos().toPoint(); + int manhattanLength = (currentPos - m_mousePressPos).manhattanLength(); + int moveTime = m_mousePressTime.elapsed(); + if (manhattanLength > 5 || moveTime > 200) { + m_dragged = true; + } + + if (m_dragged) { + + // broadcast move so other selected elements get moved too + // maybe unconventional and slow but couldn't find another way; + // Dropevents in view and dropevents in shape didn't seem to work + broadcastMove(); + } else { + this->setPos(m_mousePressPos); + this->update(); + } + m_dragged = false; + + update(); + } + // pass on + QGraphicsItem::mouseReleaseEvent(event); +} + +void ComponentShape::mouseMoveEvent(QGraphicsSceneMouseEvent* event) +{ + // pass on + QGraphicsItem::mouseMoveEvent(event); +} + +QVariant ComponentShape::itemChange(GraphicsItemChange change, + const QVariant& value) +{ + if (change == ItemSelectedHasChanged && scene()) { + if (this->isSelected()) { + m_penColorLast = m_penColor; + m_penColor = Qt::red; + m_penStylePrev = m_penStyle; + if (m_fixed) { + m_penStyle = Qt::DashDotLine; + } else { + m_penStyle = Qt::DashLine; + } + this->setZValue(2); + trace(); + update(); + } else { + m_penColor = m_penColorLast; + m_penStyle = m_penStylePrev; + this->setZValue(0); + trace(); + update(); + } + } + return QGraphicsItem::itemChange(change, value); +} + +void ComponentShape::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) +{ + QMenu menu; + + /* + create the info box + */ + QWidgetAction* infoBox = new QWidgetAction(this); + + QString info = QString("ID: "); + info.append(QString::number(m_id)); + QLabel* infoLabel = new QLabel(info); + infoLabel->setWordWrap(true); + infoLabel->setStyleSheet("QLabel {font-weight: bold; text-align: center}"); + infoLabel->setAlignment(Qt::AlignCenter); + infoBox->setDefaultWidget(infoLabel); + menu.addAction(infoBox); + + // + menu.addSeparator(); + + /* + create set object name - line edit + */ + QWidgetAction* objectNameAction = new QWidgetAction(this); + QLineEdit* objectEdit = new QLineEdit(); + + if (objectName() == "") { + objectEdit->setPlaceholderText("no object name set"); + } else { + objectEdit->setText(objectName()); + } + objectEdit->setAlignment(Qt::AlignHCenter); + objectEdit->setFrame(false); + objectEdit->setToolTip( + "Change the trajectory's name. This will not be saved in the data " + "output (yet)!"); + + QObject::connect(objectEdit, + &QLineEdit::textEdited, + this, + &ComponentShape::setObjectNameContext); + + objectNameAction->setDefaultWidget(objectEdit); + menu.addAction(objectNameAction); + + /* + show info window for current frame + */ + menu.addSeparator(); + QAction* showInfoAction = menu.addAction( + "Show full info", + dynamic_cast(this), + SLOT(createInfoWindow())); + menu.addSeparator(); + + /* + coloring + */ + QAction* changeBrushColorAction = menu.addAction( + "Change fill color", + dynamic_cast(this), + SLOT(changeBrushColor())); + QAction* changePenColorAction = menu.addAction( + "Change border color", + dynamic_cast(this), + SLOT(changePenColor())); + + /* + transparency slider + */ + QMenu* transparencyMenu = new QMenu("Transparency"); + QWidgetAction* sliderBox = new QWidgetAction(this); + QSlider* transparencySlider = new QSlider(Qt::Horizontal); + + transparencySlider->setMinimum(0); + transparencySlider->setMaximum(255); + transparencySlider->setSingleStep(1); + transparencySlider->setTickPosition(QSlider::TicksBothSides); + transparencySlider->setTickInterval(64); + transparencySlider->setValue(m_transparency); + + QObject::connect(transparencySlider, + &QSlider::sliderMoved, + this, + &ComponentShape::receiveTransparency); + + sliderBox->setDefaultWidget(transparencySlider); + transparencyMenu->addAction(sliderBox); + + menu.addMenu(transparencyMenu); + + // + menu.addSeparator(); + /* + dimension menu + */ + QMenu* dimensionMenu = new QMenu("Dimensions"); + + // Width + QWidgetAction* widthBox = new QWidgetAction(this); + QSpinBox* widthSpin = new QSpinBox; + widthSpin->setPrefix("Width: "); + widthSpin->setMinimum(1); + widthSpin->setMaximum(100000); + widthSpin->setValue(m_w); + QObject::connect(widthSpin, + QOverload::of(&QSpinBox::valueChanged), + this, + &ComponentShape::receiveWidth); + widthBox->setDefaultWidget(widthSpin); + dimensionMenu->addAction(widthBox); + + // Height + QWidgetAction* heightBox = new QWidgetAction(this); + QSpinBox* heightSpin = new QSpinBox; + heightSpin->setPrefix("Height: "); + heightSpin->setMinimum(1); + heightSpin->setMaximum(100000); + heightSpin->setValue(m_h); + QObject::connect(heightSpin, + QOverload::of(&QSpinBox::valueChanged), + this, + &ComponentShape::receiveHeight); + heightBox->setDefaultWidget(heightSpin); + dimensionMenu->addAction(heightBox); + + // + menu.addMenu(dimensionMenu); + + /* + toggle orientation line + */ + + QAction* showOrientationAction = menu.addAction( + "Show orientation line", + dynamic_cast(this), + SLOT(receiveToggleOrientationLine(bool))); + showOrientationAction->setCheckable(true); + showOrientationAction->setChecked(m_orientationLine); + + /* + toggle id + */ + + QAction* showIDAction = menu.addAction("Show ID", + dynamic_cast(this), + SLOT(receiveShowId(bool))); + showIDAction->setCheckable(true); + showIDAction->setChecked(m_showId); + + /* + tracing menu + */ + QMenu* tracingMenu = new QMenu("Tracing"); + // tracing type + QWidgetAction* typeBox = new QWidgetAction(this); + QComboBox* typeCombo = new QComboBox; + QStringList types; + types << "No tracing" + << "Shape" + << "Path" + << "Arrow Path"; + typeCombo->addItems(types); + typeCombo->setCurrentText(m_tracingStyle); + QObject::connect( + typeCombo, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &ComponentShape::receiveTracingStyle); + typeBox->setDefaultWidget(typeCombo); + QMenu* tracingTypeMenu = new QMenu("Type"); + tracingTypeMenu->addAction(typeBox); + tracingMenu->addMenu(tracingTypeMenu); + + // tracingHistory + QWidgetAction* historyBox = new QWidgetAction(this); + QSpinBox* historySpinBox = new QSpinBox; + historySpinBox->setPrefix("History: "); + historySpinBox->setMinimum(1); + historySpinBox->setMaximum(100000); + historySpinBox->setValue(m_tracingLength); + QObject::connect(historySpinBox, + QOverload::of(&QSpinBox::valueChanged), + this, + &ComponentShape::receiveTracingLength); + historyBox->setDefaultWidget(historySpinBox); + tracingMenu->addAction(historyBox); + + // tracingSteps + QWidgetAction* stepsBox = new QWidgetAction(this); + QSpinBox* stepsSpinBox = new QSpinBox; + stepsSpinBox->setPrefix("Steps: "); + stepsSpinBox->setMinimum(1); + stepsSpinBox->setMaximum(100000); + stepsSpinBox->setValue(m_tracingSteps); + QObject::connect(stepsSpinBox, + QOverload::of(&QSpinBox::valueChanged), + this, + &ComponentShape::receiveTracingSteps); + stepsBox->setDefaultWidget(stepsSpinBox); + tracingMenu->addAction(stepsBox); + + // tracingDegradation + QWidgetAction* degrBox = new QWidgetAction(this); + QComboBox* degrCombo = new QComboBox; + QStringList degrTypes; + degrTypes << "None" + << "Transparency" + << "False color"; + degrCombo->addItems(degrTypes); + degrCombo->setCurrentText(m_tracingTimeDegradation); + QObject::connect( + degrCombo, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &ComponentShape::receiveTracingTimeDegradation); + degrBox->setDefaultWidget(degrCombo); + QMenu* tracingTimeDegrMenu = new QMenu("Time degradation"); + tracingTimeDegrMenu->addAction(degrBox); + tracingMenu->addMenu(tracingTimeDegrMenu); + + // toggle orientation line + + QAction* showTrOrientationAction = tracingMenu->addAction( + "Show tracer orientation line", + dynamic_cast(this), + SLOT(receiveTracerOrientationLine(bool))); + showTrOrientationAction->setCheckable(true); + showTrOrientationAction->setChecked(m_tracingOrientationLine); + + // tracer number + QAction* showTrNumberAction = tracingMenu->addAction( + "Show framenumber on tracers", + dynamic_cast(this), + SLOT(receiveTracerFrameNumber(bool))); + showTrNumberAction->setCheckable(true); + showTrNumberAction->setChecked(m_tracerFrameNumber); + + // tracer proportions + QWidgetAction* propBox = new QWidgetAction(this); + QDoubleSpinBox* propSpinBox = new QDoubleSpinBox; + propSpinBox->setPrefix("Proportions: "); + propSpinBox->setDecimals(2); + propSpinBox->setSingleStep(0.001f); + propSpinBox->setMinimum(0.01f); + propSpinBox->setMaximum(99.99f); + propSpinBox->setValue(m_tracerProportions); + QObject::connect(propSpinBox, + QOverload::of(&QDoubleSpinBox::valueChanged), + this, + &ComponentShape::receiveTracerProportions); + propBox->setDefaultWidget(propSpinBox); + tracingMenu->addAction(propBox); + + menu.addMenu(tracingMenu); + + // + menu.addSeparator(); + + /* + removing + */ + QAction* removeTrackAction = menu.addAction( + "Remove track", + dynamic_cast(this), + SLOT(removeTrack())); + QAction* removeTrackEntityAction = menu.addAction( + "Remove track entity", + dynamic_cast(this), + SLOT(removeTrackEntity())); + if (!m_pRemovable) { + removeTrackAction->setEnabled(false); + removeTrackEntityAction->setEnabled(false); + } + + /* + fixing + */ + QString fixText = m_fixed ? "Unfix track" : "Fix Track"; + QAction* fixTrackAction = menu.addAction( + fixText, + dynamic_cast(this), + SLOT(toggleFixTrack())); + + /* + marking + */ + QString markText = m_marked ? "Unmark" : "Mark"; + QAction* markAction = menu.addAction(markText, + dynamic_cast(this), + SLOT(markShape())); + QAction* unmarkAction = menu.addAction(markText, + dynamic_cast(this), + SLOT(unmarkShape())); + markAction->setVisible(!m_marked); + unmarkAction->setVisible(m_marked); + + // + menu.addSeparator(); + + /* + morphing + */ + QMenu* morphMenu = new QMenu("Morph into..."); + if (data(1) == "rectangle" || data(1) == "ellipse" || data(1) == "point" || + data(1) == "polygon") { + QAction* morphPoint = morphMenu->addAction( + "Point", + dynamic_cast(this), + SLOT(morphIntoPoint())); + QAction* morphEllipse = morphMenu->addAction( + "Ellipse", + dynamic_cast(this), + SLOT(morphIntoEllipse())); + QAction* morphRect = morphMenu->addAction( + "Rectangle", + dynamic_cast(this), + SLOT(morphIntoRect())); + QAction* morphPoylgon = morphMenu->addAction( + "Polygon", + dynamic_cast(this), + SLOT(morphIntoPolygon())); + } else { + morphMenu->setEnabled(false); + } + menu.addMenu(morphMenu); + + // + QAction* selectedAction = menu.exec(event->screenPos()); +} + +//************************************************************************* + +/// updates this with data from new current entity +bool ComponentShape::updateAttributes(uint frameNumber) +{ + m_currentFramenumber = frameNumber; + + // if trajectory does not exist anymore, delete the shape + if (!m_trajectory) { + this->hide(); + m_tracingLayer->hide(); + this->deleteLater(); + return false; + } + + // check if trajectory is valid and current entity exists + if (m_trajectory->size() != 0 && m_trajectory->getValid() && + m_trajectory->getChild(frameNumber)) { + m_id = m_trajectory->getId(); + // update m_fixed + m_fixed = m_trajectory->getFixed(); + if (!m_fixed) { + if (this->isSelected()) { + m_penStyle = Qt::DashLine; + } else { + m_penStyle = Qt::SolidLine; + } + } else { + if (this->isSelected()) { + m_penStyle = Qt::DashDotLine; + } else { + m_penStyle = Qt::DotLine; + } + } + + // update dimensions + prepareGeometryChange(); + + // type checker + bool hasType = false; + + // if point, ellipse, rectangle and valid + IModelTrackedPoint* pointLike = dynamic_cast( + m_trajectory->getChild(m_currentFramenumber)); + if (pointLike && (pointLike->getValid())) { + hasType = true; + // update width and height or use defaults + if (m_useDefaultDimensions) { + if (pointLike->hasW()) { + m_w = pointLike->getW(); + } else { + m_w = m_wDefault; + } + if (pointLike->hasH()) { + m_h = pointLike->getH(); + } else { + m_h = m_hDefault; + } + } + // update rotation + if (pointLike->hasDeg()) { + this->setTransformOriginPoint(m_w / 2, m_h / 2); + if (m_h > m_w || data(1) == "polygon") { + m_rotation = -90 - pointLike->getDeg(); + this->setRotation(m_rotation); + } else { + m_rotation = -pointLike->getDeg(); + this->setRotation(m_rotation); + } + + // update rotation line + m_rotationLine.setP1(QPointF(m_w / 2, m_h / 2)); + if (m_h > m_w || data(1) == "polygon") { + m_rotationLine.setAngle(-90); + } else { + m_rotationLine.setAngle(0); + } + qreal length = (m_w + m_h) / 2 * 3; + m_rotationLine.setLength(length); + + // update rotation handle + m_rotationHandleLayer->setTransformOriginPoint(m_w / 2, + m_h / 2); + m_rotationHandleLayer->setRotation(0); + m_rotationHandle->setPos(m_rotationLine.p2()); + } else { + m_rotationLine = QLineF(); + } + + // update Position + this->setPos(pointLike->getXpx() - m_w / 2, + pointLike->getYpx() - m_h / 2); + m_oldPos = this->pos().toPoint(); + + /* + -when morphing into polygon: + -construct polygon from pos and width,height + -pentagon + + x / \ + / \ + | | + \_ _/ + + */ + m_polygons = QList(); + + QPolygonF polygon; + QPointF startPoint = QPointF(m_w / 2, 0); + polygon << startPoint; + polygon << QPointF(m_w, m_h / 2); + polygon << QPointF(3 * m_w / 4, m_h); + polygon << QPointF(m_w / 4, m_h); + polygon << QPointF(0, m_h / 2); + polygon << startPoint; + + if (polygon.isClosed()) { + m_polygons.append(polygon); + } + + // create tracers + trace(); + + this->show(); + update(); + + return true; + } else { + this->hide(); + return true; + } + // if polygon + IModelTrackedPolygon* polygons = dynamic_cast( + m_trajectory->getChild(frameNumber)); + if (polygons && (polygons->getValid() || m_currentFramenumber == 0)) { + hasType = true; + // update polygon + if (polygons->hasPolygon()) { + m_polygons = polygons->getPolygon(); + } + // also update position + this->setPos(polygons->getXpx() - m_w / 2, + polygons->getYpx() - m_h / 2); + m_oldPos = this->pos().toPoint(); + + // update width and height or use defaults --> for morphing + if (m_useDefaultDimensions) { + m_w = m_polygons[0].boundingRect().width(); + m_h = m_polygons[0].boundingRect().height(); + } + + // create tracers + trace(); + + this->show(); + update(); + + return true; + } + // has no type + if (!hasType) { + qDebug() << "The current entity has no known type"; + } + } else { + // trajectory is empty or null or invald or current entity is null + this->hide(); + m_tracingLayer->hide(); + // delete this; + return false; + } +} + +/// attemps to draw tracers, if _tracingStyle is set tracers are drawn +void ComponentShape::trace() +{ + // TRACING + + IModelTrackedPoint* currentChild = dynamic_cast( + m_trajectory->getChild(m_currentFramenumber)); + // return if current entity is not existant + if (!currentChild) + return; + + QPointF currentPoint = QPointF(currentChild->getXpx(), + currentChild->getYpx()); + + // update the tracing layer + m_tracingLayer->setPos(this->pos()); + m_tracingLayer->setFlag(QGraphicsItem::ItemHasNoContents); + m_tracingLayer->show(); + + // really unefficient to flush each time + // flush tracing shape history, open up the memory --> thats slow + QList tracers = m_tracingLayer->childItems(); + foreach (QGraphicsItem* tracer, tracers) { + delete tracer; + } + + // return if tracing disabled + if (m_trajectory->size() == 0 || m_tracingLength <= 0 || + m_tracingStyle == "No tracing") { + return; + } + + QPointF lastPointDifference = QPointF(0, + 0); // + QPointF(m_h / 2, m_w / 2); + + // create each n'th (m_tracingSteps) tracer of tracing history + // (m_tracingLength) + for (int i = 1; i <= m_tracingLength && i <= m_currentFramenumber; + i += m_tracingSteps) { + + IModelTrackedPoint* historyChild = dynamic_cast( + m_trajectory->getChild(m_currentFramenumber - i)); + if (historyChild && historyChild->getValid()) { + + // positioning + QPointF historyPoint = QPointF(historyChild->getXpx(), + historyChild->getYpx()); + QPointF historyPointDifference = historyPoint - currentPoint; + QPointF adjustedHistoryPointDifference = historyPointDifference; + + // time degradation colors + QPen timeDegradationPen = QPen(m_penColor, m_penWidth, m_penStyle); + QBrush timeDegradationBrush = QBrush(m_brushColor); + QColor timeDegradationBrushColor; + QColor timeDegradationPenColor; + + if (m_tracingTimeDegradation == "Transparency") { + + float tr = (float) m_transparency; + float trForThis = tr != 0 + ? tr - (tr / (float) m_tracingLength) * + (i - 1) + : 0.0f; + + timeDegradationPenColor = QColor(m_penColor.red(), + m_penColor.green(), + m_penColor.blue(), + trForThis); + timeDegradationPen = QPen(timeDegradationPenColor, + m_penWidth, + Qt::SolidLine); + + timeDegradationBrushColor = QColor(m_brushColor.red(), + m_brushColor.green(), + m_brushColor.blue(), + trForThis); + timeDegradationBrush = QBrush(timeDegradationBrushColor); + + } else if (m_tracingTimeDegradation == "False color") { + float hue = (240.0f - + ((240.0f / (float) m_tracingLength) * i)); + timeDegradationPenColor = QColor::fromHsv((int) hue, + 255.0f, + 255.0f); + timeDegradationPenColor.setAlpha(m_transparency); + timeDegradationBrushColor = QColor::fromHsv((int) hue, + 255.0f, + 255.0f); + timeDegradationBrushColor.setAlpha(m_transparency); + timeDegradationPen = QPen(m_penColor, m_penWidth, m_penStyle); + timeDegradationBrush = QBrush(timeDegradationBrushColor); + } + + // check tracing type + + // SHAPE + if (m_tracingStyle == "Shape") { + + // orientation line + if (m_tracingOrientationLine) { + QLineF orientationLine = QLineF(); + orientationLine.setP1(adjustedHistoryPointDifference); + orientationLine.setAngle(historyChild->getDeg()); + qreal length = (m_w + m_h) / 2 / m_tracerProportions * 3; + orientationLine.setLength(15); + + QGraphicsLineItem* orientationItem = new QGraphicsLineItem( + orientationLine, + m_tracingLayer); + } + + float tracerDeg = historyChild->hasDeg() + ? historyChild->getDeg() + : 0.0; + float tracerW = m_w * m_tracerProportions; + float tracerH = m_h * m_tracerProportions; + int tracerNumber = m_currentFramenumber - i; + + Tracer* tracer = new Tracer(this->data(1), + tracerNumber, + tracerDeg, + adjustedHistoryPointDifference, + tracerW, + tracerH, + timeDegradationPen, + timeDegradationBrush, + m_tracingLayer); + + QObject::connect(tracer, + &Tracer::emitGoToFrame, + this, + &ComponentShape::emitGoToFrame); + } + + // PATH + else if (m_tracingStyle == "Path") { + + if (lastPointDifference != adjustedHistoryPointDifference) { + + QLineF base = QLineF(lastPointDifference, + adjustedHistoryPointDifference); + QGraphicsLineItem* lineItem = new QGraphicsLineItem( + base, + m_tracingLayer); + lineItem->setPen( + QPen(timeDegradationPenColor, m_penWidth, m_penStyle)); + + lastPointDifference = adjustedHistoryPointDifference; + } + } + + // ARROWPATH + else if (m_tracingStyle == "Arrow path") { + + if (lastPointDifference != adjustedHistoryPointDifference) { + + QLineF base = QLineF(lastPointDifference, + adjustedHistoryPointDifference); + + int armLength = std::floor(base.length() / 9) + 2; + + QLineF arm0 = base.normalVector(); + arm0.setLength(armLength); + arm0.setAngle(base.angle() + 20); + + QLineF arm1 = base.normalVector(); + arm1.setLength(armLength); + arm1.setAngle(base.angle() - 20); + + QGraphicsLineItem* baseItem = new QGraphicsLineItem( + base, + m_tracingLayer); + baseItem->setPen(QPen(timeDegradationBrushColor, + m_penWidth, + m_penStyle)); + QGraphicsLineItem* arm0Item = new QGraphicsLineItem( + arm0, + m_tracingLayer); + arm0Item->setPen(timeDegradationPen); + QGraphicsLineItem* arm1Item = new QGraphicsLineItem( + arm1, + m_tracingLayer); + arm1Item->setPen(timeDegradationPen); + + lastPointDifference = adjustedHistoryPointDifference; + } + } + + // add framenumber to each tracer + if (m_tracerFrameNumber) { + uint tracerNumber = m_currentFramenumber - i; + QFont font = QFont(); + int fontPixelSize = (int) ((m_w + m_h) / 5) * + m_tracerProportions; + font.setPixelSize(fontPixelSize); + // font.setBold(true); + QGraphicsSimpleTextItem* tracerNumberText = + new QGraphicsSimpleTextItem(QString::number(tracerNumber), + m_tracingLayer); + tracerNumberText->setFont(font); + tracerNumberText->setBrush(QBrush(Qt::white)); // sloooow + QPen pen = QPen(Qt::black); + pen.setWidth(0); + tracerNumberText->setPen(pen); // sloooow + tracerNumberText->setPos( + adjustedHistoryPointDifference + + QPointF(-m_w * m_tracerProportions / 2.0f, + -m_h * m_tracerProportions / 5)); + } + } + } +} + +IModelTrackedTrajectory* ComponentShape::getTrajectory() +{ + return m_trajectory; +} + +void ComponentShape::setPermission( + std::pair permission) +{ + m_permissions.insert(permission); + + switch (permission.first) { + case ENUMS::COREPERMISSIONS::COMPONENTMOVE: + m_pMovable = permission.second; + this->setFlag(ItemIsMovable, permission.second); + break; + case ENUMS::COREPERMISSIONS::COMPONENTREMOVE: + m_pRemovable = permission.second; + break; + case ENUMS::COREPERMISSIONS::COMPONENTSWAP: + m_pSwappable = permission.second; + break; + case ENUMS::COREPERMISSIONS::COMPONENTROTATE: + m_pRotatable = permission.second; + + if (m_pRotatable) { + m_rotationHandleLayer->setVisible(m_orientationLine); + m_rotationHandle->setVisible(m_orientationLine); + } else { + m_rotationHandleLayer->hide(); + m_rotationHandle->hide(); + } + break; + } +} + +int ComponentShape::getId() +{ + return m_id; +} + +bool ComponentShape::isSwappable() +{ + return m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP]; +} + +bool ComponentShape::isRemovable() +{ + return m_pRemovable; +} + +bool ComponentShape::isRotatable() +{ + return m_pRotatable; +} + +QPoint ComponentShape::getOldPos() +{ + return m_oldPos; +} + +// set default members from core params +void ComponentShape::setMembers(CoreParameter* coreParams) +{ + // from coreParams + m_antialiasing = coreParams->m_antialiasingEntities; + + m_tracingStyle = coreParams->m_tracingStyle; + m_tracingTimeDegradation = coreParams->m_tracingTimeDegradation; + m_tracingLength = coreParams->m_tracingHistory; + m_tracingSteps = coreParams->m_tracingSteps; + m_tracerProportions = coreParams->m_tracerProportions; + m_tracingOrientationLine = coreParams->m_tracerOrientationLine; + m_tracerFrameNumber = coreParams->m_tracerFrameNumber; + + m_orientationLine = coreParams->m_trackOrientationLine; + m_showId = coreParams->m_trackShowId; + + m_brushColor = *(coreParams->m_colorBrush); + m_penColor = *(coreParams->m_colorBorder); + + m_dragged = false; + setFlag(QGraphicsItem::ItemIgnoresTransformations, + coreParams->m_ignoreZoom); + + // set dimensions and default dimensions + if (coreParams->m_trackWidth > 0) { + m_w = coreParams->m_trackWidth; + m_wDefault = coreParams->m_trackWidth; + } + if (coreParams->m_trackHeight > 0) { + m_h = coreParams->m_trackHeight; + m_hDefault = coreParams->m_trackHeight; + } + + // initialize helpers + m_rotationHandleLayer = new QGraphicsRectItem(this); + m_rotationHandleLayer->setPos(0, 0); + m_rotationHandleLayer->setFlag(QGraphicsItem::ItemHasNoContents); + + m_rotationHandle = new RotationHandle(QPoint(m_w / 2, m_h / 2), + m_rotationHandleLayer); + m_rotationHandle->setAntialiasing(m_antialiasing); + QObject::connect(m_rotationHandle, + &RotationHandle::emitShapeRotation, + this, + &ComponentShape::receiveShapeRotation); + + if (m_pRotatable) { + m_rotationHandleLayer->setVisible(m_orientationLine); + m_rotationHandle->setVisible(m_orientationLine); + } + + update(); +} + +double ComponentShape::constrainAngle(double x) +{ + x = fmod(x, 360); + if (x < 0) + x += 360; + return x; +} + +//################################SLOTS############################# + +//**************************context menu actions******************** + +void ComponentShape::changeBrushColor() +{ + + this->m_brushColor = QColorDialog::getColor( + m_brushColor, + nullptr, + QString("Choose fill color"), + QColorDialog::ShowAlphaChannel); + // m_transparency = m_brushColor.alpha(); + trace(); + update(); +} + +void ComponentShape::changePenColor() +{ + QColor newColor = QColorDialog::getColor(m_penColor, + nullptr, + QString("Choose border color"), + QColorDialog::ShowAlphaChannel); + // m_transparency = newColor.alpha(); + + if (!isSelected()) { + m_penColorLast = m_penColor; + m_penColor = newColor; + + trace(); + update(); + } else { + m_penColorLast = newColor; + } +} + +void ComponentShape::changeBrushColor(QColor color) +{ + m_brushColor = color; + + trace(); + update(); +} + +void ComponentShape::changePenColor(QColor color) +{ + if (!isSelected()) { + m_penColorLast = m_penColor; + m_penColor = color; + trace(); + update(); + } else { + m_penColorLast = color; + } +} + +bool ComponentShape::removeTrack() +{ + if (m_pRemovable) { + qDebug() << "Removing track..."; + + // emit to set trajectory invalid + Q_EMIT emitRemoveTrajectory(m_trajectory); + + } else { + qDebug() << "Track is not removable"; + } + return m_pRemovable; +} + +bool ComponentShape::removeTrackEntity() +{ + if (m_pRemovable) { + qDebug() << "Removing track entity..."; + + // emit to set trajectory invalid + Q_EMIT emitRemoveTrackEntity(m_trajectory, m_currentFramenumber); + } else { + qDebug() << "track entity is not removable"; + } + return m_pRemovable; +} + +void ComponentShape::markShape(int penwidth) +{ + if (!m_marked) { + m_penWidth = 3; + } else { + m_penWidth = penwidth; + } + m_marked = true; + trace(); + update(); +} + +void ComponentShape::unmarkShape() +{ + m_marked = false; + m_penWidth = 2; + + trace(); + update(); +} + +void ComponentShape::toggleFixTrack() +{ + // if traj is currently fixed-> emit flase, else emit true + bool fixToggle = m_fixed ? false : true; + Q_EMIT emitToggleFixTrack(m_trajectory, fixToggle); + update(); + trace(); +} + +// TODO create ui file for this and do this there +void ComponentShape::createInfoWindow() +{ + QTableWidget* infoTable = new QTableWidget(); + + infoTable->setRowCount(0); + infoTable->setColumnCount(2); + + infoTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Property")); + infoTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); + infoTable->verticalHeader()->hide(); + + QLinkedList> infoList; + infoList.append(QPair("ID", QString::number(m_id))); + infoList.append( + QPair("Framenumber", + QString::number(m_currentFramenumber))); + infoList.append( + QPair("Seen for frames", + QString::number(m_trajectory->validCount()))); + infoList.append(QPair("Width", QString::number(m_w))); + infoList.append(QPair("Height", QString::number(m_h))); + infoList.append(QPair("Orientation (in Degrees)", + QString::number(m_rotation))); + infoList.append( + QPair("Fixed", QString::number(m_fixed))); + + QLinkedList>::const_iterator info; + for (info = infoList.constBegin(); info != infoList.constEnd(); ++info) { + infoTable->insertRow(infoTable->rowCount()); + + QTableWidgetItem* infoKey = new QTableWidgetItem(info->first); + QTableWidgetItem* infoKeyInfo = new QTableWidgetItem(info->second); + infoKey->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | + Qt::ItemIsSelectable); + infoKeyInfo->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | + Qt::ItemIsSelectable); + + infoTable->setItem(infoTable->rowCount() - 1, 0, infoKey); + infoTable->setItem(infoTable->rowCount() - 1, 1, infoKeyInfo); + } + + // infoTable->horizontalHeader()->setStretchLastSection( true ); + infoTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + QWidget* infoWidget = new QWidget(); + const QString title = QString("Information for track %1 on frame %2") + .arg(QString::number(m_id), + QString::number(m_currentFramenumber)); + infoWidget->setWindowTitle(title); + QVBoxLayout* vLayout = new QVBoxLayout(); + + infoWidget->resize(infoTable->size()); + vLayout->addWidget(infoTable); + infoWidget->setLayout(vLayout); + + infoWidget->show(); +} + +// this is only visual, the object name is not set in the exported file +void ComponentShape::setObjectNameContext(QString name) +{ + setObjectName(name); + m_trajectory->setObjectName(name); +} + +void ComponentShape::morphIntoRect() +{ + setData(1, "rectangle"); + updateAttributes(m_currentFramenumber); + trace(); +} +void ComponentShape::morphIntoEllipse() +{ + setData(1, "ellipse"); + updateAttributes(m_currentFramenumber); + trace(); +} +void ComponentShape::morphIntoPoint() +{ + setData(1, "point"); + updateAttributes(m_currentFramenumber); + trace(); +} +void ComponentShape::morphIntoPolygon() +{ + setData(1, "polygon"); + + updateAttributes(m_currentFramenumber); + trace(); +} + +//************************************************************************ + +//*************************** SLOTS to set members***************************** +void ComponentShape::receiveTracingLength(int tracingLength) +{ + m_tracingLength = tracingLength; + trace(); + update(); +} + +void ComponentShape::receiveTracingStyle(QString style) +{ + m_tracingStyle = style; + trace(); + update(); +} + +void ComponentShape::receiveTracingSteps(int steps) +{ + m_tracingSteps = steps; + trace(); + update(); +} + +void ComponentShape::receiveTracingTimeDegradation(QString timeDegradation) +{ + m_tracingTimeDegradation = timeDegradation; + trace(); + update(); +} + +void ComponentShape::receiveTracerProportions(float proportion) +{ + m_tracerProportions = proportion; + trace(); + update(); +} + +void ComponentShape::receiveTracerOrientationLine(bool toggle) +{ + m_tracingOrientationLine = toggle; + trace(); + update(); +} + +void ComponentShape::receiveTracerFrameNumber(bool toggle) +{ + m_tracerFrameNumber = toggle; + trace(); + update(); +} + +void ComponentShape::receiveAntialiasing(bool toggle) +{ + m_antialiasing = toggle; + m_rotationHandle->setAntialiasing(toggle); + trace(); + update(); +} + +void ComponentShape::receiveDimensions(int width, int height) +{ + m_useDefaultDimensions = false; + m_w = width; + m_h = height; + updateAttributes(m_currentFramenumber); + trace(); + update(); +} + +void ComponentShape::receiveHeight(int height) +{ + m_useDefaultDimensions = false; + m_h = height; + updateAttributes(m_currentFramenumber); + trace(); + update(); +} + +void ComponentShape::receiveWidth(int width) +{ + m_useDefaultDimensions = false; + m_w = width; + updateAttributes(m_currentFramenumber); + trace(); + update(); +} + +void ComponentShape::setDimensionsToDefault() +{ + m_useDefaultDimensions = true; + m_w = m_wDefault; + m_h = m_hDefault; + updateAttributes(m_currentFramenumber); + trace(); + update(); +} + +void ComponentShape::receiveToggleOrientationLine(bool toggle) +{ + m_orientationLine = toggle; + if (m_pRotatable) { + m_rotationHandleLayer->setVisible(toggle); + m_rotationHandle->setVisible(toggle); + } + trace(); + update(); +} + +void ComponentShape::receiveShowId(bool toggle) +{ + m_showId = toggle; + trace(); + update(); +} + +void ComponentShape::receiveShapeRotation(double angle, bool rotateEntity) +{ + m_rotationHandleLayer->setTransformOriginPoint(m_w / 2, m_h / 2); + // m_rotationHandleLayer->setRotation(-angle); + + this->setTransformOriginPoint(m_w / 2, m_h / 2); + if (m_h > m_w || data(1) == "polygon") { + m_rotationHandleLayer->setRotation(-angle + 90); + this->setRotation(m_rotation + angle - 90); + } else { + m_rotationHandleLayer->setRotation(-angle); + this->setRotation(m_rotation + angle); + } + + if (rotateEntity) { + + this->pos(); + + double toAngle = -angle - m_rotation; + double oldAngle = -m_rotation; + + double toAngleNorm = constrainAngle(toAngle); + double oldAngleNorm = constrainAngle(oldAngle); + Q_EMIT emitEntityRotation(m_trajectory, + oldAngleNorm, + toAngleNorm, + m_currentFramenumber); + } + + update(); +} + +// currently disabled +void ComponentShape::receiveIgnoreZoom(bool toggle) +{ + setFlag(QGraphicsItem::ItemIgnoresTransformations, toggle); + trace(); + update(); +} + +void ComponentShape::receiveTransparency(int alpha) +{ + m_transparency = alpha; + m_brushColor.setAlpha(alpha); + m_penColor.setAlpha(alpha); + + QColor penColorHandle = m_rotationHandle->pen().color(); + penColorHandle.setAlpha(alpha); + m_rotationHandle->setPen(QPen(penColorHandle)); + + QColor brushColorHandle = m_rotationHandle->brush().color(); + brushColorHandle.setAlpha(alpha); + m_rotationHandle->setBrush(QBrush(brushColorHandle)); + + trace(); + update(); +} diff --git a/Src/View/ComponentShape.h b/Src/View/ComponentShape.h new file mode 100644 index 00000000..04eace35 --- /dev/null +++ b/Src/View/ComponentShape.h @@ -0,0 +1,246 @@ +#ifndef COMPONENTSHAPE_H +#define COMPONENTSHAPE_H + +#include "QGraphicsObject" +#include "Interfaces/IView/IViewTrackedComponent.h" +#include "Interfaces/IModel/IModelTrackedComponent.h" +#include "qpainter.h" +#include "qgraphicsitem.h" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "Model/CoreParameter.h" +#include "QTime" +#include "View/Utility/RotationHandle.h" + +/** + * This class inherits QGraphicsObject. + * It is a child of the TrackedComponentView and is generated by it for + * each trajectory in the tracking data. It visualizes the corresponding entity + * of the trajectory in the current frame of the medium. If there is no + * tracking data for that frame, this shape is hidden. It deletes itself when + * the trajectory is a nullpointer. It contains user interaction functionality + * to move, remove and rotate the corresponding entity or trajectory. The + * form/type is set when created (from entity: ellipse, point, rectangle, + * polygon) It can be changed by the user via the context menu + */ +class ComponentShape : public QGraphicsObject +{ + Q_OBJECT + +public: + // Constructor + ComponentShape(QGraphicsObject* parent = 0, + IModelTrackedTrajectory* trajectory = 0, + int id = -1); + ~ComponentShape(); + + // QGraphicsItem interface + QRectF boundingRect() const override; + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + QPainterPath shape() const override; + bool advance(); + //////////////////////////////// + + /** + * called by view when tracking data was modified + * updates this with data from new current entity + * --> rotation, position, etc.... + */ + bool updateAttributes(uint framenumber); + + /// returns the corresponding traj + IModelTrackedTrajectory* getTrajectory(); + + /// set permission to enable/disable certain user interactions + void setPermission(std::pair permission); + + /// returns ID of corresponding trajectory + int getId(); + + /// returns swappable permission + bool isSwappable(); + /// returns removeable permission + bool isRemovable(); + /// returns rotatable permission + bool isRotatable(); + + /// helper function + QPoint getOldPos(); + + /// attemps to draw tracers, if _tracingStyle is set tracers are drawn + void trace(); + + /// called in constructor to setup the members with default vlaues from + /// coreparameter component + void setMembers(CoreParameter* coreParams); + + // public members + int m_currentFramenumber; /**< current visualized framenumber --> entity */ + // to fix a bug when moving; TODO better + int m_w; /**< width of this; if polygon width of bounding rect of polygon + */ + int m_h; /**< height of this; if polygon height of bounding rect of polygon + */ + + QGraphicsRectItem* + m_tracingLayer; /**< the layer with all tracers; is counter-rotated if + component shape is rotated */ + +signals: + + /* + * These are the signals sent to the command component. + * They are all modifiying the trakcing data. + * They contain all the data to reverse them (in the commands component). + */ + void emitRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void emitRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void emitMoveElement(IModelTrackedTrajectory* trajectory, + QPoint oldPos, + QPoint newPos, + uint frameNumber, + int sizeOfStackToMove); + void emitToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); + void emitEntityRotation(IModelTrackedTrajectory* trajectory, + double oldAngleDeg, + double newAngleDeg, + uint frameNumber); + ///////////////////////////////////////////// + + void emitGoToFrame(int frame); + /// each user movement gets broadcasted to other shapes + void broadcastMove(); + +public Q_SLOTS: + // context menu actions + //(actions only give trigger signals and therefore can only connect to + // parameterless slots) + void changeBrushColor(); + void changePenColor(); + void changeBrushColor(QColor color); + void changePenColor(QColor color); + bool removeTrack(); + bool removeTrackEntity(); + void markShape(int penwidth = 0); + void unmarkShape(); + void toggleFixTrack(); + void createInfoWindow(); + void setObjectNameContext(QString name); + void morphIntoRect(); + void morphIntoEllipse(); + void morphIntoPoint(); + void morphIntoPolygon(); + ////////////////////////////////////////////// + + // Tracing + void receiveTracingLength(int tracingLength); + void receiveTracingStyle(QString style); + void receiveTracingSteps(int steps); + void receiveTracingTimeDegradation(QString timeDegradation); + void receiveTracerProportions(float proportion); + void receiveTracerOrientationLine(bool toggle); + void receiveTracerFrameNumber(bool toggle); + // Visual + void receiveAntialiasing(bool toggle); + void receiveTransparency(int alpha); + // Dimensions + void receiveDimensions(int width, int height); + void receiveHeight(int height); + void receiveWidth(int width); + void setDimensionsToDefault(); + void receiveToggleOrientationLine(bool toggle); + void receiveShowId(bool toggle); + void receiveShapeRotation(double angle, bool rotateEntity); + // Ignore zoom (disabled) + void receiveIgnoreZoom(bool toggle); + +protected: + // QGraphicsItem interface + QVariant itemChange(GraphicsItemChange change, + const QVariant& value) override; + void mousePressEvent(QGraphicsSceneMouseEvent* event) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; + void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; + //////////////////////////////// + + // constrains angles under 0 or over 360 degrees to [0, 360] + double constrainAngle(double x); + +private: + /* + * MEMBERS + */ + + QGraphicsObject* m_parent; + + // permissions + std::map + m_permissions; /**< list of permissions */ + bool m_pMovable; /**< permission to move the component shape */ + bool m_pRemovable; /**< permission to remove the component shape */ + bool m_pSwappable; /**< permission to move the component shape */ + bool m_pRotatable; /**< permission to move the component shape */ + + // dimensions + + // int m_z; + int m_wDefault = 20; /**< default width, will be set by entity */ + int m_hDefault = 20; /**< default height, will be set by entity */ + bool m_useDefaultDimensions; /**< true, if dimensions were changed by user, + they will stay */ + + // appearance + QColor m_penColor; /**< border color */ + QColor m_penColorLast; /**< last border color */ + QColor m_brushColor; /**< fill color */ + int m_transparency; /**< transparency of this */ + bool m_marked; /**< if marked, border is thick */ + int m_penWidth; /**< border_thickness */ + Qt::PenStyle m_penStyle; /**< style of border */ + Qt::PenStyle m_penStylePrev; /**< last stlye of border */ + bool m_antialiasing; /**< if true, antialiasing in enabled */ + + // tracing + QString m_tracingStyle; /**< tracing style (none, path, arrow, shape) */ + int m_tracingLength; /**< sets how many tracers are drawn (history) */ + int m_tracingSteps; /**< sets each x'th tracer is drawn */ + QString m_tracingTimeDegradation; /**< sets tracer color style (default, + transparency, false color) */ + float m_tracerProportions; /**< set the tracers proportion relative to + component shape */ + bool m_tracingOrientationLine; /**< toggles if orientation line is shwon + for tracers */ + bool m_tracerFrameNumber; /**< toggles if tracer's framenumber is shown + (very slow) */ + + // rotation + float m_rotation; /**< the current rotation of the compontent shape and + entity */ + QLineF m_rotationLine; /**< the orientation line */ + RotationHandle* m_rotationHandle; /**< the handle with wich the user can + change the rotation */ + QGraphicsRectItem* + m_rotationHandleLayer; /**< help layer for rotation handle */ + bool m_orientationLine; /**< toggles if _rotationLine is shown */ + + // misc + int m_id; /**< the traj's ID */ + bool m_showId; /**< toggles if id is shown in center */ + IModelTrackedTrajectory* m_trajectory; /**< the corresponding traj */ + QList m_polygons; /**< list of polygons to draw (if entity + inherited from polygon) */ + bool m_fixed; /**< if fixed, border is dotted and tracker cannot change + traj data */ + // bool m_trajectoryWasActiveOnce; /**< unused */ + QPoint m_oldPos; /**< position before moving by hand */ + + // dragging + bool m_dragged; /**< true if currently dragged */ + QTime m_mousePressTime; /**< helper for dragging */ + QPoint m_mousePressPos; /**< helper for dragging */ +}; + +#endif // COMPONENTSHAPE_H diff --git a/Src/View/CoreParameterView.cpp b/Src/View/CoreParameterView.cpp new file mode 100644 index 00000000..fcc8a9ac --- /dev/null +++ b/Src/View/CoreParameterView.cpp @@ -0,0 +1,635 @@ +#include "CoreParameterView.h" +#include "ui_CoreParameterView.h" +#include "qdebug.h" +#include "Model/CoreParameter.h" + +#include +#include "util/types.h" +#include +#include "Controller/ControllerCoreParameter.h" +#include +#include +#include "Controller/IControllerCfg.h" + +CoreParameterView::CoreParameterView(QWidget* parent, + IController* controller, + IModel* model) +: IViewWidget(parent, controller, model) +, ui(new Ui::CoreParameterView) +{ + _cfg = static_cast(controller)->getConfig(); + ui->setupUi(this); + + ui->lineEditRectWidth->setValidator(new QDoubleValidator(this)); + ui->lineEditRectHeight->setValidator(new QDoubleValidator(this)); + + double h = std::max(_cfg->RectificationHeight, + std::numeric_limits::epsilon()); + double w = std::max(_cfg->RectificationWidth, + std::numeric_limits::epsilon()); + std::string sw = std::to_string(w); + std::string sh = std::to_string(h); + sh.erase(sh.find_last_not_of('0') + 1, std::string::npos); + sw.erase(sw.find_last_not_of('0') + 1, std::string::npos); + ui->lineEditRectWidth->setText(sw.c_str()); + ui->lineEditRectHeight->setText(sh.c_str()); + + // TODO implement it correctly before enabling again + ui->checkBoxIgnoreZoom->hide(); + + CoreParameter* coreParams = dynamic_cast(model); + + int trial = + dynamic_cast(controller)->getTrialNumber(); + ui->label_ExpTrialNo->setText(std::to_string(trial).c_str()); + + fillUI(); + setStyle(); + + getNotified(); +} + +CoreParameterView::~CoreParameterView() +{ + delete ui; +} + +QWidget* CoreParameterView::getTrackerHook() +{ + // return ui->tabWidgetParameters; + // dead code + return nullptr; +} + +void CoreParameterView::setPermission( + std::pair permission) +{ + + // first check if permission is for view, if not pass permission to shapes + // -> view has all permissions, shapes only certain ones + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTVIEW && + permission.second == false) { + // disable everything but the area descriptor groupbox + ui->checkBoxEnableCoreView->setEnabled(false); + ui->groupBoxTracks->setEnabled(false); + ui->groupBoxTracing->setEnabled(false); + ui->groupBoxMiscellaneous->setEnabled(false); + ui->groupBoxAnno->setEnabled(false); + ui->groupBoxRectificationParm->setEnabled(true); + _expertSwitch->setEnabled(false); + return; + } + // does not need to be propagated to shapes; only handled by view + // TODO: move this to controller + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTADD && + permission.second == false) { + this->ui->pushButton_addTraj->setDisabled(true); + return; + } +} + +void CoreParameterView::triggerUpdate() +{ + on_checkBoxDisplayTrackingArea_stateChanged(0); + on_checkBoxDisplayRectification_stateChanged(0); + on_checkboxTrackingAreaAsEllipse_stateChanged(0); +} + +void CoreParameterView::areaDescriptorTypeChanged(QString type) +{ + if (type != "0") { + ui->checkboxTrackingAreaAsEllipse->setChecked(true); + } else { + ui->checkboxTrackingAreaAsEllipse->setChecked(false); + } +} + +void CoreParameterView::on_checkBoxEnableCoreView_stateChanged(int v) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + // disable + if (ui->checkBoxEnableCoreView->checkState() == Qt::Unchecked) { + // disable all groupboxes but the area descriptor one + ui->groupBoxTracks->setEnabled(false); + ui->groupBoxTracing->setEnabled(false); + ui->groupBoxMiscellaneous->setEnabled(false); + ui->groupBoxAnno->setEnabled(false); + ui->groupBoxRectificationParm->setEnabled(true); + _expertSwitch->setEnabled(false); + + emitViewSwitch(false); + coreParams->m_viewSwitch = false; + } + // enable + else if (ui->checkBoxEnableCoreView->checkState() == Qt::Checked) { + // enable all groupboxes + ui->groupBoxTracks->setEnabled(true); + ui->groupBoxTracing->setEnabled(true); + ui->groupBoxMiscellaneous->setEnabled(true); + ui->groupBoxAnno->setEnabled(true); + ui->groupBoxRectificationParm->setEnabled(true); + _expertSwitch->setEnabled(true); + + emitViewSwitch(true); + coreParams->m_viewSwitch = true; + } +} + +void CoreParameterView::on_comboBoxTracingStyle_currentIndexChanged( + const QString& text) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_tracingStyle = text; + emitTracingStyle(text); +} + +void CoreParameterView::on_spinBoxTracingHistoryLength_valueChanged(int i) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + // int value = ui->spinBoxTracingHistoryLength->value(); + coreParams->m_tracingHistory = i; + emitTracingHistoryLength(i); +} + +void CoreParameterView::on_spinBoxTracingSteps_valueChanged(int i) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + // int value = ui->spinBoxTracingSteps->value(); + coreParams->m_tracingSteps = i; + emitTracingSteps(i); +} + +void CoreParameterView::on_comboBoxTracingTimeDegradation_currentIndexChanged( + const QString& text) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_tracingTimeDegradation = text; + emitTracingTimeDegradation(text); +} + +void CoreParameterView::on_checkBoxTracerFrameNumber_stateChanged(int toggle) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_tracerFrameNumber = toggle; + emitTracerFrameNumber(toggle); +} + +void CoreParameterView::on_spinBoxTracerProportions_valueChanged(double d) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + // float value = (float)ui->spinBoxTracerProportions->value(); + coreParams->m_tracerProportions = d; + emitTracerProportions(d); +} + +void CoreParameterView::on_checkBoxTracerOrientationLine_stateChanged( + int toggle) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_tracerOrientationLine = toggle; + emitTracerOrientationLine(toggle); +} + +// void CoreParameterView::on_pushButtonSelectAll_clicked() +// { +// emitSelectAll(); +// } + +// void CoreParameterView::on_pushButtonAddTrack_clicked() +// { +// emitAddTrack(); +// } + +void CoreParameterView::on_checkBoxIgnoreZoom_stateChanged(int v) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_ignoreZoom = v; + emitIgnoreZoom(v); +} +// TODO show current color +void CoreParameterView::on_pushButtonColorChangeBorder_clicked() +{ + emitColorChangeBorderAll(); +} + +void CoreParameterView::on_pushButtonColorChangeBorderSelected_clicked() +{ + emitColorChangeBorderSelected(); +} +// TODO show current color +void CoreParameterView::on_pushButtonColorChangeBrush_clicked() +{ + emitColorChangeBrushAll(); +} + +void CoreParameterView::on_pushButtonColorchangeBrushSelected_clicked() +{ + emitColorChangeBrushSelected(); +} + +void CoreParameterView::on_checkBoxTrackOrientationLine_stateChanged(int v) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_trackOrientationLine = v; + emitTrackOrientationLine(v); +} + +void CoreParameterView::on_checkBoxShowId_stateChanged(int v) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_trackShowId = v; + emitTrackShowId(v); +} + +// if dimensions are set for all tracks they are going to be set for new tracks +// aswell +void CoreParameterView::on_pushButtonTrackDimensionSetterAll_clicked() +{ + int width = ui->spinboxTrackWidth->value(); + int height = ui->spinBoxTrackHeight->value(); + + CoreParameter* coreParams = dynamic_cast(getModel()); + if (coreParams) { + coreParams->m_trackWidth = width; + coreParams->m_trackHeight = height; + + emitTrackDimensionsAll(width, height); + } +} + +void CoreParameterView::on_pushButtonTrackDimensionSetterSelected_clicked() +{ + int width = ui->spinboxTrackWidth->value(); + int height = ui->spinBoxTrackHeight->value(); + emitTrackDimensionsSelected(width, height); +} + +void CoreParameterView::on_pushButtonDefaultDimensions_clicked() +{ + emitTrackDimensionsSetDefault(); +} + +void CoreParameterView::on_lineEditRectWidth_textChanged(QString s) +{ + double w = std::max( + ::atof(ui->lineEditRectWidth->text().toStdString().c_str()), + std::numeric_limits::epsilon()); + double h = std::max( + ::atof(ui->lineEditRectHeight->text().toStdString().c_str()), + std::numeric_limits::epsilon()); + Q_EMIT emitRectDimensions(w, h); +} + +void CoreParameterView::on_lineEditRectHeight_textChanged(QString s) +{ + double w = std::max( + ::atof(ui->lineEditRectWidth->text().toStdString().c_str()), + std::numeric_limits::epsilon()); + double h = std::max( + ::atof(ui->lineEditRectHeight->text().toStdString().c_str()), + std::numeric_limits::epsilon()); + Q_EMIT emitRectDimensions(w, h); +} + +void CoreParameterView::on_checkBoxDisplayTrackingArea_stateChanged(int v) +{ + Q_EMIT emitDisplayTrackingArea( + ui->checkBoxDisplayTrackingArea->isChecked()); +} + +void CoreParameterView::on_checkBoxDisplayRectification_stateChanged(int v) +{ + Q_EMIT emitDisplayRectification( + ui->checkBoxDisplayRectification->isChecked()); +} + +void CoreParameterView::on_checkboxTrackingAreaAsEllipse_stateChanged(int v) +{ + Q_EMIT emitTrackingAreaAsEllipse( + ui->checkboxTrackingAreaAsEllipse->isChecked()); +} + +void CoreParameterView::on_pushButtonAnnoColor_clicked() +{ + QPalette pal = ui->pushButtonAnnoColor->palette(); + QColor oldColor = pal.color(QPalette::Button); + QColor newAnnoColor = QColorDialog::getColor( + oldColor, + Q_NULLPTR, + "Set new annotation color", + QColorDialog::ShowAlphaChannel); + + if (newAnnoColor.isValid()) { + QPalette pal = ui->pushButtonAnnoColor->palette(); + pal.setColor(QPalette::Button, newAnnoColor); + ui->pushButtonAnnoColor->setAutoFillBackground(true); + ui->pushButtonAnnoColor->setPalette(pal); + ui->pushButtonAnnoColor->update(); + ui->pushButtonAnnoColor->setAutoFillBackground(true); + ui->pushButtonAnnoColor->setFlat(true); + + Q_EMIT emitSetAnnoColor(newAnnoColor); + } +} + +void CoreParameterView::toggleExpertOptions(bool toggle) +{ + ui->groupBoxTracerDimensions->setVisible(toggle); + ui->groupBoxMiscellaneous->setVisible(toggle); + ui->groupBoxTrackDimensions->setVisible(toggle); + ui->groupBoxTracerDimensions->setVisible(toggle); + ui->groupBoxAnno->setVisible(toggle); + + ui->checkBoxTracerFrameNumber->setVisible(toggle); + ui->checkBoxShowId->setVisible(toggle); +} + +void CoreParameterView::on_checkBoxAntialiasingEntities_toggled(bool toggle) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_antialiasingEntities = toggle; + emitToggleAntialiasingEntities(toggle); +} + +void CoreParameterView::on_checkBoxAntialiasingFull_toggled(bool toggle) +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + coreParams->m_antialiasingFull = toggle; + emitToggleAntialiasingFull(toggle); +} + +void CoreParameterView::fillUI() +{ + // add switchbutton for expert options + _expertSwitch = new SwitchButton("not advanced", "advanced"); + ui->widgetParameterLayout->addWidget(_expertSwitch); + QObject::connect(_expertSwitch, + &SwitchButton::emitSetEnabled, + this, + &CoreParameterView::toggleExpertOptions, + Qt::DirectConnection); + + // setup ui from params + CoreParameter* coreParams = dynamic_cast(getModel()); + + // view toggle + ui->checkBoxEnableCoreView->setChecked(coreParams->m_viewSwitch); + // track ignore zoom + ui->checkBoxIgnoreZoom->setChecked(coreParams->m_ignoreZoom); + // track orientation line + ui->checkBoxTrackOrientationLine->setChecked( + coreParams->m_trackOrientationLine); + // track show id + ui->checkBoxShowId->setChecked(coreParams->m_trackShowId); + // tracer proportions + ui->spinBoxTracerProportions->setValue(coreParams->m_tracerProportions); + // tracer orientation line + ui->checkBoxTracerOrientationLine->setChecked( + coreParams->m_tracerOrientationLine); + // tracing style + if (coreParams->m_tracingStyle == "No tracing") { + ui->comboBoxTracingStyle->setCurrentIndex(0); + } + // tracing time degradation + if (coreParams->m_tracingTimeDegradation == "None") { + ui->comboBoxTracingTimeDegradation->setCurrentIndex(0); + } + // tracing history + if (coreParams->m_tracingHistory) { + ui->spinBoxTracingHistoryLength->setValue( + coreParams->m_tracingHistory); + } + // tracing steps + if (coreParams->m_tracingSteps) { + ui->spinBoxTracingSteps->setValue(coreParams->m_tracingSteps); + } + // tracer frame number + ui->checkBoxTracerFrameNumber->setChecked(coreParams->m_tracerFrameNumber); + // antialiasing + ui->checkBoxAntialiasingEntities->setChecked( + coreParams->m_antialiasingEntities); + ui->checkBoxAntialiasingFull->setChecked(coreParams->m_antialiasingFull); + // track width + if (coreParams->m_trackWidth) { + ui->spinboxTrackWidth->setValue(coreParams->m_trackWidth); + } + // track height + if (coreParams->m_trackHeight) { + ui->spinBoxTrackHeight->setValue(coreParams->m_trackHeight); + } + + // annotation color button + QPalette pal = ui->pushButtonAnnoColor->palette(); + pal.setColor(QPalette::Button, Qt::yellow); + ui->pushButtonAnnoColor->setAutoFillBackground(true); + ui->pushButtonAnnoColor->setPalette(pal); + ui->pushButtonAnnoColor->setFlat(true); + ui->pushButtonAnnoColor->update(); + + // enable/disable widgets + + // expert options + if (_expertSwitch->state()) { + ui->groupBoxTracerDimensions->show(); + ui->groupBoxMiscellaneous->show(); + ui->groupBoxTrackDimensions->show(); + ui->groupBoxAnno->show(); + ui->checkBoxTracerFrameNumber->show(); + ui->checkBoxShowId->show(); + } else { + ui->groupBoxTracerDimensions->hide(); + ui->groupBoxMiscellaneous->hide(); + ui->groupBoxTrackDimensions->hide(); + ui->groupBoxAnno->hide(); + ui->checkBoxTracerFrameNumber->hide(); + ui->checkBoxShowId->hide(); + } +} + +void CoreParameterView::setStyle() +{ + // main groupboxes + ui->groupBoxTracks->setStyleSheet( + "QGroupBox { background-color: #bbdefb;}"); + ui->groupBoxRectificationParm->setStyleSheet( + "QGroupBox { background-color: #d1c4e9; }"); + ui->groupBoxTracing->setStyleSheet( + "QGroupBox { background-color: #c8e6c9; }"); + ui->groupBoxMiscellaneous->setStyleSheet( + "QGroupBox { background-color: #ffecb3; }"); + ui->groupBoxAnno->setStyleSheet( + "QGroupBox { background-color: #fad8ba; }"); + + // expert options are slightly darker + ui->groupBoxTrackDimensions->setStyleSheet( + "QGroupBox { background-color: #90caf9;}"); + ui->groupBoxTracerDimensions->setStyleSheet( + "QGroupBox { background-color: #a5d6a7;}"); + + // default groupbox style + ui->widgetParameter->setStyleSheet( + "QGroupBox" + " {border: 1px solid #e5e5e5; border-radius: 5px; margin-top: 1ex; /* " + "leave space at the top for the title */}" + "QGroupBox::title {subcontrol-origin: margin; padding: -1px 3px; " + "background-color: #e5e5e5; }"); +} + +void CoreParameterView::resetTrial() +{ + _trialActive = false; + _trialStarted = false; + Q_EMIT emitTrialStarted(false); + ui->pushButton_startExp->setText("Start a new Trial"); +} + +void CoreParameterView::getNotified() +{ + CoreParameter* coreParams = dynamic_cast(getModel()); + ui->labelNumberOfTracks->setText( + QString::number(coreParams->m_trackNumber)); + ui->label_ExpObjCnt->setText(QString::number(coreParams->m_trackNumber)); + + int trial = dynamic_cast(getController()) + ->getTrialNumber() + + 1; + ui->label_ExpTrialNo->setText(std::to_string(trial).c_str()); +} + +/************EXPERIMENT TAB*******************/ + +void CoreParameterView::on_pushButton_startExp_clicked() +{ + if (!_trialActive) { + + if (_currentFile == "No Media") { + int ret = QMessageBox::information( + this, + tr("BioTracker"), + tr("Please select a source video first. \nYou can do so in " + "the \"File\" menu."), + QMessageBox::Ok); + } else { + if (!_trialStarted) { + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, + "Confirmation", + "Are you sure you want to start a new trial?" + "\nThis will reset the previous tracking data!", + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) { + qDebug() << "CORE: New trial aborted"; + return; + } + + _trialStarted = true; + emitTrialStarted(true); + emitFinalizeExperiment(); + emitPausePlayback(); + QMessageBox::information( + 0, + "New trial", + "You started a new trial! Previous data was saved and " + "reset.\n\nGo to the timespot in the video you want to " + "track at." + "\n\nPlease add the number of objects you want to track " + "as trajectories.\nResume the video."); + } else { + emitStartPlayback(); + } + emitDeactivateTrackingSwitch(); + emitEnableTracking(); + ui->pushButton_startExp->setText("Pause Trial"); + ui->label_ExpSt->setText("Active - tracking"); + _trialActive = true; + } + } else { + + emitDisableTracking(); + emitPausePlayback(); + ui->pushButton_startExp->setText("Resume Trial"); + ui->label_ExpSt->setText("Paused - not tracking"); + _trialActive = false; + } +} + +void CoreParameterView::on_pushButton_finalizeExp_clicked() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, + "Confirmation", + "Are you sure you want to finalize the trial?" + "\nThis will save the current trial tracking" + " data in a new file in the 'Trials' directory" + " and reset it afterwards!", + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) { + qDebug() << "CORE: Finalize trial aborted!"; + return; + } + + Q_EMIT emitStopPlayback(); + Q_EMIT emitActivateTrackingSwitch(); + Q_EMIT emitDisableTracking(); + _trialActive = false; + _trialStarted = false; + ui->pushButton_startExp->setText("Start a new Trial"); + ui->label_ExpSt->setText("No Trial started!"); + Q_EMIT emitTrialStarted(false); + Q_EMIT emitFinalizeExperiment(); +} + +void CoreParameterView::on_trialHelpButton_clicked() +{ + QMessageBox::information( + 0, + "Trials", + "'Start a new Trial' will cause all the previous data to be saved and " + "then reset.\n\n" + "Go to the time spot you want to track and create a trajectory for " + "each object you want to track.\n" + "Resume the video and the tracker will track your objects.\n\n" + "If you want to pause the tracking you can just pause the video. " + "Resuming the video will continue the tracking.\n" + "If you want to pause the video and resume without tracking you will " + "have to click 'Pause Trial' causing the tracking to be disabled.\n" + "You can now watch the video without tracking.\n\n" + "'Resume trial' will cause the tracking to be activated AND the video " + "to be resumed"); +} + +void CoreParameterView::on_pushButton_saveData_clicked() +{ + emitSaveDataToFile(); +} + +void CoreParameterView::on_pushButton_resetData_clicked() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, + "Confirmation", + "Are you sure you want to reset the current tracking data?" + "This will firstly save the data and then reset it!", + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) { + qDebug() << "CORE: Data reset aborted"; + return; + } + Q_EMIT emitFinalizeExperiment(); +} + +void CoreParameterView::on_pushButton_addTraj_clicked() +{ + emitAddTrack(); +} + +void CoreParameterView::rcvPlayerParameters( + std::shared_ptr parameters) +{ + QFileInfo f(parameters->m_CurrentFilename); + _currentFile = f.baseName(); + ui->label_ExpSrcCnt->setText(_currentFile); +} diff --git a/Src/View/CoreParameterView.h b/Src/View/CoreParameterView.h new file mode 100644 index 00000000..ba197e4b --- /dev/null +++ b/Src/View/CoreParameterView.h @@ -0,0 +1,201 @@ +#ifndef COREPARAMETERVIEW_H +#define COREPARAMETERVIEW_H + +#include "Interfaces/IView/IViewWidget.h" +#include "View/Utility/SwitchButton.h" +#include "Model/MediaPlayerStateMachine/MediaPlayerStateMachine.h" +#include "util/Config.h" + +namespace Ui +{ + class CoreParameterView; +} + +/** + * This class contains the 'Experiment' tab and the 'Visualisation options' + *tab in the GUI It basically displays the current set parameters The + */ + +class CoreParameterView : public IViewWidget +{ + Q_OBJECT + +public: + explicit CoreParameterView(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); + ~CoreParameterView(); + + QWidget* getTrackerHook(); + void setPermission(std::pair permission); + + // Triggers re-sending essential signals + void triggerUpdate(); + + void areaDescriptorTypeChanged(QString type); + +private slots: + + /* + VIEW TAB + */ + // Enable view + void on_checkBoxEnableCoreView_stateChanged(int v); + // Tracing + void on_comboBoxTracingStyle_currentIndexChanged(const QString& text); + void on_spinBoxTracingHistoryLength_valueChanged(int i); + void on_spinBoxTracingSteps_valueChanged(int i); + void on_comboBoxTracingTimeDegradation_currentIndexChanged( + const QString& text); + void on_checkBoxTracerFrameNumber_stateChanged(int toggle); + + void on_spinBoxTracerProportions_valueChanged(double d); + void on_checkBoxTracerOrientationLine_stateChanged(int toggle); + + // Track + // void on_pushButtonSelectAll_clicked(); + // void on_pushButtonAddTrack_clicked(); + + void on_checkBoxIgnoreZoom_stateChanged(int v); + + // Track color + void on_pushButtonColorChangeBorder_clicked(); + void on_pushButtonColorChangeBorderSelected_clicked(); + void on_pushButtonColorChangeBrush_clicked(); + void on_pushButtonColorchangeBrushSelected_clicked(); + + // Track dimensions + void on_checkBoxTrackOrientationLine_stateChanged(int v); + void on_checkBoxShowId_stateChanged(int v); + + void on_pushButtonTrackDimensionSetterAll_clicked(); + void on_pushButtonTrackDimensionSetterSelected_clicked(); + void on_pushButtonDefaultDimensions_clicked(); + + // Area descriptor + void on_lineEditRectWidth_textChanged(QString s); + void on_lineEditRectHeight_textChanged(QString s); + void on_checkBoxDisplayTrackingArea_stateChanged(int v); + void on_checkBoxDisplayRectification_stateChanged(int v); + void on_checkboxTrackingAreaAsEllipse_stateChanged(int v); + + // Annotations + void on_pushButtonAnnoColor_clicked(); + + // Finalize experiment + // void on_pushButtonFinalizeExperiment_clicked(); + + // Misc + // void on_checkBoxExpertOptions_stateChanged(int v); + void toggleExpertOptions(bool toggle); + void on_checkBoxAntialiasingEntities_toggled(bool toggle); + void on_checkBoxAntialiasingFull_toggled(bool toggle); + + /* + EXPERIMENT TAB + */ + + // label_ExpTrialNo + // label_ExpSrcCnt + // label_ExpObjCnt + // pushButton_startExp + // pushButton_finalizeExp + void on_pushButton_startExp_clicked(); + void on_pushButton_finalizeExp_clicked(); + void on_trialHelpButton_clicked(); + void on_pushButton_saveData_clicked(); + void on_pushButton_resetData_clicked(); + void on_pushButton_addTraj_clicked(); +public slots: + void rcvPlayerParameters( + std::shared_ptr parameters); + +public: +signals: + + /* + EXPERIMENT TAB + */ + void emitEnableTracking(); + void emitDisableTracking(); + void emitActivateTrackingSwitch(); + void emitDeactivateTrackingSwitch(); + void emitStartPlayback(); + void emitStopPlayback(); + void emitPausePlayback(); + void emitTrialStarted(bool started); + void emitSaveDataToFile(); + + // Enable view + void emitViewSwitch(bool lever); + // Select all tracks + // void emitSelectAll(); + // Add tracks + void emitAddTrack(); + // Ignore zoom + void emitIgnoreZoom(bool toggle); + // Track color + void emitColorChangeBorderAll(); + void emitColorChangeBorderSelected(); + void emitColorChangeBrushAll(); + void emitColorChangeBrushSelected(); + // Track dimensions + void emitTrackOrientationLine(bool toggle); + void emitTrackShowId(bool toggle); + void emitTrackDimensionsAll(int width, int height); + void emitTrackDimensionsSelected(int width, int height); + void emitTrackDimensionsSetDefault(); + // Tracing + void emitTracingHistoryLength(int history); + void emitTracingStyle(QString style); + void emitTracingSteps(int steps); + void emitTracingTimeDegradation(QString degradation); + void emitTracerFrameNumber(bool toggle); + // Tracing dimensions + void emitTracerProportions(float proportion); + void emitTracerOrientationLine(bool toggle); + + // Area descriptor + void emitRectDimensions(double w, double h); + void emitDisplayTrackingArea(bool b); + void emitDisplayRectification(bool b); + void emitTrackingAreaAsEllipse(bool b); + + // Annotations + void emitSetAnnoColor(QColor color); + + // Finalize Experiment + void emitFinalizeExperiment(); + + // Misc + void emitToggleAntialiasingEntities(bool toggle); + void emitToggleAntialiasingFull(bool toggle); + +private: + Ui::CoreParameterView* ui; /**< processed ui file */ + + bool m_viewSwitch; /**< switch to enable/disable visualization options tab + */ + SwitchButton* + _expertSwitch; /**< switch to expand visualization options tab */ + bool _trialActive = false; /**< currently trial active? */ + bool _trialStarted = false; /**< was trial started? */ + QString _currentFile = + "No Media"; /**< show media name in experiment tab */ + + Config* _cfg; + + // IViewWidget interface +public slots: + + void getNotified(); + + /// fills the ui elements with the current default parameters + void fillUI(); + + /// styles the "visualisation options" tab + void setStyle(); + void resetTrial(); +}; + +#endif // COREPARAMETERVIEW_H diff --git a/BioTracker/CoreApp/BioTracker/View/CoreParameterView.ui b/Src/View/CoreParameterView.ui similarity index 99% rename from BioTracker/CoreApp/BioTracker/View/CoreParameterView.ui rename to Src/View/CoreParameterView.ui index 70f6c8e1..7e449dae 100644 --- a/BioTracker/CoreApp/BioTracker/View/CoreParameterView.ui +++ b/Src/View/CoreParameterView.ui @@ -1235,7 +1235,7 @@ 0 - + 3 @@ -2046,7 +2046,7 @@ You can add some by right-clicking the video (if loaded). - + Current status of the trial. If paused the tracking is deactivated. diff --git a/Src/View/GLVideoView.cpp b/Src/View/GLVideoView.cpp new file mode 100644 index 00000000..7741842c --- /dev/null +++ b/Src/View/GLVideoView.cpp @@ -0,0 +1,54 @@ +#include "GLVideoView.h" + +#include +#include "Interfaces/IController/IController.h" + +#include "Model/TextureObject.h" + +GLVideoView::GLVideoView(QWidget* parent, + IController* controller, + IModel* model) +: IViewOpenGLWidget(parent, controller, model) +{ +} + +GLVideoView::~GLVideoView() +{ +} + +void GLVideoView::paintGL() +{ + TextureObject* textureObject = dynamic_cast(getModel()); + QImage img = textureObject->get(); + + QPainter painter(this); + + painter.setBrush(QColor(0, 0, 0)); + painter.drawRect(QRect(0, 0, this->width(), this->height())); + painter.setBrush(QColor(0, 0, 0, 0)); + + QRect window; + QRect viewport; + const float viewport_skew = + BioTracker::Core::ScreenHelper::calculate_viewport( + textureObject->width(), + textureObject->height(), + this->width(), + this->height(), + window, + viewport); + + painter.setWindow(window); + painter.setViewport(viewport); + + QRectF target(0, 0, textureObject->width(), textureObject->height()); + QRectF source(0, 0, textureObject->width(), textureObject->height()); + + painter.drawImage(target, img, source); + QPainter p(this); +} + +void GLVideoView::getNotified() +{ + this->update(); +} diff --git a/BioTracker/CoreApp/BioTracker/View/GLVideoView.h b/Src/View/GLVideoView.h similarity index 65% rename from BioTracker/CoreApp/BioTracker/View/GLVideoView.h rename to Src/View/GLVideoView.h index afc0bd29..e60bcd0c 100644 --- a/BioTracker/CoreApp/BioTracker/View/GLVideoView.h +++ b/Src/View/GLVideoView.h @@ -5,22 +5,20 @@ #include "QPainter" #include "Interfaces/IView/IViewWidget.h" -#include "Model/TextureObject.h" -class GLVideoView: public IViewOpenGLWidget +class GLVideoView : public IViewOpenGLWidget { public: - GLVideoView(QWidget *parent, IController *controller = 0, IModel *model = 0); + GLVideoView(QWidget* parent, + IController* controller = 0, + IModel* model = 0); ~GLVideoView(); private: void paintGL() override; - public Q_SLOTS: void getNotified(); - - }; #endif // BIOTRACKER3VIDEOVIEW_H diff --git a/Src/View/GraphicsScene.cpp b/Src/View/GraphicsScene.cpp new file mode 100644 index 00000000..5fa099e1 --- /dev/null +++ b/Src/View/GraphicsScene.cpp @@ -0,0 +1,12 @@ +#include "GraphicsScene.h" + +GraphicsScene::GraphicsScene(QObject* parent, + IController* controller, + IModel* model) +: IViewGraphicsScene(parent, controller, model) +{ +} + +void GraphicsScene::getNotified() +{ +} diff --git a/BioTracker/CoreApp/BioTracker/View/GraphicsScene.h b/Src/View/GraphicsScene.h similarity index 66% rename from BioTracker/CoreApp/BioTracker/View/GraphicsScene.h rename to Src/View/GraphicsScene.h index d590051a..37367584 100644 --- a/BioTracker/CoreApp/BioTracker/View/GraphicsScene.h +++ b/Src/View/GraphicsScene.h @@ -6,7 +6,9 @@ class GraphicsScene : public IViewGraphicsScene { public: - GraphicsScene(QObject *parent = 0, IController *controller = 0, IModel *model = 0); + GraphicsScene(QObject* parent = 0, + IController* controller = 0, + IModel* model = 0); // IViewGraphicsScene interface public Q_SLOTS: diff --git a/Src/View/GraphicsView.cpp b/Src/View/GraphicsView.cpp new file mode 100644 index 00000000..b0ada981 --- /dev/null +++ b/Src/View/GraphicsView.cpp @@ -0,0 +1,148 @@ +#include "GraphicsView.h" + +#include +#include +#include +#include + +#include "../Controller/ControllerGraphicScene.h" +#include "../Model/Annotations.h" + +GraphicsView::GraphicsView(QWidget* parent, + IController* controller, + IModel* model) +: IViewGraphicsView(parent, controller, model) +{ + m_GraphicsScene = new QGraphicsScene(); + m_BackgroundImage = NULL; + + this->setScene(m_GraphicsScene); + + this->setBackgroundBrush(QBrush(Qt::white)); + + this->show(); + + setTransformationAnchor(AnchorUnderMouse); + setViewportUpdateMode(FullViewportUpdate); + + setDragMode(RubberBandDrag); +} + +void GraphicsView::addGraphicsItem(QGraphicsItem* item) +{ + m_GraphicsScene->addItem(item); + + update(); +} + +void GraphicsView::removeGraphicsItem(QGraphicsItem* item) +{ + m_GraphicsScene->removeItem(item); + + update(); +} + +void GraphicsView::addPixmapItem(QGraphicsItem* item) +{ + m_BackgroundImage = item; + m_GraphicsScene->addItem(item); + item->setZValue(-5); + + update(); +} + +void GraphicsView::getNotified() +{ +} + +void GraphicsView::wheelEvent(QWheelEvent* event) +{ + // if ctrl pressed, use original functionality + if (event->modifiers() & Qt::ControlModifier) { + QGraphicsView::wheelEvent(event); + } + // otherwise, do yours + else { + if (event->delta() > 0) { + scale(1.1, 1.1); + } else { + scale(0.9, 0.9); + } + } +} + +void GraphicsView::keyReleaseEvent(QKeyEvent* event) +{ + emit(onKeyReleaseEvent(event)); +} + +void GraphicsView::keyPressEvent(QKeyEvent* event) +{ + emit(onKeyPressEvent(event)); +} + +void GraphicsView::mousePressEvent(QMouseEvent* event) +{ + // The middle mouse button is not forwarded but handled here. + if (event->buttons() & Qt::MidButton) { + m_ViewportDragOrigin = event->pos(); + } else { + const QPointF imagePosition = mapToScene(event->pos()); + const QPoint imagePositionInt = QPoint(imagePosition.x(), + imagePosition.y()); + event->ignore(); + emit(onMousePressEvent(event, imagePositionInt)); + if (!event->isAccepted()) + QGraphicsView::mousePressEvent(event); + } +} + +void GraphicsView::mouseReleaseEvent(QMouseEvent* event) +{ + if (!(event->buttons() & Qt::MidButton)) { + const QPointF imagePosition = mapToScene(event->pos()); + const QPoint imagePositionInt = QPoint(imagePosition.x(), + imagePosition.y()); + event->ignore(); + emit(onMouseReleaseEvent(event, imagePositionInt)); + if (!event->isAccepted()) + QGraphicsView::mouseReleaseEvent(event); + } +} + +void GraphicsView::mouseMoveEvent(QMouseEvent* event) +{ + viewport()->update(); + // The middle mouse button is not forwarded but handled here. + if (event->buttons() & Qt::MidButton) { + const QPoint currentPosition{event->pos()}; + // Ignore position-reset events.. + if (currentPosition != m_ViewportDragOrigin) { + const QPoint currentPositionScene = currentPosition; + const QPoint originPositionScene = m_ViewportDragOrigin; + const auto offset = currentPositionScene - originPositionScene; + + QGraphicsView::horizontalScrollBar()->setValue( + horizontalScrollBar()->value() + offset.x() + 1); + QGraphicsView::verticalScrollBar()->setValue( + verticalScrollBar()->value() + offset.y() + 1); + // Freeze mouse position in place. + QCursor::setPos(mapToGlobal(m_ViewportDragOrigin)); + } + } else { + const QPointF imagePosition = mapToScene(event->pos()); + const QPoint imagePositionInt = QPoint(imagePosition.x(), + imagePosition.y()); + m_cursorPos = imagePositionInt; + emitCursorPosition(m_cursorPos); // to mainwindow + event->ignore(); + emit(onMouseMoveEvent(event, imagePositionInt)); + if (!event->isAccepted()) + QGraphicsView::mouseMoveEvent(event); + } +} + +void GraphicsView::receiveToggleAntialiasingFull(bool toggle) +{ + setRenderHint(QPainter::Antialiasing, toggle); +} \ No newline at end of file diff --git a/Src/View/GraphicsView.h b/Src/View/GraphicsView.h new file mode 100644 index 00000000..64f4e54b --- /dev/null +++ b/Src/View/GraphicsView.h @@ -0,0 +1,54 @@ +#ifndef GRAPHICSVIEW_H +#define GRAPHICSVIEW_H + +#include "Interfaces/IView/IViewGraphicsView.h" +#include "QGraphicsScene" + +class GraphicsView : public IViewGraphicsView +{ + Q_OBJECT +public: + GraphicsView(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); + + void addGraphicsItem(QGraphicsItem* item); + void addPixmapItem(QGraphicsItem* item); + void removeGraphicsItem(QGraphicsItem* item); + + QGraphicsScene* m_GraphicsScene; // MARKER + + void mousePressEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; + void keyPressEvent(QKeyEvent* event) override; + + // IGraphicsView interface +public Q_SLOTS: + void getNotified() override; + void receiveToggleAntialiasingFull(bool toggle); + + // QWidget interface +protected: + void wheelEvent(QWheelEvent* event) override; + +private: + QGraphicsItem* m_BackgroundImage; + QPoint m_ViewportDragOrigin{0, 0}; + QPoint m_cursorPos; + +Q_SIGNALS: + // If you connect to these signals, you MUST use Qt::DirectConnection. + // You also SHOULD call event->accept() if you handle it. + // You MAY want to only handle events with isAccepted() == false. + void onMousePressEvent(QMouseEvent* event, QPoint imagePosition); + void onMouseReleaseEvent(QMouseEvent* event, QPoint imagePosition); + void onMouseMoveEvent(QMouseEvent* event, QPoint imagePosition); + void onKeyReleaseEvent(QKeyEvent* event); + void onKeyPressEvent(QKeyEvent* event); + + void emitCursorPosition(QPoint pos); +}; + +#endif // GRAPHICSVIEW_H diff --git a/Src/View/MainWindow.cpp b/Src/View/MainWindow.cpp new file mode 100644 index 00000000..834b3e0c --- /dev/null +++ b/Src/View/MainWindow.cpp @@ -0,0 +1,1223 @@ +#include "MainWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ui_MainWindow.h" + +#include "util/types.h" + +#include "Model/null_Model.h" +#include "View/CoreParameterView.h" +#include "View/GraphicsView.h" +#include "View/AnnotationsView.h" +#include "Controller/ControllerMainWindow.h" +#include "Controller/null_Controller.h" +#include "Controller/ControllerTextureObject.h" + +#include "VideoControllWidget.h" + +MainWindow::MainWindow(QWidget* parent, IController* controller, IModel* model) +: IViewMainWindow(parent, controller, model) +, ui(new Ui::MainWindow) +{ + _cfg = static_cast(controller)->getConfig(); + _previouslySelectedTracker = ""; + _currentParameterView = 0; + _currentCoreParameterView = 0; + _currentElementView = 0; + ui->setupUi(this); + + // add cursor position label + QLabel* _cursorPosition = new QLabel("0,0"); + _cursorPosition->setObjectName("_cursorPosition"); + statusBar()->insertPermanentWidget(0, _cursorPosition); + + // TODO + ui->actionToggle_compact_menu_toolbar_2->setEnabled(false); + + // setup toolbars + setupUpperToolBar(); + setupVideoToolBar(); + ui->toolBarTools->setEnabled(false); + + ui->toolBox->setStyleSheet( + "QToolBox::tab {" + " background-color: #e5e5e5;}"); + + // resize to full size + QWidget::showMaximized(); + + createIntroductionWizard(); + + // set window icon + QApplication::setWindowIcon( + QIcon(":/Logo/resources/logo/BT-3_non_transparent_rounded.ico")); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +//******************************************SETUP******************************************* + +void MainWindow::setupUpperToolBar() +{ + + _trackerActivator = new SwitchButton("not tracking", "tracking"); + _trackerActivator->setToolTip("Activate/Disable tracking"); + QObject::connect(_trackerActivator, + &SwitchButton::emitSetEnabled, + this, + &MainWindow::receiveSetTracking, + Qt::DirectConnection); + // QAction* activatorAction = + // ui->toolBarMenu->addWidget(_trackerActivator); + + /////////////////////media groupbox + _mediaBox = new QGroupBox("Load media"); + // style groupbox (initial red border -> no video loaded) + _mediaBox->setStyleSheet( + "QGroupBox" + " {border: 1px solid #e56262;}"); + // "QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top + // center; padding: 0 3px;}"); + QFont font = QFont(); + font.setPointSize(8); + font.setBold(true); + _mediaBox->setFont(font); + + QHBoxLayout* mediaBoxLayout = new QHBoxLayout; + mediaBoxLayout->setContentsMargins(0, 0, 0, 0); + // mediaBoxLayout->setSpacing(0); + QToolButton* cameraButton = new QToolButton; + cameraButton->setIconSize(QSize(24, 24)); + cameraButton->setDefaultAction(ui->actionOpen_Camera); + cameraButton->setAutoRaise(true); + + QToolButton* videoButton = new QToolButton; + videoButton->setIconSize(QSize(24, 24)); + videoButton->setDefaultAction(ui->actionOpen_Video); + videoButton->setAutoRaise(true); + + QToolButton* imageButton = new QToolButton; + imageButton->setIconSize(QSize(24, 24)); + imageButton->setDefaultAction(ui->actionOpen_Picture); + imageButton->setAutoRaise(true); + + mediaBoxLayout->addWidget(videoButton); + mediaBoxLayout->addWidget(imageButton); + mediaBoxLayout->addWidget(cameraButton); + + _mediaBox->setLayout(mediaBoxLayout); + + ui->toolBarMenu->addWidget(_mediaBox); + + ////////trackerbox + _trackerBox = new QGroupBox("Load tracker"); + // style groupbox + _trackerBox->setStyleSheet( + "QGroupBox" + " {border: 1px solid #e56262;}"); + // "QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top + // center; padding: 0 3px;}"); + + QFont font0 = QFont(); + font0.setPointSize(8); + font0.setBold(true); + _trackerBox->setFont(font0); + + QHBoxLayout* trackerBoxLayout = new QHBoxLayout; + trackerBoxLayout->setContentsMargins(0, 0, 0, 0); + + QToolButton* trackerButton = new QToolButton; + trackerButton->setIconSize(QSize(24, 24)); + trackerButton->setDefaultAction(ui->actionLoad_Tracker); + trackerButton->setAutoRaise(true); + + trackerBoxLayout->addWidget(trackerButton); + _trackerBox->setLayout(trackerBoxLayout); + + ui->toolBarMenu->addWidget(_trackerBox); + + ////////loadSaveBox + QGroupBox* loadSaveBox = new QGroupBox("Load/Save Data"); + // style loadSaveBox + // loadSaveBox->setStyleSheet("QGroupBox" + // " {border: 1px solid #e5e5e5;border-radius: 5px;margin-top: 1ex; /* + // leave space at the top for the title */}" "QGroupBox::title + // {subcontrol-origin: margin;subcontrol-position: top center; padding: 0 + // 3px;}"); + + QFont font2 = QFont(); + font2.setPointSize(8); + font2.setBold(true); + loadSaveBox->setFont(font2); + + QHBoxLayout* loadSaveBoxLayout = new QHBoxLayout; + loadSaveBoxLayout->setContentsMargins(5, 0, 5, 0); + + QToolButton* loadFileButton = new QToolButton; + loadFileButton->setIconSize(QSize(24, 24)); + loadFileButton->setDefaultAction(ui->actionLoad_trackingdata); + loadFileButton->setAutoRaise(true); + + QToolButton* saveFileButton = new QToolButton; + saveFileButton->setIconSize(QSize(24, 24)); + saveFileButton->setDefaultAction(ui->actionSave_trackingdata); + saveFileButton->setAutoRaise(true); + + loadSaveBoxLayout->addWidget(loadFileButton); + loadSaveBoxLayout->addWidget(saveFileButton); + loadSaveBox->setLayout(loadSaveBoxLayout); + + ui->toolBarMenu->addWidget(loadSaveBox); + + //////////////////choose tracker groupbox + QGroupBox* chooseTrackerBox = new QGroupBox("Choose tracker"); + // style groupbox + // chooseTrackerBox->setStyleSheet("QGroupBox" + // " {border: 1px solid #e5e5e5;border-radius: 5px;margin-top: 1ex; /* + // leave space at the top for the title */}" "QGroupBox::title + // {subcontrol-origin: margin;subcontrol-position: top center; padding: 0 + // 3px;}"); + + QFont font1 = QFont(); + font1.setPointSize(8); + font1.setBold(true); + chooseTrackerBox->setFont(font1); + // + QHBoxLayout* chooseTrackerBoxLayout = new QHBoxLayout; + chooseTrackerBoxLayout->addWidget(ui->comboBox_TrackerSelect); + chooseTrackerBoxLayout->addWidget(_trackerActivator); + + chooseTrackerBox->setLayout(chooseTrackerBoxLayout); + + ui->toolBarMenu->addWidget(chooseTrackerBox); + + /// Display image + { + auto container = new QGroupBox("Select tracking view image"); + + auto layout = new QHBoxLayout(); + + auto selector = new QComboBox(); + + auto textureController = qobject_cast( + getController()->getBioTrackerContext()->requestController( + ENUMS::CONTROLLERTYPE::TEXTUREOBJECT)); + + selector->setModel(textureController->textureNamesModel()); + + connect(selector, + QOverload::of(&QComboBox::currentIndexChanged), + this, + [=](int index) { + auto imageName = selector->itemText(index); + qDebug() << imageName; + if (textureController->hasTexture(imageName)) { + textureController->changeTextureModel(imageName); + } + }); + + layout->addWidget(selector); + + container->setLayout(layout); + + ui->toolBarMenu->addWidget(container); + } +} + +void MainWindow::checkTrackerGroupBox() +{ + _trackerBox->setStyleSheet( + "QGroupBox" + " {border: 1px solid #82c985;}"); +} + +void MainWindow::checkMediaGroupBox() +{ + _mediaBox->setStyleSheet( + "QGroupBox" + " {border: 1px solid #82c985;}"); +} + +void MainWindow::setupVideoToolBar() +{ +} + +void MainWindow::addVideoControllWidget(IView* widget) +{ + QLayout* layout = new QGridLayout(); + // layout->addWidget(dynamic_cast(widget)); + + QWidget* controlW = dynamic_cast(widget); + if (controlW) { + layout->addWidget(controlW->findChild("sld_video")); + } + ui->videoControls->setLayout(layout); + + // ui->videoControls->adjustSize(); +} + +void MainWindow::addVideoView(IView* videoView) +{ + m_graphView = dynamic_cast(videoView); + m_graphView->setParent(ui->trackingArea); + + ui->videoViewLayout->addWidget(m_graphView); +} + +void MainWindow::addTrackerElementsView(IView* elemView) +{ + + QGraphicsObject* graphObj = dynamic_cast(elemView); + graphObj->setParent(ui->trackingArea); + + m_graphView->addGraphicsItem(graphObj); + QRectF viewSceneRect = m_graphView->sceneRect(); + + _currentElementView = graphObj; +} + +void MainWindow::addCoreElementsView(IView* coreView) +{ + QGraphicsObject* graphObj = dynamic_cast(coreView); + graphObj->setParent(ui->trackingArea); + + m_graphView->addGraphicsItem(graphObj); + _currentCoreView = graphObj; +} + +void MainWindow::addNotificationBrowser(IView* notificationBrowser) +{ + QWidget* notificationWidget = dynamic_cast(notificationBrowser); + if (notificationWidget) { + notificationWidget->updateGeometry(); + + ui->notificationTab->layout()->addWidget(notificationWidget); + + notificationWidget->setVisible(1); + } + + // createIntroductionWizard(); +} + +void MainWindow::addTrackerParameterView(IView* parameter) +{ + QWidget* pluginParameter = dynamic_cast(parameter); + + while (auto item = ui->trackerOptions->layout()->takeAt(0)) { + delete item->widget(); + } + + ui->trackerOptions->layout()->addWidget(pluginParameter); +} + +void MainWindow::addCoreParameterView(IView* coreParameterView) +{ + + QWidget* coreParameter = dynamic_cast(coreParameterView); + if (coreParameter) { + // add experiment widget to toolbar + QWidget* experimentWidget = coreParameter->findChild( + "experimentWidget"); + if (experimentWidget) { + ui->experimentItem->layout()->addWidget(experimentWidget); + } + + ui->widget_alg->updateGeometry(); + coreParameter->updateGeometry(); + coreParameter->setContentsMargins(QMargins(0, 0, 0, 0)); + coreParameter->setParent(ui->widget_alg); + + QHBoxLayout* hLayout = new QHBoxLayout; + hLayout->addWidget(coreParameter, 100, 0); + hLayout->setContentsMargins( + QMargins(0, 0, 0, 0)); // left, top, right, bottom + hLayout->setMargin(0); + + ui->widget_alg->setLayout(hLayout); + + coreParameter->setVisible(1); + _currentCoreParameterView = coreParameterView; + + // resize rightpanel + QList splitterSizes; + splitterSizes << 20000 << 10000; // 2:1 TODO make this fixed (right + // panel fixed start size) + ui->mainSplitter->setSizes(splitterSizes); + } +} + +void MainWindow::setTrackerList(QStringListModel* trackerList, QString current) +{ + ui->comboBox_TrackerSelect->setModel(trackerList); + ui->comboBox_TrackerSelect->setCurrentText(current); +} + +// TODO put this in a class +void MainWindow::createIntroductionWizard() +{ + m_introWiz = new QWizard; + + // BioTracker::Core::Settings *disableIntroWiz = + // GET_CORESETTINGS(CORE_CONFIGURATION); + bool disabled = _cfg->DisableWizard; + + // dont show again checkbox + QCheckBox* noShowCheck = new QCheckBox("Don't show this again"); + noShowCheck->setChecked(disabled); + QObject::connect(noShowCheck, + &QCheckBox::toggled, + this, + &MainWindow::toggleNoShowWiz); + + // introduction + QWizardPage* p1 = new QWizardPage; + { + p1->setTitle("BioTracker 3 - Introduction"); + + QPixmap logoImg(":/Logo/resources/logo/BT3-big.png"); + QPixmap scaledImg = logoImg.scaled(QSize(600, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + + QLabel* imgLabel = new QLabel; + imgLabel->setPixmap(scaledImg); + imgLabel->setAttribute(Qt::WA_TranslucentBackground); + imgLabel->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + imgLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + + QFile file(":/Introduction/resources/introduction/intro.txt"); + QLabel* introLabel = new QLabel; + introLabel->setWordWrap(true); + + // read introduction text from file + QString line; + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + line.append(stream.readLine() + "\n"); + } + introLabel->setText(line); + } + file.close(); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(imgLabel); + QScrollArea* textScroll = new QScrollArea; + textScroll->setFrameShape(QFrame::NoFrame); + textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + textScroll->setWidget(introLabel); + textScroll->setWidgetResizable(true); + layout->addWidget(textScroll); + layout->setAlignment(Qt::AlignHCenter); + p1->setLayout(layout); + } + + // overview + QWizardPage* p2 = new QWizardPage; + { + p2->setTitle("BioTracker 3 - Overview"); + QLabel* label = new QLabel( + "This is the BioTracker. Don't let yourself be overwhelmed as it " + "is actually pretty simple."); + label->setWordWrap(true); + + QPixmap overviewImg( + ":/Introduction/resources/introduction/images/BioTracker.PNG"); + QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + + QLabel* imgLabel = new QLabel; + imgLabel->setPixmap(scaledImg); + imgLabel->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + // imgLabel->setScaledContents(true); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(imgLabel); + QScrollArea* textScroll = new QScrollArea; + textScroll->setFrameShape(QFrame::NoFrame); + textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + textScroll->setWidget(label); + textScroll->setWidgetResizable(true); + layout->addWidget(textScroll); + layout->setAlignment(Qt::AlignHCenter); + p2->setLayout(layout); + } + + // toolbars + QWizardPage* p3 = new QWizardPage; + { + p3->setTitle("BioTracker 3 - Toolbars"); + + // image + QPixmap overviewImg( + ":/Introduction/resources/introduction/images/toolbars.png"); + QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + QLabel* imgLabel = new QLabel; + + imgLabel->setPixmap(scaledImg); + + // read toolbar text from file + QFile file(":/Introduction/resources/introduction/toolbars.txt"); + QLabel* label = new QLabel(); + label->setWordWrap(true); + + QString line; + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + line.append(stream.readLine() + "\n"); + } + label->setText(line); + } + file.close(); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(imgLabel); + QScrollArea* textScroll = new QScrollArea; + textScroll->setFrameShape(QFrame::NoFrame); + textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + textScroll->setWidget(label); + textScroll->setWidgetResizable(true); + layout->addWidget(textScroll); + layout->setAlignment(Qt::AlignHCenter); + p3->setLayout(layout); + } + + // right panel - overview + QWizardPage* p4 = new QWizardPage; + { + p4->setTitle("BioTracker 3 - Right panel overview"); + + // image + QPixmap overviewImg( + ":/Introduction/resources/introduction/images/right_panel.png"); + QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + QLabel* imgLabel = new QLabel; + imgLabel->setPixmap(scaledImg); + + // read right panel text from file + QFile file(":/Introduction/resources/introduction/right_panel.txt"); + QLabel* label = new QLabel(); + label->setWordWrap(true); + + QString line; + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + line.append(stream.readLine() + "\n"); + } + label->setText(line); + } + file.close(); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(imgLabel); + QScrollArea* textScroll = new QScrollArea; + textScroll->setFrameShape(QFrame::NoFrame); + textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + textScroll->setWidget(label); + textScroll->setWidgetResizable(true); + layout->addWidget(textScroll); + layout->setAlignment(Qt::AlignHCenter); + + p4->setLayout(layout); + } + + // how to track + QWizardPage* p5 = new QWizardPage; + { + p5->setTitle("BioTracker 3 - Tracking"); + + // image + QPixmap overviewImg( + ":/Introduction/resources/introduction/images/tracking.png"); + QPixmap scaledImg = overviewImg.scaled(QSize(600, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + QLabel* imgLabel = new QLabel; + imgLabel->setPixmap(scaledImg); + + // read tracking text from file + QFile file(":/Introduction/resources/introduction/tracking.txt"); + QLabel* label = new QLabel(); + label->setWordWrap(true); + + QString line; + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + line.append(stream.readLine() + "\n"); + } + label->setText(line); + } + file.close(); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(imgLabel); + QScrollArea* textScroll = new QScrollArea; + textScroll->setFrameShape(QFrame::NoFrame); + textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + textScroll->setWidget(label); + textScroll->setWidgetResizable(true); + layout->addWidget(textScroll); + layout->setAlignment(Qt::AlignHCenter); + + p5->setLayout(layout); + } + + // context menus + QWizardPage* p6 = new QWizardPage; + { + p6->setTitle("BioTracker 3 - Context menus"); + + // images + QPixmap contextEntityImg( + ":/Introduction/resources/introduction/images/context_entity.png"); + QPixmap scaledImg1 = contextEntityImg.scaled(QSize(300, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + QLabel* imgEntityLabel = new QLabel; + imgEntityLabel->setPixmap(scaledImg1); + + QPixmap contextVideoImg( + ":/Introduction/resources/introduction/images/context_video.png"); + QPixmap scaledImg2 = contextVideoImg.scaled(QSize(300, 400), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + QLabel* imgVideoLabel = new QLabel; + imgVideoLabel->setPixmap(scaledImg2); + + // read tracking text from file + QFile file(":/Introduction/resources/introduction/context_menus.txt"); + QLabel* label = new QLabel(); + label->setWordWrap(true); + + QString line; + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + line.append(stream.readLine() + "\n"); + } + label->setText(line); + } + file.close(); + + QVBoxLayout* outerLayout = new QVBoxLayout; + QHBoxLayout* imgLayout = new QHBoxLayout; + imgLayout->addWidget(imgEntityLabel); + imgLayout->addWidget(imgVideoLabel); + QFrame* imgFrame = new QFrame; + imgFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken); + imgFrame->setLayout(imgLayout); + + outerLayout->addWidget(imgFrame); + QScrollArea* textScroll = new QScrollArea; + textScroll->setFrameShape(QFrame::NoFrame); + textScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + textScroll->setWidget(label); + textScroll->setWidgetResizable(true); + outerLayout->addWidget(textScroll); + outerLayout->addWidget(noShowCheck); + + outerLayout->setAlignment(Qt::AlignHCenter); + + p6->setLayout(outerLayout); + } + + m_introWiz->addPage(p1); + m_introWiz->addPage(p2); + m_introWiz->addPage(p3); + m_introWiz->addPage(p4); + m_introWiz->addPage(p5); + m_introWiz->addPage(p6); + // m_introWiz->addPage(p7); + + m_introWiz->setWindowTitle("Introduction"); + if (!disabled) { + QRect rec = QApplication::desktop()->availableGeometry(); + m_introWiz->resize(m_introWiz->width(), 500); + m_introWiz->show(); + // m_introWiz->showMaximized(); + } +} + +/////////////////////////////////////////// + +void MainWindow::setCorePermission( + std::pair permission) +{ + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTADD) { + ui->actionAdd_Track->setEnabled(permission.second); + return; + } + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTREMOVE) { + ui->actionDelete_selected_tracks->setEnabled(permission.second); + return; + } + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTSWAP) { + ui->actionSwap_ID_s->setEnabled(permission.second); + return; + } +} + +void MainWindow::on_comboBox_TrackerSelect_currentIndexChanged(QString s) +{ + QString ct = ui->comboBox_TrackerSelect->currentText(); + if (!ct.isEmpty() && _previouslySelectedTracker != ct) { + _previouslySelectedTracker = ct; + Q_EMIT selectPlugin(ct); + } +} + +void MainWindow::setCursorPositionLabel(QPoint pos) +{ + QString posString = QString("%1, %2").arg(QString::number(pos.x()), + QString::number(pos.y())); + + QLabel* currentChild = statusBar()->findChild("_cursorPosition"); + currentChild->setText(posString); +} + +void MainWindow::activeTrackingCheckBox() +{ + // ui->checkBox_TrackingActivated->setEnabled(true); + _trackerActivator->setEnabled(true); + checkTrackerGroupBox(); + ui->toolBarTools->setEnabled(true); +} + +void MainWindow::deactivateTrackingCheckBox() +{ + // ui->checkBox_TrackingActivated->setEnabled(false); + _trackerActivator->setEnabled(false); +} + +void MainWindow::saveDataToFile() +{ + static const QString fileFilter( + "tracking data files (*.csv *.dat *.json)"); + + boost::filesystem::path file; + + std::string locStr = _cfg->DefaultLocationManualSave.toStdString(); + QString locStrQ = QString::fromStdString(locStr); + + QString f = QFileDialog::getSaveFileName(this, + "Save trajectory data to file", + locStrQ, + fileFilter, + 0); + + if (f != "") { + qobject_cast(getController()) + ->saveTrajectoryFile(f.toStdString()); + } +} + +////////////////////////////////////////////////SLOTS///////////////////////////////////// + +void MainWindow::toggleNoShowWiz(bool toggle) +{ + _cfg->DisableWizard = toggle; // Todo implicit cast bool->int +} + +void MainWindow::receiveSelectedCameraDevice(CameraConfiguration conf) +{ + qobject_cast(getController()) + ->loadCameraDevice(conf); +} + +void MainWindow::on_rightPanelViewControllerButton_clicked() +{ + QList splitterSizes = QList(); + if (ui->widgetParameterAreaOuterCanvas->isVisible()) { + _lastRightPanelWidth = + ui->mainSplitter->sizes()[1]; // save last width to restore on show + _lastVideoWidgetWidth = ui->mainSplitter->sizes()[0]; + + ui->widgetParameterAreaOuterCanvas->hide(); + splitterSizes + << 20000 + << ui->rightPanelViewControllerWidget->minimumSizeHint().width(); + + ui->rightPanelViewControllerButton->setText("<"); + // set menu action unchecked + ui->actionRight_panel->setChecked(false); + } else { + ui->widgetParameterAreaOuterCanvas->show(); + splitterSizes << _lastVideoWidgetWidth << _lastRightPanelWidth; + ui->rightPanelViewControllerButton->setText(">"); + + // set menu action checked + ui->actionRight_panel->setChecked(true); + } + ui->mainSplitter->setSizes(splitterSizes); +} + +void MainWindow::on_bottomPanelViewControllerButton_clicked() +{ + ui->videoControls->setVisible( + ui->bottomPanelViewControllerButton->text() == "^"); + ui->bottomPanelViewControllerButton->setText( + ui->bottomPanelViewControllerButton->text() == "v" ? "^" : "v"); +} + +void MainWindow::activateTracking() +{ + _trackerActivator->setState(true); +} + +void MainWindow::deactivateTracking() +{ + _trackerActivator->setState(false); +} + +void MainWindow::receiveSetTracking(bool toggle) +{ + if (toggle) { + qobject_cast(getController())->activeTracking(); + } else { + qobject_cast(getController()) + ->deactiveTrackring(); + } +} + +void MainWindow::resetTrackerViews() +{ + if (_currentElementView && _currentCoreView) { + _currentElementView->setParent(0); + _currentCoreView->setParent(0); + m_graphView->removeGraphicsItem(_currentElementView); + m_graphView->removeGraphicsItem(_currentCoreView); + } + + _currentElementView = nullptr; + _currentCoreView = nullptr; +} + +//////////////////////////utility toolbar action +/// slots/////////////////////////// +void MainWindow::on_actionAdd_Track_triggered() +{ + qobject_cast(getController())->emitAddTrack(); +} +void MainWindow::on_actionDelete_selected_tracks_triggered() +{ + qobject_cast(getController()) + ->emitDeleteSelectedTracks(); +} +void MainWindow::on_actionSwap_ID_s_triggered() +{ + qobject_cast(getController())->emitSwapIds(); +} +void MainWindow::on_actionSelect_all_triggered() +{ + qobject_cast(getController())->emitSelectAll(); +} +void MainWindow::on_actionChange_the_border_color_triggered() +{ + qobject_cast(getController()) + ->emitChangeColorBorder(); +} +void MainWindow::on_actionChange_the_fill_color_triggered() +{ + qobject_cast(getController()) + ->emitChangeColorFill(); +} +void MainWindow::on_actionAdd_label_Annotation_triggered() +{ + qobject_cast(getController())->emitAddLabelAnno(); +} +void MainWindow::on_actionAdd_rectangular_annotation_triggered() +{ + qobject_cast(getController())->emitAddRectAnno(); +} +void MainWindow::on_actionAdd_arrow_annotation_triggered() +{ + qobject_cast(getController())->emitAddArrAnno(); +} +void MainWindow::on_actionAdd_elliptical_annotation_triggered() +{ + qobject_cast(getController())->emitAddEllAnno(); +} +void MainWindow::on_actionDelete_selected_Annotation_triggered() +{ + qobject_cast(getController())->emitDelSelAnno(); +} + +///////////////////////////////menu->file slots///////////////////////////// + +void MainWindow::on_actionOpen_Video_triggered() +{ + static const QString videoFilter( + "Video files (*.avi *.wmv *.mp4 *.mkv *.mov)"); + + QString filename = + QFileDialog::getOpenFileName(this, "Open video", "", videoFilter, 0); + + if (!filename.isEmpty()) { + dynamic_cast(getController()) + ->loadVideo({filename.toStdString().c_str()}); + } +} + +void MainWindow::on_actionOpen_Video_batch_triggered() +{ + static const QString videoFilter( + "Video files (*.avi *.wmv *.mp4 *.mkv *.mov)"); + + std::vector files; + + for (QString const& path : + QFileDialog::getOpenFileNames(this, + "Open image files", + "", + videoFilter, + 0)) { + files.push_back(boost::filesystem::path(path.toStdString())); + } + + if (!files.empty()) { + qobject_cast(getController())->loadVideo(files); + } +} + +void MainWindow::on_actionLoad_Tracker_triggered() +{ + static const QString pluginFilter( + "BioTracker Tracking Plugin files (*.bio_tracker.so *.bio_tracker.dll " + "*.bio_tracker.dylib)"); + + QString filename = QFileDialog::getOpenFileName( + this, + "Open BioTracker Tracking Plugin", + "", + pluginFilter, + 0); + + if (!filename.isEmpty()) { + qobject_cast(getController()) + ->loadTracker(filename); + } +} + +void MainWindow::on_actionOpen_Picture_triggered() +{ + static const QString imageFilter( + "image files (*.png *.jpg *.jpeg *.gif *.bmp *.jpe *.ppm *.tiff *.tif " + "*.sr *.ras *.pbm *.pgm *.jp2 *.dib)"); + + std::vector files; + for (QString const& path : + QFileDialog::getOpenFileNames(this, + "Open image files", + "", + imageFilter, + 0)) { + files.push_back(boost::filesystem::path(path.toStdString())); + } + + if (!files.empty()) { + qobject_cast(getController()) + ->loadPictures(files); + } +} + +void MainWindow::on_actionLoad_trackingdata_triggered() +{ + static const QString imageFilter( + "tracking data files (*.csv *.dat *.json)"); + + std::vector files; + for (QString const& path : + QFileDialog::getOpenFileNames(this, + "Open tracking file", + "", + imageFilter, + 0)) { + files.push_back(boost::filesystem::path(path.toStdString())); + } + + if (!files.empty()) { + qobject_cast(getController()) + ->loadTrajectoryFile(files[0].string()); + } +} + +void MainWindow::on_actionSave_trackingdata_triggered() +{ + saveDataToFile(); +} + +void MainWindow::on_actionOpen_Camera_triggered() +{ + m_CameraDevice = new CameraDevice(); + + m_CameraDevice->show(); + + QObject::connect(m_CameraDevice, + &CameraDevice::emitSelectedCameraDevice, + this, + &MainWindow::receiveSelectedCameraDevice); +} + +void MainWindow::on_actionQuit_triggered() +{ + qobject_cast(getController())->exit(); +} + +///////////////////////////////menu->edit slots///////////////////////////// + +void MainWindow::on_actionUndo_triggered() +{ + qobject_cast(getController())->emitUndoCommand(); +} + +void MainWindow::on_actionRedo_triggered() +{ + qobject_cast(getController())->emitRedoCommand(); +} + +void MainWindow::on_actionShowActionList_triggered() +{ + qobject_cast(getController()) + ->emitShowActionListCommand(); +} + +void MainWindow::on_actionSettings_triggered() +{ + m_SettingsWindow = new SettingsWindow(0, _cfg); + + m_SettingsWindow->show(); +} + +///////////////////////////////menu->view slots///////////////////////////// + +// toggle toolbars actions +void MainWindow::on_actionToggle_menu_toolbar_triggered() +{ + bool currentState = ui->toolBarMenu->isVisible(); + ui->toolBarMenu->setVisible(!currentState); + ui->actionToggle_menu_toolbar->setText( + !currentState ? "Hide menu toolbar" : "Show menu toolbar"); +} +void MainWindow::on_actionToggle_view_toolbar_triggered() +{ + bool currentState = ui->toolBarTools->isVisible(); + ui->toolBarTools->setVisible(!currentState); + ui->actionToggle_view_toolbar->setText( + !currentState ? "Hide view toolbar" : "Show view toolbar"); +} +void MainWindow::on_actionToggle_video_toolbar_triggered() +{ + bool currentState = ui->toolBarVideo->isVisible(); + ui->toolBarVideo->setVisible(!currentState); + ui->actionToggle_video_toolbar->setText( + !currentState ? "Hide view toolbar" : "Show view toolbar"); +} + +void MainWindow::on_actionToggle_compact_menu_toolbar_2_triggered() +{ + ui->toolBarMenu->setStyleSheet( + "QGroupBox" + " {border-style: none; margin-top: 0ex; font-size: 1px;}" + "QGroupBox::title {font-size: 1px; padding: 0 3px;}"); +} + +void MainWindow::on_toolBarMenu_visibilityChanged(bool visible) +{ + ui->actionToggle_menu_toolbar->setText(visible ? "Hide menu toolbar" + : "Show menu toolbar"); +} +void MainWindow::on_toolBarTools_visibilityChanged(bool visible) +{ + ui->actionToggle_view_toolbar->setText(visible ? "Hide view toolbar" + : "Show view toolbar"); +} +void MainWindow::on_toolBarVideo_visibilityChanged(bool visible) +{ + ui->actionToggle_video_toolbar->setText(visible ? "Hide video toolbar" + : "Show video toolbar"); +} + +void MainWindow::on_actionBottom_panel_triggered(bool checked) +{ + ui->bottomPanelViewControllerButton->click(); +} +void MainWindow::on_actionRight_panel_triggered(bool checked) +{ + ui->rightPanelViewControllerButton->click(); +} + +void MainWindow::on_actionToggle_fullscreen_triggered() +{ + if (isFullScreen()) { + showNormal(); + } else { + showFullScreen(); + } +} + +//////////////////////////////////menu->Go to +/// slots////////////////////////////////// + +void MainWindow::on_actionOpen_Plugins_directory_triggered() +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(_cfg->DirPlugins)); +} +void MainWindow::on_actionOpen_Track_directory_triggered() +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(_cfg->DirTracks)); +} +void MainWindow::on_actionOpen_Trial_directory_triggered() +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(_cfg->DirTrials)); +} +void MainWindow::on_actionOpen_Screenshot_directory_triggered() +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(_cfg->DirScreenshots)); +} +void MainWindow::on_actionOpen_Videos_directory_triggered() +{ + QDesktopServices::openUrl(QUrl::fromLocalFile(_cfg->DirVideos)); +} + +//////////////////////////////////menu->Help +/// slots////////////////////////////// + +void MainWindow::on_actionUser_guide_triggered() +{ + QDesktopServices::openUrl( + QUrl("https://github.com/BioroboticsLab/biotracker_core/wiki")); +} + +void MainWindow::on_actionAbout_triggered() +{ + std::string version = ""; + version = "BioTracker3

"; + + version = "Source Version: "; + version += SOURCE_VERSION; + version += +"

"; + + version += "External libraries used:

"; + std::string qt = MyQT_VERSION; + version += "QT " + qt + "
"; + + std::string cv = MyCV_VERSION; + version += "OpenCV " + cv + "
"; + + std::string boost = MyBT_VERSION; + version += "Boost " + boost + "
"; + + version += "

Icons by icons8
"; + + version += "

Published under LGPL licence"; + + QMessageBox msgBox(this); + msgBox.setWindowTitle("About BioTracker"); + msgBox.setTextFormat( + Qt::RichText); // this is what makes the links clickable + msgBox.setText(tr(version.c_str())); + msgBox.exec(); + + // QMessageBox::about(this, tr("About BioTracker"), tr(version.c_str())); +} + +void MainWindow::on_actionShortcuts_triggered() +{ + + QTableWidget* scTable = new QTableWidget(); + + scTable->setRowCount(0); + scTable->setColumnCount(2); + + scTable->setHorizontalHeaderItem(0, new QTableWidgetItem("Shortcut")); + scTable->setHorizontalHeaderItem(1, new QTableWidgetItem("Description")); + scTable->verticalHeader()->hide(); + + QLinkedList> scList; + + // read from file in resources and add to linked list + QFile shortcutFile(":Shortcuts/resources/shortcuts.txt"); + + if (!shortcutFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + + QString line; + while (!shortcutFile.atEnd()) { + QTextStream stream(&shortcutFile); + while (!stream.atEnd()) { + line = stream.readLine(); + QStringList shortCutAndDescription = line.split(':'); + if (shortCutAndDescription.size() == 2) { + scList.append( + QPair(shortCutAndDescription[0], + shortCutAndDescription[1])); + } + } + } + + QLinkedList>::const_iterator sc; + for (sc = scList.constBegin(); sc != scList.constEnd(); ++sc) { + scTable->insertRow(scTable->rowCount()); + + QTableWidgetItem* scKey = new QTableWidgetItem(sc->first); + QTableWidgetItem* scKeyInfo = new QTableWidgetItem(sc->second); + scKey->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | + Qt::ItemIsSelectable); + scKeyInfo->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | + Qt::ItemIsSelectable); + + scTable->setItem(scTable->rowCount() - 1, 0, scKey); + scTable->setItem(scTable->rowCount() - 1, 1, scKeyInfo); + } + + // scTable->horizontalHeader()->setStretchLastSection( true ); + scTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + QWidget* outerWidget = new QWidget(); + outerWidget->setWindowTitle("Shortcuts"); + outerWidget->resize(scTable->size()); + QVBoxLayout* vLayout = new QVBoxLayout(); + + vLayout->addWidget(scTable); + + outerWidget->setLayout(vLayout); + + outerWidget->show(); +} + +void MainWindow::on_actionShow_introduction_triggered() +{ + m_introWiz->show(); +} + +///////////// +void MainWindow::closeEvent(QCloseEvent* event) +{ + qobject_cast(getController())->exit(); +} diff --git a/Src/View/MainWindow.h b/Src/View/MainWindow.h new file mode 100644 index 00000000..587a6ca5 --- /dev/null +++ b/Src/View/MainWindow.h @@ -0,0 +1,197 @@ +#ifndef BIOTRACKER3MAINWINDOW_H +#define BIOTRACKER3MAINWINDOW_H + +//#include +#include "Interfaces/IView/IViewMainWindow.h" + +// delete +#include "GLVideoView.h" +#include "CameraDevice.h" +#include "QPointer" +#include "QStringListModel" +#include "QGraphicsObject" +#include "View/GraphicsView.h" +#include "util/types.h" +#include "util/camera/base.h" +#include "SettingsWindow.h" +#include +#include "QWizard" + +#include "Utility/SwitchButton.h" +#include "Controller/IControllerCfg.h" + +namespace Ui +{ + class MainWindow; +} + +class IController; + +/** + * This class inherits IViewMainWindow. + * It is the canvas (GUI) for most of the view of other components. + * It also provides its own fuctionality, like an introduction dialog + */ +class MainWindow : public IViewMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); + ~MainWindow(); + + void addVideoControllWidget(IView* widget); + void addVideoView(IView* videoView); + void addTrackerParameterView(IView* parameter); + void addCoreParameterView(IView* coreParameterView); + // void addExperimentView(QWidget* experimentWidget); + void addTrackerElementsView(IView* elemView); + void addCoreElementsView(IView* coreView); + void addNotificationBrowser(IView* notificationBrowser); + void setTrackerList(QStringListModel* trackerList, QString current); + void setCursorPositionLabel(QPoint pos); + void setCorePermission(std::pair permission); + + void activeTrackingCheckBox(); + void deactivateTrackingCheckBox(); + + void closeEvent(QCloseEvent* event); + + void setupUpperToolBar(); + void setupVideoToolBar(); + + // intro wizard + void createIntroductionWizard(); + + void saveDataToFile(); + + void checkTrackerGroupBox(); + void checkMediaGroupBox(); + void activateTracking(); + + void deactivateTracking(); + + void resetTrackerViews(); + +Q_SIGNALS: + void selectPlugin(QString ct); + +private Q_SLOTS: + + void toggleNoShowWiz(bool toggle); + + // menu->File + void on_actionOpen_Video_triggered(); + + void on_actionOpen_Video_batch_triggered(); + + void on_actionLoad_Tracker_triggered(); + + void on_actionOpen_Picture_triggered(); + + void on_actionLoad_trackingdata_triggered(); + + void on_actionSave_trackingdata_triggered(); + + void on_actionQuit_triggered(); + + void on_actionOpen_Camera_triggered(); + + // menu->Edit + + void on_actionUndo_triggered(); + + void on_actionRedo_triggered(); + + void on_actionShowActionList_triggered(); + + void on_actionSettings_triggered(); + + // menu->View + // menu->View->Toolbars + void on_actionToggle_menu_toolbar_triggered(); + void on_actionToggle_view_toolbar_triggered(); + void on_actionToggle_compact_menu_toolbar_2_triggered(); + void on_actionToggle_video_toolbar_triggered(); + void on_actionToggle_fullscreen_triggered(); + + // menu->Go to + void on_actionOpen_Plugins_directory_triggered(); + void on_actionOpen_Track_directory_triggered(); + void on_actionOpen_Trial_directory_triggered(); + void on_actionOpen_Screenshot_directory_triggered(); + void on_actionOpen_Videos_directory_triggered(); + + // view toolbar actions + void on_actionAdd_Track_triggered(); + void on_actionDelete_selected_tracks_triggered(); + void on_actionSwap_ID_s_triggered(); + void on_actionSelect_all_triggered(); + void on_actionChange_the_border_color_triggered(); + void on_actionChange_the_fill_color_triggered(); + void on_actionAdd_label_Annotation_triggered(); + void on_actionAdd_rectangular_annotation_triggered(); + void on_actionAdd_arrow_annotation_triggered(); + void on_actionAdd_elliptical_annotation_triggered(); + void on_actionDelete_selected_Annotation_triggered(); + + // menu->Help + + void on_actionAbout_triggered(); + + void on_actionShortcuts_triggered(); + + void on_actionUser_guide_triggered(); + + void on_actionShow_introduction_triggered(); + // GUI + + void receiveSelectedCameraDevice(CameraConfiguration conf); + + void on_comboBox_TrackerSelect_currentIndexChanged(QString s); + + void receiveSetTracking(bool toggle); + + // hider + void on_rightPanelViewControllerButton_clicked(); + void on_bottomPanelViewControllerButton_clicked(); + void on_actionBottom_panel_triggered(bool checked = false); + void on_actionRight_panel_triggered(bool checked = false); + // ui signals + void on_toolBarMenu_visibilityChanged(bool visible); + void on_toolBarTools_visibilityChanged(bool visible); + void on_toolBarVideo_visibilityChanged(bool visible); + +private: + Ui::MainWindow* ui; /**< ui file */ + GraphicsView* m_graphView; /**< media panel */ + QLabel* _cursorPosition; /**< cursor Position in media panel */ + int _lastRightPanelWidth; /**< lastRightPanelWidth for layouting */ + int _lastVideoWidgetWidth; /**< lastVideoWidgetWidth for layouting */ + QLabel* cursorPositionLabel; /**< cursonpositionlabel in status bar */ + + QPointer m_CameraDevice; /**< pointer on camera device */ + QPointer m_SettingsWindow; /**< settings window */ + + IView* _currentParameterView; /**< current tracker paramter view */ + IView* _currentCoreParameterView; /**< current core parameter view */ + QGraphicsObject* + _currentElementView; /**< current visualisation view of tracker */ + QGraphicsObject* + _currentCoreView; /**< current visualisation view of core app */ + // QWidget* _currentTrackerP; /**< current tracker + // paramter view + // */ + QString _previouslySelectedTracker; /**< previous tracker */ + + SwitchButton* _trackerActivator; /**< tracking switch */ + QGroupBox* _mediaBox; /**< tracker groupbox in menu toolbar */ + QGroupBox* _trackerBox; /**< media groupbox in menu toolbar */ + + QWizard* m_introWiz; /**< introduction wizard-dialog */ + Config* _cfg; +}; + +#endif // BIOTRACKER3MAINWINDOW_H diff --git a/BioTracker/CoreApp/BioTracker/View/MainWindow.ui b/Src/View/MainWindow.ui similarity index 99% rename from BioTracker/CoreApp/BioTracker/View/MainWindow.ui rename to Src/View/MainWindow.ui index 18665ead..de7321a3 100644 --- a/BioTracker/CoreApp/BioTracker/View/MainWindow.ui +++ b/Src/View/MainWindow.ui @@ -446,8 +446,8 @@ 0 0 - 98 - 28 + 743 + 304 @@ -469,8 +469,8 @@ 0 0 - 98 - 50 + 743 + 304 @@ -515,8 +515,8 @@ 0 0 - 98 - 28 + 743 + 304 @@ -641,8 +641,8 @@ p, li { white-space: pre-wrap; } 0 0 - 98 - 28 + 743 + 304 @@ -699,6 +699,7 @@ p, li { white-space: pre-wrap; } &File + @@ -1363,6 +1364,11 @@ QToolButton { Open Plugins directory + + + Open Video Batch... + +
diff --git a/Src/View/NotificationLogBrowser.cpp b/Src/View/NotificationLogBrowser.cpp new file mode 100644 index 00000000..a17a0fb6 --- /dev/null +++ b/Src/View/NotificationLogBrowser.cpp @@ -0,0 +1,56 @@ +#include "NotificationLogBrowser.h" +#include "QVBoxLayout" + +NotificationLogBrowser::NotificationLogBrowser(QWidget* parent, + IController* controller, + IModel* model) +: IViewWidget(parent, controller, model) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + + browser = new QTextBrowser(this); + browser->setLineWrapMode(QTextEdit::NoWrap); + + layout->addWidget(browser); + + setLayout(layout); + + m_font = QFont(); + m_font.setPointSize(8); + setFont(m_font); + + resize(200, 400); + + this->show(); +} + +NotificationLogBrowser::~NotificationLogBrowser() +{ +} + +void NotificationLogBrowser::outputMessage(QtMsgType type, const QString& msg) +{ + switch (type) { + case QtDebugMsg: + browser->append(msg); + break; + + case QtWarningMsg: + browser->append( + tr("- %1 ").arg(msg)); + break; + + case QtCriticalMsg: + browser->append(tr("- %1 ").arg(msg)); + break; + + case QtFatalMsg: + browser->append( + tr("- %1 ") + .arg(msg)); + break; + } +} +void NotificationLogBrowser::getNotified() +{ +} diff --git a/Src/View/NotificationLogBrowser.h b/Src/View/NotificationLogBrowser.h new file mode 100644 index 00000000..a739c03f --- /dev/null +++ b/Src/View/NotificationLogBrowser.h @@ -0,0 +1,34 @@ +#ifndef NOTIFICATIONLOGBROWSER_H +#define NOTIFICATIONLOGBROWSER_H +#pragma once + +#include "Interfaces/IView/IViewWidget.h" +#include + +/** + * This is the view of the notifications component. + * It displays all intercepted qdebug messages (color-coded). + * http://doc.qt.io/qt-5/qdebug.html + */ +class NotificationLogBrowser : public IViewWidget +{ + Q_OBJECT + +public: + explicit NotificationLogBrowser(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); + ~NotificationLogBrowser(); + + void outputMessage(QtMsgType type, const QString& msg); + + // IViewWidget interface +public slots: + void getNotified(); + +private: + QTextBrowser* browser; + QFont m_font; +}; + +#endif // NOTIFICATIONLOGBROWSER_H \ No newline at end of file diff --git a/Src/View/SettingsWindow.cpp b/Src/View/SettingsWindow.cpp new file mode 100644 index 00000000..c5146dc5 --- /dev/null +++ b/Src/View/SettingsWindow.cpp @@ -0,0 +1,76 @@ +#include "SettingsWindow.h" + +#include "util/Config.h" + +#include + +SettingsWindow::SettingsWindow(QWidget* parent, Config* cfg) +: QWidget(parent) +, ui(new Ui::SettingsForm) +{ + _cfg = cfg; + ui->setupUi(this); + + for (int i = 0; i < codecList.size(); i++) + ui->comboBoxVideoCodec->addItem(codecList[i].first.c_str()); + + int defaultIndex = _cfg->VideoCodecUsed; + ui->comboBoxVideoCodec->setCurrentIndex(defaultIndex); + + bool dropFrames = _cfg->DropFrames; + ui->checkBoxDropFrames->setChecked(dropFrames); + + bool recordScaled = _cfg->RecordScaledOutput; + ui->checkBox_scaledOutput->setChecked(recordScaled); + + for (int i = 0; i < exporterList.size(); i++) + ui->comboBoxDefaultExporter->addItem(exporterList[i].c_str()); + + int exporter = _cfg->DataExporter; + ui->comboBoxDefaultExporter->setCurrentIndex(exporter); + + ui->lineEdit_nthFrame->setValidator(new QIntValidator(this)); + int stride = _cfg->FrameStride; + ui->lineEdit_nthFrame->setText(std::to_string(stride).c_str()); + + ui->lineEdit_qp->setValidator(new QIntValidator(this)); + int qp = _cfg->GpuQp; + ui->lineEdit_qp->setText(std::to_string(qp).c_str()); + + ui->lineEditLocationManSave->setText(_cfg->DefaultLocationManualSave); + +#ifndef WITH_CUDA + ui->lineEdit_qp->setVisible(false); + ui->label_qp->setVisible(false); +#endif +} + +void SettingsWindow::on_buttonSaveClose_clicked() +{ + + _cfg->RecordScaledOutput = ui->checkBox_scaledOutput->isChecked(); + _cfg->DropFrames = ui->checkBoxDropFrames->isChecked(); + _cfg->VideoCodecUsed = ui->comboBoxVideoCodec->currentIndex(); + _cfg->DataExporter = ui->comboBoxDefaultExporter->currentIndex(); + _cfg->FrameStride = (ui->lineEdit_nthFrame->text()).toInt(); + _cfg->GpuQp = (ui->lineEdit_qp->text()).toInt(); + _cfg->DefaultLocationManualSave = (ui->lineEditLocationManSave->text()); + + this->close(); +} + +void SettingsWindow::on_pushButtonSetNewLocManSave_clicked() +{ + QString dirStr = QFileDialog::getExistingDirectory( + this, + tr("Select Directory"), + "", + QFileDialog::ShowDirsOnly); + if (dirStr != "") { + ui->lineEditLocationManSave->setText(dirStr); + } +} + +SettingsWindow::~SettingsWindow() +{ +} diff --git a/Src/View/SettingsWindow.h b/Src/View/SettingsWindow.h new file mode 100644 index 00000000..7c333aeb --- /dev/null +++ b/Src/View/SettingsWindow.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include +#include "QCameraViewfinder" +#include "QPointer" +#include "util/types.h" +#include +#include "ui_SettingsWindow.h" +#include "Controller/IControllerCfg.h" + +namespace Ui +{ + class SettingsWindow; +} + +class SettingsWindow : public QWidget +{ + Q_OBJECT + +public: + explicit SettingsWindow(QWidget* parent, Config* cfg); + ~SettingsWindow(); + +private Q_SLOTS: + void on_buttonSaveClose_clicked(); + void on_pushButtonSetNewLocManSave_clicked(); + +private: + Ui::SettingsForm* ui; + Config* _cfg; +}; \ No newline at end of file diff --git a/BioTracker/CoreApp/BioTracker/View/SettingsWindow.ui b/Src/View/SettingsWindow.ui similarity index 100% rename from BioTracker/CoreApp/BioTracker/View/SettingsWindow.ui rename to Src/View/SettingsWindow.ui diff --git a/Src/View/TextureObjectView.cpp b/Src/View/TextureObjectView.cpp new file mode 100644 index 00000000..aec69c9d --- /dev/null +++ b/Src/View/TextureObjectView.cpp @@ -0,0 +1,54 @@ +#include "TextureObjectView.h" +#include "Model/TextureObject.h" +#include "QGraphicsScene" +#include "View/GraphicsView.h" + +TextureObjectView::TextureObjectView(QObject* parent, + IController* controller, + IModel* model) +: IViewGraphicsPixmapItem(parent, controller, model) +{ + setZValue(-1); + _oldBoundingRect = QRectF(); +} + +void TextureObjectView::getNotified() +{ + TextureObject* texture = dynamic_cast(getModel()); + QPixmap pma; + pma.convertFromImage(texture->get()); + setPixmap(pma); + + // if frame is set, set the boundingrect of the scene to the size of the + // frame + if (texture->height() > 1) { + QGraphicsScene* scene = this->scene(); + + QRectF currentBoundingRect = this->boundingRect(); + + // check if bounding rect changed -> this means that a new video has + // been loaded, right? + if (currentBoundingRect != _oldBoundingRect) { + QRectF boundingWithMargins = currentBoundingRect.marginsAdded( + QMarginsF(150, 150, 150, 150)); + scene->setSceneRect(boundingWithMargins); + + GraphicsView* view = dynamic_cast( + scene->views()[0]); + view->fitInView(boundingWithMargins, Qt::KeepAspectRatio); + + _oldBoundingRect = currentBoundingRect; + } + } + update(); +} + +void TextureObjectView::connectModelView() +{ + QObject::connect(getModel(), + &IModel::notifyView, + this, + &TextureObjectView::getNotified); + + getNotified(); +} diff --git a/BioTracker/CoreApp/BioTracker/View/TextureObjectView.h b/Src/View/TextureObjectView.h similarity index 66% rename from BioTracker/CoreApp/BioTracker/View/TextureObjectView.h rename to Src/View/TextureObjectView.h index 071bbb22..b4bc0f66 100644 --- a/BioTracker/CoreApp/BioTracker/View/TextureObjectView.h +++ b/Src/View/TextureObjectView.h @@ -7,7 +7,9 @@ class TextureObjectView : public IViewGraphicsPixmapItem { Q_OBJECT public: - TextureObjectView(QObject *parent = 0, IController *controller = 0, IModel *model = 0); + TextureObjectView(QObject* parent = 0, + IController* controller = 0, + IModel* model = 0); // IGraphicsPixmapItem interface public Q_SLOTS: @@ -17,8 +19,8 @@ public Q_SLOTS: protected: void connectModelView() override; - //member - QRectF _oldBoundingRect; + // member + QRectF _oldBoundingRect; }; #endif // TEXTUREOBJECTVIEW_H diff --git a/Src/View/TrackedComponentView.cpp b/Src/View/TrackedComponentView.cpp new file mode 100644 index 00000000..7dca627d --- /dev/null +++ b/Src/View/TrackedComponentView.cpp @@ -0,0 +1,846 @@ +#include "TrackedComponentView.h" +#include + +#include "QBrush" +#include "QPainter" +#include +#include "QGraphicsScene" +#include "QGraphicsEllipseItem" + +#include "ComponentShape.h" +#include "Model/CoreParameter.h" +#include "Controller/ControllerTrackedComponentCore.h" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "QDebug" +#include "QMenu" +#include "qlabel.h" +#include "QWidgetAction" +#include "QAction" +#include "qcolordialog.h" + +class QGraphicsSceneHoverEvent; + +TrackedComponentView::TrackedComponentView(QGraphicsItem* parent, + IController* controller, + IModel* model) +: IViewTrackedComponent(parent, controller, model) +{ + + m_boundingRect = QRectF(0, 0, 4080, 4080); + m_currentFrameNumber = 0; + setAcceptHoverEvents(true); + setAcceptDrops(true); + _watchingDrag = 0; + + m_permissions.insert(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTVIEW, + true)); + m_permissions.insert(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTADD, + true)); + m_permissions.insert(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTMOVE, + true)); + m_permissions.insert(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTREMOVE, + true)); + m_permissions.insert(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTSWAP, + true)); + m_permissions.insert(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTROTATE, + true)); +} + +void TrackedComponentView::rcvDimensionUpdate(int x, int y) +{ + m_boundingRect = QRectF(0, 0, x, y); + update(); +} + +QRectF TrackedComponentView::boundingRect() const +{ + return m_boundingRect; +} + +void TrackedComponentView::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + IModelTrackedTrajectory* all = dynamic_cast( + getModel()); + + // check if model exists + if (!all) { + return; + } +} + +void TrackedComponentView::getNotified() +{ + updateShapes(m_currentFrameNumber); + update(); +} + +bool TrackedComponentView::sceneEventFilter(QGraphicsItem* watched, + QEvent* event) +{ + return true; +} + +bool TrackedComponentView::eventFilter(QObject* target, QEvent* event) +{ + return false; +} + +void TrackedComponentView::hoverEnterEvent(QGraphicsSceneHoverEvent* event) +{ +} + +void TrackedComponentView::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) +{ +} + +QVariant TrackedComponentView::itemChange(GraphicsItemChange change, + const QVariant& value) +{ + if (change == ItemSceneHasChanged && this->scene()) { + createChildShapesAtStart(); + } + return QGraphicsItem::itemChange(change, value); +} + +void TrackedComponentView::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ + // right clicking the view unselects all selected items so do this to avoid + // this behavior + if (event->button() != Qt::LeftButton) { + event->accept(); + return; + } + QGraphicsItem::mousePressEvent(event); +} + +/// opens a context menu when right clicked +void TrackedComponentView::contextMenuEvent( + QGraphicsSceneContextMenuEvent* event) +{ + + lastClickedPos = event->pos().toPoint(); + + QMenu menu; + + // create the info box + QWidgetAction* infoBox = new QWidgetAction(this); + QString info = QString("Position (x,y) : "); + info.append(QString("(" + QString::number(lastClickedPos.x()) + ", " + + QString::number(lastClickedPos.y()) + ")")); + QLabel* infoLabel = new QLabel(info); + infoLabel->setWordWrap(true); + infoLabel->setStyleSheet("QLabel {font-weight: bold; text-align: center}"); + infoLabel->setAlignment(Qt::AlignCenter); + infoBox->setDefaultWidget(infoLabel); + menu.addAction(infoBox); + menu.addSeparator(); + QAction* addComponentAction = menu.addAction( + "Add trajectory here", + dynamic_cast(this), + SLOT(addTrajectory())); + QAction* swapIdsAction = menu.addAction( + "Swap ID's", + dynamic_cast(this), + SLOT(swapIds())); + QAction* unmarkAllAction = menu.addAction( + "Unmark all...", + dynamic_cast(this), + SLOT(unmarkAll())); + QAction* removeSelectedAction = menu.addAction( + "Remove selected trajectories", + dynamic_cast(this), + SLOT(removeTrajectories())); + + // manage permissions + addComponentAction->setEnabled( + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTADD]); + swapIdsAction->setEnabled( + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP]); + removeSelectedAction->setEnabled( + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTREMOVE]); + + // manage swapping + swapIdsAction->setEnabled(false); + QList allSelectedItems = this->scene()->selectedItems(); + // check if two shapes are selected + if (allSelectedItems.size() == 2 && + dynamic_cast(allSelectedItems[0]) && + dynamic_cast(allSelectedItems[1])) { + ComponentShape* selectedItem0 = dynamic_cast( + allSelectedItems[0]); + ComponentShape* selectedItem1 = dynamic_cast( + allSelectedItems[1]); + // check if both shapes are swappable (check permission for each shape) + // and general permission + if (selectedItem0->isSwappable() && selectedItem1->isSwappable() && + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP]) { + swapIdsAction->setEnabled(true); + } + } + + // execute menu + QAction* selectedAction = menu.exec(event->screenPos()); + lastClickedPos = QPoint(0, 0); +} + +/// set permissions for this and all component shapes, which were send by the +/// plugin +void TrackedComponentView::setPermission( + std::pair permission) +{ + m_permissions[permission.first] = permission.second; + qDebug() << permission.first << " set to" << permission.second; + + // first check if permission is for view, if not pass permission to shapes + // -> view has all permissions, shapes only certain ones + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTVIEW) { + this->setVisible(permission.second); + return; + } + // does not need to be propagated to shapes; only handled by view + if (permission.first == ENUMS::COREPERMISSIONS::COMPONENTADD) { + return; + } + + QGraphicsItem* child; + foreach (child, this->childItems()) { + ComponentShape* shape = dynamic_cast(child); + if (shape) { + shape->setPermission(permission); + } + } +} + +/// at plugin load, draw each element of initial main trajectory +void TrackedComponentView::createChildShapesAtStart() +{ + + // flush all old children (e.g. from previous trackers) + foreach (QGraphicsItem* child, this->childItems()) { + child->hide(); + delete child; + } + + // check if scene is set + assert(this->scene()); + + // create a shape for each model-component upon plugin-init + IModelTrackedTrajectory* all = dynamic_cast( + getModel()); + if (all) { + for (int i = 0; i < all->size(); i++) { + IModelTrackedTrajectory* trajectory = + dynamic_cast(all->getChild(i)); + if (trajectory) { + // create componentshape for trajectory + ComponentShape* newShape = + new ComponentShape(this, trajectory, trajectory->getId()); + connectShape(newShape); + } + + IModelTrackedPoint* rect = dynamic_cast( + all->getChild(i)); + if (rect) { + int x = rect->getX(); + int y = rect->getY(); + int w = 20; + int h = 20; + + QGraphicsRectItem* rect = + new QGraphicsRectItem(x - w / 2, y - h / 2, w, h, this); + rect->setPen(QPen(Qt::blue)); + rect->setBrush(QBrush(Qt::blue)); + rect->setFlag(ItemIsMovable); + rect->setFlag(ItemIsSelectable); + rect->setFlag(ItemSendsGeometryChanges); + rect->setData(0, i); + } + } + } +} + +/// connect a newly created component shape to all slots it needs and set +/// permissions +void TrackedComponentView::connectShape(ComponentShape* shape) +{ + CoreParameter* coreParams = dynamic_cast( + dynamic_cast(getController()) + ->getCoreParameter()); + + // set type + IModelTrackedTrajectory* trajectory = shape->getTrajectory(); + + IModelTrackedPoint* point = dynamic_cast( + trajectory->getChild(m_currentFrameNumber)); + if (point) { + shape->setData(1, "point"); + } + IModelTrackedEllipse* ellipse = dynamic_cast( + trajectory->getChild(m_currentFrameNumber)); + if (ellipse) { + shape->setData(1, "ellipse"); + } + IModelTrackedRectangle* rectangle = dynamic_cast( + trajectory->getChild(m_currentFrameNumber)); + if (rectangle) { + shape->setData(1, "rectangle"); + } + IModelTrackedPolygon* polygon = dynamic_cast( + trajectory->getChild(m_currentFrameNumber)); + if (polygon) { + shape->setData(1, "polygon"); + } + + // connect slots/signals + QObject::connect( + shape, + SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), + dynamic_cast(this->getController()), + SIGNAL(emitRemoveTrajectory(IModelTrackedTrajectory*)), + Qt::DirectConnection); + QObject::connect( + shape, + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), + dynamic_cast(this->getController()), + SIGNAL(emitRemoveTrackEntity(IModelTrackedTrajectory*, uint)), + Qt::DirectConnection); + QObject::connect( + shape, + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, + QPoint, + QPoint, + uint, + int)), + dynamic_cast(this->getController()), + SIGNAL(emitMoveElement(IModelTrackedTrajectory*, + QPoint, + QPoint, + uint, + int)), + Qt::DirectConnection); + QObject::connect( + shape, + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), + dynamic_cast(this->getController()), + SIGNAL(emitToggleFixTrack(IModelTrackedTrajectory*, bool)), + Qt::DirectConnection); + QObject::connect( + shape, + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, + double, + double, + uint)), + dynamic_cast(this->getController()), + SIGNAL(emitEntityRotation(IModelTrackedTrajectory*, + double, + double, + uint)), + Qt::DirectConnection); + QObject::connect( + shape, + &ComponentShape::emitGoToFrame, + dynamic_cast(this->getController()), + &ControllerTrackedComponentCore::emitGoToFrame, + Qt::DirectConnection); + + QObject::connect(shape, + SIGNAL(broadcastMove()), + this, + SLOT(receiveBroadcastMove()), + Qt::DirectConnection); + + // set the shapes members + shape->m_currentFramenumber = m_currentFrameNumber; + shape->setMembers(coreParams); + + // set permissions + shape->setPermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTMOVE, + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTMOVE])); + shape->setPermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTREMOVE, + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTREMOVE])); + shape->setPermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTSWAP, + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTSWAP])); + shape->setPermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTROTATE, + m_permissions[ENUMS::COREPERMISSIONS::COMPONENTROTATE])); + + // update the shape + shape->updateAttributes(m_currentFrameNumber); +} + +/*********************************************************************/ /** + *******************************SLOTS************************************* + *************************************************************************/ + +/** + * updates componentshapes, deletes all if tracking data empty and creates new + * if new trajectories were added componentshapes are children of this view + * (see qt's parent-child-system) + */ +void TrackedComponentView::updateShapes(uint framenumber) +{ + m_currentFrameNumber = framenumber; + + IModelTrackedTrajectory* all = dynamic_cast( + getModel()); + if (!all || all->size() == 0) { + // if root is nullptr, delete all children + foreach (auto child, this->childItems()) { + delete child; + } + return; + } + + // update each shape; shape hides itself if trajectory is empty or not + // existant or currentchild + foreach (auto child, this->childItems()) { + ComponentShape* shape = dynamic_cast(child); + if (shape) { + shape->updateAttributes(m_currentFrameNumber); + } + } + + // check for new trajectories; for each create a new shape + if (this->childItems().size() < all->size()) { + + // iterate over trajectories from back to increase performance + for (int i = all->size() - 1; + i >= 0 && this->childItems().size() <= all->size(); + i--) { + IModelTrackedTrajectory* trajectory = + dynamic_cast(all->getChild(i)); + + // check if trajectory already has shape object + if (trajectory && !checkTrajectory(trajectory)) { + ComponentShape* newShape = + new ComponentShape(this, trajectory, trajectory->getId()); + connectShape(newShape); + } else { + // already there or nullptr + } + + // all trajectories already have shapes + if (all->size() == this->childItems().size()) { + break; + } + } + } +} + +/** + * gets triggered when one or more shape is moved; emits move signal to tracker + * for all selected shapes if not broadcasted, only the position of actually + * moved componentshape is saved in tracking data the rest would be reset after + * update + */ +void TrackedComponentView::receiveBroadcastMove() +{ + QList allSelectedItems = this->scene()->selectedItems(); + QList allSelectedEntitiesList; + + QGraphicsItem* item; + + foreach (item, allSelectedItems) { + ComponentShape* shape = dynamic_cast(item); + if (shape) { + if (shape->isSelected()) { + allSelectedEntitiesList.append(shape); + } + } + } + + int numberSelectedEntitiesToMove = allSelectedEntitiesList.size(); + ComponentShape* entity; + foreach (entity, allSelectedEntitiesList) { + ComponentShape* shape = dynamic_cast(entity); + if (shape) { + if (shape->isSelected()) { + IModelTrackedTrajectory* shapeTrajectory = + shape->getTrajectory(); + // calculate the current pos and emit it to the commands + // component + shape->emitMoveElement( + shapeTrajectory, + shape->getOldPos() + + QPoint(shape->m_w / 2, shape->m_h / 2), + shape->pos().toPoint() + + QPoint(shape->m_w / 2, shape->m_h / 2), + m_currentFrameNumber, + numberSelectedEntitiesToMove); + numberSelectedEntitiesToMove--; + } + } + } +} + +void TrackedComponentView::receiveViewSwitch(bool lever) +{ + this->setVisible(lever); + + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->m_tracingLayer->setVisible(lever); + } + } +} + +void TrackedComponentView::receiveTrackDimensionsAll(int width, int height) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveDimensions(width, height); + } + } +} + +void TrackedComponentView::receiveTrackDimensionsSelected(int width, + int height) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape && childShape->isSelected()) { + childShape->receiveDimensions(width, height); + } + } +} + +void TrackedComponentView::receiveTrackOrientationLine(bool toggle) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveToggleOrientationLine(toggle); + } + } +} + +void TrackedComponentView::receiveTrackShowId(bool toggle) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveShowId(toggle); + } + } +} + +void TrackedComponentView::receiveTrackDimensionsSetDefault() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->setDimensionsToDefault(); + } + } +} + +void TrackedComponentView::receiveTracingSteps(int steps) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracingSteps(steps); + } + } +} + +void TrackedComponentView::receiveTracingStyle(QString style) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracingStyle(style); + } + } +} + +void TrackedComponentView::receiveTracingHistoryLength(int history) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracingLength(history); + } + } +} + +void TrackedComponentView::receiveTracingTimeDegradation(QString degradation) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracingTimeDegradation(degradation); + } + } +} + +void TrackedComponentView::receiveColorChangeBrushAll() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + const QColorDialog::ColorDialogOptions options = QFlag( + QColorDialog::ShowAlphaChannel || QColorDialog::DontUseNativeDialog); + QColor color = QColorDialog::getColor(Qt::white, + nullptr, + QString("Choose fill color"), + options); + // QColorDialog* cDialog = new QColorDialog(Qt::white); + // cDialog->show(); + // cDialog->activateWindow(); + // cDialog->raise(); + // cDialog->setFocus(); + + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->changeBrushColor(color); + } + } +} + +void TrackedComponentView::receiveColorChangeBorderAll() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + QColor color = QColorDialog::getColor(Qt::white, + nullptr, + QString("Choose border color"), + QColorDialog::ShowAlphaChannel); + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->changePenColor(color); + } + } +} + +void TrackedComponentView::receiveColorChangeBorderSelected() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + QColor color = QColorDialog::getColor(Qt::white, + nullptr, + QString("Choose border color"), + QColorDialog::ShowAlphaChannel); + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape && childShape->isSelected()) { + childShape->changePenColor(color); + } + } +} + +void TrackedComponentView::receiveColorChangeBrushSelected() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + QColor color = QColorDialog::getColor(Qt::white, + nullptr, + QString("Choose fill color"), + QColorDialog::ShowAlphaChannel); + ; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape && childShape->isSelected()) { + childShape->changeBrushColor(color); + } + } +} + +void TrackedComponentView::receiveSelectAll() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + if (dynamic_cast(childItem)) { + childItem->setSelected(true); + } + } +} + +///////////////////////context menu action slots/////////////// + +void TrackedComponentView::addTrajectory() +{ + IModelTrackedTrajectory* all = dynamic_cast( + getModel()); + int id = -1; + if (all) { + id = all->size() + 1; + } + + if (id <= 0) { + qWarning() << "ID cannot be smaller than or equal 0"; + } + + if (!lastClickedPos.isNull()) { + // qDebug() << "TCV: new track at position " << lastClickedPos; + emitAddTrajectory(lastClickedPos, id); + lastClickedPos = QPoint(0, 0); + } else { + // qDebug() << "TCV: new track at center of top left quarter of video"; + QPoint topLeftQuarterCenter = QPoint(this->boundingRect().width() / 8, + this->boundingRect().height() / + 8); + emitAddTrajectory(topLeftQuarterCenter, id); + } +} + +void TrackedComponentView::swapIds() +{ + QList allSelectedItems = this->scene()->selectedItems(); + if (allSelectedItems.size() != 2) { + qWarning() + << "There need to be exactly two tracks selected to swap ID's!"; + return; + } + ComponentShape* shape0 = dynamic_cast( + allSelectedItems[0]); + ComponentShape* shape1 = dynamic_cast( + allSelectedItems[1]); + if (shape0 && shape1 && shape0->isSwappable() && shape1->isSwappable()) { + IModelTrackedTrajectory* trajectory0 = + dynamic_cast(shape0->getTrajectory()); + IModelTrackedTrajectory* trajectory1 = + dynamic_cast(shape1->getTrajectory()); + emitSwapIds(trajectory0, trajectory1); + } else { + qWarning() << "Selected objects are not swappable"; + } +} + +void TrackedComponentView::removeTrajectories() +{ + QList allSelectedItems = this->scene()->selectedItems(); + QGraphicsItem* item; + foreach (item, allSelectedItems) { + ComponentShape* shape = dynamic_cast(item); + if (shape) { + shape->removeTrack(); + } + } +} + +void TrackedComponentView::unmarkAll() +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->unmarkShape(); + } + } +} + +/////////////////////////////////////////////////////// + +bool TrackedComponentView::checkTrajectory(IModelTrackedTrajectory* trajectory) +{ + bool isVisualized = false; + + for (int i = 0; i < this->childItems().size(); i++) { + ComponentShape* shape = dynamic_cast( + this->childItems()[i]); + if (shape) { + if (shape->getTrajectory() == trajectory) { + isVisualized = true; + break; + } + } + } + return isVisualized; +} + +void TrackedComponentView::receiveTracerProportions(float proportion) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracerProportions(proportion); + } + } +} + +void TrackedComponentView::receiveTracerOrientationLine(bool toggle) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracerOrientationLine(toggle); + } + } +} + +void TrackedComponentView::receiveTracerFrameNumber(bool toggle) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveTracerFrameNumber(toggle); + } + } +} + +void TrackedComponentView::receiveToggleAntialiasingEntities(bool toggle) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveAntialiasing(toggle); + } + } +} + +void TrackedComponentView::receiveIgnoreZoom(bool toggle) +{ + QList childrenItems = this->childItems(); + QGraphicsItem* childItem; + foreach (childItem, childrenItems) { + ComponentShape* childShape = dynamic_cast(childItem); + if (childShape) { + childShape->receiveIgnoreZoom(toggle); + } + } +} diff --git a/Src/View/TrackedComponentView.h b/Src/View/TrackedComponentView.h new file mode 100644 index 00000000..ef859d78 --- /dev/null +++ b/Src/View/TrackedComponentView.h @@ -0,0 +1,208 @@ +#ifndef TRACKEDCOMPONENTVIEW_H +#define TRACKEDCOMPONENTVIEW_H + +#pragma once + +#include "Interfaces/IView/IViewTrackedComponent.h" +#include "Interfaces/ENUMS.h" +#include "QPoint" +#include "QSignalMapper" +#include "Interfaces/IModel/IModelTrackedTrajectory.h" +#include "View/ComponentShape.h" + +/** + * This class inherits from the IViewTrackedComponent class and is therefore + * part of the Composite Pattern. This view is visualized in the media panel of + * the main window on top of the loaded medium. It creates a component shape + * for each trajectory. The component shape is the visualized current entity of + * the trajectory. Each time the tracking plugins singals tracking done to the + * core app, all component shapes are updated (updateshapes(framnumber)) + */ +class TrackedComponentView : public IViewTrackedComponent +{ + Q_OBJECT +public: + TrackedComponentView(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; + + /// creates initial componentshapes + void createChildShapesAtStart(); + + /// connect a newly created component shape to all slots it needs and set + /// permissions + void connectShape(ComponentShape* shape); + + // check if trajectory already has corresponding component shape + bool checkTrajectory(IModelTrackedTrajectory* trajectory); + + // IView interface + void setPermission(std::pair permission); + + /** + * SIGNALS + */ +signals: + void emitUpdateCornersChanged(int id, int relX, int relY); + + /// signal to commands component to add a new trajectory + void emitAddTrajectory(QPoint pos, int id); + + /// signal to commands component to swap ID's of two trajectories + void emitSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + + /** + * SLOTS + */ +public slots: + // IViewTrackedComponent interface + void getNotified() override; + + /// updates dimensions on load of new medium + void rcvDimensionUpdate(int x, int y); + + ////////////// contextmenu actions (must be parameterless because Qt + /// actions require it) + + /// add a new trajectory --> view updates componentshapes and generates a + /// new component shape for that trajectory + void addTrajectory(); + + /// swap id's of excatcly two selected trajectories --> also componetshapes + void swapIds(); + + /// remove all selected trajectories --> also removes componentshapes + void removeTrajectories(); + + /// unmark all component shapes (border from fat to slim) + void unmarkAll(); + + ////////////////////////////////////////////////////////////////////////////// + + /// update shapes when receiving tracking done + void updateShapes(uint framenumber); + + /// broadcast the movment to all selected componentshapes so they are moved + /// too + void receiveBroadcastMove(); + + /// receive toggle to hide or show the view and all its component shapes + void receiveViewSwitch(bool lever); + + /// select all tracks + void receiveSelectAll(); + + /* + * set dimensions of componentshapes + */ + + /// set dimensions for all component shapes + void receiveTrackDimensionsAll(int width, int height); + + /// set dimensions for selected component shapes + void receiveTrackDimensionsSelected(int width, int height); + + /// set dimensions for to default for all componentshapes + void receiveTrackDimensionsSetDefault(); + + /* + * Change Color of componentshapes + */ + + /// open color dialog and set border color for all componentshapes + void receiveColorChangeBorderAll(); + + /// open color dialog and set border color for selected componentshapes + void receiveColorChangeBorderSelected(); + + /// open color dialog and set fill color for all componentshapes + void receiveColorChangeBrushAll(); + + /// open color dialog and set fill color for all componentshapes + void receiveColorChangeBrushSelected(); + + /* + * Tracing of componentshapes + */ + + /// set tracing history length for all componentshapes + void receiveTracingHistoryLength(int history); + + /// set tracing style for all componentshapes + void receiveTracingStyle(QString style); + + /// set tracing steps for all componentshapes + void receiveTracingSteps(int steps); + + /// set tracing time degradation style for all componentshapes + void receiveTracingTimeDegradation(QString degradation); + + /// toggle show framenumber of tracers for all componentshapes + void receiveTracerFrameNumber(bool toggle); + + /// set tracing proportions for all componentshapes + void receiveTracerProportions(float proportion); + + /// set tracer orientation line for all componentshapes + void receiveTracerOrientationLine(bool toggle); + + /* + * Misc + */ + + /// toggle antialiasing for all componentshapes + void receiveToggleAntialiasingEntities(bool toggle); + + /// set ignore zoom for all componentshapes (unused) + void receiveIgnoreZoom(bool toggle); + + /// toggle orientation line for all component shapes + void receiveTrackOrientationLine(bool toggle); + + /// toggle show id for all component shapes + void receiveTrackShowId(bool toggle); + +public: + /// updates tracking data model when new trakcing plugin is loaded + void setNewModel(IModel* model) override + { + setModel(model); + }; + +private: + QRectF m_boundingRect; /**< bounding rect of the view */ + + std::map> + _rectification; /**< id of the component */ + QGraphicsItem* _watchingDrag = nullptr; /**< unused drag bool */ + int _dragX = 0; /**< unused drag x-coordinate */ + int _dragY = 0; /**< unused drag y-coordinate */ + std::map + m_permissions; /**< list of permissions to set for new component shapes + */ + QPoint lastClickedPos; /**< last clicked position in the view */ + + // QGraphicsItem interface +protected: + bool sceneEventFilter(QGraphicsItem* watched, QEvent* event) override; + bool eventFilter(QObject* target, QEvent* event) override; + void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; + void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; + QVariant itemChange(GraphicsItemChange change, + const QVariant& value) override; + void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; + void mousePressEvent(QGraphicsSceneMouseEvent* event); + + int m_currentFrameNumber = + 0; /**< current visualized framenumber of the medium */ +}; + +#endif // TRACKEDCOMPONENTVIEW_H diff --git a/Src/View/TrackedImageView.cpp b/Src/View/TrackedImageView.cpp new file mode 100644 index 00000000..a5b3b426 --- /dev/null +++ b/Src/View/TrackedImageView.cpp @@ -0,0 +1,54 @@ +#include "TrackedImageView.h" + +#include +#include "Interfaces/IController/IController.h" + +#include "Model/TextureObject.h" + +TrackedImageView::TrackedImageView(QWidget* parent, + IController* controller, + IModel* model) +: IViewOpenGLWidget(parent, controller, model) +{ +} + +TrackedImageView::~TrackedImageView() +{ +} + +void TrackedImageView::paintGL() +{ + TextureObject* textureObject = dynamic_cast(getModel()); + QImage img = textureObject->get(); + + QPainter painter(this); + + painter.setBrush(QColor(0, 0, 0)); + painter.drawRect(QRect(0, 0, this->width(), this->height())); + painter.setBrush(QColor(0, 0, 0, 0)); + + QRect window; + QRect viewport; + const float viewport_skew = + BioTracker::Core::ScreenHelper::calculate_viewport( + textureObject->width(), + textureObject->height(), + this->width(), + this->height(), + window, + viewport); + + painter.setWindow(window); + painter.setViewport(viewport); + + QRectF target(0, 0, textureObject->width(), textureObject->height()); + QRectF source(0, 0, textureObject->width(), textureObject->height()); + + painter.drawImage(target, img, source); + QPainter p(this); +} + +void TrackedImageView::getNotified() +{ + this->update(); +} diff --git a/BioTracker/CoreApp/BioTracker/View/TrackedImageView.h b/Src/View/TrackedImageView.h similarity index 84% rename from BioTracker/CoreApp/BioTracker/View/TrackedImageView.h rename to Src/View/TrackedImageView.h index 0bdfb749..da2ed712 100644 --- a/BioTracker/CoreApp/BioTracker/View/TrackedImageView.h +++ b/Src/View/TrackedImageView.h @@ -9,7 +9,7 @@ class TrackedImageView : public IViewOpenGLWidget { public: - TrackedImageView(QWidget *parent, IController *controller, IModel *model); + TrackedImageView(QWidget* parent, IController* controller, IModel* model); ~TrackedImageView(); // QOpenGLWidget interface diff --git a/Src/View/Utility/RotationHandle.cpp b/Src/View/Utility/RotationHandle.cpp new file mode 100644 index 00000000..d5e3ed51 --- /dev/null +++ b/Src/View/Utility/RotationHandle.cpp @@ -0,0 +1,100 @@ +#include "RotationHandle.h" +#include "QPainter" +#include "QGraphicsSceneMouseEvent" +#include "QCursor" +#include "QtMath" +#include "QGraphicsScene" +#include "qdebug.h" + +RotationHandle::RotationHandle(QPoint origin, + QAbstractGraphicsShapeItem* parent) +: QAbstractGraphicsShapeItem(parent) +, _origin(origin) +{ + setFlag(ItemIsMovable); + setPen(QPen(Qt::black)); + setBrush(QBrush(Qt::red)); + // setFlag(QGraphicsItem::ItemIsSelectable); + // setFlag(ItemIgnoresTransformations); +} + +RotationHandle::~RotationHandle() +{ +} + +QRectF RotationHandle::boundingRect() const +{ + return QRectF(-5, -5, 10, 10); +} + +void RotationHandle::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + if (m_antialiasing) { + painter->setRenderHint(QPainter::Antialiasing); + } + painter->setPen(this->pen()); + painter->setBrush(this->brush()); + + painter->drawEllipse(QRect(-5, -5, 10, 10)); + + // painter->drawRect(boundingRect()); +} + +void RotationHandle::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) { + // handle left mouse button here + + // unselect all selected items so this can be moved + QList allSelectedItems = scene()->selectedItems(); + QGraphicsItem* item; + foreach (item, allSelectedItems) { + item->setSelected(false); + } + + setCursor(Qt::ClosedHandCursor); + update(); + } + + // pass on + QGraphicsItem::mousePressEvent(event); +} + +void RotationHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) { + // handle left mouse button here + setCursor(Qt::ArrowCursor); + + double angleRad = atan2(this->y() - _origin.y(), + this->x() - _origin.x()); + double angleDeg = qRadiansToDegrees(angleRad); + + Q_EMIT emitShapeRotation(angleDeg, true); + + update(); + } + // pass on + QGraphicsItem::mouseReleaseEvent(event); +} + +void RotationHandle::mouseMoveEvent(QGraphicsSceneMouseEvent* event) +{ + double angleRad = atan2(this->y() - _origin.y(), this->x() - _origin.x()); + double angleDeg = qRadiansToDegrees(angleRad); + + Q_EMIT emitShapeRotation(angleDeg); + + update(); + + // pass on + QGraphicsItem::mouseMoveEvent(event); +} + +void RotationHandle::setAntialiasing(bool toggle) +{ + m_antialiasing = toggle; + update(); +} diff --git a/Src/View/Utility/RotationHandle.h b/Src/View/Utility/RotationHandle.h new file mode 100644 index 00000000..be886524 --- /dev/null +++ b/Src/View/Utility/RotationHandle.h @@ -0,0 +1,42 @@ +#pragma once + +#ifndef ROTATIONHANDLE_H + #define ROTATIONHANDLE_H + + #include "QGraphicsObject" + +/** + * This class inherits QAbstractGraphicsShapeItem. + * It is a child of an componentshape and is used to rotate it. + * (the rotation then gets forwarded to the command compontent, + * which then forwards it to the tracking plugin + * It is attached to the end of the orientation line of the component shape + */ +class RotationHandle : public QObject, public QAbstractGraphicsShapeItem +{ + Q_OBJECT + +public: + RotationHandle(QPoint origin, QAbstractGraphicsShapeItem* parent = 0); + ~RotationHandle(); + + QRectF boundingRect() const override; + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + + void mousePressEvent(QGraphicsSceneMouseEvent* event) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; + + void setAntialiasing(bool toggle); + +signals: + void emitShapeRotation(double angle, bool rotateEntity = false); + +private: + QPoint _origin; /**< the position in the coordinate frame of the shape + object */ + bool m_antialiasing; /**< if true, antialiasing is enabled */ +}; +#endif // ROTATIONHANDLE_H \ No newline at end of file diff --git a/Src/View/Utility/SwitchButton.cpp b/Src/View/Utility/SwitchButton.cpp new file mode 100644 index 00000000..27604992 --- /dev/null +++ b/Src/View/Utility/SwitchButton.cpp @@ -0,0 +1,132 @@ +#include "SwitchButton.h" +#include "QPainter" +#include "QMouseEvent" + +void SwitchButton::setHeight(int h) +{ + _height = h - 2 * _margin; +} + +SwitchButton::SwitchButton(QString s0, QString s1, QWidget* parent) +: QAbstractButton(parent) +, _height(16) +, _opacity(0.000) +, _switch(false) +, _margin(3) +, _thumb("#d5d5d5") +, _anim(new QPropertyAnimation(this, "offset", this)) +, _s0(s0) +, _s1(s1) +{ + setOffset(_height / 2); + _y = _height / 2; + setBrush(QColor("#009688")); +}; + +void SwitchButton::paintEvent(QPaintEvent* e) +{ + QPainter p(this); + p.setPen(Qt::NoPen); + if (isEnabled()) { + + // background rect + // p.setBrush(_switch ? brush() : Qt::black); + p.setBrush(_switch ? Qt::green : Qt::red); + // p.setOpacity(_switch ? 0.5 : 0.38); + p.setOpacity(0.5); + p.setRenderHint(QPainter::Antialiasing, true); + p.drawRoundedRect(QRect(_margin, + _margin, + width() - 2 * _margin, + height() - 2 * _margin), + 8.0, + 8.0); + + // handle + p.setBrush(_thumb); + p.setOpacity(1.0); + p.drawEllipse(QRectF(offset() - (_height / 2), + _y - (_height / 2), + height(), + height())); + + // text + p.setPen(Qt::black); + QFont font = p.font(); + font.setPixelSize(height() - 3 * _margin); + p.setFont(font); + QRectF textRect = QRectF(_margin, + _margin, + width() - 2 * _margin, + height() - 2 * _margin); + p.drawText(textRect, + Qt::AlignHCenter | Qt::AlignVCenter, + _switch ? _s1 : _s0); + } else { + p.setRenderHint(QPainter::Antialiasing, true); + p.setBrush(Qt::black); + p.setOpacity(0.12); + p.drawRoundedRect(QRect(_margin, + _margin, + width() - 2 * _margin, + height() - 2 * _margin), + 8.0, + 8.0); + p.setOpacity(1.0); + p.setBrush(QColor("#BDBDBD")); + p.drawEllipse(QRectF(offset() - (_height / 2), + _y - (_height / 2), + height(), + height())); + + // text + p.setPen(Qt::black); + QFont font = p.font(); + font.setPixelSize(height() - 3 * _margin); + p.setFont(font); + QRectF textRect = QRectF(_margin, + _margin, + width() - 2 * _margin, + height() - 2 * _margin); + p.drawText(textRect, + Qt::AlignHCenter | Qt::AlignVCenter, + _switch ? _s1 : _s0); + } +} + +void SwitchButton::mouseReleaseEvent(QMouseEvent* e) +{ + if (e->button() & Qt::LeftButton) { + _switch = _switch ? false : true; + animateSwitch(); + + emitSetEnabled(_switch); + } + QAbstractButton::mouseReleaseEvent(e); +} + +void SwitchButton::enterEvent(QEvent* e) +{ + setCursor(Qt::PointingHandCursor); + QAbstractButton::enterEvent(e); +} + +void SwitchButton::animateSwitch() +{ + if (_switch) { + _anim->setStartValue(_height / 2); + _anim->setEndValue(width() - _height); + _anim->setDuration(240); + _anim->start(); + } else { + _anim->setStartValue(offset()); + _anim->setEndValue(_height / 2); + _anim->setDuration(240); + _anim->start(); + } +} + +QSize SwitchButton::sizeHint() const +{ + return QSize(8 * (_height + _margin), _height + 2 * _margin); +} \ No newline at end of file diff --git a/Src/View/Utility/SwitchButton.h b/Src/View/Utility/SwitchButton.h new file mode 100644 index 00000000..ef4985a6 --- /dev/null +++ b/Src/View/Utility/SwitchButton.h @@ -0,0 +1,76 @@ +#pragma once + +#ifndef SWITCHBUTTON_H + #define SWITCHBUTTON_H + + #include "QAbstractButton" + #include "QPropertyAnimation" + +/** + * This class inherits QAbstractButton. + * It is an utility class to create android-like animated switches + * inspiration: + * https://stackoverflow.com/questions/14780517/toggle-switch-in-qt + */ +class SwitchButton : public QAbstractButton +{ + Q_OBJECT + Q_PROPERTY(int offset READ offset WRITE setOffset) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(bool _switch READ state WRITE setState) + +public: + SwitchButton(QString s0, QString s1, QWidget* parent = 0); + //~SwitchButton(); + + QSize sizeHint() const override; + + void setHeight(int h); + int offset() const + { + return _x; + } + void setOffset(int o) + { + _x = o; + update(); + } + QBrush brush() const + { + return _brush; + } + void setBrush(const QBrush& brsh) + { + _brush = brsh; + } + bool state() const + { + return _switch; + } + void setState(bool toggle) + { + _switch = toggle; + animateSwitch(); + update(); + } + + void animateSwitch(); + +signals: + void emitSetEnabled(bool toggle); + +protected: + void paintEvent(QPaintEvent* event) override; + void mouseReleaseEvent(QMouseEvent*) override; + void enterEvent(QEvent* e) override; + + bool _switch; /**< state fo the switch */ + qreal _opacity; /**< opacity */ + int _x, _y, _height, _margin; /**< position and dimensions */ + QBrush _thumb, _track, _brush; + QPropertyAnimation* _anim = nullptr; /**< animation */ + QString _s0; /**< text in state 0 */ + QString _s1; /**< text in state 1 */ +}; + +#endif // SWITCHBUTTON_H \ No newline at end of file diff --git a/Src/View/Utility/Tracer.cpp b/Src/View/Utility/Tracer.cpp new file mode 100644 index 00000000..ce8a1512 --- /dev/null +++ b/Src/View/Utility/Tracer.cpp @@ -0,0 +1,75 @@ +#include "Tracer.h" +#include "QDebug" +#include "QPen" +#include "QBrush" +#include "QPainter" +#include "QMenu" +#include "QGraphicsSceneContextMenuEvent" + +Tracer::Tracer(QVariant type, + int frame, + float orientation, + QPointF pos, + float w, + float h, + QPen pen, + QBrush brush, + QAbstractGraphicsShapeItem* parent) +: QAbstractGraphicsShapeItem(parent) +, _type(type.toString()) +, _frame(frame) +, _w(w) +, _h(h) +{ + setPos(pos); + setPen(pen); + setBrush(brush); + setRotation(_h > _w ? -90 - orientation : -orientation); +} + +Tracer::~Tracer() +{ +} + +QRectF Tracer::boundingRect() const +{ + return QRect(-_w / 2, -_h / 2, _w, _h); +} + +void Tracer::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) +{ + painter->setPen(pen()); + painter->setBrush(brush()); + + if (_type == "point") { + int dim = _w <= _h ? _w : _h; + painter->drawEllipse(QRect(-dim / 2, -dim / 2, dim, dim)); + } else if (_type == "ellipse") { + + painter->drawEllipse(QRect(-_w / 2, -_h / 2, _w, _h)); + } else if (_type == "rectangle") { + + painter->drawRect(QRect(-_w / 2, -_h / 2, _w, _h)); + } + // default for polygon shape are point tracers for simplicity + else if (_type == "polygon") { + int dim = _w <= _h ? _w : _h; + painter->drawEllipse(QRect(-dim / 2, -dim / 2, dim, dim)); + } +} + +void Tracer::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) +{ + QMenu menu; + menu.addAction("Go to frame ", + dynamic_cast(this), + SLOT(goToFrame())); + menu.exec(event->screenPos()); +} + +void Tracer::goToFrame() +{ + Q_EMIT emitGoToFrame(_frame); +} diff --git a/Src/View/Utility/Tracer.h b/Src/View/Utility/Tracer.h new file mode 100644 index 00000000..abe3c51e --- /dev/null +++ b/Src/View/Utility/Tracer.h @@ -0,0 +1,57 @@ +#pragma once + +#ifndef TRACER_H + #define TRACER_H + + #include "QAbstractGraphicsShapeItem" + +/** + * This class inherits QAbstractGraphicsShapeItem. + * It is created by and an child of a componenntshape. + * It is a helper class used to visualize shape type tracers. + * It has a context menu to set medium to the tracer's frame + * Apart from the polygon it is visualized as the componentshapes + * current type. + */ +class Tracer : public QObject, public QAbstractGraphicsShapeItem +{ + Q_OBJECT + +public: + Tracer(QVariant type, + int frame, + float orientation, + QPointF pos, + float w, + float h, + QPen pen, + QBrush brush, + QAbstractGraphicsShapeItem* parent); + ~Tracer(); +signals: + void emitGoToFrame(int frame); + +public slots: + + // signals the media player rewind to the tracer's frame + void goToFrame(); + +protected: + // Interface of QAbstractGraphicsShapeItem + QRectF boundingRect() const override; + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; + + // member + QString _type; /**< type visualized */ + int _frame; /**< corresponding frame */ + float + _orientation; /**< orientation of tracer --> of corresponding entity */ + QPointF pos; /**< position in coordinateframe of parent shape object */ + float _w; /**< width */ + float _h; /**< height */ +}; + +#endif // TRACER_H diff --git a/Src/View/VideoControllWidget.cpp b/Src/View/VideoControllWidget.cpp new file mode 100644 index 00000000..4b0bb766 --- /dev/null +++ b/Src/View/VideoControllWidget.cpp @@ -0,0 +1,372 @@ +#include "VideoControllWidget.h" +#include "ui_VideoControllWidget.h" +#include "Controller/ControllerPlayer.h" +#include "Model/MediaPlayer.h" + +#include +#include +#include +#include + +VideoControllWidget::VideoControllWidget(QWidget* parent, + IController* controller, + IModel* model) +: IViewWidget(parent, controller, model) +, ui(new Ui::VideoControllWidget) +{ + ui->setupUi(this); + m_RecO = false; + m_RecI = false; + m_Paus = false; + + m_iconPause.addFile(QStringLiteral("qrc:/Images/resources/pause-sign.png"), + QSize(), + QIcon::Normal, + QIcon::Off); + m_iconPlay.addFile( + QStringLiteral("qrc:/Images/resources/arrow-forward1.png"), + QSize(), + QIcon::Normal, + QIcon::Off); + + ui->sld_video->setMinimum(0); + this->setSelectedView("Original"); + updateGeometry(); +} + +VideoControllWidget::~VideoControllWidget() +{ + delete ui; +} + +void VideoControllWidget::setSelectedView(QString str) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + controller->changeImageView(str); +} + +void VideoControllWidget::setVideoViewComboboxModel( + QStringListModel* comboboxModel) +{ +} + +void VideoControllWidget::getNotified() +{ + MediaPlayer* mediaPlayer = dynamic_cast(getModel()); + + ui->actionNext_frame->setEnabled(mediaPlayer->getForwardState()); + ui->actionPrev_frame->setEnabled(mediaPlayer->getBackwardState()); + ui->actionPlay_Pause->setEnabled(mediaPlayer->getPlayState()); + ui->actionStop->setEnabled(mediaPlayer->getStopState()); + + m_Paus = mediaPlayer->getPauseState(); + + if (m_Paus) { + ui->actionPlay_Pause->setIcon( + QIcon(":/Images/resources/pause-sign.png")); + } else { + ui->actionPlay_Pause->setIcon( + QIcon(":/Images/resources/arrow-forward1.png")); + } + + m_RecI = mediaPlayer->getRecIState(); + if (m_RecI) { + ui->actionRecord_cam->setIcon( + QIcon(":/Images/resources/recordingCam.png")); + } else { + ui->actionRecord_cam->setIcon( + QIcon(":/Images/resources/recordCam.png")); + } + + int currentFrameNr = static_cast( + mediaPlayer->getCurrentFrameNumber()); + int totalNumberOfFrames = static_cast( + mediaPlayer->getTotalNumberOfFrames()); + int mediaFps = mediaPlayer->getFpsOfSourceFile(); + // ui->frame_num_edit->setText(QString::number(currentFrameNr)); + ui->frame_num_spin->setMaximum(totalNumberOfFrames); + ui->frame_num_spin->setValue(currentFrameNr); + ui->sld_video->setValue(currentFrameNr); + + QString currentVideoTime = + QDateTime::fromMSecsSinceEpoch( + ((float) currentFrameNr / (float) mediaFps) * 1000) + .toUTC() + .toString("hh:mm:ss:zzz"); + + ui->time_edit->setText(currentVideoTime); + + // Write current fps label every 1/2 second + std::chrono::system_clock::time_point now = + std::chrono::system_clock::now(); + long long dt = std::chrono::duration_cast( + now - lastFpsSet) + .count(); + int fps = mediaPlayer->getCurrentFPS(); + if (dt > 500 || fps <= 0) { + ui->lcd_currentFpsNum->display(fps); + lastFpsSet = now; + + // for average fps calculation + _fpsSum += fps; + _fpsCounter += 1; + } + + ui->fps_label->setText(QString::number(mediaFps)); + double cfps = mediaPlayer->getCurrentFPS(); + + if (totalNumberOfFrames >= 1) { + ui->sld_video->setEnabled(true); + ui->sld_video->setMaximum(totalNumberOfFrames - 1); + + int intervalPower = floor(log10(totalNumberOfFrames)); + int tickInterval = pow( + 10, + intervalPower > 0 ? floor(log10(totalNumberOfFrames)) - 1 : 0); + + ui->sld_video->setTickInterval(tickInterval); + } +} + +// void VideoControllWidget::on_button_nextFrame_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); +// controller->nextFrame(); +// } + +// void VideoControllWidget::on_button_playPause_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); + +// if (m_Paus) { +// controller->pause(); +// } else { +// controller->play(); +// } +// } + +// void VideoControllWidget::on_button_stop_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); controller->stop(); +// } + +// void VideoControllWidget::on_button_previousFrame_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); +// controller->prevFrame(); +// } + +void VideoControllWidget::on_DurationChanged(int position) +{ +} + +void VideoControllWidget::on_PositionChanged(int position) +{ +} + +// void VideoControllWidget::on_button_record_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); + +// int success = controller->recordOutput(); +// if (success == 1) { +// QPixmap pix(":/Images/resources/recording.png"); +// QIcon icon(pix); +// ui->actionRecord_all->setIcon(icon); +// //ui->actionRecord_all->setIconSize(QSize(32,32)); +// } +// else { +// QPixmap pix(":/Images/resources/record.png"); +// QIcon icon(pix); +// ui->actionRecord_all->setIcon(icon); +// //ui->actionRecord_all->setIconSize(QSize(32, 32)); +// } +// } + +// void VideoControllWidget::on_button_record_cam_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); + +// int success = controller->recordInput(); +// } + +// void VideoControllWidget::on_button_screenshot_clicked() { +// ControllerPlayer* controller = +// dynamic_cast(getController()); +// controller->takeScreenshot(); +// } + +void VideoControllWidget::on_sld_video_sliderReleased() +{ +} + +void VideoControllWidget::on_sld_video_actionTriggered(int action) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + int position = ui->sld_video->sliderPosition(); + controller->setGoToFrame(position); +} + +/** + * If the video slider is moved, this function sets the value to the current + * frame number lable + */ +void VideoControllWidget::on_sld_video_sliderMoved(int position) +{ + // ui->frame_num_edit->setText(QString::number(position)); + ui->frame_num_spin->setValue(position); + MediaPlayer* mediaPlayer = dynamic_cast(getModel()); + int mediaFps = mediaPlayer->getFpsOfSourceFile(); + QString currentVideoTime = QDateTime::fromMSecsSinceEpoch( + ((float) position / (float) mediaFps) * + 1000) + .toUTC() + .toString("hh:mm:ss:zzz"); + ui->time_edit->setText(currentVideoTime); +} + +void VideoControllWidget::on_doubleSpinBoxTargetFps_editingFinished() +{ + double val = ui->doubleSpinBoxTargetFps->value(); + ControllerPlayer* controller = dynamic_cast( + getController()); + controller->setTargetFps(val); +} + +void VideoControllWidget::on_frame_num_spin_editingFinished() +{ + int val = ui->frame_num_spin->value(); + ControllerPlayer* controller = dynamic_cast( + getController()); + controller->setGoToFrame(val); +} + +// actions +void VideoControllWidget::on_actionPlay_Pause_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + + if (m_Paus) { + controller->pause(); + // qDebug() << "The average fps of this run was: " << _fpsSum / + // _fpsCounter; + } else { + controller->play(); + _fpsSum = 0; + _fpsCounter = 0; + } +} +void VideoControllWidget::on_actionStop_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + controller->stop(); +} +void VideoControllWidget::on_actionNext_frame_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + controller->nextFrame(); +} +void VideoControllWidget::on_actionPrev_frame_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + controller->prevFrame(); +} +void VideoControllWidget::on_actionScreenshot_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + QString filePathStr = controller->takeScreenshot(); + QFileInfo fi(filePathStr); + QString filePathAbs = fi.absoluteFilePath(); + QString msgText = "The Screenshot has been saved to:\n " + filePathAbs; + + // QMessageBox::information(nullptr, "Screenshot taken!", msgText); + + QMessageBox msgBox; + msgBox.setText("You took a screenshot!"); + msgBox.setInformativeText(msgText); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + QPushButton* goToFileDirButton = msgBox.addButton(tr("Show in folder"), + QMessageBox::ActionRole); + QPushButton* openFileButton = msgBox.addButton(tr("Open screenshot"), + QMessageBox::ActionRole); + + msgBox.setIcon(QMessageBox::Information); + msgBox.exec(); + + if (msgBox.clickedButton() == goToFileDirButton) { + QUrl fileDirUrl = QUrl::fromLocalFile(fi.absolutePath()); + QDesktopServices::openUrl(fileDirUrl); + } else if (msgBox.clickedButton() == openFileButton) { + QUrl fileUrl = QUrl::fromLocalFile(filePathAbs); + QDesktopServices::openUrl(fileUrl); + } +} +void VideoControllWidget::on_actionRecord_cam_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + + int success = controller->recordInput(); +} +void VideoControllWidget::on_actionRecord_all_triggered(bool checked) +{ + ControllerPlayer* controller = dynamic_cast( + getController()); + + int success = controller->recordOutput(); + if (success == 1) { + QPixmap pix(":/Images/resources/recording.png"); + QIcon icon(pix); + ui->actionRecord_all->setIcon(icon); + // ui->actionRecord_all->setIconSize(QSize(32,32)); + } else { + QPixmap pix(":/Images/resources/record.png"); + QIcon icon(pix); + ui->actionRecord_all->setIcon(icon); + // ui->actionRecord_all->setIconSize(QSize(32, 32)); + } +} + +MainWindow* VideoControllWidget::getMainWindow() +{ + foreach (QWidget* widget, qApp->topLevelWidgets()) + if (MainWindow* mainWindow = dynamic_cast(widget)) + return mainWindow; + return NULL; +} + +void VideoControllWidget::setupVideoToolbar() +{ + MainWindow* mw = getMainWindow(); + + if (mw) { + QToolBar* videoToolBar = mw->findChild("toolBarVideo"); + if (videoToolBar) { + + videoToolBar->addAction(ui->actionPrev_frame); + videoToolBar->addSeparator(); + videoToolBar->addAction(ui->actionPlay_Pause); + videoToolBar->addSeparator(); + videoToolBar->addAction(ui->actionStop); + videoToolBar->addSeparator(); + videoToolBar->addAction(ui->actionNext_frame); + videoToolBar->addSeparator(); + videoToolBar->addAction(ui->actionScreenshot); + videoToolBar->addSeparator(); + videoToolBar->addAction(ui->actionRecord_cam); + videoToolBar->addSeparator(); + videoToolBar->addAction(ui->actionRecord_all); + videoToolBar->addSeparator(); + + videoToolBar->addWidget(ui->scrollAreaVideoInfo); + } + } +} diff --git a/BioTracker/CoreApp/BioTracker/View/VideoControllWidget.h b/Src/View/VideoControllWidget.h similarity index 59% rename from BioTracker/CoreApp/BioTracker/View/VideoControllWidget.h rename to Src/View/VideoControllWidget.h index 405e3e18..c3bbec43 100644 --- a/BioTracker/CoreApp/BioTracker/View/VideoControllWidget.h +++ b/Src/View/VideoControllWidget.h @@ -10,16 +10,19 @@ #include "View/MainWindow.h" #include - -namespace Ui { -class VideoControllWidget; +namespace Ui +{ + class VideoControllWidget; } -class VideoControllWidget : public IViewWidget { +class VideoControllWidget : public IViewWidget +{ Q_OBJECT - public: - explicit VideoControllWidget(QWidget* parent = 0, IController* controller = 0, IModel* model = 0); +public: + explicit VideoControllWidget(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); ~VideoControllWidget(); void setSelectedView(QString str); @@ -32,40 +35,35 @@ class VideoControllWidget : public IViewWidget { void setVideoControllsStates(QVector states); MainWindow* getMainWindow(); - void setupVideoToolbar(); - + void setupVideoToolbar(); - public Q_SLOTS: +public Q_SLOTS: void getNotified(); - private Q_SLOTS: +private Q_SLOTS: void on_DurationChanged(int position); void on_PositionChanged(int position); - // void on_button_nextFrame_clicked(); - // void on_button_playPause_clicked(); - // void on_button_record_clicked(); - // void on_button_record_cam_clicked(); - - // void on_button_stop_clicked(); + // void on_button_nextFrame_clicked(); + // void on_button_playPause_clicked(); + // void on_button_record_clicked(); + // void on_button_record_cam_clicked(); - // void on_button_screenshot_clicked(); + // void on_button_stop_clicked(); - // void on_button_previousFrame_clicked(); + // void on_button_screenshot_clicked(); - - void on_comboBoxSelectedView_currentTextChanged(const QString& arg1); + // void on_button_previousFrame_clicked(); void on_sld_video_sliderReleased(); void on_sld_video_sliderMoved(int position); - void on_sld_video_actionTriggered(int action); + void on_sld_video_actionTriggered(int action); void on_doubleSpinBoxTargetFps_editingFinished(); void on_frame_num_spin_editingFinished(); - void on_actionPlay_Pause_triggered(bool checked = false); void on_actionStop_triggered(bool checked = false); void on_actionNext_frame_triggered(bool checked = false); @@ -74,7 +72,7 @@ class VideoControllWidget : public IViewWidget { void on_actionRecord_cam_triggered(bool checked = false); void on_actionRecord_all_triggered(bool checked = false); - private: +private: Ui::VideoControllWidget* ui; QIcon m_iconPause; @@ -82,21 +80,21 @@ class VideoControllWidget : public IViewWidget { size_t m_TotalNumbFrames; - bool m_Paus; - bool m_RecI; - bool m_RecO; + bool m_Paus; + bool m_RecI; + bool m_RecO; - QAction* action_play_pause; - QAction* action_stop; - QAction* action_next_frame; - QAction* action_prev_frame; - QAction* action_rec_cam; - QAction* action_rec; + QAction* action_play_pause; + QAction* action_stop; + QAction* action_next_frame; + QAction* action_prev_frame; + QAction* action_rec_cam; + QAction* action_rec; - std::chrono::system_clock::time_point lastFpsSet; + std::chrono::system_clock::time_point lastFpsSet; - uint _fpsSum = 0; - int _fpsCounter = 0; + uint _fpsSum = 0; + int _fpsCounter = 0; }; #endif // BIOTRACKER3VIDEOCONTROLLWIDGET_H diff --git a/BioTracker/CoreApp/BioTracker/View/VideoControllWidget.ui b/Src/View/VideoControllWidget.ui similarity index 100% rename from BioTracker/CoreApp/BioTracker/View/VideoControllWidget.ui rename to Src/View/VideoControllWidget.ui diff --git a/Src/cmake/CPackLinuxDeployQt.cmake.in b/Src/cmake/CPackLinuxDeployQt.cmake.in new file mode 100644 index 00000000..e78748d6 --- /dev/null +++ b/Src/cmake/CPackLinuxDeployQt.cmake.in @@ -0,0 +1,20 @@ + +set(APPIMAGE_APP_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/appdir") +file(REMOVE_RECURSE "${APPIMAGE_APP_DIRECTORY}") +file(MAKE_DIRECTORY "${APPIMAGE_APP_DIRECTORY}") + +file(COPY "${CPACK_TEMPORARY_DIRECTORY}/@CMAKE_INSTALL_BINDIR@" DESTINATION "${APPIMAGE_APP_DIRECTORY}/usr") +file(COPY "${CPACK_TEMPORARY_DIRECTORY}/@CMAKE_INSTALL_LIBDIR@" DESTINATION "${APPIMAGE_APP_DIRECTORY}/usr") +file(COPY "${CPACK_TEMPORARY_DIRECTORY}/@CMAKE_INSTALL_DATAROOTDIR@" DESTINATION "${APPIMAGE_APP_DIRECTORY}/usr") + +file(RENAME "${APPIMAGE_APP_DIRECTORY}/usr/@CMAKE_INSTALL_BINDIR@" "${APPIMAGE_APP_DIRECTORY}/usr/bin") +file(RENAME "${APPIMAGE_APP_DIRECTORY}/usr/@CMAKE_INSTALL_LIBDIR@" "${APPIMAGE_APP_DIRECTORY}/usr/lib") +file(RENAME "${APPIMAGE_APP_DIRECTORY}/usr/@CMAKE_INSTALL_DATAROOTDIR@" "${APPIMAGE_APP_DIRECTORY}/usr/share") + +execute_process(COMMAND "@LINUXDEPLOYQT_EXECUTABLE@" + ${APPIMAGE_APP_DIRECTORY}/usr/share/applications/BioTracker.desktop -bundle-non-qt-libs -appimage -no-translations) + +file(GLOB LINUXDEPLOYQT_OUTPUT_FILE RELATIVE "${CPACK_PACKAGE_DIRECTORY}" "BioTracker-*.AppImage") +if(LINUXDEPLOYQT_OUTPUT_FILE) + file(RENAME "${CPACK_PACKAGE_DIRECTORY}/${LINUXDEPLOYQT_OUTPUT_FILE}" "${CPACK_PACKAGE_DIRECTORY}/@APPIMAGE_FILE_NAME@.AppImage") +endif() diff --git a/Src/cmake/FindPylon5.cmake b/Src/cmake/FindPylon5.cmake new file mode 100644 index 00000000..b0da309c --- /dev/null +++ b/Src/cmake/FindPylon5.cmake @@ -0,0 +1,69 @@ + +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(Pylon5_LIBRARY_DIR "/opt/pylon5/lib64") + else() + set(Pylon5_LIBRARY_DIR "/opt/pylon5/lib32") + endif() +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(Pylon5_LIBRARY_DIR "$ENV{PYLON5_DIR}/lib/x64") + else() + set(Pylon5_LIBRARY_DIR "$ENV{PYLON5_DIR}/lib/Win32") + endif() +endif() + +find_path(Pylon5_INCLUDE_DIR pylon/PylonBase.h + PATHS + /opt/pylon5/include + "$ENV{PYLON5_DIR}/include") + +find_library(Pylon5_Base_LIBRARY + NAMES + pylonbase + PylonBase_v5_2 + PATHS ${Pylon5_LIBRARY_DIR}) + +find_library(Pylon5_Utility_LIBRARY + NAMES + pylonutility + PylonUtility_v5_2 + PATHS ${Pylon5_LIBRARY_DIR}) + +find_library(Pylon5_GenAPI_LIBRARY + NAMES + GenApi_gcc_v3_1_Basler_pylon + GenApi_MD_VC141_v3_1_Basler_pylon + PATHS ${Pylon5_LIBRARY_DIR}) + +find_library(Pylon5_GCBase_LIBRARY + NAMES + GCBase_gcc_v3_1_Basler_pylon + GCBase_MD_VC141_v3_1_Basler_pylon + PATHS ${Pylon5_LIBRARY_DIR}) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(Pylon5 DEFAULT_MSG + Pylon5_INCLUDE_DIR Pylon5_Base_LIBRARY Pylon5_Utility_LIBRARY Pylon5_GenAPI_LIBRARY Pylon5_GCBase_LIBRARY) + +mark_as_advanced(Pylon5_INCLUDE_DIR Pylon5_Base_LIBRARY Pylon5_Utility_LIBRARY Pylon5_GenAPI_LIBRARY Pylon5_GCBase_LIBRARY) + +set(Pylon5_LIBRARIES ${Pylon5_Base_LIBRARY} ${Pylon5_Utility_LIBRARY} ${Pylon5_GenAPI_LIBRARY} ${Pylon5_GCBase_LIBRARY}) +set(Pylon5_INCLUDE_DIRS ${Pylon5_INCLUDE_DIR}) + +add_library(Pylon5::Base UNKNOWN IMPORTED) +set_target_properties (Pylon5::Base PROPERTIES IMPORTED_LOCATION ${Pylon5_Base_LIBRARY}) +set_target_properties (Pylon5::Base PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${Pylon5_INCLUDE_DIRS}) + +add_library(Pylon5::Utility UNKNOWN IMPORTED) +set_target_properties (Pylon5::Utility PROPERTIES IMPORTED_LOCATION ${Pylon5_Utility_LIBRARY}) +set_target_properties (Pylon5::Utility PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${Pylon5_INCLUDE_DIRS}) + +add_library(Pylon5::GenAPI UNKNOWN IMPORTED) +set_target_properties (Pylon5::GenAPI PROPERTIES IMPORTED_LOCATION ${Pylon5_GenAPI_LIBRARY}) +set_target_properties (Pylon5::GenAPI PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${Pylon5_INCLUDE_DIRS}) + +add_library(Pylon5::GCBase UNKNOWN IMPORTED) +set_target_properties (Pylon5::GCBase PROPERTIES IMPORTED_LOCATION ${Pylon5_GCBase_LIBRARY}) +set_target_properties (Pylon5::GCBase PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${Pylon5_INCLUDE_DIRS}) diff --git a/Src/cmake/Locate.cmake b/Src/cmake/Locate.cmake new file mode 100644 index 00000000..0e674217 --- /dev/null +++ b/Src/cmake/Locate.cmake @@ -0,0 +1,118 @@ + +function(locate_shared_library_anyof VAR) + foreach(name ${ARGN}) + set(_filename "${CMAKE_SHARED_LIBRARY_PREFIX}${name}${CMAKE_SHARED_LIBRARY_SUFFIX}") + message(STATUS "Locating ${_filename}") + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + execute_process( + COMMAND where.exe "${_filename}" + OUTPUT_VARIABLE _matches + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _res + ) + if("${_res}" STREQUAL "0") + string(REGEX REPLACE "\n" ";" _matches "${_matches}") + list(GET _matches 0 _match) + string(REGEX REPLACE "\\\\" "/" _match "${_match}") + + if(DEFINED ${VAR}) + list(APPEND ${VAR} "${_match}") + set(${VAR} ${${VAR}} PARENT_SCOPE) + else() + set(${VAR} "${_match}" PARENT_SCOPE) + endif() + return() + endif() + else() + message(FATAL_ERROR "Platform not supported") + endif() + endforeach() + message(FATAL_ERROR "Could not locate any of ${ARGN}") +endfunction() + +function(locate_shared_library VAR) + foreach(name ${ARGN}) + set(_filename "${CMAKE_SHARED_LIBRARY_PREFIX}${name}${CMAKE_SHARED_LIBRARY_SUFFIX}") + message(STATUS "Locating ${_filename}") + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + execute_process( + COMMAND where.exe "${_filename}" + OUTPUT_VARIABLE _matches + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _res + ) + if(NOT "${_res}" STREQUAL "0") + message(FATAL_ERROR "Could not locate ${_filename}") + endif() + string(REGEX REPLACE "\n" ";" _matches "${_matches}") + list(GET _matches 0 _match) + string(REGEX REPLACE "\\\\" "/" _match "${_match}") + + if(DEFINED ${VAR}) + list(APPEND ${VAR} "${_match}") + set(${VAR} ${${VAR}} PARENT_SCOPE) + else() + set(${VAR} "${_match}" PARENT_SCOPE) + endif() + else() + message(FATAL_ERROR "Platform not supported") + endif() + endforeach() +endfunction() + +function(locate_opencv VAR) + cmake_parse_arguments(ARG "" "" "COMPONENTS" ${ARGN}) + + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + set(version "${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}") + + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(platform "64") + else() + set(platform "32") + endif() + + foreach(component ${ARG_COMPONENTS}) + locate_shared_library_anyof(${VAR} "opencv_${component}" "opencv_${component}${version}" "opencv_${component}${version}_${platform}") + endforeach() + set(${VAR} ${${VAR}} PARENT_SCOPE) + else() + message(FATAL_ERROR "Platform not supported") + endif() +endfunction() + +function(locate_cuda VAR) + cmake_parse_arguments(ARG "" "" "COMPONENTS" ${ARGN}) + + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(suffix "64_${CUDA_VERSION_MAJOR}") + else() + set(suffix "32_${CUDA_VERSION_MAJOR}") + endif() + + foreach(component ${ARG_COMPONENTS}) + locate_shared_library_anyof(${VAR} "${component}${suffix}" "${component}${suffix}${CUDA_VERSION_MINOR}") + endforeach() + set(${VAR} ${${VAR}} PARENT_SCOPE) + else() + message(FATAL_ERROR "Platform not supported") + endif() +endfunction() + +function(locate_cudnn VAR) + cmake_parse_arguments(ARG "" "" "COMPONENTS" ${ARGN}) + + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(suffix "64_${version}") + else() + set(suffix "32_${version}") + endif() + + locate_shared_library(${VAR} "cudnn${suffix}") + set(${VAR} ${${VAR}} PARENT_SCOPE) + else() + message(FATAL_ERROR "Platform not supported") + endif() +endfunction() diff --git a/Src/cmake/WIX/WIX.template.in b/Src/cmake/WIX/WIX.template.in new file mode 100644 index 00000000..b1331288 --- /dev/null +++ b/Src/cmake/WIX/WIX.template.in @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + ProductIcon.ico + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Src/cmake/WIX/licence.rtf b/Src/cmake/WIX/licence.rtf new file mode 100644 index 00000000..4a4d654a --- /dev/null +++ b/Src/cmake/WIX/licence.rtf @@ -0,0 +1,665 @@ +{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}} +{\colortbl ;\red0\green0\blue255;} +{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\sa200\sl276\slmult1\lang7\f0\fs22 GNU AFFERO GENERAL PUBLIC LICENSE\par + Version 3, 19 November 2007\par +\par + Copyright (C) 2007 Free Software Foundation, Inc. <{\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt{\ul\cf1 https://fsf.org/}}}\f0\fs22 >\par + Everyone is permitted to copy and distribute verbatim copies\par + of this license document, but changing it is not allowed.\par +\par + Preamble\par +\par + The GNU Affero General Public License is a free, copyleft license for\par +software and other kinds of works, specifically designed to ensure\par +cooperation with the community in the case of network server software.\par +\par + The licenses for most software and other practical works are designed\par +to take away your freedom to share and change the works. By contrast,\par +our General Public Licenses are intended to guarantee your freedom to\par +share and change all versions of a program--to make sure it remains free\par +software for all its users.\par +\par + When we speak of free software, we are referring to freedom, not\par +price. Our General Public Licenses are designed to make sure that you\par +have the freedom to distribute copies of free software (and charge for\par +them if you wish), that you receive source code or can get it if you\par +want it, that you can change the software or use pieces of it in new\par +free programs, and that you know you can do these things.\par +\par + Developers that use our General Public Licenses protect your rights\par +with two steps: (1) assert copyright on the software, and (2) offer\par +you this License which gives you legal permission to copy, distribute\par +and/or modify the software.\par +\par + A secondary benefit of defending all users' freedom is that\par +improvements made in alternate versions of the program, if they\par +receive widespread use, become available for other developers to\par +incorporate. Many developers of free software are heartened and\par +encouraged by the resulting cooperation. However, in the case of\par +software used on network servers, this result may fail to come about.\par +The GNU General Public License permits making a modified version and\par +letting the public access it on a server without ever releasing its\par +source code to the public.\par +\par + The GNU Affero General Public License is designed specifically to\par +ensure that, in such cases, the modified source code becomes available\par +to the community. It requires the operator of a network server to\par +provide the source code of the modified version running there to the\par +users of that server. Therefore, public use of a modified version, on\par +a publicly accessible server, gives the public access to the source\par +code of the modified version.\par +\par + An older license, called the Affero General Public License and\par +published by Affero, was designed to accomplish similar goals. This is\par +a different license, not a version of the Affero GPL, but Affero has\par +released a new version of the Affero GPL which permits relicensing under\par +this license.\par +\par + The precise terms and conditions for copying, distribution and\par +modification follow.\par +\par + TERMS AND CONDITIONS\par +\par + 0. Definitions.\par +\par + "This License" refers to version 3 of the GNU Affero General Public License.\par +\par + "Copyright" also means copyright-like laws that apply to other kinds of\par +works, such as semiconductor masks.\par +\par + "The Program" refers to any copyrightable work licensed under this\par +License. Each licensee is addressed as "you". "Licensees" and\par +"recipients" may be individuals or organizations.\par +\par + To "modify" a work means to copy from or adapt all or part of the work\par +in a fashion requiring copyright permission, other than the making of an\par +exact copy. The resulting work is called a "modified version" of the\par +earlier work or a work "based on" the earlier work.\par +\par + A "covered work" means either the unmodified Program or a work based\par +on the Program.\par +\par + To "propagate" a work means to do anything with it that, without\par +permission, would make you directly or secondarily liable for\par +infringement under applicable copyright law, except executing it on a\par +computer or modifying a private copy. Propagation includes copying,\par +distribution (with or without modification), making available to the\par +public, and in some countries other activities as well.\par +\par + To "convey" a work means any kind of propagation that enables other\par +parties to make or receive copies. Mere interaction with a user through\par +a computer network, with no transfer of a copy, is not conveying.\par +\par + An interactive user interface displays "Appropriate Legal Notices"\par +to the extent that it includes a convenient and prominently visible\par +feature that (1) displays an appropriate copyright notice, and (2)\par +tells the user that there is no warranty for the work (except to the\par +extent that warranties are provided), that licensees may convey the\par +work under this License, and how to view a copy of this License. If\par +the interface presents a list of user commands or options, such as a\par +menu, a prominent item in the list meets this criterion.\par +\par + 1. Source Code.\par +\par + The "source code" for a work means the preferred form of the work\par +for making modifications to it. "Object code" means any non-source\par +form of a work.\par +\par + A "Standard Interface" means an interface that either is an official\par +standard defined by a recognized standards body, or, in the case of\par +interfaces specified for a particular programming language, one that\par +is widely used among developers working in that language.\par +\par + The "System Libraries" of an executable work include anything, other\par +than the work as a whole, that (a) is included in the normal form of\par +packaging a Major Component, but which is not part of that Major\par +Component, and (b) serves only to enable use of the work with that\par +Major Component, or to implement a Standard Interface for which an\par +implementation is available to the public in source code form. A\par +"Major Component", in this context, means a major essential component\par +(kernel, window system, and so on) of the specific operating system\par +(if any) on which the executable work runs, or a compiler used to\par +produce the work, or an object code interpreter used to run it.\par +\par + The "Corresponding Source" for a work in object code form means all\par +the source code needed to generate, install, and (for an executable\par +work) run the object code and to modify the work, including scripts to\par +control those activities. However, it does not include the work's\par +System Libraries, or general-purpose tools or generally available free\par +programs which are used unmodified in performing those activities but\par +which are not part of the work. For example, Corresponding Source\par +includes interface definition files associated with source files for\par +the work, and the source code for shared libraries and dynamically\par +linked subprograms that the work is specifically designed to require,\par +such as by intimate data communication or control flow between those\par +subprograms and other parts of the work.\par +\par + The Corresponding Source need not include anything that users\par +can regenerate automatically from other parts of the Corresponding\par +Source.\par +\par + The Corresponding Source for a work in source code form is that\par +same work.\par +\par + 2. Basic Permissions.\par +\par + All rights granted under this License are granted for the term of\par +copyright on the Program, and are irrevocable provided the stated\par +conditions are met. This License explicitly affirms your unlimited\par +permission to run the unmodified Program. The output from running a\par +covered work is covered by this License only if the output, given its\par +content, constitutes a covered work. This License acknowledges your\par +rights of fair use or other equivalent, as provided by copyright law.\par +\par + You may make, run and propagate covered works that you do not\par +convey, without conditions so long as your license otherwise remains\par +in force. You may convey covered works to others for the sole purpose\par +of having them make modifications exclusively for you, or provide you\par +with facilities for running those works, provided that you comply with\par +the terms of this License in conveying all material for which you do\par +not control copyright. Those thus making or running the covered works\par +for you must do so exclusively on your behalf, under your direction\par +and control, on terms that prohibit them from making any copies of\par +your copyrighted material outside their relationship with you.\par +\par + Conveying under any other circumstances is permitted solely under\par +the conditions stated below. Sublicensing is not allowed; section 10\par +makes it unnecessary.\par +\par + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\par +\par + No covered work shall be deemed part of an effective technological\par +measure under any applicable law fulfilling obligations under article\par +11 of the WIPO copyright treaty adopted on 20 December 1996, or\par +similar laws prohibiting or restricting circumvention of such\par +measures.\par +\par + When you convey a covered work, you waive any legal power to forbid\par +circumvention of technological measures to the extent such circumvention\par +is effected by exercising rights under this License with respect to\par +the covered work, and you disclaim any intention to limit operation or\par +modification of the work as a means of enforcing, against the work's\par +users, your or third parties' legal rights to forbid circumvention of\par +technological measures.\par +\par + 4. Conveying Verbatim Copies.\par +\par + You may convey verbatim copies of the Program's source code as you\par +receive it, in any medium, provided that you conspicuously and\par +appropriately publish on each copy an appropriate copyright notice;\par +keep intact all notices stating that this License and any\par +non-permissive terms added in accord with section 7 apply to the code;\par +keep intact all notices of the absence of any warranty; and give all\par +recipients a copy of this License along with the Program.\par +\par + You may charge any price or no price for each copy that you convey,\par +and you may offer support or warranty protection for a fee.\par +\par + 5. Conveying Modified Source Versions.\par +\par + You may convey a work based on the Program, or the modifications to\par +produce it from the Program, in the form of source code under the\par +terms of section 4, provided that you also meet all of these conditions:\par +\par + a) The work must carry prominent notices stating that you modified\par + it, and giving a relevant date.\par +\par + b) The work must carry prominent notices stating that it is\par + released under this License and any conditions added under section\par + 7. This requirement modifies the requirement in section 4 to\par + "keep intact all notices".\par +\par + c) You must license the entire work, as a whole, under this\par + License to anyone who comes into possession of a copy. This\par + License will therefore apply, along with any applicable section 7\par + additional terms, to the whole of the work, and all its parts,\par + regardless of how they are packaged. This License gives no\par + permission to license the work in any other way, but it does not\par + invalidate such permission if you have separately received it.\par +\par + d) If the work has interactive user interfaces, each must display\par + Appropriate Legal Notices; however, if the Program has interactive\par + interfaces that do not display Appropriate Legal Notices, your\par + work need not make them do so.\par +\par + A compilation of a covered work with other separate and independent\par +works, which are not by their nature extensions of the covered work,\par +and which are not combined with it such as to form a larger program,\par +in or on a volume of a storage or distribution medium, is called an\par +"aggregate" if the compilation and its resulting copyright are not\par +used to limit the access or legal rights of the compilation's users\par +beyond what the individual works permit. Inclusion of a covered work\par +in an aggregate does not cause this License to apply to the other\par +parts of the aggregate.\par +\par + 6. Conveying Non-Source Forms.\par +\par + You may convey a covered work in object code form under the terms\par +of sections 4 and 5, provided that you also convey the\par +machine-readable Corresponding Source under the terms of this License,\par +in one of these ways:\par +\par + a) Convey the object code in, or embodied in, a physical product\par + (including a physical distribution medium), accompanied by the\par + Corresponding Source fixed on a durable physical medium\par + customarily used for software interchange.\par +\par + b) Convey the object code in, or embodied in, a physical product\par + (including a physical distribution medium), accompanied by a\par + written offer, valid for at least three years and valid for as\par + long as you offer spare parts or customer support for that product\par + model, to give anyone who possesses the object code either (1) a\par + copy of the Corresponding Source for all the software in the\par + product that is covered by this License, on a durable physical\par + medium customarily used for software interchange, for a price no\par + more than your reasonable cost of physically performing this\par + conveying of source, or (2) access to copy the\par + Corresponding Source from a network server at no charge.\par +\par + c) Convey individual copies of the object code with a copy of the\par + written offer to provide the Corresponding Source. This\par + alternative is allowed only occasionally and noncommercially, and\par + only if you received the object code with such an offer, in accord\par + with subsection 6b.\par +\par + d) Convey the object code by offering access from a designated\par + place (gratis or for a charge), and offer equivalent access to the\par + Corresponding Source in the same way through the same place at no\par + further charge. You need not require recipients to copy the\par + Corresponding Source along with the object code. If the place to\par + copy the object code is a network server, the Corresponding Source\par + may be on a different server (operated by you or a third party)\par + that supports equivalent copying facilities, provided you maintain\par + clear directions next to the object code saying where to find the\par + Corresponding Source. Regardless of what server hosts the\par + Corresponding Source, you remain obligated to ensure that it is\par + available for as long as needed to satisfy these requirements.\par +\par + e) Convey the object code using peer-to-peer transmission, provided\par + you inform other peers where the object code and Corresponding\par + Source of the work are being offered to the general public at no\par + charge under subsection 6d.\par +\par + A separable portion of the object code, whose source code is excluded\par +from the Corresponding Source as a System Library, need not be\par +included in conveying the object code work.\par +\par + A "User Product" is either (1) a "consumer product", which means any\par +tangible personal property which is normally used for personal, family,\par +or household purposes, or (2) anything designed or sold for incorporation\par +into a dwelling. In determining whether a product is a consumer product,\par +doubtful cases shall be resolved in favor of coverage. For a particular\par +product received by a particular user, "normally used" refers to a\par +typical or common use of that class of product, regardless of the status\par +of the particular user or of the way in which the particular user\par +actually uses, or expects or is expected to use, the product. A product\par +is a consumer product regardless of whether the product has substantial\par +commercial, industrial or non-consumer uses, unless such uses represent\par +the only significant mode of use of the product.\par +\par + "Installation Information" for a User Product means any methods,\par +procedures, authorization keys, or other information required to install\par +and execute modified versions of a covered work in that User Product from\par +a modified version of its Corresponding Source. The information must\par +suffice to ensure that the continued functioning of the modified object\par +code is in no case prevented or interfered with solely because\par +modification has been made.\par +\par + If you convey an object code work under this section in, or with, or\par +specifically for use in, a User Product, and the conveying occurs as\par +part of a transaction in which the right of possession and use of the\par +User Product is transferred to the recipient in perpetuity or for a\par +fixed term (regardless of how the transaction is characterized), the\par +Corresponding Source conveyed under this section must be accompanied\par +by the Installation Information. But this requirement does not apply\par +if neither you nor any third party retains the ability to install\par +modified object code on the User Product (for example, the work has\par +been installed in ROM).\par +\par + The requirement to provide Installation Information does not include a\par +requirement to continue to provide support service, warranty, or updates\par +for a work that has been modified or installed by the recipient, or for\par +the User Product in which it has been modified or installed. Access to a\par +network may be denied when the modification itself materially and\par +adversely affects the operation of the network or violates the rules and\par +protocols for communication across the network.\par +\par + Corresponding Source conveyed, and Installation Information provided,\par +in accord with this section must be in a format that is publicly\par +documented (and with an implementation available to the public in\par +source code form), and must require no special password or key for\par +unpacking, reading or copying.\par +\par + 7. Additional Terms.\par +\par + "Additional permissions" are terms that supplement the terms of this\par +License by making exceptions from one or more of its conditions.\par +Additional permissions that are applicable to the entire Program shall\par +be treated as though they were included in this License, to the extent\par +that they are valid under applicable law. If additional permissions\par +apply only to part of the Program, that part may be used separately\par +under those permissions, but the entire Program remains governed by\par +this License without regard to the additional permissions.\par +\par + When you convey a copy of a covered work, you may at your option\par +remove any additional permissions from that copy, or from any part of\par +it. (Additional permissions may be written to require their own\par +removal in certain cases when you modify the work.) You may place\par +additional permissions on material, added by you to a covered work,\par +for which you have or can give appropriate copyright permission.\par +\par + Notwithstanding any other provision of this License, for material you\par +add to a covered work, you may (if authorized by the copyright holders of\par +that material) supplement the terms of this License with terms:\par +\par + a) Disclaiming warranty or limiting liability differently from the\par + terms of sections 15 and 16 of this License; or\par +\par + b) Requiring preservation of specified reasonable legal notices or\par + author attributions in that material or in the Appropriate Legal\par + Notices displayed by works containing it; or\par +\par + c) Prohibiting misrepresentation of the origin of that material, or\par + requiring that modified versions of such material be marked in\par + reasonable ways as different from the original version; or\par +\par + d) Limiting the use for publicity purposes of names of licensors or\par + authors of the material; or\par +\par + e) Declining to grant rights under trademark law for use of some\par + trade names, trademarks, or service marks; or\par +\par + f) Requiring indemnification of licensors and authors of that\par + material by anyone who conveys the material (or modified versions of\par + it) with contractual assumptions of liability to the recipient, for\par + any liability that these contractual assumptions directly impose on\par + those licensors and authors.\par +\par + All other non-permissive additional terms are considered "further\par +restrictions" within the meaning of section 10. If the Program as you\par +received it, or any part of it, contains a notice stating that it is\par +governed by this License along with a term that is a further\par +restriction, you may remove that term. If a license document contains\par +a further restriction but permits relicensing or conveying under this\par +License, you may add to a covered work material governed by the terms\par +of that license document, provided that the further restriction does\par +not survive such relicensing or conveying.\par +\par + If you add terms to a covered work in accord with this section, you\par +must place, in the relevant source files, a statement of the\par +additional terms that apply to those files, or a notice indicating\par +where to find the applicable terms.\par +\par + Additional terms, permissive or non-permissive, may be stated in the\par +form of a separately written license, or stated as exceptions;\par +the above requirements apply either way.\par +\par + 8. Termination.\par +\par + You may not propagate or modify a covered work except as expressly\par +provided under this License. Any attempt otherwise to propagate or\par +modify it is void, and will automatically terminate your rights under\par +this License (including any patent licenses granted under the third\par +paragraph of section 11).\par +\par + However, if you cease all violation of this License, then your\par +license from a particular copyright holder is reinstated (a)\par +provisionally, unless and until the copyright holder explicitly and\par +finally terminates your license, and (b) permanently, if the copyright\par +holder fails to notify you of the violation by some reasonable means\par +prior to 60 days after the cessation.\par +\par + Moreover, your license from a particular copyright holder is\par +reinstated permanently if the copyright holder notifies you of the\par +violation by some reasonable means, this is the first time you have\par +received notice of violation of this License (for any work) from that\par +copyright holder, and you cure the violation prior to 30 days after\par +your receipt of the notice.\par +\par + Termination of your rights under this section does not terminate the\par +licenses of parties who have received copies or rights from you under\par +this License. If your rights have been terminated and not permanently\par +reinstated, you do not qualify to receive new licenses for the same\par +material under section 10.\par +\par + 9. Acceptance Not Required for Having Copies.\par +\par + You are not required to accept this License in order to receive or\par +run a copy of the Program. Ancillary propagation of a covered work\par +occurring solely as a consequence of using peer-to-peer transmission\par +to receive a copy likewise does not require acceptance. However,\par +nothing other than this License grants you permission to propagate or\par +modify any covered work. These actions infringe copyright if you do\par +not accept this License. Therefore, by modifying or propagating a\par +covered work, you indicate your acceptance of this License to do so.\par +\par + 10. Automatic Licensing of Downstream Recipients.\par +\par + Each time you convey a covered work, the recipient automatically\par +receives a license from the original licensors, to run, modify and\par +propagate that work, subject to this License. You are not responsible\par +for enforcing compliance by third parties with this License.\par +\par + An "entity transaction" is a transaction transferring control of an\par +organization, or substantially all assets of one, or subdividing an\par +organization, or merging organizations. If propagation of a covered\par +work results from an entity transaction, each party to that\par +transaction who receives a copy of the work also receives whatever\par +licenses to the work the party's predecessor in interest had or could\par +give under the previous paragraph, plus a right to possession of the\par +Corresponding Source of the work from the predecessor in interest, if\par +the predecessor has it or can get it with reasonable efforts.\par +\par + You may not impose any further restrictions on the exercise of the\par +rights granted or affirmed under this License. For example, you may\par +not impose a license fee, royalty, or other charge for exercise of\par +rights granted under this License, and you may not initiate litigation\par +(including a cross-claim or counterclaim in a lawsuit) alleging that\par +any patent claim is infringed by making, using, selling, offering for\par +sale, or importing the Program or any portion of it.\par +\par + 11. Patents.\par +\par + A "contributor" is a copyright holder who authorizes use under this\par +License of the Program or a work on which the Program is based. The\par +work thus licensed is called the contributor's "contributor version".\par +\par + A contributor's "essential patent claims" are all patent claims\par +owned or controlled by the contributor, whether already acquired or\par +hereafter acquired, that would be infringed by some manner, permitted\par +by this License, of making, using, or selling its contributor version,\par +but do not include claims that would be infringed only as a\par +consequence of further modification of the contributor version. For\par +purposes of this definition, "control" includes the right to grant\par +patent sublicenses in a manner consistent with the requirements of\par +this License.\par +\par + Each contributor grants you a non-exclusive, worldwide, royalty-free\par +patent license under the contributor's essential patent claims, to\par +make, use, sell, offer for sale, import and otherwise run, modify and\par +propagate the contents of its contributor version.\par +\par + In the following three paragraphs, a "patent license" is any express\par +agreement or commitment, however denominated, not to enforce a patent\par +(such as an express permission to practice a patent or covenant not to\par +sue for patent infringement). To "grant" such a patent license to a\par +party means to make such an agreement or commitment not to enforce a\par +patent against the party.\par +\par + If you convey a covered work, knowingly relying on a patent license,\par +and the Corresponding Source of the work is not available for anyone\par +to copy, free of charge and under the terms of this License, through a\par +publicly available network server or other readily accessible means,\par +then you must either (1) cause the Corresponding Source to be so\par +available, or (2) arrange to deprive yourself of the benefit of the\par +patent license for this particular work, or (3) arrange, in a manner\par +consistent with the requirements of this License, to extend the patent\par +license to downstream recipients. "Knowingly relying" means you have\par +actual knowledge that, but for the patent license, your conveying the\par +covered work in a country, or your recipient's use of the covered work\par +in a country, would infringe one or more identifiable patents in that\par +country that you have reason to believe are valid.\par +\par + If, pursuant to or in connection with a single transaction or\par +arrangement, you convey, or propagate by procuring conveyance of, a\par +covered work, and grant a patent license to some of the parties\par +receiving the covered work authorizing them to use, propagate, modify\par +or convey a specific copy of the covered work, then the patent license\par +you grant is automatically extended to all recipients of the covered\par +work and works based on it.\par +\par + A patent license is "discriminatory" if it does not include within\par +the scope of its coverage, prohibits the exercise of, or is\par +conditioned on the non-exercise of one or more of the rights that are\par +specifically granted under this License. You may not convey a covered\par +work if you are a party to an arrangement with a third party that is\par +in the business of distributing software, under which you make payment\par +to the third party based on the extent of your activity of conveying\par +the work, and under which the third party grants, to any of the\par +parties who would receive the covered work from you, a discriminatory\par +patent license (a) in connection with copies of the covered work\par +conveyed by you (or copies made from those copies), or (b) primarily\par +for and in connection with specific products or compilations that\par +contain the covered work, unless you entered into that arrangement,\par +or that patent license was granted, prior to 28 March 2007.\par +\par + Nothing in this License shall be construed as excluding or limiting\par +any implied license or other defenses to infringement that may\par +otherwise be available to you under applicable patent law.\par +\par + 12. No Surrender of Others' Freedom.\par +\par + If conditions are imposed on you (whether by court order, agreement or\par +otherwise) that contradict the conditions of this License, they do not\par +excuse you from the conditions of this License. If you cannot convey a\par +covered work so as to satisfy simultaneously your obligations under this\par +License and any other pertinent obligations, then as a consequence you may\par +not convey it at all. For example, if you agree to terms that obligate you\par +to collect a royalty for further conveying from those to whom you convey\par +the Program, the only way you could satisfy both those terms and this\par +License would be to refrain entirely from conveying the Program.\par +\par + 13. Remote Network Interaction; Use with the GNU General Public License.\par +\par + Notwithstanding any other provision of this License, if you modify the\par +Program, your modified version must prominently offer all users\par +interacting with it remotely through a computer network (if your version\par +supports such interaction) an opportunity to receive the Corresponding\par +Source of your version by providing access to the Corresponding Source\par +from a network server at no charge, through some standard or customary\par +means of facilitating copying of software. This Corresponding Source\par +shall include the Corresponding Source for any work covered by version 3\par +of the GNU General Public License that is incorporated pursuant to the\par +following paragraph.\par +\par + Notwithstanding any other provision of this License, you have\par +permission to link or combine any covered work with a work licensed\par +under version 3 of the GNU General Public License into a single\par +combined work, and to convey the resulting work. The terms of this\par +License will continue to apply to the part which is the covered work,\par +but the work with which it is combined will remain governed by version\par +3 of the GNU General Public License.\par +\par + 14. Revised Versions of this License.\par +\par + The Free Software Foundation may publish revised and/or new versions of\par +the GNU Affero General Public License from time to time. Such new versions\par +will be similar in spirit to the present version, but may differ in detail to\par +address new problems or concerns.\par +\par + Each version is given a distinguishing version number. If the\par +Program specifies that a certain numbered version of the GNU Affero General\par +Public License "or any later version" applies to it, you have the\par +option of following the terms and conditions either of that numbered\par +version or of any later version published by the Free Software\par +Foundation. If the Program does not specify a version number of the\par +GNU Affero General Public License, you may choose any version ever published\par +by the Free Software Foundation.\par +\par + If the Program specifies that a proxy can decide which future\par +versions of the GNU Affero General Public License can be used, that proxy's\par +public statement of acceptance of a version permanently authorizes you\par +to choose that version for the Program.\par +\par + Later license versions may give you additional or different\par +permissions. However, no additional obligations are imposed on any\par +author or copyright holder as a result of your choosing to follow a\par +later version.\par +\par + 15. Disclaimer of Warranty.\par +\par + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\par +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\par +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\par +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\par +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\par +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\par +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\par +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\par +\par + 16. Limitation of Liability.\par +\par + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\par +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\par +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\par +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\par +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\par +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\par +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\par +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\par +SUCH DAMAGES.\par +\par + 17. Interpretation of Sections 15 and 16.\par +\par + If the disclaimer of warranty and limitation of liability provided\par +above cannot be given local legal effect according to their terms,\par +reviewing courts shall apply local law that most closely approximates\par +an absolute waiver of all civil liability in connection with the\par +Program, unless a warranty or assumption of liability accompanies a\par +copy of the Program in return for a fee.\par +\par + END OF TERMS AND CONDITIONS\par +\par + How to Apply These Terms to Your New Programs\par +\par + If you develop a new program, and you want it to be of the greatest\par +possible use to the public, the best way to achieve this is to make it\par +free software which everyone can redistribute and change under these terms.\par +\par + To do so, attach the following notices to the program. It is safest\par +to attach them to the start of each source file to most effectively\par +state the exclusion of warranty; and each file should have at least\par +the "copyright" line and a pointer to where the full notice is found.\par +\par + \par + Copyright (C) \par +\par + This program is free software: you can redistribute it and/or modify\par + it under the terms of the GNU Affero General Public License as published by\par + the Free Software Foundation, either version 3 of the License, or\par + (at your option) any later version.\par +\par + This program is distributed in the hope that it will be useful,\par + but WITHOUT ANY WARRANTY; without even the implied warranty of\par + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\par + GNU Affero General Public License for more details.\par +\par + You should have received a copy of the GNU Affero General Public License\par + along with this program. If not, see <{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{\ul\cf1 https://www.gnu.org/licenses/}}}\f0\fs22 >.\par +\par +Also add information on how to contact you by electronic and paper mail.\par +\par + If your software can interact with users remotely through a computer\par +network, you should also make sure that it provides a way for users to\par +get its source. For example, if your program is a web application, its\par +interface could display a "Source" link that leads users to an archive\par +of the code. There are many ways you could offer source, and different\par +solutions will be better for different programs; see section 13 for the\par +specific requirements.\par +\par + You should also get your employer (if you work as a programmer) or school,\par +if any, to sign a "copyright disclaimer" for the program, if necessary.\par +For more information on this, and how to apply and follow the GNU AGPL, see\par +<{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{\ul\cf1 https://www.gnu.org/licenses/}}}\f0\fs22 >.\par +} + \ No newline at end of file diff --git a/Src/cmake/WinDeployQt5.cmake b/Src/cmake/WinDeployQt5.cmake new file mode 100644 index 00000000..9a95ef5c --- /dev/null +++ b/Src/cmake/WinDeployQt5.cmake @@ -0,0 +1,81 @@ +# The MIT License (MIT) +# +# Copyright (c) 2017 Nathan Osman +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +find_package(Qt5Core REQUIRED) + +# Retrieve the absolute path to qmake and then use that path to find +# the windeployqt binary +get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION) +get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY) +find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}") + +# Running this with MSVC 2015 requires CMake 3.6+ +if((MSVC_VERSION VERSION_EQUAL 1900 OR MSVC_VERSION VERSION_GREATER 1900) + AND CMAKE_VERSION VERSION_LESS "3.6") + message(FATAL_ERROR "Deploying with MSVC 2015+ requires CMake 3.6+") +endif() + +function(deploy_qt5 target) + cmake_parse_arguments(ARG "" "DESTINATION" "" ${ARGN}) + + # install(CODE ...) does not support generator expressions, but file(GENERATE ...) does -> store the path in a file + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${target}_path" + CONTENT "$" + ) + + # Before installation, run a series of commands that copy each of the Qt + # runtime files to the appropriate directory for installation + install(CODE + " + file(READ \"${CMAKE_CURRENT_BINARY_DIR}/${target}_path\" _file) + execute_process( + COMMAND \"${CMAKE_COMMAND}\" -E + env PATH=\"${_qt_bin_dir}\" \"${WINDEPLOYQT_EXECUTABLE}\" + --dry-run + --no-compiler-runtime + --no-angle + --no-opengl-sw + --list mapping + \${_file} + OUTPUT_VARIABLE _output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + separate_arguments(_files WINDOWS_COMMAND \${_output}) + while(_files) + list(GET _files 0 _src) + list(GET _files 1 _dest) + if(\"${ARG_DESTINATION}\" STREQUAL \"\") + set(_dest \"\${CMAKE_INSTALL_PREFIX}/\${_dest}\") + else() + set(_dest \"\${CMAKE_INSTALL_PREFIX}/${ARG_DESTINATION}/\${_dest}\") + endif() + execute_process( + COMMAND \"${CMAKE_COMMAND}\" -E + copy \${_src} \"\${_dest}\" + ) + list(REMOVE_AT _files 0 1) + endwhile() + " + ) +endfunction() + +mark_as_advanced(WINDEPLOYQT_EXECUTABLE) diff --git a/BioTracker/CoreApp/BioTracker/guiresources.qrc b/Src/guiresources.qrc similarity index 100% rename from BioTracker/CoreApp/BioTracker/guiresources.qrc rename to Src/guiresources.qrc diff --git a/Src/main.cpp b/Src/main.cpp new file mode 100644 index 00000000..c3a95b2b --- /dev/null +++ b/Src/main.cpp @@ -0,0 +1,117 @@ +#include +#include "BioTracker3App.h" +#include "GuiContext.h" +#include "opencv2/core/core.hpp" +#include +#include +#include +#include +#include +#include "Model/MediaPlayerStateMachine/PlayerParameters.h" +#include "util/types.h" +#include "util/camera/base.h" + +#include "util/CLIcommands.h" +#include "Interfaces/IModel/IModelTrackedComponent.h" +#include "util/Config.h" +#include + +#include + +#if HAS_PYLON + #include +#endif + +// This will hide the console. +// See +// https://stackoverflow.com/questions/2139637/hide-console-of-windows-application +#ifdef _WIN32 +//#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") +#endif + +// Get the default Qt message handler. +static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = + qInstallMessageHandler(0); + +void myMessageOutput(QtMsgType type, + const QMessageLogContext& context, + const QString& msg) +{ + if (type == QtMsgType::QtInfoMsg) + return; + + QString fmsg = qFormatLogMessage(type, context, msg); + QString outf = IConfig::dataLocation + "/log.txt"; + std::string debugs = outf.toStdString(); + QFile outFile(outf); + outFile.open(QIODevice::WriteOnly | QIODevice::Append); + QTextStream ts(&outFile); + ts << fmsg << endl; + + (*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg); +} + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + + app.setOrganizationName("FU Berlin"); + app.setApplicationName("BioTracker"); + IConfig::configLocation = QStandardPaths::writableLocation( + QStandardPaths::AppConfigLocation); + IConfig::dataLocation = QStandardPaths::writableLocation( + QStandardPaths::AppDataLocation); + Config* cfg = new Config(); + CLI::optionParser(argc, argv, cfg); + QString cfgLoc = cfg->CfgCustomLocation.isEmpty() ? Config::configLocation + : cfg->CfgCustomLocation; + cfg->load(cfgLoc, "config.ini"); + cfg->save(cfgLoc, "config.ini"); + +#if HAS_PYLON + const auto cache = boost::filesystem::path{ + QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + .toStdString()}; + const auto genicamCache = cache / "genicam_xml_cache"; + + boost::filesystem::create_directories(genicamCache); + GenICam::SetGenICamCacheFolder(GenICam::gcstring{genicamCache.c_str()}); + + qputenv(GENICAM_CACHE_VERSION, + QByteArray::fromStdString(genicamCache.string())); +#endif + + qRegisterMetaType("cv::Mat"); + qRegisterMetaType("std::size_t"); + qRegisterMetaType("size_t"); + qRegisterMetaType>( + "std::vector"); + qRegisterMetaType("BiotrackerTypes::AreaType"); + qRegisterMetaType>("QVector"); + qRegisterMetaType>("QVector"); + qRegisterMetaType>("QMap"); + qRegisterMetaType>( + "std::shared_ptr"); + qRegisterMetaType("CameraConfiguration"); + qRegisterMetaTypeStreamOperators>( + "QList"); + + qInstallMessageHandler(myMessageOutput); + + QDir qd; + qd.mkpath(IConfig::configLocation); + qd.mkpath(IConfig::dataLocation); + qd.mkpath(cfg->DirPlugins); + qd.mkpath(cfg->DirVideos); + qd.mkpath(cfg->DirTracks); + qd.mkpath(cfg->DirTrials); + qd.mkpath(cfg->DirScreenshots); + qd.mkpath(cfg->DirTemp); + + BioTracker3App bioTracker3(&app); + GuiContext context(&bioTracker3, cfg); + bioTracker3.setBioTrackerContext(&context); + bioTracker3.runBioTracker(); + + app.exec(); +} diff --git a/BioTracker/CoreApp/BioTracker/resources/arrow-back.png b/Src/resources/arrow-back.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/arrow-back.png rename to Src/resources/arrow-back.png diff --git a/BioTracker/CoreApp/BioTracker/resources/arrow-forward1.png b/Src/resources/arrow-forward1.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/arrow-forward1.png rename to Src/resources/arrow-forward1.png diff --git a/BioTracker/CoreApp/BioTracker/resources/arrows-skip-back.png b/Src/resources/arrows-skip-back.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/arrows-skip-back.png rename to Src/resources/arrows-skip-back.png diff --git a/BioTracker/CoreApp/BioTracker/resources/arrows-skip-forward.png b/Src/resources/arrows-skip-forward.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/arrows-skip-forward.png rename to Src/resources/arrows-skip-forward.png diff --git a/BioTracker/CoreApp/BioTracker/resources/fullscreen.png b/Src/resources/fullscreen.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/fullscreen.png rename to Src/resources/fullscreen.png diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/context_menus.txt b/Src/resources/introduction/context_menus.txt similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/context_menus.txt rename to Src/resources/introduction/context_menus.txt diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/images/BioTracker.PNG b/Src/resources/introduction/images/BioTracker.PNG similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/images/BioTracker.PNG rename to Src/resources/introduction/images/BioTracker.PNG diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/images/context_entity.png b/Src/resources/introduction/images/context_entity.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/images/context_entity.png rename to Src/resources/introduction/images/context_entity.png diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/images/context_video.png b/Src/resources/introduction/images/context_video.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/images/context_video.png rename to Src/resources/introduction/images/context_video.png diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/images/right_panel.png b/Src/resources/introduction/images/right_panel.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/images/right_panel.png rename to Src/resources/introduction/images/right_panel.png diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/images/toolbars.png b/Src/resources/introduction/images/toolbars.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/images/toolbars.png rename to Src/resources/introduction/images/toolbars.png diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/images/tracking.png b/Src/resources/introduction/images/tracking.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/images/tracking.png rename to Src/resources/introduction/images/tracking.png diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/intro.txt b/Src/resources/introduction/intro.txt similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/intro.txt rename to Src/resources/introduction/intro.txt diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/right_panel.txt b/Src/resources/introduction/right_panel.txt similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/right_panel.txt rename to Src/resources/introduction/right_panel.txt diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/toolbars.txt b/Src/resources/introduction/toolbars.txt similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/toolbars.txt rename to Src/resources/introduction/toolbars.txt diff --git a/BioTracker/CoreApp/BioTracker/resources/introduction/tracking.txt b/Src/resources/introduction/tracking.txt similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/introduction/tracking.txt rename to Src/resources/introduction/tracking.txt diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/add-track.png b/Src/resources/left_toolbar/add-track.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/add-track.png rename to Src/resources/left_toolbar/add-track.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-arrow.png b/Src/resources/left_toolbar/anno-arrow.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-arrow.png rename to Src/resources/left_toolbar/anno-arrow.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-del.png b/Src/resources/left_toolbar/anno-del.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-del.png rename to Src/resources/left_toolbar/anno-del.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-ellipse.png b/Src/resources/left_toolbar/anno-ellipse.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-ellipse.png rename to Src/resources/left_toolbar/anno-ellipse.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-label.png b/Src/resources/left_toolbar/anno-label.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-label.png rename to Src/resources/left_toolbar/anno-label.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-rect.png b/Src/resources/left_toolbar/anno-rect.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/anno-rect.png rename to Src/resources/left_toolbar/anno-rect.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/color-border.png b/Src/resources/left_toolbar/color-border.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/color-border.png rename to Src/resources/left_toolbar/color-border.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/color-fill.png b/Src/resources/left_toolbar/color-fill.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/color-fill.png rename to Src/resources/left_toolbar/color-fill.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/delete-track.png b/Src/resources/left_toolbar/delete-track.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/delete-track.png rename to Src/resources/left_toolbar/delete-track.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/select-all.png b/Src/resources/left_toolbar/select-all.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/select-all.png rename to Src/resources/left_toolbar/select-all.png diff --git a/BioTracker/CoreApp/BioTracker/resources/left_toolbar/swap.png b/Src/resources/left_toolbar/swap.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/left_toolbar/swap.png rename to Src/resources/left_toolbar/swap.png diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT-3_non_transparent_rounded.ico b/Src/resources/logo/BT-3_non_transparent_rounded.ico similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT-3_non_transparent_rounded.ico rename to Src/resources/logo/BT-3_non_transparent_rounded.ico diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT-3_non_transparent_rounded.png b/Src/resources/logo/BT-3_non_transparent_rounded.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT-3_non_transparent_rounded.png rename to Src/resources/logo/BT-3_non_transparent_rounded.png diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT3-big.ico b/Src/resources/logo/BT3-big.ico similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT3-big.ico rename to Src/resources/logo/BT3-big.ico diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT3-big.png b/Src/resources/logo/BT3-big.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT3-big.png rename to Src/resources/logo/BT3-big.png diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT3-big_non_transparent.ico b/Src/resources/logo/BT3-big_non_transparent.ico similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT3-big_non_transparent.ico rename to Src/resources/logo/BT3-big_non_transparent.ico diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT3-big_non_transparent.png b/Src/resources/logo/BT3-big_non_transparent.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT3-big_non_transparent.png rename to Src/resources/logo/BT3-big_non_transparent.png diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/BT3-small.png b/Src/resources/logo/BT3-small.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/BT3-small.png rename to Src/resources/logo/BT3-small.png diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/firstlogo.ico b/Src/resources/logo/firstlogo.ico similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/firstlogo.ico rename to Src/resources/logo/firstlogo.ico diff --git a/BioTracker/CoreApp/BioTracker/resources/logo/firstlogo.png b/Src/resources/logo/firstlogo.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/logo/firstlogo.png rename to Src/resources/logo/firstlogo.png diff --git a/BioTracker/CoreApp/BioTracker/resources/panZoom.png b/Src/resources/panZoom.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/panZoom.png rename to Src/resources/panZoom.png diff --git a/BioTracker/CoreApp/BioTracker/resources/pause-sign.png b/Src/resources/pause-sign.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/pause-sign.png rename to Src/resources/pause-sign.png diff --git a/BioTracker/CoreApp/BioTracker/resources/record.png b/Src/resources/record.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/record.png rename to Src/resources/record.png diff --git a/BioTracker/CoreApp/BioTracker/resources/recordCam.png b/Src/resources/recordCam.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/recordCam.png rename to Src/resources/recordCam.png diff --git a/BioTracker/CoreApp/BioTracker/resources/recording.png b/Src/resources/recording.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/recording.png rename to Src/resources/recording.png diff --git a/BioTracker/CoreApp/BioTracker/resources/recordingCam.png b/Src/resources/recordingCam.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/recordingCam.png rename to Src/resources/recordingCam.png diff --git a/BioTracker/CoreApp/BioTracker/resources/screenshot.png b/Src/resources/screenshot.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/screenshot.png rename to Src/resources/screenshot.png diff --git a/BioTracker/CoreApp/BioTracker/resources/shortcuts.txt b/Src/resources/shortcuts.txt similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/shortcuts.txt rename to Src/resources/shortcuts.txt diff --git a/BioTracker/CoreApp/BioTracker/resources/stop.png b/Src/resources/stop.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/stop.png rename to Src/resources/stop.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/download.png b/Src/resources/upper_toolbar/download.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/download.png rename to Src/resources/upper_toolbar/download.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/file-picture.png b/Src/resources/upper_toolbar/file-picture.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/file-picture.png rename to Src/resources/upper_toolbar/file-picture.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/file-play.png b/Src/resources/upper_toolbar/file-play.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/file-play.png rename to Src/resources/upper_toolbar/file-play.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/icons8-video-camera-26.png b/Src/resources/upper_toolbar/icons8-video-camera-26.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/icons8-video-camera-26.png rename to Src/resources/upper_toolbar/icons8-video-camera-26.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/redo2.png b/Src/resources/upper_toolbar/redo2.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/redo2.png rename to Src/resources/upper_toolbar/redo2.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/save.png b/Src/resources/upper_toolbar/save.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/save.png rename to Src/resources/upper_toolbar/save.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker.png b/Src/resources/upper_toolbar/tracker.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker.png rename to Src/resources/upper_toolbar/tracker.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker2.png b/Src/resources/upper_toolbar/tracker2.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker2.png rename to Src/resources/upper_toolbar/tracker2.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker3.png b/Src/resources/upper_toolbar/tracker3.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker3.png rename to Src/resources/upper_toolbar/tracker3.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker4.png b/Src/resources/upper_toolbar/tracker4.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker4.png rename to Src/resources/upper_toolbar/tracker4.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker5.png b/Src/resources/upper_toolbar/tracker5.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/tracker5.png rename to Src/resources/upper_toolbar/tracker5.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/undo2.png b/Src/resources/upper_toolbar/undo2.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/undo2.png rename to Src/resources/upper_toolbar/undo2.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/upload.png b/Src/resources/upper_toolbar/upload.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/upload.png rename to Src/resources/upper_toolbar/upload.png diff --git a/BioTracker/CoreApp/BioTracker/resources/upper_toolbar/video-camera.png b/Src/resources/upper_toolbar/video-camera.png similarity index 100% rename from BioTracker/CoreApp/BioTracker/resources/upper_toolbar/video-camera.png rename to Src/resources/upper_toolbar/video-camera.png diff --git a/BioTracker/CoreApp/BioTracker/util/CLIcommands.cpp b/Src/util/CLIcommands.cpp similarity index 100% rename from BioTracker/CoreApp/BioTracker/util/CLIcommands.cpp rename to Src/util/CLIcommands.cpp diff --git a/Src/util/CLIcommands.h b/Src/util/CLIcommands.h new file mode 100644 index 00000000..7943094e --- /dev/null +++ b/Src/util/CLIcommands.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "util/types.h" +#include "util/Config.h" + +class CLI +{ +public: + static void optionParser(int ac, char* av[], Config* cfg) + { + // Taken from + // http://www.boost.org/doc/libs/1_64_0/libs/program_options/example/option_groups.cpp + using namespace boost; + using namespace boost::program_options; + try { + // Declare three groups of options. + options_description general("General options"); + general.add_options()("help", "Produce this help message")( + "usePlugin", + value(), + "Uses plugin from given filepath")( + "video", + value(), + "Loads a video from given filepath")( + "cfg", + value(), + "Provide custom path to a config file"); + + options_description gui("GUI options"); + // gui.add_options() + // ("display", value(), "display to use") + // ; + + // For "Open with ..." + positional_options_description unnamed; + unnamed.add("video", 1); + + // Declare an options description instance which will include + // all the options + options_description all("Allowed options"); + all.add(general).add(gui); + + // Declare an options description instance which will be shown + // to the user + options_description visible("Allowed options"); + visible.add(general).add(gui); + + variables_map vm; + store(command_line_parser(ac, av) + .options(all) + .positional(unnamed) + .run(), + vm); + + if (vm.count("help")) { + std::cout << visible; + exit(0); + } + if (vm.count("usePlugin")) { + auto str = vm["usePlugin"].as(); + cfg->UsePlugins = QString(str.c_str()); + } + if (vm.count("video")) { + auto str = vm["video"].as(); + cfg->LoadVideo = QString(str.c_str()); + } + if (vm.count("cfg")) { + auto str = vm["cfg"].as(); + cfg->CfgCustomLocation = QString(str.c_str()); + } + } catch (std::exception& e) { + std::cout << e.what() << "\n"; + } + } +}; diff --git a/Src/util/Config.cpp b/Src/util/Config.cpp new file mode 100644 index 00000000..3cdbfd31 --- /dev/null +++ b/Src/util/Config.cpp @@ -0,0 +1,163 @@ +#include "Config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const QString Config::DefaultArena = "10,10;10,100;100,100;100,10"; + +template +Stream& operator>>(Stream& s, QString& q) +{ + std::string tmp; + s >> tmp; + q = tmp.data(); + return s; +} + +template +Stream& operator<<(Stream& s, QString const& q) +{ + return s << q.toStdString(); +} + +void workMap(boost::property_tree::basic_ptree* tree, + std::string rep, + std::map* mp) +{ + + auto bakCM = *mp; + mp->clear(); + + for (auto kv : *tree) { + if (boost::starts_with(kv.first, rep)) { + for (auto xx : kv.second) { + std::string snd = tree->get(rep + "." + xx.first); + std::string fst = xx.first; + (*mp)[fst] = snd; + } + } + } + + if (mp->empty()) + *mp = bakCM; +} + +void Config::load(QString dir, QString file) +{ + using namespace boost::property_tree; + + auto tree = ptree{}; + QDir d(dir); + d.mkpath(dir); + QFile fin(dir + "/" + file); + + if (!fin.exists()) { + fin.open(QIODevice::ReadWrite); + fin.close(); + } + + read_ini((dir + "/" + file).toStdString(), tree); + + Config* config = this; + + std::string globalPrefix = "General."; + config->DisableWizard = tree.get(globalPrefix + "DisableWizard", + config->DisableWizard); + config->FrameStride = tree.get(globalPrefix + "FrameStride", + config->FrameStride); + config->RectificationHeight = tree.get( + globalPrefix + "RectificationHeight", + config->RectificationHeight); + config->RectificationWidth = tree.get(globalPrefix + + "RectificationWidth", + config->RectificationWidth); + config->AppertureType = tree.get(globalPrefix + "AppertureType", + config->AppertureType); + config->CsvSeperator = tree.get(globalPrefix + "CsvSeperator", + config->CsvSeperator); + config->CoreConfigFile = tree.get(globalPrefix + "CoreConfigFile", + config->CoreConfigFile); + config->VideoCodecUsed = tree.get(globalPrefix + "VideoCodecUsed", + config->VideoCodecUsed); + config->DropFrames = tree.get(globalPrefix + "DropFrames", + config->DropFrames); + config->RecordScaledOutput = tree.get(globalPrefix + + "RecordScaledOutput", + config->RecordScaledOutput); + config->DataExporter = tree.get(globalPrefix + "DataExporter", + config->DataExporter); + config->RecordFPS = tree.get(globalPrefix + "RecordFPS", + config->RecordFPS); + config->CameraWidth = tree.get(globalPrefix + "CameraWidth", + config->CameraWidth); + config->CameraHeight = tree.get(globalPrefix + "CameraHeight", + config->CameraHeight); + config->GpuQp = tree.get(globalPrefix + "GpuQp", config->GpuQp); + config->DefaultLocationManualSave = tree.get( + globalPrefix + "DefaultLocationManualSave", + config->DefaultLocationManualSave); + config->DirPlugins = tree.get(globalPrefix + "DirPlugins", + config->DirPlugins); + config->DirVideos = tree.get(globalPrefix + "DirVideos", + config->DirVideos); + config->DirTracks = tree.get(globalPrefix + "DirTracks", + config->DirTracks); + config->DirTrials = tree.get(globalPrefix + "DirTrials", + config->DirTrials); + config->DirScreenshots = tree.get(globalPrefix + "DirScreenshots", + config->DirScreenshots); + config->DirTemp = tree.get(globalPrefix + "DirTemp", + config->DirTemp); + config->AreaDefinitions = tree.get(globalPrefix + + "AreaDefinitions", + config->AreaDefinitions); + config->UseRegistryLocations = tree.get(globalPrefix + + "UseRegistryLocations", + config->UseRegistryLocations); +} + +void Config::save(QString dir, QString file) +{ + using namespace boost::property_tree; + + auto tree = ptree{}; + Config* config = this; + + std::string globalPrefix = "General."; + tree.put(globalPrefix + "DisableWizard", config->DisableWizard); + tree.put(globalPrefix + "FrameStride", config->FrameStride); + tree.put(globalPrefix + "RectificationHeight", + config->RectificationHeight); + tree.put(globalPrefix + "RectificationWidth", config->RectificationWidth); + tree.put(globalPrefix + "AppertureType", config->AppertureType); + tree.put(globalPrefix + "CsvSeperator", config->CsvSeperator); + tree.put(globalPrefix + "CoreConfigFile", config->CoreConfigFile); + tree.put(globalPrefix + "VideoCodecUsed", config->VideoCodecUsed); + tree.put(globalPrefix + "DropFrames", config->DropFrames); + tree.put(globalPrefix + "RecordScaledOutput", config->RecordScaledOutput); + tree.put(globalPrefix + "DataExporter", config->DataExporter); + tree.put(globalPrefix + "RecordFPS", config->RecordFPS); + tree.put(globalPrefix + "CameraWidth", config->CameraWidth); + tree.put(globalPrefix + "CameraHeight", config->CameraHeight); + tree.put(globalPrefix + "GpuQp", config->GpuQp); + tree.put(globalPrefix + "DefaultLocationManualSave", + config->DefaultLocationManualSave); + tree.put(globalPrefix + "DirPlugins", config->DirPlugins); + tree.put(globalPrefix + "DirVideos", config->DirVideos); + tree.put(globalPrefix + "DirTracks", config->DirTracks); + tree.put(globalPrefix + "DirTrials", config->DirTrials); + tree.put(globalPrefix + "DirScreenshots", config->DirScreenshots); + tree.put(globalPrefix + "DirTemp", config->DirTemp); + tree.put(globalPrefix + "AreaDefinitions", config->AreaDefinitions); + tree.put(globalPrefix + "UseRegistryLocations", + config->UseRegistryLocations); + + write_ini((dir + "/" + file).toStdString(), tree); +} diff --git a/Src/util/Config.h b/Src/util/Config.h new file mode 100644 index 00000000..c48b1889 --- /dev/null +++ b/Src/util/Config.h @@ -0,0 +1,44 @@ +#pragma once + +#include "Utility/IConfig.h" +#include +#include + +class Config : public IConfig +{ +public: + int DisableWizard = 0; + int FrameStride = 1; + double RectificationHeight = 100; + double RectificationWidth = 100; + int AppertureType = 0; + QString CsvSeperator = ";"; + QString CoreConfigFile = "BiotrackerCore.ini"; + int VideoCodecUsed = 0; + int DropFrames = 0; + int RecordScaledOutput = 0; + int DataExporter = 0; + int RecordFPS = -1; + int CameraWidth = -1; + int CameraHeight = -1; + double GpuQp = 20; + int UseRegistryLocations = true; + QString DefaultLocationManualSave = ""; + QString DirPlugins = IConfig::dataLocation + "/Plugins/"; + QString DirVideos = IConfig::dataLocation + "/Videos/"; + QString DirTracks = IConfig::dataLocation + "/Tracks/"; + QString DirTrials = IConfig::dataLocation + "/Tracks/Trials/"; + QString DirScreenshots = IConfig::dataLocation + "/Screenshots/"; + QString DirTemp = IConfig::dataLocation + "/temp/"; + QString AreaDefinitions = IConfig::configLocation + "/areas.csv"; + + // Temporary CLI configuration + QString LoadVideo = ""; + QString UsePlugins = ""; + QString CfgCustomLocation = ""; + + void load(QString dir, QString file = "config.ini") override; + void save(QString dir, QString file) override; + + static const QString DefaultArena; +}; diff --git a/Src/util/Exceptions.h b/Src/util/Exceptions.h new file mode 100644 index 00000000..48bc845b --- /dev/null +++ b/Src/util/Exceptions.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace BioTracker +{ + namespace Core + { + + struct video_open_error : std::invalid_argument + { + using std::invalid_argument::invalid_argument; + }; + + struct file_not_found : std::invalid_argument + { + using std::invalid_argument::invalid_argument; + }; + + struct directory_not_found : std::invalid_argument + { + using std::invalid_argument::invalid_argument; + }; + + struct device_open_error : std::invalid_argument + { + using std::invalid_argument::invalid_argument; + }; + + struct invalid_tracker_lib_error : std::invalid_argument + { + using std::invalid_argument::invalid_argument; + }; + + struct path_creation_error : std::runtime_error + { + using std::runtime_error::runtime_error; + }; + + } +} diff --git a/Src/util/Messages.h b/Src/util/Messages.h new file mode 100644 index 00000000..e0abbfc9 --- /dev/null +++ b/Src/util/Messages.h @@ -0,0 +1,40 @@ +#pragma once + +namespace BioTracker +{ + namespace Core + { + + namespace Messages + { + namespace System + { + + static const std::string APPLICATION_CANNOT_START = + "Application cannot start"; + static const std::string NO_OPENGL = + "This system has no OpenGL support!"; + static const std::string MISSING_CONFIGURATION_FILE = + "Configuration file is missing! Using default parameters."; + + } + + enum class MessageType : size_t + { + NOTIFICATION = 0, + WARNING, + FAIL, + FILE_OPEN + }; + + inline MessageType fromInt(const size_t v) + { + return static_cast(v); + } + + } + + using Messages::MessageType; + + } +} diff --git a/Src/util/PanZoomState.h b/Src/util/PanZoomState.h new file mode 100644 index 00000000..24da99f3 --- /dev/null +++ b/Src/util/PanZoomState.h @@ -0,0 +1,39 @@ +#pragma once + +#include "boost/optional.hpp" +#include + +namespace BioTracker +{ + namespace Core + { + + /** + * @brief Used to store mouse cursor offsets while panning. + */ + struct CurrentPanState + { + QPointF lastPos; + + CurrentPanState(const QPointF lastPos) + : lastPos(lastPos) + { + } + }; + + /** + * @brief Stores the current zoom and pan offsets. While panning, + * panState stores the last mouse cursor position. + */ + struct PanZoomState + { + float zoomFactor = 0.f; + float panX = 0.f; + float panY = 0.f; + bool isChanged = false; + + boost::optional panState; + }; + + } +} diff --git a/Src/util/ParamNames.h b/Src/util/ParamNames.h new file mode 100644 index 00000000..529a4511 --- /dev/null +++ b/Src/util/ParamNames.h @@ -0,0 +1,105 @@ +#pragma once + +#include // std::string + +#include + +#include +#include + +namespace ConfigParam +{ + static const boost::filesystem::path CONFIG_PATH = boost::filesystem::path( + QDir::toNativeSeparators( + QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)) + .toStdString()); + static const boost::filesystem::path BASE_PATH = CONFIG_PATH / + "BioTracker"; + static const boost::filesystem::path CONFIGURATION_FILE = BASE_PATH / + "config.json"; + static const boost::filesystem::path GEOMETRY_FILE = BASE_PATH / + "geometry.cfg"; + static const boost::filesystem::path STATE_FILE = BASE_PATH / "state.cfg"; + static const boost::filesystem::path MODULE_PATH = BASE_PATH / "modules"; +} + +namespace TrackerParam +{ + static const std::string TRACKING_ENABLED = + "TRACKERPARAM.TRACKING_ENABLED"; + + static const std::string SELECTED_TRACKER = + "TRACKERPARAM.SELECTED_TRACKER"; +} + +namespace GuiParam +{ + enum class MediaType : uint8_t + { + NoMedia = 0, + Video, + Images, + Camera + }; + + enum class VideoMode : uint8_t + { + Playing = 0, + Paused, + Stopped, + Init + }; + + static const std::string MEDIA_TYPE = "GUIPARAM.MEDIA_TYPE"; + static const std::string SHORTCUT_PLAY = "GUIPARAM.SHORTCUT_PLAY"; + static const std::string SHORTCUT_NEXT = "GUIPARAM.SHORTCUT_NEXT"; + static const std::string SHORTCUT_PREV = "GUIPARAM.SHORTCUT_PREV"; + static const std::string SHORTCUT_ZOOM = "GUIPARAM.SHORTCUT_ZOOM"; + static const std::string SHORTCUT_TRACKING = "GUIPARAM.SHORTCUT_TRACKING"; + + static const std::string PAUSED_AT_FRAME = "GUIPARAM.PAUSED_AT_FRAME"; +} + +namespace PictureParam +{ + // path to picture + static const std::string PICTURE_FILES = "PICTUREPARAM.PICTURE_FILES"; +} + +namespace CaptureParam +{ + // Video path + static const std::string CAP_VIDEO_FILE = "CAPTUREPARAM.CAP_VIDEO_FILE"; + static const std::string CAP_SCREENSHOT_PATH = + "CAPTUREPARAM.CAP_SCREENSHOT_PATH"; + static const std::string CAP_CAMERA_ID = "CAPTUREPARAM.CAP_CAMERA_ID"; + + // Video paths + static const std::string ENABLE_RECORD_RAW = + "CAPTUREPARAM.ENABLE_RECORD_RAW"; + static const std::string ENABLE_RECORD_TRACKING = + "CAPTUREPARAM.ENABLE_RECORD_TRACKING"; + static const std::string ENABLE_RECORD_TRACK_INFO = + "CAPTUREPARAM.ENABLE_RECORD_TRACK_INFO"; + + static const std::string RECORDING_TRACKING_PATH = + "CAPTUREPARAM.RECORDING_TRACKING_PATH"; + static const std::string RECORDING_RAW_PATH = + "CAPTUREPARAM.RECORDING_RAW_PATH"; + static const std::string TRACKING_INFO_OUTPUT_PATH = + "CAPTUREPARAM.TRACKING_INFO_OUTPUT_PATH"; + + enum CAP_TYPE_ENUM + { + CAP_FROM_CAM = 0, + CAP_FROM_FILE = 1 + }; + + enum CAP_STATE_ENUM + { + CAP_FINISHED = 0, + CAP_PAUSE = 1, + CAP_AVAILABLE = 2, + CAP_EXITED = 3 + }; +} diff --git a/Src/util/ScreenHelper.h b/Src/util/ScreenHelper.h new file mode 100644 index 00000000..a9050c27 --- /dev/null +++ b/Src/util/ScreenHelper.h @@ -0,0 +1,233 @@ +#pragma once + +#include // QRect +#include // QPoint +#include "PanZoomState.h" +#include "math.h" + +/** + * Screen helper functions + */ +namespace BioTracker +{ + namespace Core + { + namespace ScreenHelper + { + + /** + * @brief calculate_viewport + * @param im_w width of the image + * @param im_h height of the image + * @param w width of the videoview + * @param h height of the videoview + * @param window OUT parameter + * @param viewport OUT parameter + */ + inline float calculate_viewport(const int im_w, + const int im_h, + const int w, + const int h, + QRect& window, + QRect& viewport) + { + + // We use setWindow and setViewport to fit the video into the + // given video widget frame (with width "w" and height "h") + // we later need to adjust an offset caused the use of + // different dimensions for window and viewport. + const float im_wf = static_cast(im_w); + const float im_hf = static_cast(im_h); + const float w_f = static_cast(w); + const float h_f = static_cast(h); + + float ratio = 0; + int offset_top = 0; + int offset_left = 0; + + if ((im_wf / im_hf) > (w_f / h_f)) { + // image ratio is bigger (wider image than window) + ratio = im_wf / w_f; + const float px = w_f / im_wf; + const float px_im_hf = px * im_hf; + offset_top = h / 2 - static_cast(px_im_hf / 2); + } else { + // window ratio is bigger (narrow image) + ratio = im_hf / h_f; + const float px = h_f / im_hf; + const float px_im_wf = px * im_wf; + offset_left = w / 2 - static_cast(px_im_wf / 2); + } + + const int screen_w = static_cast(im_wf * ratio); + const int screen_h = static_cast(im_hf * ratio); + + window.setX(0); + window.setY(0); + window.setWidth(screen_w); + window.setHeight(screen_h); + + viewport.setX(offset_left); + viewport.setY(offset_top); + viewport.setWidth(im_w); + viewport.setHeight(im_h); + + // adjust the panning as the viewport is potentially scewed + // and mouse movements given by the window are not translated + // one-to-one anymore + return screen_w / im_wf; + } + + /** + * @brief getImDimsInScreenCoords + * Calculates the actual dimension of the image with all zoom, pan + * and viewport transformations applied + * @return a rectangle that represents the position and dimension + * of the image in the videoview element + */ + inline QRect getImDimsInScreenCoords(const PanZoomState zoomState, + const int im_w, + const int im_h, + const int w, + const int h) + { + + QRect viewport, window; + const float viewportRatio = + calculate_viewport(im_w, im_h, w, h, window, viewport); + const float zoom = 1 + zoomState.zoomFactor; + // back-translate the pan to non-zoomed coordinate space + float realPanX = -zoomState.panX; + float realPanY = -zoomState.panY; + realPanX += (viewport.x()); + realPanY += (viewport.y()); + + // The image in screen coords + QRect actualIm( + static_cast(realPanX), + static_cast(realPanY), + static_cast((im_w / viewportRatio) * zoom), + static_cast((im_h / viewportRatio) * zoom)); + return actualIm; + } + + /** + * @brief imageToScreenCoords + */ + inline QPoint imageToScreenCoords(const PanZoomState zoomState, + const int im_w, + const int im_h, + const int w, + const int h, + const QPoint poi) + { + QPoint result; + const QRect actualIm = + getImDimsInScreenCoords(zoomState, im_w, im_h, w, h); + const float one_step_x = actualIm.width() / + static_cast(im_w); + const float one_step_y = actualIm.height() / + static_cast(im_h); + const int actualPosXInIm = static_cast( + round(poi.x() * one_step_x)); + const int actualPosYInIm = static_cast( + round(poi.y() * one_step_y)); + result.setX(actualPosXInIm + actualIm.x()); + result.setY(actualPosYInIm + actualIm.y()); + return result; + } + + /** + * @brief screenToImageCoords + * Translate the window coordinates to the actual image coords + * @param im_w image width + * @param im_h image height + * @param w width of the videoview + * @param h height of the videoview + * @param poi Point in Screen Coords + */ + inline QPoint screenToImageCoords( + const BioTracker::Core::PanZoomState zoomState, + const int im_w, + const int im_h, + const int w, + const int h, + QPoint poi) + { + QPoint result(0, 0); + + // The image in screen coords + QRect actualIm = + getImDimsInScreenCoords(zoomState, im_w, im_h, w, h); + + const float im_wf = static_cast(im_w); + const float im_hf = static_cast(im_h); + const float one_step_x = im_wf / actualIm.width(); + const float one_step_y = im_hf / actualIm.height(); + + const float transformedX = (-actualIm.x() + poi.x()) * + one_step_x; + const float transformedY = (-actualIm.y() + poi.y()) * + one_step_y; + + result.setX(static_cast(round(transformedX))); + result.setY(static_cast(round(transformedY))); + + return result; + } + + /** + * @brief zoomTo + * Modifies the panzoomstate so that the cursor (zoomCenter) will + * point to the same location in the image as prior to the zoom + * @param im_w width of the image (in px) + * @param im_h height of the image (in px) + * @param w width of the videoview element + * @param h height of the videoview element + */ + inline PanZoomState zoomTo(PanZoomState state, + const int im_w, + const int im_h, + const int w, + const int h, + const float deltaZoom, + const QPoint zoomCenter) + { + + const QPoint imPos = + screenToImageCoords(state, im_w, im_h, w, h, zoomCenter); + + const float oldZoomFactor = state.zoomFactor; + const float newZoomFactor = state.zoomFactor - + (deltaZoom / 2000); + + if (newZoomFactor <= -1.0f) { + // MAX VALUE + return state; + } + + const float zoom = 1 + newZoomFactor; + + const float oldPanX = state.panX / (1 + oldZoomFactor); + const float oldPanY = state.panY / (1 + oldZoomFactor); + + // zoom with origin in (0/0) + state.panX = oldPanX * zoom; + state.panY = oldPanY * zoom; + state.zoomFactor = newZoomFactor; + + // As we do not want to zoom to (0/0) but rather keep the focus + // on the chosen image position (zoomCenter) we now have to + // "back-translate" to our initial position + const QPoint translatedZoomCenter = + imageToScreenCoords(state, im_w, im_h, w, h, imPos); + const QPoint translate = translatedZoomCenter - zoomCenter; + state.panX += translate.x(); + state.panY += translate.y(); + state.isChanged = true; + return state; + } + + } + } +} diff --git a/Src/util/VideoCoder.cpp b/Src/util/VideoCoder.cpp new file mode 100644 index 00000000..69f8c68d --- /dev/null +++ b/Src/util/VideoCoder.cpp @@ -0,0 +1,276 @@ +#include "VideoCoder.h" +#include +#include + +#ifdef _WIN32 + #include + #include +#endif + +using namespace BioTrackerUtilsMisc; // getTimeAndDate + +#define mySleep(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)); + +void MutexLinkedList::push(std::shared_ptr imbuffer, + bool dropFrames) +{ + + if (dropFrames) { + while (images.size() > MAXIMUMQUEUE) + pop(); + } else { + while (images.size() > MAXIMUMQUEUE) + mySleep(10); + } + + _Access.lock(); + + images.push_back(imbuffer); + unsigned long s = static_cast(images.size()); + unsigned long w = imbuffer->getWidth(); + unsigned long h = imbuffer->getHeight(); + // if (s*w*h / 1024 / 1024 > BUFFER_HARDLIMIT) { + // std::cout << "ERROR: Buffer exceeds hardlimit (" << BUFFER_HARDLIMIT << + //" MB). Exiting. " << std::endl; std::exit(1); + //} + _Access.unlock(); +} + +std::shared_ptr MutexLinkedList::pop() +{ + _Access.lock(); + if (images.size() > 0) { + std::shared_ptr img = images.front(); + images.pop_front(); + _Access.unlock(); + return img; + } + _Access.unlock(); + + return std::make_shared(); +} + +void MutexLinkedList::MutexLinkedList::clear() +{ + _Access.lock(); + while (images.size() > 0) { + images.pop_front(); + } + _Access.unlock(); +} + +// Simple function to get the current size of the buffer in elements. +// Locks the data structure. +int MutexLinkedList::size() +{ + int tsize = 0; + _Access.lock(); + tsize = static_cast(images.size()); + _Access.unlock(); + return tsize; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +void YuvConverter::convert() +{ + int w = inImg.size().width; + int h = inImg.size().height; + unsigned char* prtM = inImg.data; + unsigned int stride = 1; + // Y + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + // This works but is horribly slow! + // out0[y * w + x] = inImg.at(y, x)[0]; + // out1[y * w + x] = inImg.at(y, x)[1]; + // out2[y * w + x] = inImg.at(y, x)[2]; + // This works and is quite a bunch faster + out0[y * w + x] = (uint8_t)(*prtM); + prtM++; + out1[y * w + x] = (uint8_t)(*prtM); + prtM++; + out2[y * w + x] = (uint8_t)(*prtM); + prtM++; + } + } +} + +void YuvConverter::convert420() +{ + int w = inImg.size().width; + int h = inImg.size().height; + unsigned char* prtM = inImg.data; + unsigned int stride = 1; + // Y + int x, y; + for (y = 0; y < (h / 3 * 2); y++) { + for (x = 0; x < w; x++) { + unsigned char ch = (uint8_t)(*prtM); + out0[y * w + x] = ch; + prtM++; + } + } + + for (y = 0; y < (h / 3 * 1); y++) { + for (x = 0; x < w / 2; x++) { + out2[y * w + x] = (uint8_t)(*prtM); + prtM++; + out1[y * w + x] = (uint8_t)(*prtM); + prtM++; + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +void Worker::run() +{ + +#ifdef WITH_CUDA + if (m_nvEncoder) { + unsigned char* o0 = m_nvEncoder->getYuvChannel(0); + unsigned char* o1 = m_nvEncoder->getYuvChannel(1); + unsigned char* o2 = m_nvEncoder->getYuvChannel(2); + std::shared_ptr mat; + while (1) { + while ((mat = ll.pop())->getWidth() == -1) { + mySleep(10); + if (m_abort) + return; + } + if (m_abort) + return; + + cv::Mat writeMat; + cv::cvtColor(*(mat->_img), + writeMat, + CV_BGR2YUV_I420); // CV_BGR2YUV_I420 //CV_BGR2YUV + int chans = writeMat.channels(); + YuvConverter yc(writeMat, o0, o1, o2); + yc.convert420(); + m_nvEncoder->encodeNext(); + } + } else +#endif + { + std::shared_ptr mat; + while (1) { + while ((mat = ll.pop())->getWidth() == -1) { + mySleep(10); + if (m_abort) + return; + } + if (m_abort) + return; + + m_vWriter->write(*mat->_img); + } + } +} + +int VideoCoder::toggle(int w, int h, double fps) +{ + + // Grab the codec from config file + std::string codecStr = codecList[_cfg->VideoCodecUsed].second; + std::string videoDir = _cfg->DirVideos.toStdString(); + m_dropFrames = _cfg->DropFrames; + m_qp = _cfg->GpuQp; + if (fps == -1) { + fps = m_fps; + } + + if (!m_recording) { + worker = std::make_shared(); + + // Check which one to use + if (codecStr == "X264") { + int codec = cv::VideoWriter::fourcc('X', 'V', 'I', 'D'); + vWriter = std::make_shared( + getTimeAndDate(videoDir + "CameraCapture", ".avi"), + codec, + fps, + cv::Size(w, h), + 1); + m_recording = vWriter->isOpened(); + vWriter->set(cv::VIDEOWRITER_PROP_QUALITY, 100); + std::cout << "Video is open:" << m_recording << std::endl; + m_recType = 2; + int ok = start(); + m_recording = (ok == 1 ? false : true); + } else if (codecStr == "X264GPU") { +#ifdef WITH_CUDA + auto cfg = m_nvEncoder->getEncodeConfig(); + cfg->fps = fps; + cfg->width = w; + cfg->height = h; + cfg->codec = NV_ENC_H264; + cfg->inputFormat = + NV_ENC_BUFFER_FORMAT_NV12; // NV_ENC_BUFFER_FORMAT_NV12;//NV_ENC_BUFFER_FORMAT_YUV444 + const std::string f = getTimeAndDate(std::string(CFG_DIR_VIDEOS) + + "CameraCapture", + ".avi"); + char* chr = strdup(f.c_str()); + m_nvEncoder->setOutfile(chr); + cfg->qp = m_qp; + m_recType = 1; + int ok = start(); + free(chr); + m_recording = (ok == 1 ? false : true); + std::cout << "Video is open:" << m_recording << std::endl; +#endif + } + } else { + m_recording = false; + if (m_recType == 1) + stop(); + if (m_recType == 2) + stop(); // vWriter->release(); + vWriter = 0; + } + if (!m_recording) + m_recType = 0; + return m_recording; +} + +void VideoCoder::add(cv::Mat m, int needsConversion) +{ + worker->ll.push(std::make_shared(m, needsConversion), + m_dropFrames); +} + +int VideoCoder::start() +{ +#ifdef WITH_CUDA + if (m_recType == 1) { + int ok = m_nvEncoder->init(); + if (ok > 0) + return ok; + worker->m_nvEncoder = m_nvEncoder; + worker->start(); + } else +#endif + if (m_recType == 2) { + worker->m_vWriter = vWriter; + worker->start(); + } + + return 0; +} + +void VideoCoder::stop() +{ + if (m_recType > 0) { + worker->m_abort = true; + worker->wait(); +#ifdef WITH_CUDA + if (m_nvEncoder) + m_nvEncoder->close(); +#endif + if (vWriter) + vWriter->release(); + worker->ll.clear(); + } +} diff --git a/Src/util/VideoCoder.h b/Src/util/VideoCoder.h new file mode 100644 index 00000000..75700893 --- /dev/null +++ b/Src/util/VideoCoder.h @@ -0,0 +1,164 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "Utility/misc.h" +#ifdef WITH_CUDA + #include "EncoderInterface.h" +#endif + +#include "types.h" +#include "Config.h" + +#define MAXIMUMQUEUE 30 + +class YuvConverter +{ +private: + cv::Mat& inImg; + unsigned char* out0; + unsigned char* out1; + unsigned char* out2; + +public: + YuvConverter(cv::Mat& inputImgage, + unsigned char* o0, + unsigned char* o1, + unsigned char* o2) + : inImg(inputImgage) + , out0(o0) + , out1(o1) + , out2(o2) + { + } + void convert(); + void convert420(); +}; + +class ImageBuffer +{ +public: + std::optional _img; + int _needsConversion; + + ImageBuffer(cv::Mat img, int ncv) + : _img(img) + , _needsConversion(ncv) + { + } + ImageBuffer() + { + } + + int getWidth() + { + if (_img) + return _img->size().width; + return -1; + } + + int getHeight() + { + if (_img) + return _img->size().height; + return -1; + } +}; + +class MutexLinkedList +{ +public: + std::list> images; + std::mutex _Access; + + void push(std::shared_ptr imbuffer, bool dropFrames = false); + + std::shared_ptr pop(); + + void clear(); + + // Simple function to get the current size of the buffer in elements. + // Locks the data structure. + virtual int size(); + + MutexLinkedList() + { + } + ~MutexLinkedList() + { + } +}; + +class Worker : public QThread +{ + Q_OBJECT + +public: + MutexLinkedList ll; + bool m_abort; +#ifdef WITH_CUDA + std::shared_ptr m_nvEncoder; +#endif + std::shared_ptr m_vWriter; + + Worker() + { + m_abort = false; + }; + void run(); + +public slots: + + // void doWork(const QString ¶meter); +}; + +class VideoCoder : public QObject +{ + Q_OBJECT + +public: + VideoCoder(double fps, Config* cfg) + { +#ifdef WITH_CUDA + m_nvEncoder = std::make_shared(); +#endif + m_recType = 0; + m_recording = false; + m_dropFrames = false; + m_fps = fps; + _cfg = cfg; + } + + ~VideoCoder() + { + stop(); + } + + int toggle(int w, int h, double fps = -1); + + void add(cv::Mat m, int needsConversion = 0); + + int start(); + void stop(); +#ifdef WITH_CUDA + std::shared_ptr m_nvEncoder; +#endif + +private: + std::shared_ptr worker; + std::shared_ptr vWriter; + int m_recType; + int m_recording; + bool m_dropFrames; + int m_qp; + double m_fps; + Config* _cfg; +signals: + void operate(const QString&); +}; diff --git a/Src/util/camera/base.h b/Src/util/camera/base.h new file mode 100644 index 00000000..31cfa079 --- /dev/null +++ b/Src/util/camera/base.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include + +enum class CameraType +{ + OpenCV, +#if HAS_PYLON + Pylon, +#endif +}; + +struct CameraSelector +{ + CameraType type; + int index; + std::string name; +}; + +Q_DECLARE_METATYPE(CameraSelector); + +class CameraConfiguration +{ +public: + CameraConfiguration() + : _selector{CameraType::OpenCV, 0} + , _width(-1) + , _height(-1) + , _fps(30) + , _recordInput(false) + , _fourcc("X264") + { + } + CameraConfiguration(CameraSelector p_selector, + int p_width, + int p_height, + double p_fps, + bool p_recordInput, + std::string p_fourcc) + : _selector(p_selector) + , _width(p_width) + , _height(p_height) + , _fps(p_fps) + , _recordInput(p_recordInput) + , _fourcc(p_fourcc) + { + } + + CameraSelector _selector; + int _width; + int _height; + bool _recordInput; + double _fps; + std::string _fourcc; +}; diff --git a/Src/util/camera/pylon.cpp b/Src/util/camera/pylon.cpp new file mode 100644 index 00000000..a2d0c0c8 --- /dev/null +++ b/Src/util/camera/pylon.cpp @@ -0,0 +1,39 @@ +#include "util/camera/pylon.h" + +#if HAS_PYLON + + #include + +Pylon::IPylonDevice* getPylonDevice(int index) +{ + Pylon::PylonAutoInitTerm pylon; + auto& factory = Pylon::CTlFactory::GetInstance(); + Pylon::DeviceInfoList_t devices; + factory.EnumerateDevices(devices); + if (0 <= index && index < devices.size()) + return factory.CreateDevice(devices[index]); + throw std::out_of_range("No such Pylon camera available"); +} + +cv::Mat toOpenCV(Pylon::CGrabResultPtr image) +{ + auto size = cv::Size{static_cast(image->GetWidth()), + static_cast(image->GetHeight())}; + auto data = image->GetBuffer(); + + switch (image->GetPixelType()) { + case Pylon::PixelType_Mono8: { + auto mat = cv::Mat{size, CV_8UC1, data}; + cv::cvtColor(mat, mat, cv::COLOR_GRAY2BGR); + return mat; + } + case Pylon::PixelType_BayerBG8: { + auto mat = cv::Mat{size, CV_8UC1, data}; + cv::cvtColor(mat, mat, cv::COLOR_BayerBG2BGR_EA); + return mat; + } + default: + throw std::logic_error("Pixel type support not implemented"); + } +} +#endif diff --git a/Src/util/camera/pylon.h b/Src/util/camera/pylon.h new file mode 100644 index 00000000..fc9b364b --- /dev/null +++ b/Src/util/camera/pylon.h @@ -0,0 +1,13 @@ +#pragma once + +#if HAS_PYLON + + #include "util/camera/base.h" + + #include + #include + +Pylon::IPylonDevice* getPylonDevice(int index); +cv::Mat toOpenCV(Pylon::CGrabResultPtr image); + +#endif diff --git a/Src/util/stdext.h b/Src/util/stdext.h new file mode 100644 index 00000000..38b2114a --- /dev/null +++ b/Src/util/stdext.h @@ -0,0 +1,54 @@ +#ifndef STDEXT_H +#define STDEXT_H + +/* implementation of std::make_unique for c++<14 + * implementation according to N3656 + * see: http://isocpp.org/files/papers/N3656.txt + */ + +#include +#if (!defined(_MSC_VER) && __cplusplus <= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER < 1800) + #include + #include + #include + +namespace std +{ + template + struct _Unique_if + { + typedef unique_ptr _Single_object; + }; + + template + struct _Unique_if + { + typedef unique_ptr _Unknown_bound; + }; + + template + struct _Unique_if + { + typedef void _Known_bound; + }; + + template + typename _Unique_if::_Single_object make_unique(Args&&... args) + { + return unique_ptr(new T(std::forward(args)...)); + } + + template + typename _Unique_if::_Unknown_bound make_unique(size_t n) + { + typedef typename remove_extent::type U; + return unique_ptr(new U[n]()); + } + + template + typename _Unique_if::_Known_bound make_unique(Args&&...) = delete; +} +#endif + +#endif diff --git a/Src/util/types.h b/Src/util/types.h new file mode 100644 index 00000000..0fd514fd --- /dev/null +++ b/Src/util/types.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +namespace BiotrackerTypes +{ + enum AreaType + { + NONE = -1, + RECT = 0, + APPERTURE = 1, + COMBINED = 2 + }; + +} + +namespace AREADESCRIPTOR +{ + const std::string CN_ARENA = "TRACKERPARAM/CN_CORNERS_ARENA"; + const std::string CN_APPERTURE = "TRACKERPARAM/CN_CORNERS_APPERTURE"; + const std::string CN_APPERTURE_TYPE = + "TRACKERPARAM/CN_CORNERS_APPERTURE_TYPE"; + const std::string DISP_AREA = "TRACKERPARAM/DISPLAY_TRACKING_AREA"; + const std::string DISP_RECT = "TRACKERPARAM/DISPLAY_RECTIFICATION_AREA"; + const std::string RECT_W = "RECTIFICATION/WIDTH"; + const int RECT_W_DEFAULT = 100; + const std::string RECT_H = "RECTIFICATION/HEIGHT"; + const int RECT_H_DEFAULT = 100; +} + +const std::vector> codecList = { + std::pair("X264 (CPU)", "X264"), +#ifdef WITH_CUDA + std::pair("X264 (GPU)", "X264GPU") +#endif +}; + +const std::vector exporterList = {std::string("CSV"), + std::string("Serialize"), + std::string("Json")}; diff --git a/ci/compile.py b/ci/compile.py new file mode 100755 index 00000000..bf791920 --- /dev/null +++ b/ci/compile.py @@ -0,0 +1,7 @@ +#! /usr/bin/env python3 + +from subprocess import check_call + +if __name__ == "__main__": + command = ["ninja", "-C", "build"] + check_call(command) diff --git a/ci/configure.py b/ci/configure.py new file mode 100755 index 00000000..3b0ed7e3 --- /dev/null +++ b/ci/configure.py @@ -0,0 +1,90 @@ +#! /usr/bin/env python3 + +from ast import literal_eval +from os import environ as env, pathsep +from subprocess import check_call +from pathlib import Path +from platform import system + + +def define(key: str, value: str): + return ["-D", f"{key}={value}"] + + +def define_env(name: str): + return define(name, env[name]) if name in env else [] + + + +if __name__ == "__main__": + if system() == "Windows": + env["PATH"] += f"{pathsep}{env['VCPKG_INSTALL_DIR']}/bin" + for path in Path("vendor").glob("*/bin"): + env["PATH"] += f"{pathsep}{path}" + + shared_libraries = [ + "zlib1", + "tiff", + "jpeg62", + "libpng16", + "webp", + "lzma", + "openblas", + "avformat-58", + "avcodec-58", + "avutil-56", + "swscale-5", + "swresample-3", + "pcre2-16", + "zstd", + "harfbuzz", + "freetype", + "brotlidec", + "bz2", + "brotlicommon", + ] + + opencv_components = [ + "core", + "calib3d", + "features2d", + "flann", + "highgui", + "imgcodecs", + "imgproc", + "ml", + "objdetect", + "photo", + "shape", + "stitching", + "superres", + "video", + "videoio", + "videostab", + ] + + command = ["cmake"] + command += ["-S", "."] + command += ["-B", "build"] + command += ["-G", "Ninja"] + command += define("CMAKE_PREFIX_PATH", Path("vendor").resolve()) + command += define_env("CMAKE_BUILD_TYPE") + command += define_env("CMAKE_TOOLCHAIN_FILE") + command += define("CMAKE_SUPPRESS_REGENERATION", "ON") + command += define("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY", "ON") + command += define_env("VCPKG_TARGET_TRIPLET") + + command += define("Boost_USE_STATIC_LIBS", "ON") + + if system() == "Windows": + command += define("PACKAGE_MSI", "ON") + command += define("INSTALL_SYSTEM_LIBRARIES", "ON") + command += define("INSTALL_SHARED_LIBRARIES", ";".join(shared_libraries),) + command += define("INSTALL_OPENCV_COMPONENTS", ";".join(opencv_components),) + + elif system() == "Linux": + command += define("PACKAGE_APPIMAGE", "ON") + else: + assert False + + check_call(command) diff --git a/ci/package.py b/ci/package.py new file mode 100755 index 00000000..9c151b01 --- /dev/null +++ b/ci/package.py @@ -0,0 +1,15 @@ +#! /usr/bin/env python3 + +from os import environ as env, pathsep +from subprocess import check_call +from pathlib import Path +from platform import system + +if __name__ == "__main__": + if system() == "Linux": + for path in Path("vendor").glob("*/bin"): + env["PATH"] += f"{pathsep}{path}" + env['PATH'] += f"{pathsep}{env['Qt5_DIR']}/../../../bin/" + + command = ["ninja", "-C", "build", "package"] + check_call(command) diff --git a/ci/prepare.py b/ci/prepare.py new file mode 100755 index 00000000..0d97cd75 --- /dev/null +++ b/ci/prepare.py @@ -0,0 +1,62 @@ +#! /usr/bin/env python3 + +import tarfile +import shutil +import ssl + +from os import environ as env, symlink +from platform import system +from io import BytesIO +from urllib.request import Request, urlopen +from urllib.parse import quote, urlencode +from zipfile import ZipFile +from pathlib import Path + + +def define(key: str, value: str): + return ["-D", f"{key}={value}"] + + +def define_env(name: str): + return define(name, env[name]) if name in env else [] + + +def fetch_artifacts(project, reference, job): + gitlab_host = "https://git.imp.fu-berlin.de" + project = quote(project, safe="") + reference = quote(reference, safe="") + params = urlencode([("job", job)], doseq=True) + url = f"{gitlab_host}/api/v4/projects/{project}/jobs/artifacts/{reference}/download?{params}" + headers = {"JOB-TOKEN": env["CI_JOB_TOKEN"]} + return ZipFile( + BytesIO( + urlopen( + Request(url, headers=headers), context=ssl._create_unverified_context() + ).read() + ) + ) + + +def extract_cmake_package(artifacts, name): + for filename in artifacts.namelist(): + if Path(filename).match(f"{name}-*.tar.xz"): + with tarfile.open(fileobj=BytesIO(artifacts.read(filename))) as f: + f.extractall("vendor") + shutil.move(next(Path("vendor").glob(f"{name}-*/")), f"vendor/{name}") + + +if __name__ == "__main__": + if system() == "Windows": + job_stem = "package: [windows]" + elif system() == "Linux": + job_stem = "package: [centos]" + else: + assert False + + for name, project, job in [ + ("biotracker-interfaces", "bioroboticslab/biotracker/interfaces", job_stem), + ("biotracker-utility", "bioroboticslab/biotracker/utility", job_stem), + ("robofish-behavior_loader", "bioroboticslab/biotracker/behavior_loader", job_stem), + ]: + with fetch_artifacts(project, "master", job) as artifacts: + extract_cmake_package(artifacts, name)