From 15f9678bae801fdc3e70b531bebe719616e675f3 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Wed, 3 Mar 2021 14:16:49 +0100 Subject: [PATCH 01/22] [ci] update --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4f82377..cacdb51 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,26 +37,26 @@ stages: script: - ./ci/package.py -build centos: +"build: [centos]": extends: .centos <<: *build variables: <<: [*release] -build windows: +"build: [windows]": extends: .windows <<: *build variables: <<: [*release] -package centos: +"package: [centos]": extends: .centos dependencies: - - build centos + - "build: [centos]" <<: *package -package windows: +"package: [windows]": extends: .windows dependencies: - - build windows + - "build: [windows]" <<: *package From f5e11f9aba1f71a7b7db7cb056310d0d6510d8fc Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Wed, 3 Mar 2021 14:24:29 +0100 Subject: [PATCH 02/22] [ci] fix update --- ci/prepare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/prepare.py b/ci/prepare.py index da3b9e1..df1f6e4 100755 --- a/ci/prepare.py +++ b/ci/prepare.py @@ -47,9 +47,9 @@ def extract_cmake_package(artifacts, name): if __name__ == "__main__": if system() == "Windows": - job_stem = "package windows" + job_stem = "package: [windows]" elif system() == "Linux": - job_stem = "package centos" + job_stem = "package: [centos]" else: assert False From c2d4f01e0a3d48aacee9a79c1636ea4c8fc7b34d Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 12:13:25 +0100 Subject: [PATCH 03/22] Cleanup --- Src/Config.cpp | 8 +- Src/Config.h | 4 +- Src/Model/BioTrackerTrackingAlgorithm.cpp | 36 +- Src/Model/BioTrackerTrackingAlgorithm.h | 3 - Src/Model/TrackerParameter.cpp | 18 +- Src/Model/TrackerParameter.h | 42 +- Src/Model/TrackingAlgorithm/ParamNames.h | 86 --- .../preprocessor/ImagePreProcessor.cpp | 38 +- .../preprocessor/ImagePreProcessor.h | 8 - Src/View/TrackedElementView.cpp | 1 - Src/View/TrackerParameterView.cpp | 66 +- Src/View/TrackerParameterView.h | 1 - Src/View/TrackerParameterView.ui | 594 +++++++++--------- 13 files changed, 350 insertions(+), 555 deletions(-) delete mode 100644 Src/Model/TrackingAlgorithm/ParamNames.h diff --git a/Src/Config.cpp b/Src/Config.cpp index d06efff..4946b5e 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -56,9 +56,7 @@ void Config::load(QString dir, QString file) config->SizeDilate = tree.get(globalPrefix+"SizeDilate",config->SizeDilate); config->MinBlobSize = tree.get(globalPrefix+"MinBlobSize",config->MinBlobSize); config->MaxBlobSize = tree.get(globalPrefix+"MaxBlobSize",config->MaxBlobSize); - config->Mog2History = tree.get(globalPrefix+"Mog2History",config->Mog2History); - config->Mog2VarThresh = tree.get(globalPrefix+"Mog2VarThresh",config->Mog2VarThresh); - config->Mog2BackgroundRatio = tree.get(globalPrefix+"Mog2BackgroundRatio",config->Mog2BackgroundRatio); + config->BackgroundRatio = tree.get(globalPrefix+"BackgroundRatio",config->BackgroundRatio); config->DoNetwork = tree.get(globalPrefix+"DoNetwork",config->DoNetwork); config->NetworkPort = tree.get(globalPrefix+"NetworkPort",config->NetworkPort); config->DoBackground = tree.get(globalPrefix+"DoBackground",config->DoBackground); @@ -84,9 +82,7 @@ void Config::save(QString dir, QString file) tree.put(globalPrefix+"SizeDilate", config->SizeDilate); tree.put(globalPrefix+"MinBlobSize", config->MinBlobSize); tree.put(globalPrefix+"MaxBlobSize", config->MaxBlobSize); - tree.put(globalPrefix+"Mog2History", config->Mog2History); - tree.put(globalPrefix+"Mog2VarThresh", config->Mog2VarThresh); - tree.put(globalPrefix+"Mog2BackgroundRatio", config->Mog2BackgroundRatio); + tree.put(globalPrefix+"BackgroundRatio", config->BackgroundRatio); tree.put(globalPrefix+"DoNetwork", config->DoNetwork); tree.put(globalPrefix+"NetworkPort", config->NetworkPort); tree.put(globalPrefix+"DoBackground", config->DoBackground); diff --git a/Src/Config.h b/Src/Config.h index 06543ea..db181ca 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -13,9 +13,7 @@ class Config : public IConfig int MinBlobSize = 40; int MaxBlobSize = 999999; - int Mog2History = 200; - int Mog2VarThresh = 64; - double Mog2BackgroundRatio = 0.05; + double BackgroundRatio = 0.05; int DoNetwork = false; int NetworkPort = 54444; diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 7d99a09..36dd076 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -69,35 +69,33 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage(std::mapgetSendImage()) { 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("Background"))->second; + Q_EMIT emitCvMatA(sendImage, QString("Background")); + Q_EMIT emitChangeDisplayImage(QString("Background")); + break; + case 2: + sendImage = images->find(std::string("Foreground"))->second; + Q_EMIT emitCvMatA(sendImage, QString("Foreground")); + Q_EMIT emitChangeDisplayImage(QString("Foreground")); + break; + case 3: sendImage = images->find(std::string("Binarized"))->second; Q_EMIT emitCvMatA(sendImage, QString("Binarized")); Q_EMIT emitChangeDisplayImage(QString("Binarized")); break; - case 2: + case 4: sendImage = images->find(std::string("Eroded"))->second; Q_EMIT emitCvMatA(sendImage, QString("Eroded")); Q_EMIT emitChangeDisplayImage(QString("Eroded")); break; - case 3: + case 5: 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; } } @@ -134,17 +132,8 @@ std::vector BioTrackerTrackingAlgorithm::getContourCentroids(cv::Mat& return centroids; } -#define EEE duration = std::chrono::duration_cast< std::chrono::milliseconds> (std::chrono::steady_clock::now() - startt); block++; std::cout << "Block " << block << ": " << duration.count() << std::endl; -#define SSS startt = std::chrono::steady_clock::now(); - void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr p_image, uint framenumber) { - //Q_EMIT emitCvMatA(p_image, QString("Original")); - //Q_EMIT emitChangeDisplayImage("Original"); - //Q_EMIT emitTrackingDone(framenumber); - //return; - int block = 0; - _ipp.m_TrackingParameter = _TrackingParameter; _lastImage = p_image; _lastFramenumber = framenumber; @@ -172,7 +161,6 @@ void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr p_image, u //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); } diff --git a/Src/Model/BioTrackerTrackingAlgorithm.h b/Src/Model/BioTrackerTrackingAlgorithm.h index e9562c6..8518aa0 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.h +++ b/Src/Model/BioTrackerTrackingAlgorithm.h @@ -56,9 +56,6 @@ std::vector getContourCentroids(cv::Mat& image, int minSize); BlobsDetector _bd; std::shared_ptr _nn2d; - // background subtraction - cv::Ptr _pMOG; - int _noFish; //std::ofstream _ofs; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 7ce5891..97fe160 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -14,15 +14,11 @@ TrackerParameter::TrackerParameter(QObject *parent) : _MinBlobSize = _cfg->MinBlobSize; _MaxBlobSize = _cfg->MaxBlobSize; - _mog2History = _cfg->Mog2History; - _mog2VarThresh = _cfg->Mog2VarThresh; - _mog2BackgroundRatio = _cfg->Mog2BackgroundRatio; + _BackgroundRatio = _cfg->BackgroundRatio; _doNetwork = _cfg->DoNetwork; _networkPort = _cfg->NetworkPort; - _Threshold = 12345; - _doBackground = true; _sendImage = 0; //Send no image _resetBackground = false; @@ -30,18 +26,6 @@ TrackerParameter::TrackerParameter(QObject *parent) : 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; diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 5bc9736..0e4faf0 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -4,7 +4,6 @@ #include "Interfaces/IModel/IModel.h" #include "../Config.h" -#include "TrackingAlgorithm/ParamNames.h" class TrackerParameter : public IModel { @@ -12,9 +11,7 @@ class TrackerParameter : public IModel public: TrackerParameter(QObject *parent = 0); - void setThreshold(int x); - - int getThreshold(); +public slots: void setBinarizationThreshold(int x); int getBinarizationThreshold(); @@ -31,21 +28,9 @@ class TrackerParameter : public IModel 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; + double getBackgroundRatio() { return _BackgroundRatio; }; + void setBackgroundRatio(double x) { + _BackgroundRatio = x; Q_EMIT notifyView(); }; @@ -99,23 +84,17 @@ class TrackerParameter : public IModel void setAll( - int Threshold, int BinarizationThreshold, int SizeErode, int SizeDilate, - int mog2History, - int mog2VarThresh, - double mog2BackgroundRatio, + double BackgroundRatio, int minBlobSize, int maxBlobSize) { - _Threshold = Threshold; _BinarizationThreshold = BinarizationThreshold; _SizeErode = SizeErode; _SizeDilate = SizeDilate; - _mog2History = mog2History; - _mog2VarThresh = mog2VarThresh; - _mog2BackgroundRatio = mog2BackgroundRatio; + _BackgroundRatio = BackgroundRatio; _MinBlobSize = minBlobSize; _MaxBlobSize = maxBlobSize; _cfg->BinarizationThreshold = BinarizationThreshold; @@ -123,9 +102,7 @@ class TrackerParameter : public IModel _cfg->SizeDilate = SizeDilate; _cfg->MinBlobSize = minBlobSize; _cfg->MaxBlobSize = maxBlobSize; - _cfg->Mog2History = mog2History; - _cfg->Mog2VarThresh = mog2VarThresh; - _cfg->Mog2BackgroundRatio = mog2BackgroundRatio; + _cfg->BackgroundRatio = BackgroundRatio; Q_EMIT notifyView(); }; @@ -133,13 +110,10 @@ class TrackerParameter : public IModel private: - int _Threshold; int _BinarizationThreshold; int _SizeErode; int _SizeDilate; - int _mog2History; - int _mog2VarThresh; - double _mog2BackgroundRatio; + double _BackgroundRatio; int _MinBlobSize; int _MaxBlobSize; diff --git a/Src/Model/TrackingAlgorithm/ParamNames.h b/Src/Model/TrackingAlgorithm/ParamNames.h deleted file mode 100644 index 7e7a587..0000000 --- a/Src/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/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index e0ae07b..b44a253 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -8,11 +8,9 @@ QMutex bgsMutex; QMutex oriImageMutex; QMutex initBgkFrameNumMutex; -QMutex mog2Mutex; ImagePreProcessor::ImagePreProcessor(TrackerParameter* p_TrackingParameter) : - _maxBackgroundImageInitTime(0), //BG_MOG2_INIT_FRAME_NUMBER TODO - _bkgSubMethodMog2(false) + _maxBackgroundImageInitTime(0) { _TrackingParameter = p_TrackingParameter; init(); @@ -41,11 +39,6 @@ void ImagePreProcessor::init() m_backgroundImage = std::make_shared(); m_foregroundImage = std::make_shared(); - - _pMOG = cv::createBackgroundSubtractorMOG2( - _TrackingParameter->getmog2History(), - _TrackingParameter->getmog2VarThresh(), - true); //Shadow detection _backgroundSubtractionEnabled = true; _backgroundEnabled = true; @@ -107,24 +100,11 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image) 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 double alpha = m_TrackingParameter->getBackgroundRatio(); const int &imageWidth = m_backgroundImage->cols; const int &imageHeight = m_backgroundImage->rows; @@ -171,7 +151,6 @@ std::map> ImagePreProcessor::preProcess(st 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::COLOR_BGR2GRAY); @@ -190,7 +169,7 @@ std::map> ImagePreProcessor::preProcess(st 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("Foreground"), 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)); @@ -203,14 +182,3 @@ 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/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index 7a8d55e..70b6709 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -81,13 +81,9 @@ class ImagePreProcessor 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; @@ -98,14 +94,10 @@ class ImagePreProcessor bool _resetBackgroundImageEnabled; int _maxBackgroundImageInitTime; - bool _bkgSubMethodMog2; TrackerParameter* _TrackingParameter; // functions void setBkgFrameNum(int); int getBkgFrameNum(); - - void setEnabledMog2(bool); - bool isEnabledMog2(); }; diff --git a/Src/View/TrackedElementView.cpp b/Src/View/TrackedElementView.cpp index f9cdea1..8b29f6a 100644 --- a/Src/View/TrackedElementView.cpp +++ b/Src/View/TrackedElementView.cpp @@ -1,7 +1,6 @@ #include "TrackedElementView.h" #include "../Model/TrackedComponents/TrackedElement.h" #include "../Model/TrackedComponents/TrackedTrajectory.h" -#include "../Model/TrackingAlgorithm/ParamNames.h" #include "QBrush" #include "QPainter" #include "QGraphicsScene" diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index c1d9a43..e366d49 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -3,62 +3,54 @@ #include -TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : - IViewWidget(parent, controller, model), - _ui(new Ui::TrackerParameterView) +TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : IViewWidget(parent, controller, model), + _ui(new Ui::TrackerParameterView) { - _ui->setupUi(this); - getNotified(); + _ui->setupUi(this); + getNotified(); + auto parameter = qobject_cast(getModel()); - 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())); + connect(_ui->lineEdit_2_binThresh, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setBinarizationThreshold); + connect(_ui->lineEdit_2_binThresh, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - _ui->pushButton->setVisible(false); + connect(_ui->lineEdit_3_SizeErode, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeErode); + connect(_ui->lineEdit_3_SizeErode, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_4_SizeDilate, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeDilate); + connect(_ui->lineEdit_4_SizeDilate, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_8_MinBlob, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMinBlobSize); + connect(_ui->lineEdit_8_MinBlob, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize); + connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_7_bgRatio, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setBackgroundRatio); + connect(_ui->lineEdit_7_bgRatio, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); } TrackerParameterView::~TrackerParameterView() { - delete _ui; + delete _ui; } -void TrackerParameterView::on_pushButtonResetBackground_clicked() { +void TrackerParameterView::on_pushButtonResetBackground_clicked() +{ TrackerParameter *parameter = qobject_cast(getModel()); parameter->setResetBackground(true); } -void TrackerParameterView::on_comboBoxSendImage_currentIndexChanged(int v) { +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 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, 0, 0, - setmog2BackgroundRatio, setMinBlobSize, setMaxBlobSize); - - Q_EMIT parametersChanged(); -} - void TrackerParameterView::getNotified() { - TrackerParameter *parameter = qobject_cast(getModel()); + TrackerParameter *parameter = qobject_cast(getModel()); int val = parameter->getBinarizationThreshold(); _ui->lineEdit_2_binThresh->setValue(val); @@ -69,8 +61,8 @@ void TrackerParameterView::getNotified() val = parameter->getSizeDilate(); _ui->lineEdit_4_SizeDilate->setValue(val); - double dval = parameter->getmog2BackgroundRatio(); - _ui->lineEdit_7_MogBack->setValue(dval); + double dval = parameter->getBackgroundRatio(); + _ui->lineEdit_7_bgRatio->setValue(dval); val = parameter->getMinBlobSize(); _ui->lineEdit_8_MinBlob->setValue(val); diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index 7362e1b..cc3b97c 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -17,7 +17,6 @@ class TrackerParameterView : public IViewWidget ~TrackerParameterView(); private slots: - void on_pushButton_clicked(); void on_pushButtonResetBackground_clicked(); void on_comboBoxSendImage_currentIndexChanged(int v); diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index 5fc284f..71b703d 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -6,10 +6,22 @@ 0 0 - 304 - 481 + 583 + 782 + + + 0 + 0 + + + + + 320 + 0 + + Form @@ -54,8 +66,8 @@ 0 0 - 304 - 472 + 583 + 773 @@ -68,333 +80,315 @@ - - - #frame{color: #e5e5e5;} - - - QFrame::Box + + + Background Subtraction - - QFrame::Plain - - - - 3 - - - 5 - - - 5 - - - 5 - - - 5 - - - - - Set the binarization threshold - - - - - - Binarization Threshold - - - - - - - Set the binarization threshold - - - - - - + - - - color: #e5e5e5; + + + QFormLayout::ExpandingFieldsGrow - - QFrame::Plain + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - Qt::Horizontal + + 44 - + + + + Background Ratio: + + + + + + + + 132 + 30 + + + + Set the background ratio + + + 6 + + + 1.000000000000000 + + + 0.001000000000000 + + + 0.001000000000000 + + + + - - - Set the erosion size - - - - - - Size Erode - - - - - - - Set the erosion size - - - - - + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 78 + 20 + + + + + + + + Reset the current background + + + Reset Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Morphology + + - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal + + + QFormLayout::ExpandingFieldsGrow - - - - - - Set the dilation size + + 16 - - - - - Size Dilate - - - - - - - Set the dilation size - - - - - + + + + Binarization Threshold: + + + + + + + + 132 + 30 + + + + Set the binarization threshold + + + + + + + Size Erosion: + + + + + + + + 132 + 30 + + + + Set the erosion size + + + + + + + Size Dilation: + + + + + + + + 132 + 30 + + + + Set the dilation size + + + + + + + + + + + Blob Detection + + - - - color: #e5e5e5; - - - QFrame::Plain + + + QFormLayout::ExpandingFieldsGrow - - Qt::Horizontal + + 66 - + + + + Min Blob Size: + + + + + + + + 132 + 30 + + + + Set the minimal blob size + + + + + + + Max Blob Size: + + + + + + + + 132 + 30 + + + + Sets the maximum blob size + + + 10000 + + + + + + + + + + + Display + + - - - Set the background ratio + + + QFormLayout::ExpandingFieldsGrow - - - + + 108 + + + + + Image: + + + + + + + + 132 + 0 + + + + Choose which image to display for the next frames. Tracking must be actived. + + + Original + + - Background Ratio - - - - - - - Set the background ratio - - - 6 - - - 1.000000000000000 - - - 0.001000000000000 + Original - - 0.001000000000000 - - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Set the minimal blob size - - - - + + - Min Blob Size + Background - - - - - - Set the minimal blob size + + + + Foreground - - - - - - - - - color: #e5e5e5; - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - Sets the maximum blob size - - - - + + - Max Blob Size + Binarized - - - - - - Sets the maximum blob size + + + + Eroded - - 10000 + + + + Dilated - - - - - - - - - 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 - - - From b86189cb2389f03713d9eb930ef2933bcb6f446b Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 15:53:15 +0100 Subject: [PATCH 04/22] Move custom background algorithm into cv::BackgroundSubtractor compatible class --- Src/CMakeLists.txt | 2 + .../CustomBackgroundSubtractor.cpp | 53 +++++++++++++++++++ .../preprocessor/CustomBackgroundSubtractor.h | 14 +++++ .../preprocessor/ImagePreProcessor.cpp | 51 +++--------------- .../preprocessor/ImagePreProcessor.h | 2 + 5 files changed, 78 insertions(+), 44 deletions(-) create mode 100644 Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp create mode 100644 Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt index 8e6b18b..8dc0aae 100644 --- a/Src/CMakeLists.txt +++ b/Src/CMakeLists.txt @@ -21,6 +21,8 @@ add_behavior_plugin(${target} "Model/TrackedComponents/TrackedTrajectory.cpp" "Model/TrackedComponents/pose/FishPose.cpp" "Model/TrackingAlgorithm/NN2dMapper.cpp" + "Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h" + "Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp" "Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp" "Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp" "Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp" diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp new file mode 100644 index 0000000..6265374 --- /dev/null +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -0,0 +1,53 @@ +#include "CustomBackgroundSubtractor.h" + +#include +#include + +void CustomBackgroundSubtractor::getBackgroundImage(cv::OutputArray backgroundImage) const +{ + m_background.copyTo(backgroundImage); +} + +void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate) +{ + if (!m_background.data) { + image.copyTo(m_background); + } + + const int imageWidth = m_background.cols; + const int imageHeight = m_background.rows; + const int totalRegionsX = 4; + const int totalRegionsY = 4; + const int totalRegions = totalRegionsX * totalRegionsY; + const int regionWidth = imageWidth / totalRegionsX; + const int regionHeight = imageHeight / totalRegionsY; + + fgmask.create(imageHeight, imageWidth, image.type()); + + auto 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_background(subArea); + cv::Mat subImage = image.getMat()(subArea); + cv::Mat subResults = fgmask.getMat()(subArea); + + subResults = (subBackground - subImage); + subBackground = (1.0 - learningRate) * subBackground + learningRate * 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(); + } +} diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h new file mode 100644 index 0000000..0f28bc2 --- /dev/null +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +class CustomBackgroundSubtractor : public cv::BackgroundSubtractor +{ +public: + void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = -1) override; + + void getBackgroundImage(cv::OutputArray backgroundImage) const override; + +private: + cv::Mat m_background; +}; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index b44a253..cac1f19 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -2,15 +2,17 @@ #include -#include #include +#include "CustomBackgroundSubtractor.h" + QMutex bgsMutex; QMutex oriImageMutex; QMutex initBgkFrameNumMutex; ImagePreProcessor::ImagePreProcessor(TrackerParameter* p_TrackingParameter) : _maxBackgroundImageInitTime(0) + , m_subtractor(new CustomBackgroundSubtractor()) { _TrackingParameter = p_TrackingParameter; init(); @@ -100,49 +102,10 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image) cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) { - if (!m_backgroundImage->data) - image.copyTo(*m_backgroundImage); - - // calculate the image difference - const double alpha = m_TrackingParameter->getBackgroundRatio(); - - 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; + cv::Mat foreground; + m_subtractor->apply(image, foreground, m_TrackingParameter->getBackgroundRatio()); + m_subtractor->getBackgroundImage(*m_backgroundImage); + return foreground; } std::map> ImagePreProcessor::preProcess(std::shared_ptr p_image) diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index 70b6709..925e5d2 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -97,6 +97,8 @@ class ImagePreProcessor TrackerParameter* _TrackingParameter; + cv::BackgroundSubtractor* m_subtractor; + // functions void setBkgFrameNum(int); int getBkgFrameNum(); From d722a18eb88011c73b38eeb6f4543adb3d632a42 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 15:56:44 +0100 Subject: [PATCH 05/22] Rename "background ratio" -> "learning rate" --- Src/Config.cpp | 4 ++-- Src/Config.h | 2 +- Src/Model/TrackerParameter.cpp | 2 +- Src/Model/TrackerParameter.h | 12 ++++++------ Src/View/TrackerParameterView.cpp | 6 +++--- Src/View/TrackerParameterView.ui | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Src/Config.cpp b/Src/Config.cpp index 4946b5e..ef92d20 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -56,7 +56,7 @@ void Config::load(QString dir, QString file) config->SizeDilate = tree.get(globalPrefix+"SizeDilate",config->SizeDilate); config->MinBlobSize = tree.get(globalPrefix+"MinBlobSize",config->MinBlobSize); config->MaxBlobSize = tree.get(globalPrefix+"MaxBlobSize",config->MaxBlobSize); - config->BackgroundRatio = tree.get(globalPrefix+"BackgroundRatio",config->BackgroundRatio); + config->LearningRate = tree.get(globalPrefix+"LearningRate",config->LearningRate); config->DoNetwork = tree.get(globalPrefix+"DoNetwork",config->DoNetwork); config->NetworkPort = tree.get(globalPrefix+"NetworkPort",config->NetworkPort); config->DoBackground = tree.get(globalPrefix+"DoBackground",config->DoBackground); @@ -82,7 +82,7 @@ void Config::save(QString dir, QString file) tree.put(globalPrefix+"SizeDilate", config->SizeDilate); tree.put(globalPrefix+"MinBlobSize", config->MinBlobSize); tree.put(globalPrefix+"MaxBlobSize", config->MaxBlobSize); - tree.put(globalPrefix+"BackgroundRatio", config->BackgroundRatio); + tree.put(globalPrefix+"LearningRate", config->LearningRate); tree.put(globalPrefix+"DoNetwork", config->DoNetwork); tree.put(globalPrefix+"NetworkPort", config->NetworkPort); tree.put(globalPrefix+"DoBackground", config->DoBackground); diff --git a/Src/Config.h b/Src/Config.h index db181ca..31f70ba 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -13,7 +13,7 @@ class Config : public IConfig int MinBlobSize = 40; int MaxBlobSize = 999999; - double BackgroundRatio = 0.05; + double LearningRate = 0.05; int DoNetwork = false; int NetworkPort = 54444; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 97fe160..b156042 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -14,7 +14,7 @@ TrackerParameter::TrackerParameter(QObject *parent) : _MinBlobSize = _cfg->MinBlobSize; _MaxBlobSize = _cfg->MaxBlobSize; - _BackgroundRatio = _cfg->BackgroundRatio; + _LearningRate = _cfg->LearningRate; _doNetwork = _cfg->DoNetwork; _networkPort = _cfg->NetworkPort; diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 0e4faf0..2a62b7b 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -28,9 +28,9 @@ public slots: Q_EMIT notifyView(); }; - double getBackgroundRatio() { return _BackgroundRatio; }; + double getBackgroundRatio() { return _LearningRate; }; void setBackgroundRatio(double x) { - _BackgroundRatio = x; + _LearningRate = x; Q_EMIT notifyView(); }; @@ -87,14 +87,14 @@ public slots: int BinarizationThreshold, int SizeErode, int SizeDilate, - double BackgroundRatio, + double LearningRate, int minBlobSize, int maxBlobSize) { _BinarizationThreshold = BinarizationThreshold; _SizeErode = SizeErode; _SizeDilate = SizeDilate; - _BackgroundRatio = BackgroundRatio; + _LearningRate = LearningRate; _MinBlobSize = minBlobSize; _MaxBlobSize = maxBlobSize; _cfg->BinarizationThreshold = BinarizationThreshold; @@ -102,7 +102,7 @@ public slots: _cfg->SizeDilate = SizeDilate; _cfg->MinBlobSize = minBlobSize; _cfg->MaxBlobSize = maxBlobSize; - _cfg->BackgroundRatio = BackgroundRatio; + _cfg->LearningRate = LearningRate; Q_EMIT notifyView(); }; @@ -113,7 +113,7 @@ public slots: int _BinarizationThreshold; int _SizeErode; int _SizeDilate; - double _BackgroundRatio; + double _LearningRate; int _MinBlobSize; int _MaxBlobSize; diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index e366d49..a91d559 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -26,8 +26,8 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *control connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize); connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - connect(_ui->lineEdit_7_bgRatio, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setBackgroundRatio); - connect(_ui->lineEdit_7_bgRatio, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setBackgroundRatio); + connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); } TrackerParameterView::~TrackerParameterView() @@ -62,7 +62,7 @@ void TrackerParameterView::getNotified() _ui->lineEdit_4_SizeDilate->setValue(val); double dval = parameter->getBackgroundRatio(); - _ui->lineEdit_7_bgRatio->setValue(dval); + _ui->lineEdit_7_learningRate->setValue(dval); val = parameter->getMinBlobSize(); _ui->lineEdit_8_MinBlob->setValue(val); diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index 71b703d..be7087c 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -99,12 +99,12 @@ - Background Ratio: + Learning Rate: - + 132 From 32cf21ea19e2c6fd40ea18618c4725471784e2a7 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 17:22:23 +0100 Subject: [PATCH 06/22] Fix violation of cv::BackgroundSubtractor API by previous implementation. --- Src/Model/BioTrackerTrackingAlgorithm.cpp | 13 ++--- Src/Model/TrackerParameter.h | 4 +- .../CustomBackgroundSubtractor.cpp | 15 ++++- .../preprocessor/CustomBackgroundSubtractor.h | 4 ++ .../preprocessor/ImagePreProcessor.cpp | 42 +++++--------- .../preprocessor/ImagePreProcessor.h | 9 +-- Src/View/TrackerParameterView.cpp | 4 +- Src/View/TrackerParameterView.ui | 57 +++++++++---------- 8 files changed, 66 insertions(+), 82 deletions(-) diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 36dd076..483c498 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -77,21 +77,16 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage(std::mapfind(std::string("Foreground"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Foreground")); - Q_EMIT emitChangeDisplayImage(QString("Foreground")); + sendImage = images->find(std::string("Foreground Mask"))->second; + Q_EMIT emitCvMatA(sendImage, QString("Foreground Mask")); + Q_EMIT emitChangeDisplayImage(QString("Foreground Mask")); break; case 3: - sendImage = images->find(std::string("Binarized"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Binarized")); - Q_EMIT emitChangeDisplayImage(QString("Binarized")); - break; - case 4: sendImage = images->find(std::string("Eroded"))->second; Q_EMIT emitCvMatA(sendImage, QString("Eroded")); Q_EMIT emitChangeDisplayImage(QString("Eroded")); break; - case 5: + case 4: sendImage = images->find(std::string("Dilated"))->second; Q_EMIT emitCvMatA(sendImage, QString("Dilated")); Q_EMIT emitChangeDisplayImage(QString("Dilated")); diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 2a62b7b..02479e0 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -28,8 +28,8 @@ public slots: Q_EMIT notifyView(); }; - double getBackgroundRatio() { return _LearningRate; }; - void setBackgroundRatio(double x) { + double getLearningRate() { return _LearningRate; }; + void setLearningRate(double x) { _LearningRate = x; Q_EMIT notifyView(); }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp index 6265374..95e46cc 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -3,6 +3,13 @@ #include #include +#include + +void CustomBackgroundSubtractor::setBinarizationThreshold(int value) +{ + m_binarizationThreshold = value; +} + void CustomBackgroundSubtractor::getBackgroundImage(cv::OutputArray backgroundImage) const { m_background.copyTo(backgroundImage); @@ -24,13 +31,15 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm fgmask.create(imageHeight, imageWidth, image.type()); + auto fgmaskmat = fgmask.getMat(); + 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_background(subArea); cv::Mat subImage = image.getMat()(subArea); - cv::Mat subResults = fgmask.getMat()(subArea); + cv::Mat subResults = fgmaskmat(subArea); subResults = (subBackground - subImage); subBackground = (1.0 - learningRate) * subBackground + learningRate * subImage; @@ -50,4 +59,8 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm for (const auto & asyncResult : merger) { asyncResult.wait(); } + + if (fgmaskmat.data) { + cv::threshold(fgmaskmat, fgmaskmat, m_binarizationThreshold, 255, cv::THRESH_BINARY); + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h index 0f28bc2..551748c 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h @@ -9,6 +9,10 @@ class CustomBackgroundSubtractor : public cv::BackgroundSubtractor void getBackgroundImage(cv::OutputArray backgroundImage) const override; + void setBinarizationThreshold(int value); + private: cv::Mat m_background; + + int m_binarizationThreshold; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index cac1f19..06497ef 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -40,7 +40,7 @@ void ImagePreProcessor::init() QMutexLocker locker(&bgsMutex); m_backgroundImage = std::make_shared(); - m_foregroundImage = std::make_shared(); + m_foregroundMask = std::make_shared(); _backgroundSubtractionEnabled = true; _backgroundEnabled = true; @@ -51,21 +51,6 @@ void ImagePreProcessor::init() _resetBackgroundImageEnabled = false; } -cv::Mat ImagePreProcessor::binarize(cv::Mat& image) -{ - cv::Mat binarizedImage; - - if (image.channels() >= 3) - cv::cvtColor(image, binarizedImage, cv::COLOR_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; @@ -102,38 +87,37 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image) cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) { - cv::Mat foreground; - m_subtractor->apply(image, foreground, m_TrackingParameter->getBackgroundRatio()); + if (auto subtractor = dynamic_cast(m_subtractor); subtractor) { + subtractor->setBinarizationThreshold(m_TrackingParameter->getBinarizationThreshold()); + } + + cv::Mat fgmask; + m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate()); m_subtractor->getBackgroundImage(*m_backgroundImage); - return foreground; + return fgmask; } 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::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); // 1. step: do the background subtraction - *m_foregroundImage = backgroundSubtraction(*greyMat); - - // 2. step: binarize the image - *binarizedImage = binarize(*m_foregroundImage); + *m_foregroundMask = backgroundSubtraction(*greyMat); - // 3. step: erode the image - *erodedImage = erode(*binarizedImage); + // 2. step: erode the image + *erodedImage = erode(*m_foregroundMask); - // 4. step: dilate the image + // 3. 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("Foreground"), m_foregroundImage)); - all.insert(std::pair>(std::string("Binarized"), binarizedImage)); + all.insert(std::pair>(std::string("Foreground Mask"), m_foregroundMask)); all.insert(std::pair>(std::string("Eroded"), erodedImage)); all.insert(std::pair>(std::string("Dilated"), dilatedImage)); diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index 925e5d2..1cc9417 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -28,13 +28,6 @@ class ImagePreProcessor */ 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. @@ -82,7 +75,7 @@ class ImagePreProcessor cv::Mat _outputImage; std::shared_ptr m_backgroundImage; - std::shared_ptr m_foregroundImage; + std::shared_ptr m_foregroundMask; //parameters for image pre-processing bool _backgroundSubtractionEnabled; diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index a91d559..984c2c9 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -26,7 +26,7 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *control connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize); connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setBackgroundRatio); + connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setLearningRate); connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); } @@ -61,7 +61,7 @@ void TrackerParameterView::getNotified() val = parameter->getSizeDilate(); _ui->lineEdit_4_SizeDilate->setValue(val); - double dval = parameter->getBackgroundRatio(); + double dval = parameter->getLearningRate(); _ui->lineEdit_7_learningRate->setValue(dval); val = parameter->getMinBlobSize(); diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index be7087c..1c183b7 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -94,7 +94,7 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - 44 + 13 @@ -103,6 +103,26 @@ + + + + Binarization Threshold: + + + + + + + + 132 + 30 + + + + Set the binarization threshold + + + @@ -188,36 +208,16 @@ QFormLayout::ExpandingFieldsGrow - 16 + 74 - - - Binarization Threshold: - - - - - - - - 132 - 30 - - - - Set the binarization threshold - - - - Size Erosion: - + @@ -230,14 +230,14 @@ - + Size Dilation: - + @@ -364,12 +364,7 @@ - Foreground - - - - - Binarized + Foreground Mask From d636a68bea32efad22c054a8455a1fc5561c3235 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 17:24:07 +0100 Subject: [PATCH 07/22] Cleanup --- .../preprocessor/ImagePreProcessor.cpp | 17 +---------------- .../preprocessor/ImagePreProcessor.h | 6 ------ 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 06497ef..3a52f7a 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -7,12 +7,9 @@ #include "CustomBackgroundSubtractor.h" QMutex bgsMutex; -QMutex oriImageMutex; -QMutex initBgkFrameNumMutex; ImagePreProcessor::ImagePreProcessor(TrackerParameter* p_TrackingParameter) : - _maxBackgroundImageInitTime(0) - , m_subtractor(new CustomBackgroundSubtractor()) + m_subtractor(new CustomBackgroundSubtractor()) { _TrackingParameter = p_TrackingParameter; init(); @@ -22,18 +19,6 @@ ImagePreProcessor::~ImagePreProcessor(void) { } -void ImagePreProcessor::setBkgFrameNum(int frameNum) -{ - QMutexLocker locker(&initBgkFrameNumMutex); - _maxBackgroundImageInitTime = frameNum; -} - -int ImagePreProcessor::getBkgFrameNum() -{ - QMutexLocker locker(&initBgkFrameNumMutex); - return _maxBackgroundImageInitTime; -} - void ImagePreProcessor::init() { diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index 1cc9417..9df20d0 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -86,13 +86,7 @@ class ImagePreProcessor bool _gaussianBlurEnabled; bool _resetBackgroundImageEnabled; - int _maxBackgroundImageInitTime; - TrackerParameter* _TrackingParameter; cv::BackgroundSubtractor* m_subtractor; - - // functions - void setBkgFrameNum(int); - int getBkgFrameNum(); }; From 17b698becef2909ecd26141be53a4e22765f4aae Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 17:35:55 +0100 Subject: [PATCH 08/22] misc --- Src/View/TrackerParameterView.ui | 74 ++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index 1c183b7..86973da 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -97,33 +97,20 @@ 13 - + - Learning Rate: + Algorithm: - + - Binarization Threshold: + Learning Rate: - - - - 132 - 30 - - - - Set the binarization threshold - - - - @@ -148,6 +135,47 @@ + + + + Binarization Threshold: + + + + + + + + 132 + 30 + + + + Set the binarization threshold + + + + + + + + 132 + 0 + + + + + 132 + 16777215 + + + + + Custom + + + + @@ -340,12 +368,24 @@ + + + 0 + 0 + + 132 0 + + + 132 + 16777215 + + Choose which image to display for the next frames. Tracking must be actived. From d5bb7657039c45dee7be64f59989f14e3fde5695 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 12 Nov 2021 18:35:29 +0100 Subject: [PATCH 09/22] misc --- CMakeLists.txt | 4 + Src/CMakeLists.txt | 2 + Src/Model/BioTrackerTrackingAlgorithm.cpp | 2 +- Src/Model/TrackerParameter.cpp | 2 + Src/Model/TrackerParameter.h | 7 ++ .../preprocessor/ImagePreProcessor.cpp | 22 ++++- .../preprocessor/ImagePreProcessor.h | 8 +- Src/View/TrackerParameterView.cpp | 57 +++++++++--- Src/View/TrackerParameterView.h | 7 ++ Src/View/TrackerParameterView.ui | 92 +++++++++---------- 10 files changed, 127 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d9b45a..df196cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,10 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") endif() option(PACKAGE_TXZ "Create .tar.xz package" OFF) +find_package(OpenCV 4 QUIET COMPONENTS bgsegm) +if(NOT OpenCV_FOUND) + find_package(OpenCV 3 REQUIRED COMPONENTS bgsegm) +endif() find_package(biotracker-utility REQUIRED) add_subdirectory(Src) diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt index 8dc0aae..9b2e99a 100644 --- a/Src/CMakeLists.txt +++ b/Src/CMakeLists.txt @@ -47,3 +47,5 @@ add_behavior_plugin(${target} install(TARGETS ${target} OPTIONAL DESTINATION .) find_package(Qt5 REQUIRED COMPONENTS Xml Network) target_link_libraries (${target} Qt5::Xml Qt5::Network) + +target_link_libraries(${target} ${OpenCV_LIBS}) diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 483c498..52a3788 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -5,7 +5,7 @@ BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController *parent, IModel* parameter, IModel* trajectory) : IModelTrackingAlgorithm(parent) -, _ipp((TrackerParameter*)parameter) +, _ipp((TrackerParameter*) parameter) { _cfg = static_cast(parent)->getConfig(); _TrackingParameter = (TrackerParameter*)parameter; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index b156042..8363a86 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -23,6 +23,8 @@ TrackerParameter::TrackerParameter(QObject *parent) : _sendImage = 0; //Send no image _resetBackground = false; + _algorithm = "Custom"; + Q_EMIT notifyView(); } diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 02479e0..db3384f 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -13,6 +13,11 @@ class TrackerParameter : public IModel public slots: + QString getAlgorithm() { return _algorithm; } + void setAlgorithm(QString algorithm) { + _algorithm = algorithm; + } + void setBinarizationThreshold(int x); int getBinarizationThreshold(); @@ -110,6 +115,8 @@ public slots: private: + QString _algorithm; + int _BinarizationThreshold; int _SizeErode; int _SizeDilate; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 3a52f7a..621d935 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -4,14 +4,16 @@ #include +#include + #include "CustomBackgroundSubtractor.h" QMutex bgsMutex; -ImagePreProcessor::ImagePreProcessor(TrackerParameter* p_TrackingParameter) : - m_subtractor(new CustomBackgroundSubtractor()) +ImagePreProcessor::ImagePreProcessor(TrackerParameter* TrackingParameter) : + m_subtractor(nullptr), + m_TrackingParameter{TrackingParameter} { - _TrackingParameter = p_TrackingParameter; init(); } @@ -24,6 +26,13 @@ void ImagePreProcessor::init() { QMutexLocker locker(&bgsMutex); + auto algorithm = m_TrackingParameter->getAlgorithm(); + if (algorithm == QString("Custom")) { + m_subtractor = new CustomBackgroundSubtractor(); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + m_backgroundImage = std::make_shared(); m_foregroundMask = std::make_shared(); @@ -72,8 +81,13 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image) cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) { - if (auto subtractor = dynamic_cast(m_subtractor); subtractor) { + if (auto subtractor = m_subtractor.dynamicCast(); subtractor) { + if (m_TrackingParameter->getAlgorithm() != QString("Custom")) { + init(); + } subtractor->setBinarizationThreshold(m_TrackingParameter->getBinarizationThreshold()); + } else { + qFatal("Unsupported background subtraction algorithm"); } cv::Mat fgmask; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index 9df20d0..bb03f38 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -15,12 +15,12 @@ class ImagePreProcessor /** * The standard constructor. */ - ImagePreProcessor(TrackerParameter* p_TrackingParameter); + ImagePreProcessor(TrackerParameter* TrackingParameter); /** * The standard destructor. */ - ~ImagePreProcessor(void); + ~ImagePreProcessor(); /** * Init function. Sets the property for the imge pre-processing. @@ -86,7 +86,5 @@ class ImagePreProcessor bool _gaussianBlurEnabled; bool _resetBackgroundImageEnabled; - TrackerParameter* _TrackingParameter; - - cv::BackgroundSubtractor* m_subtractor; + cv::Ptr m_subtractor; }; diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 984c2c9..bf58593 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -4,15 +4,16 @@ #include TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : IViewWidget(parent, controller, model), - _ui(new Ui::TrackerParameterView) + _ui(new Ui::TrackerParameterView), + _binThres(nullptr) { _ui->setupUi(this); getNotified(); auto parameter = qobject_cast(getModel()); - connect(_ui->lineEdit_2_binThresh, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setBinarizationThreshold); - connect(_ui->lineEdit_2_binThresh, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + connect(_ui->algorithmCB, &QComboBox::currentTextChanged, parameter, &TrackerParameter::setAlgorithm); + connect(_ui->algorithmCB, &QComboBox::currentTextChanged, this, &TrackerParameterView::initSubtractorSpecificUI); connect(_ui->lineEdit_3_SizeErode, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeErode); connect(_ui->lineEdit_3_SizeErode, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); @@ -28,6 +29,8 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *control connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setLearningRate); connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + + initSubtractorSpecificUI(_ui->algorithmCB->currentText()); } TrackerParameterView::~TrackerParameterView() @@ -35,6 +38,34 @@ TrackerParameterView::~TrackerParameterView() delete _ui; } +void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) +{ + auto parameter = qobject_cast(getModel()); + + while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { + _ui->algorithmSpecificParameterLayout->removeRow(0); + } + + if (_binThres) { + _binThres = nullptr; + } + + if (algorithm == QString("Custom")) { + _binThres = new QSpinBox(); + _binThres->setMinimum(1); + _binThres->setMaximum(255); + _binThres->setValue(parameter->getBinarizationThreshold()); + _ui->algorithmSpecificParameterLayout->addRow(tr("Binarization Threshold:"), _binThres); + + connect(_binThres, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setBinarizationThreshold); + connect(_binThres, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + emit parametersChanged(); +} + void TrackerParameterView::on_pushButtonResetBackground_clicked() { TrackerParameter *parameter = qobject_cast(getModel()); @@ -52,21 +83,17 @@ void TrackerParameterView::getNotified() { TrackerParameter *parameter = qobject_cast(getModel()); - int val = parameter->getBinarizationThreshold(); - _ui->lineEdit_2_binThresh->setValue(val); + _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); - val = parameter->getSizeErode(); - _ui->lineEdit_3_SizeErode->setValue(val); + if (_binThres) { + _binThres->setValue(parameter->getBinarizationThreshold()); + } - val = parameter->getSizeDilate(); - _ui->lineEdit_4_SizeDilate->setValue(val); + _ui->lineEdit_3_SizeErode->setValue(parameter->getSizeErode()); - double dval = parameter->getLearningRate(); - _ui->lineEdit_7_learningRate->setValue(dval); + _ui->lineEdit_4_SizeDilate->setValue(parameter->getSizeDilate()); - val = parameter->getMinBlobSize(); - _ui->lineEdit_8_MinBlob->setValue(val); + _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); - val = parameter->getMaxBlobSize(); - _ui->lineEdit_9MaxBlob->setValue(val); + _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); } diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index cc3b97c..6412b0b 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -4,6 +4,8 @@ #include "Interfaces/IView/IViewWidget.h" #include "../Model/TrackerParameter.h" +#include + namespace Ui { class TrackerParameterView; } @@ -29,6 +31,11 @@ private slots: private: Ui::TrackerParameterView *_ui; + QSpinBox* _binThres; + +private slots: + void initSubtractorSpecificUI(QString algorithm); + // IViewWidget interface public slots: diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index 86973da..59e548d 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -7,7 +7,7 @@ 0 0 583 - 782 + 916 @@ -67,7 +67,7 @@ 0 0 583 - 773 + 907 @@ -88,7 +88,7 @@ - QFormLayout::ExpandingFieldsGrow + QFormLayout::AllNonFixedFieldsGrow Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter @@ -103,6 +103,27 @@ + + + + + 230 + 0 + + + + + 132 + 16777215 + + + + + Custom + + + + @@ -114,8 +135,8 @@ - 132 - 30 + 230 + 60 @@ -135,47 +156,16 @@ - - - - Binarization Threshold: - - - - - - - - 132 - 30 - - - - Set the binarization threshold - - - - - - - - 132 - 0 - - - - - 132 - 16777215 - - - - - Custom - - - - + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + @@ -250,7 +240,7 @@ 132 - 30 + 60 @@ -270,7 +260,7 @@ 132 - 30 + 60 @@ -309,7 +299,7 @@ 132 - 30 + 60 @@ -328,8 +318,8 @@ - 132 - 30 + 171 + 60 From d9d51c12aee7ac5c35b58b9b247d28011ae84353 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Mon, 15 Nov 2021 01:25:40 +0100 Subject: [PATCH 10/22] Replace erroneous subtraction leading to underflow. Instead allow selection between two new subtractions: 1. Absolute Difference 2. Saturated Difference (Truncation at 0,255 limits) --- Src/Config.cpp | 2 + Src/Config.h | 2 + Src/Model/TrackerParameter.cpp | 15 +++++++- Src/Model/TrackerParameter.h | 38 ++++++------------- .../CustomBackgroundSubtractor.cpp | 23 ++++++++++- .../preprocessor/CustomBackgroundSubtractor.h | 5 +++ .../preprocessor/ImagePreProcessor.cpp | 1 + Src/View/TrackerParameterView.cpp | 20 ++++++++-- Src/View/TrackerParameterView.h | 3 ++ 9 files changed, 77 insertions(+), 32 deletions(-) diff --git a/Src/Config.cpp b/Src/Config.cpp index ef92d20..72e8d3c 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -51,6 +51,7 @@ void Config::load(QString dir, QString file) config->EnableSwap = tree.get(globalPrefix+"EnableSwap",config->EnableSwap); config->EnableAdd = tree.get(globalPrefix+"EnableAdd",config->EnableAdd); config->EnableRotate = tree.get(globalPrefix+"EnableRotate",config->EnableRotate); + config->UseAbsoluteDifference = tree.get(globalPrefix+"UseAbsoluteDifference",config->UseAbsoluteDifference); config->BinarizationThreshold = tree.get(globalPrefix+"BinarizationThreshold",config->BinarizationThreshold); config->SizeErode = tree.get(globalPrefix+"SizeErode",config->SizeErode); config->SizeDilate = tree.get(globalPrefix+"SizeDilate",config->SizeDilate); @@ -77,6 +78,7 @@ void Config::save(QString dir, QString file) tree.put(globalPrefix+"EnableSwap", config->EnableSwap); tree.put(globalPrefix+"EnableAdd", config->EnableAdd); tree.put(globalPrefix+"EnableRotate", config->EnableRotate); + tree.put(globalPrefix+"UseAbsoluteDifference", config->UseAbsoluteDifference); tree.put(globalPrefix+"BinarizationThreshold", config->BinarizationThreshold); tree.put(globalPrefix+"SizeErode", config->SizeErode); tree.put(globalPrefix+"SizeDilate", config->SizeDilate); diff --git a/Src/Config.h b/Src/Config.h index 31f70ba..f268060 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -7,7 +7,9 @@ class Config : public IConfig { public: + bool UseAbsoluteDifference = true; int BinarizationThreshold = 40; + int SizeErode = 8; int SizeDilate = 8; int MinBlobSize = 40; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 8363a86..645159c 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -7,7 +7,7 @@ TrackerParameter::TrackerParameter(QObject *parent) : _cfg = static_cast(parent)->getConfig(); - + _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; _BinarizationThreshold = _cfg->BinarizationThreshold; _SizeErode = _cfg->SizeErode; _SizeDilate = _cfg->SizeDilate; @@ -38,4 +38,17 @@ void TrackerParameter::setBinarizationThreshold(int x) int TrackerParameter::getBinarizationThreshold() { return _BinarizationThreshold; +} + + +void TrackerParameter::setUseAbsoluteDifference(bool value) +{ + _UseAbsoluteDifference = value; + _cfg->UseAbsoluteDifference = value; + Q_EMIT notifyView(); +} + +bool TrackerParameter::getUseAbsoluteDifference() +{ + return _UseAbsoluteDifference; } \ No newline at end of file diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index db3384f..5ad37d1 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -18,48 +18,58 @@ public slots: _algorithm = algorithm; } + void setUseAbsoluteDifference(bool x); + bool getUseAbsoluteDifference(); + void setBinarizationThreshold(int x); int getBinarizationThreshold(); int getSizeErode() { return _SizeErode; }; void setSizeErode(int x) { _SizeErode = x; + _cfg->SizeErode = x; Q_EMIT notifyView(); }; int getSizeDilate() { return _SizeDilate; }; void setSizeDilate(int x) { _SizeDilate = x; + _cfg->SizeDilate = x; Q_EMIT notifyView(); }; double getLearningRate() { return _LearningRate; }; void setLearningRate(double x) { _LearningRate = x; + _cfg->LearningRate = x; Q_EMIT notifyView(); }; double getMinBlobSize() { return _MinBlobSize; }; void setMinBlobSize(double x) { _MinBlobSize = x; + _cfg->MinBlobSize = x; Q_EMIT notifyView(); }; double getMaxBlobSize() { return _MaxBlobSize; }; void setMaxBlobSize(double x) { _MaxBlobSize = x; + _cfg->MaxBlobSize = x; Q_EMIT notifyView(); }; bool getDoBackground() { return _doBackground; }; void setDoBackground(bool x) { _doBackground = x; + _cfg->DoBackground = x; Q_EMIT notifyView(); }; bool getDoNetwork() { return _doNetwork; }; void setDoNetwork(bool x) { _doNetwork = x; + _cfg->DoNetwork = x; Q_EMIT notifyView(); }; @@ -86,38 +96,14 @@ public slots: void setNewSelection(std::string x) { _newSelection = x; } - - - void setAll( - int BinarizationThreshold, - int SizeErode, - int SizeDilate, - double LearningRate, - int minBlobSize, - int maxBlobSize) - { - _BinarizationThreshold = BinarizationThreshold; - _SizeErode = SizeErode; - _SizeDilate = SizeDilate; - _LearningRate = LearningRate; - _MinBlobSize = minBlobSize; - _MaxBlobSize = maxBlobSize; - _cfg->BinarizationThreshold = BinarizationThreshold; - _cfg->SizeErode = SizeErode; - _cfg->SizeDilate = SizeDilate; - _cfg->MinBlobSize = minBlobSize; - _cfg->MaxBlobSize = maxBlobSize; - _cfg->LearningRate = LearningRate; - Q_EMIT notifyView(); - }; - - private: QString _algorithm; + bool _UseAbsoluteDifference; int _BinarizationThreshold; + int _SizeErode; int _SizeDilate; double _LearningRate; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp index 95e46cc..cf8f62a 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -5,6 +5,18 @@ #include +CustomBackgroundSubtractor::CustomBackgroundSubtractor() +: m_useAbsoluteDifference{true} +, m_binarizationThreshold{8} +{ + +} + +void CustomBackgroundSubtractor::setUseAbsoluteDifference(bool value) +{ + m_useAbsoluteDifference = value; +} + void CustomBackgroundSubtractor::setBinarizationThreshold(int value) { m_binarizationThreshold = value; @@ -33,7 +45,9 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm auto fgmaskmat = fgmask.getMat(); - auto workOnRegion = [&](int x, int y) { + const auto useAbsoluteDifference = m_useAbsoluteDifference; + + auto workOnRegion = [&, useAbsoluteDifference](int x, int y) { const int startingX = x * regionWidth; const int startingY = y * regionHeight; const cv::Rect subArea = cv::Rect(startingX, startingY, regionWidth, regionHeight); @@ -41,7 +55,12 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgm cv::Mat subImage = image.getMat()(subArea); cv::Mat subResults = fgmaskmat(subArea); - subResults = (subBackground - subImage); + if (useAbsoluteDifference) { + cv::absdiff(subBackground, subImage, subResults); + } else { + cv::subtract(subBackground, subImage, subResults); + } + subBackground = (1.0 - learningRate) * subBackground + learningRate * subImage; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h index 551748c..94c79b0 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h @@ -5,14 +5,19 @@ class CustomBackgroundSubtractor : public cv::BackgroundSubtractor { public: + CustomBackgroundSubtractor(); + void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = -1) override; void getBackgroundImage(cv::OutputArray backgroundImage) const override; + void setUseAbsoluteDifference(bool value); void setBinarizationThreshold(int value); private: cv::Mat m_background; + bool m_useAbsoluteDifference; + int m_binarizationThreshold; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 621d935..9f241aa 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -85,6 +85,7 @@ cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) if (m_TrackingParameter->getAlgorithm() != QString("Custom")) { init(); } + subtractor->setUseAbsoluteDifference(m_TrackingParameter->getUseAbsoluteDifference()); subtractor->setBinarizationThreshold(m_TrackingParameter->getBinarizationThreshold()); } else { qFatal("Unsupported background subtraction algorithm"); diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index bf58593..5f21a2f 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -5,6 +5,7 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : IViewWidget(parent, controller, model), _ui(new Ui::TrackerParameterView), + _useAbsDiff(nullptr), _binThres(nullptr) { _ui->setupUi(this); @@ -31,6 +32,8 @@ TrackerParameterView::TrackerParameterView(QWidget *parent, IController *control connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); initSubtractorSpecificUI(_ui->algorithmCB->currentText()); + + _ui->algorithmCB->setEnabled(false); } TrackerParameterView::~TrackerParameterView() @@ -46,11 +49,18 @@ void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) _ui->algorithmSpecificParameterLayout->removeRow(0); } - if (_binThres) { - _binThres = nullptr; - } + _useAbsDiff = nullptr; + _binThres = nullptr; if (algorithm == QString("Custom")) { + _useAbsDiff = new QCheckBox(); + _useAbsDiff->setText(" "); + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + _ui->algorithmSpecificParameterLayout->addRow(tr("Use Absolute Difference:"), _useAbsDiff); + + connect(_useAbsDiff, &QCheckBox::toggled, parameter, &TrackerParameter::setUseAbsoluteDifference); + connect(_useAbsDiff, &QCheckBox::toggled, this, &TrackerParameterView::parametersChanged); + _binThres = new QSpinBox(); _binThres->setMinimum(1); _binThres->setMaximum(255); @@ -85,6 +95,10 @@ void TrackerParameterView::getNotified() _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); + if (_useAbsDiff) { + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + } + if (_binThres) { _binThres->setValue(parameter->getBinarizationThreshold()); } diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index 6412b0b..172a0e9 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -5,6 +5,7 @@ #include "../Model/TrackerParameter.h" #include +#include namespace Ui { class TrackerParameterView; @@ -31,6 +32,8 @@ private slots: private: Ui::TrackerParameterView *_ui; + QCheckBox* _useAbsDiff; + QSpinBox* _binThres; private slots: From 1ea011dfe5cb7cb771d968186d2f885409b97a15 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Mon, 15 Nov 2021 18:08:56 +0100 Subject: [PATCH 11/22] cleanup --- Src/BioTrackerPlugin.cpp | 18 +++------------ Src/BioTrackerPlugin.h | 3 --- .../ControllerTrackingAlgorithm.cpp | 22 ++++--------------- Src/Controller/ControllerTrackingAlgorithm.h | 15 +++++-------- 4 files changed, 12 insertions(+), 46 deletions(-) diff --git a/Src/BioTrackerPlugin.cpp b/Src/BioTrackerPlugin.cpp index c3e52bb..a10baf4 100644 --- a/Src/BioTrackerPlugin.cpp +++ b/Src/BioTrackerPlugin.cpp @@ -56,9 +56,9 @@ void BioTrackerPlugin::connectInterfaces() { 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(ctrAlg, &ControllerTrackingAlgorithm::emitCvMat, this, &BioTrackerPlugin::emitCvMat); + QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitTrackingDone, this, &BioTrackerPlugin::emitTrackingDone); + QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitChangeDisplayImage, this, &BioTrackerPlugin::emitChangeDisplayImage); QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrAlg, &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); //tracking algorithm QObject::connect(static_cast(ctrAlg->getModel()), SIGNAL(emitDimensionUpdate(int, int)), this, SIGNAL(emitDimensionUpdate(int, int))); @@ -93,18 +93,6 @@ 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); } diff --git a/Src/BioTrackerPlugin.h b/Src/BioTrackerPlugin.h index 7544588..10679bd 100644 --- a/Src/BioTrackerPlugin.h +++ b/Src/BioTrackerPlugin.h @@ -60,9 +60,6 @@ public slots: 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: diff --git a/Src/Controller/ControllerTrackingAlgorithm.cpp b/Src/Controller/ControllerTrackingAlgorithm.cpp index 935f36a..8544888 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.cpp +++ b/Src/Controller/ControllerTrackingAlgorithm.cpp @@ -46,10 +46,10 @@ void ControllerTrackingAlgorithm::createView() 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(trackingAlg, &BioTrackerTrackingAlgorithm::emitCvMatA, this, &ControllerTrackingAlgorithm::emitCvMat); + QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitTrackingDone, this, &ControllerTrackingAlgorithm::emitTrackingDone); + QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, this, &ControllerTrackingAlgorithm::emitChangeDisplayImage); + QObject::connect(this, &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, trackingAlg, &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); QObject::connect(static_cast(m_View), &TrackerParameterView::parametersChanged, trackingAlg, &BioTrackerTrackingAlgorithm::receiveParametersChanged); @@ -61,20 +61,6 @@ void ControllerTrackingAlgorithm::connectModelToController() 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/Src/Controller/ControllerTrackingAlgorithm.h b/Src/Controller/ControllerTrackingAlgorithm.h index 0435fa1..7854934 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.h +++ b/Src/Controller/ControllerTrackingAlgorithm.h @@ -12,9 +12,9 @@ class ControllerTrackingAlgorithm : public IController { Q_OBJECT public: - ControllerTrackingAlgorithm(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + ControllerTrackingAlgorithm(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - Config *getConfig() { return _cfg;}; + Config* getConfig() { return _cfg;}; void setConfig(Config *cfg) { _cfg = cfg;}; // IController interface public: @@ -22,7 +22,7 @@ class ControllerTrackingAlgorithm : public IController void doTracking(std::shared_ptr mat, uint number); - IView *getTrackingParameterWidget(); + IView* getTrackingParameterWidget(); public Q_SLOTS: void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); @@ -38,15 +38,10 @@ public Q_SLOTS: 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; - Config *_cfg; + IModel* m_TrackedTrajectoryMajor; + Config* _cfg; }; #endif // CONTROLLERTRACKINGALGORITHM_H From e9abc2d047905a8df936a9c9c81eba0022d54756 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 29 Jul 2022 16:57:29 +0200 Subject: [PATCH 12/22] Reformat, remove unused null controller --- .clang-format | 104 ++ .editorconfig | 19 + Src/BioTrackerPlugin.cpp | 244 ++-- Src/BioTrackerPlugin.h | 107 +- Src/CMakeLists.txt | 1 - Src/Config.cpp | 106 +- Src/Config.h | 32 +- Src/Controller/ControllerTrackedComponent.cpp | 213 ++-- Src/Controller/ControllerTrackedComponent.h | 74 +- .../ControllerTrackingAlgorithm.cpp | 84 +- Src/Controller/ControllerTrackingAlgorithm.h | 26 +- Src/Controller/null_Controller.cpp | 26 - Src/Controller/null_Controller.h | 18 - Src/Model/BioTrackerTrackingAlgorithm.cpp | 294 ++--- Src/Model/BioTrackerTrackingAlgorithm.h | 48 +- Src/Model/Network/TcpListener.cpp | 92 +- Src/Model/Network/TcpListener.h | 18 +- .../TrackedComponentFactory.cpp | 69 +- .../TrackedComponentFactory.h | 30 +- .../TrackedComponents/TrackedElement.cpp | 401 ++++--- Src/Model/TrackedComponents/TrackedElement.h | 220 ++-- .../TrackedComponents/TrackedTrajectory.cpp | 62 +- .../TrackedComponents/TrackedTrajectory.h | 78 +- Src/Model/TrackedComponents/pose/FishPose.cpp | 53 +- Src/Model/TrackedComponents/pose/FishPose.h | 301 +++-- Src/Model/TrackedComponents/pose/IPose.h | 36 +- Src/Model/TrackerParameter.cpp | 53 +- Src/Model/TrackerParameter.h | 250 ++-- Src/Model/TrackingAlgorithm/NN2dMapper.cpp | 598 +++++----- Src/Model/TrackingAlgorithm/NN2dMapper.h | 33 +- .../imageProcessor/cvblobs/BlobContour.cpp | 345 +++--- .../imageProcessor/cvblobs/BlobContour.h | 137 ++- .../cvblobs/BlobLibraryConfiguration.h | 4 +- .../imageProcessor/cvblobs/BlobOperators.cpp | 409 +++---- .../imageProcessor/cvblobs/BlobOperators.h | 1004 ++++++++-------- .../imageProcessor/cvblobs/BlobProperties.cpp | 72 +- .../imageProcessor/cvblobs/BlobProperties.h | 74 +- .../imageProcessor/cvblobs/BlobResult.cpp | 952 ++++++++------- .../imageProcessor/cvblobs/BlobResult.h | 268 ++--- .../cvblobs/ComponentLabeling.cpp | 717 ++++++------ .../cvblobs/ComponentLabeling.h | 56 +- .../imageProcessor/cvblobs/blob.cpp | 1021 ++++++++--------- .../imageProcessor/cvblobs/blob.h | 282 ++--- .../imageProcessor/detector/IDetector.cpp | 33 +- .../imageProcessor/detector/IDetector.h | 98 +- .../imageProcessor/detector/blob/BlobPose.cpp | 22 +- .../imageProcessor/detector/blob/BlobPose.h | 162 +-- .../detector/blob/cvBlob/BlobsDetector.cpp | 122 +- .../detector/blob/cvBlob/BlobsDetector.h | 89 +- .../blob/simpleBlob/SimpleBlobsDetector.cpp | 116 +- .../blob/simpleBlob/SimpleBlobsDetector.h | 61 +- .../detector/contour/ContourPose.cpp | 22 +- .../detector/contour/ContourPose.h | 134 ++- .../detector/contour/ContoursDetector.cpp | 42 +- .../detector/contour/ContoursDetector.h | 41 +- .../CustomBackgroundSubtractor.cpp | 124 +- .../preprocessor/CustomBackgroundSubtractor.h | 18 +- .../preprocessor/ImagePreProcessor.cpp | 194 ++-- .../preprocessor/ImagePreProcessor.h | 142 ++- Src/Model/null_Model.cpp | 1 - Src/PluginContext.cpp | 46 +- Src/PluginContext.h | 13 +- Src/View/TrackedElementView.cpp | 25 +- Src/View/TrackedElementView.h | 20 +- Src/View/TrackerParameterView.cpp | 214 ++-- Src/View/TrackerParameterView.h | 18 +- Src/helper/CvHelper.cpp | 441 +++---- Src/helper/CvHelper.h | 382 +++--- Src/helper/StringHelper.cpp | 94 +- Src/helper/StringHelper.h | 123 +- 70 files changed, 6373 insertions(+), 5455 deletions(-) create mode 100644 .clang-format create mode 100644 .editorconfig delete mode 100644 Src/Controller/null_Controller.cpp delete mode 100644 Src/Controller/null_Controller.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..2b27bb2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,104 @@ +--- +Language: Cpp +Standard: Cpp11 +UseTab: Never +TabWidth: 4 +IndentWidth: 4 +AccessModifierOffset: -4 +ContinuationIndentWidth: 4 +ColumnLimit: 79 +ConstructorInitializerIndentWidth: 0 +BinPackArguments: false +BinPackParameters: false +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignOperands: true +AlignEscapedNewlines: Right +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +CompactNamespaces: false +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +IndentCaseLabels: false +IndentPPDirectives: BeforeHash +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +PenaltyBreakAssignment: 100 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +CommentPragmas: '' +MacroBlockBegin: '' +MacroBlockEnd: '' +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +... diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7b80d1c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{c,h,cc,hh,cpp,hpp,cxx,hxx}] +indent_style = space +indent_size = 4 + +[*.py] +indent_style = space +indent_size = 4 + +[*.yml] +indent_style = space +indent_size = 2 diff --git a/Src/BioTrackerPlugin.cpp b/Src/BioTrackerPlugin.cpp index a10baf4..d683f94 100644 --- a/Src/BioTrackerPlugin.cpp +++ b/Src/BioTrackerPlugin.cpp @@ -9,111 +9,213 @@ #include "View/TrackedElementView.h" #include "Utility/TrackedComponents/TrackedComponentFactory.h" -BioTrackerPlugin::BioTrackerPlugin() { +BioTrackerPlugin::BioTrackerPlugin() +{ } -BioTrackerPlugin::~BioTrackerPlugin() { +BioTrackerPlugin::~BioTrackerPlugin() +{ _cfg->save(Config::configLocation, "BackgroundSubtractionConfig.ini"); - delete _cfg; + delete _cfg; } -IView* BioTrackerPlugin::getTrackerParameterWidget() { - return qobject_cast (m_TrackerController)->getTrackingParameterWidget(); +IView* BioTrackerPlugin::getTrackerParameterWidget() +{ + return qobject_cast(m_TrackerController) + ->getTrackingParameterWidget(); } -IView *BioTrackerPlugin::getTrackerElementsWidget() +IView* BioTrackerPlugin::getTrackerElementsWidget() { - return qobject_cast (m_ComponentController)->getTrackingElementsWidget(); + return qobject_cast(m_ComponentController) + ->getTrackingElementsWidget(); } // forwards tracked component model to coreApp -IModel* BioTrackerPlugin::getTrackerComponentModel() { - return qobject_cast (m_ComponentController)->getModel(); +IModel* BioTrackerPlugin::getTrackerComponentModel() +{ + return qobject_cast(m_ComponentController) + ->getModel(); } -IModelTrackedComponentFactory *BioTrackerPlugin::getComponentFactory() { - return new TrackedComponentFactory(); +IModelTrackedComponentFactory* BioTrackerPlugin::getComponentFactory() +{ + return new TrackedComponentFactory(); } -void BioTrackerPlugin::createPlugin() { - _cfg = new Config(); +void BioTrackerPlugin::createPlugin() +{ + _cfg = new Config(); _cfg->load(Config::configLocation, "BackgroundSubtractionConfig.ini"); - m_PluginContext = new PluginContext(this, _cfg); - m_PluginContext->createApplication(); + m_PluginContext = new PluginContext(this, _cfg); + m_PluginContext->createApplication(); - IController * ctr = m_PluginContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - m_ComponentController = qobject_cast(ctr); + 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); + IController* ctr2 = m_PluginContext->requestController( + ENUMS::CONTROLLERTYPE::TRACKING); + m_TrackerController = qobject_cast(ctr2); - connectInterfaces(); + connectInterfaces(); - qDebug() << "BST-Tracker loaded!"; + qDebug() << "BST-Tracker loaded!"; } -void BioTrackerPlugin::connectInterfaces() { - ControllerTrackingAlgorithm* ctrAlg = qobject_cast (m_TrackerController); - ControllerTrackedComponent* ctrTrC = qobject_cast (m_ComponentController); - - //controllertrackingalgorithm - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitCvMat, this, &BioTrackerPlugin::emitCvMat); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitTrackingDone, this, &BioTrackerPlugin::emitTrackingDone); - QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitChangeDisplayImage, this, &BioTrackerPlugin::emitChangeDisplayImage); - QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrAlg, &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); - //tracking algorithm - QObject::connect(static_cast(ctrAlg->getModel()), SIGNAL(emitDimensionUpdate(int, int)), this, SIGNAL(emitDimensionUpdate(int, int))); - //controllertrackedcomponents - QObject::connect(this, &BioTrackerPlugin::emitAddTrajectory, ctrTrC, &ControllerTrackedComponent::receiveAddTrajectory, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitRemoveTrajectory, ctrTrC, &ControllerTrackedComponent::receiveRemoveTrajectory, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitRemoveTrajectoryId, ctrTrC, &ControllerTrackedComponent::receiveRemoveTrajectoryId, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitRemoveTrackEntity, ctrTrC, &ControllerTrackedComponent::receiveRemoveTrackEntity, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitValidateTrajectory, ctrTrC, &ControllerTrackedComponent::receiveValidateTrajectory, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitValidateEntity, ctrTrC, &ControllerTrackedComponent::receiveValidateEntity, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitEntityRotation, ctrTrC, &ControllerTrackedComponent::receiveEntityRotation, Qt::DirectConnection); - //connect this to enable moving of elements -> we need pxtocm() to create new poses - QObject::connect(this, &BioTrackerPlugin::emitAreaDescriptorUpdate, ctrTrC, &ControllerTrackedComponent::receiveAreaDescriptorUpdate, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitMoveElement, ctrTrC, &ControllerTrackedComponent::receiveMoveElement, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitSwapIds, ctrTrC, &ControllerTrackedComponent::receiveSwapIds, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitToggleFixTrack, ctrTrC, &ControllerTrackedComponent::receiveToggleFixTrack, Qt::DirectConnection); - QObject::connect(this, &BioTrackerPlugin::emitCurrentFrameNumber, ctrTrC, &ControllerTrackedComponent::receiveCurrentFrameNumber, Qt::DirectConnection); +void BioTrackerPlugin::connectInterfaces() +{ + ControllerTrackingAlgorithm* ctrAlg = + qobject_cast(m_TrackerController); + ControllerTrackedComponent* ctrTrC = + qobject_cast(m_ComponentController); + + // controllertrackingalgorithm + QObject::connect(ctrAlg, + &ControllerTrackingAlgorithm::emitCvMat, + this, + &BioTrackerPlugin::emitCvMat); + QObject::connect(ctrAlg, + &ControllerTrackingAlgorithm::emitTrackingDone, + this, + &BioTrackerPlugin::emitTrackingDone); + QObject::connect(ctrAlg, + &ControllerTrackingAlgorithm::emitChangeDisplayImage, + this, + &BioTrackerPlugin::emitChangeDisplayImage); + QObject::connect( + this, + &BioTrackerPlugin::emitAreaDescriptorUpdate, + ctrAlg, + &ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate); + // tracking algorithm + QObject::connect( + static_cast(ctrAlg->getModel()), + SIGNAL(emitDimensionUpdate(int, int)), + this, + SIGNAL(emitDimensionUpdate(int, int))); + // controllertrackedcomponents + QObject::connect(this, + &BioTrackerPlugin::emitAddTrajectory, + ctrTrC, + &ControllerTrackedComponent::receiveAddTrajectory, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitRemoveTrajectory, + ctrTrC, + &ControllerTrackedComponent::receiveRemoveTrajectory, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitRemoveTrajectoryId, + ctrTrC, + &ControllerTrackedComponent::receiveRemoveTrajectoryId, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitRemoveTrackEntity, + ctrTrC, + &ControllerTrackedComponent::receiveRemoveTrackEntity, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitValidateTrajectory, + ctrTrC, + &ControllerTrackedComponent::receiveValidateTrajectory, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitValidateEntity, + ctrTrC, + &ControllerTrackedComponent::receiveValidateEntity, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitEntityRotation, + ctrTrC, + &ControllerTrackedComponent::receiveEntityRotation, + Qt::DirectConnection); + // connect this to enable moving of elements -> we need pxtocm() to create + // new poses + QObject::connect(this, + &BioTrackerPlugin::emitAreaDescriptorUpdate, + ctrTrC, + &ControllerTrackedComponent::receiveAreaDescriptorUpdate, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitMoveElement, + ctrTrC, + &ControllerTrackedComponent::receiveMoveElement, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitSwapIds, + ctrTrC, + &ControllerTrackedComponent::receiveSwapIds, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitToggleFixTrack, + ctrTrC, + &ControllerTrackedComponent::receiveToggleFixTrack, + Qt::DirectConnection); + QObject::connect(this, + &BioTrackerPlugin::emitCurrentFrameNumber, + ctrTrC, + &ControllerTrackedComponent::receiveCurrentFrameNumber, + Qt::DirectConnection); } - -void BioTrackerPlugin::receiveAreaDescriptor(IModelAreaDescriptor *areaDescr) { - Q_EMIT emitAreaDescriptorUpdate(areaDescr); +void BioTrackerPlugin::receiveAreaDescriptor(IModelAreaDescriptor* areaDescr) +{ + Q_EMIT emitAreaDescriptorUpdate(areaDescr); } -void BioTrackerPlugin::receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber) { - qobject_cast (m_TrackerController)->doTracking(mat, frameNumber); +void BioTrackerPlugin::receiveCurrentFrameFromMainApp( + std::shared_ptr mat, + uint frameNumber) +{ + qobject_cast(m_TrackerController) + ->doTracking(mat, frameNumber); - Q_EMIT emitCurrentFrameNumber(frameNumber); + Q_EMIT emitCurrentFrameNumber(frameNumber); } -void BioTrackerPlugin::receiveCurrentFrameNumberFromMainApp(uint frameNumber) { - Q_EMIT emitCurrentFrameNumber(frameNumber); +void BioTrackerPlugin::receiveCurrentFrameNumberFromMainApp(uint frameNumber) +{ + Q_EMIT emitCurrentFrameNumber(frameNumber); } -void BioTrackerPlugin::receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory) { - Q_EMIT emitRemoveTrajectory(trajectory); +void BioTrackerPlugin::receiveRemoveTrajectory( + IModelTrackedTrajectory* trajectory) +{ + Q_EMIT emitRemoveTrajectory(trajectory); } -void BioTrackerPlugin::receiveAddTrajectory(QPoint pos) { - Q_EMIT emitAddTrajectory(pos); +void BioTrackerPlugin::receiveAddTrajectory(QPoint pos) +{ + Q_EMIT emitAddTrajectory(pos); } -void BioTrackerPlugin::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) { - Q_EMIT emitSwapIds(trajectory0, trajectory1); +void BioTrackerPlugin::receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1) +{ + Q_EMIT emitSwapIds(trajectory0, trajectory1); } -void BioTrackerPlugin::sendCorePermissions() { - // get plugin settings - - // signal permissions - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTVIEW, _cfg->EnableView)); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTMOVE, _cfg->EnableMove)); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTREMOVE, _cfg->EnableRemove)); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTSWAP, _cfg->EnableSwap)); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTADD, _cfg->EnableAdd)); - Q_EMIT emitCorePermission(std::pair(ENUMS::COREPERMISSIONS::COMPONENTROTATE, _cfg->EnableRotate)); +void BioTrackerPlugin::sendCorePermissions() +{ + // get plugin settings + + // signal permissions + Q_EMIT emitCorePermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTVIEW, + _cfg->EnableView)); + Q_EMIT emitCorePermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTMOVE, + _cfg->EnableMove)); + Q_EMIT emitCorePermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTREMOVE, + _cfg->EnableRemove)); + Q_EMIT emitCorePermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTSWAP, + _cfg->EnableSwap)); + Q_EMIT emitCorePermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTADD, + _cfg->EnableAdd)); + Q_EMIT emitCorePermission(std::pair( + ENUMS::COREPERMISSIONS::COMPONENTROTATE, + _cfg->EnableRotate)); } - diff --git a/Src/BioTrackerPlugin.h b/Src/BioTrackerPlugin.h index 10679bd..cbf2cf2 100644 --- a/Src/BioTrackerPlugin.h +++ b/Src/BioTrackerPlugin.h @@ -11,69 +11,78 @@ #include "QPoint" #include "Config.h" -class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin { - Q_OBJECT - Q_INTERFACES(IBioTrackerPlugin) - Q_PLUGIN_METADATA(IID IBioTrackerPlugin_iid FILE "plugin.json") +class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin +{ + Q_OBJECT + Q_INTERFACES(IBioTrackerPlugin) + Q_PLUGIN_METADATA(IID IBioTrackerPlugin_iid FILE "plugin.json") - public: - BioTrackerPlugin(); - ~BioTrackerPlugin(); +public: + BioTrackerPlugin(); + ~BioTrackerPlugin(); - // IBioTrackerPlugin interface - IView* getTrackerParameterWidget(); - IView *getTrackerElementsWidget(); - IModel* getTrackerComponentModel(); - IModelTrackedComponentFactory *getComponentFactory(); + // IBioTrackerPlugin interface + IView* getTrackerParameterWidget(); + IView* getTrackerElementsWidget(); + IModel* getTrackerComponentModel(); + IModelTrackedComponentFactory* getComponentFactory(); - public: - void createPlugin(); - void receiveCurrentFrameFromMainApp(std::shared_ptr mat, uint frameNumber); - void sendCorePermissions(); +public: + void createPlugin(); + void receiveCurrentFrameFromMainApp(std::shared_ptr mat, + uint frameNumber); + void sendCorePermissions(); - private: - void connectInterfaces(); +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); + 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); + void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void receiveAddTrajectory(QPoint pos); + void receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + void receiveCurrentFrameNumberFromMainApp(uint frameNumber); private slots: - void receiveAreaDescriptor(IModelAreaDescriptor *areaDescr); + void receiveAreaDescriptor(IModelAreaDescriptor* areaDescr); private: - IController *m_TrackerController; - IController *m_ComponentController; - IController *m_AreaDescrController; + IController* m_TrackerController; + IController* m_ComponentController; + IController* m_AreaDescrController; - IBioTrackerContext *m_PluginContext; - Config* _cfg; + IBioTrackerContext* m_PluginContext; + Config* _cfg; public: - QList m_CorePermissions; - - + QList m_CorePermissions; }; #endif // BIOTRACKERPLUGIN_H diff --git a/Src/CMakeLists.txt b/Src/CMakeLists.txt index 9b2e99a..337279f 100644 --- a/Src/CMakeLists.txt +++ b/Src/CMakeLists.txt @@ -41,7 +41,6 @@ add_behavior_plugin(${target} "helper/StringHelper.cpp" "Controller/ControllerTrackedComponent.cpp" "Controller/ControllerTrackingAlgorithm.cpp" - "Controller/null_Controller.cpp" ) install(TARGETS ${target} OPTIONAL DESTINATION .) diff --git a/Src/Config.cpp b/Src/Config.cpp index 72e8d3c..1f06a68 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -11,18 +11,18 @@ #include template -Stream &operator>>(Stream& s, QString& q) +Stream& operator>>(Stream& s, QString& q) { std::string tmp; s >> tmp; q = tmp.data(); - return s; + return s; } template -Stream &operator<<(Stream& s, QString const& q) +Stream& operator<<(Stream& s, QString const& q) { - return s << q.toStdString(); + return s << q.toStdString(); } void Config::load(QString dir, QString file) @@ -34,61 +34,81 @@ void Config::load(QString dir, QString file) d.mkpath(dir); QFile fin(dir + "/" + file); - if(!fin.exists()) - { + if (!fin.exists()) { fin.open(QIODevice::ReadWrite); fin.close(); } - + read_ini((dir + "/" + file).toStdString(), tree); Config* config = this; std::string globalPrefix = "General."; - config->EnableView = tree.get(globalPrefix+"EnableView",config->EnableView); - config->EnableMove = tree.get(globalPrefix+"EnableMove",config->EnableMove); - config->EnableRemove = tree.get(globalPrefix+"EnableRemove",config->EnableRemove); - config->EnableSwap = tree.get(globalPrefix+"EnableSwap",config->EnableSwap); - config->EnableAdd = tree.get(globalPrefix+"EnableAdd",config->EnableAdd); - config->EnableRotate = tree.get(globalPrefix+"EnableRotate",config->EnableRotate); - config->UseAbsoluteDifference = tree.get(globalPrefix+"UseAbsoluteDifference",config->UseAbsoluteDifference); - config->BinarizationThreshold = tree.get(globalPrefix+"BinarizationThreshold",config->BinarizationThreshold); - config->SizeErode = tree.get(globalPrefix+"SizeErode",config->SizeErode); - config->SizeDilate = tree.get(globalPrefix+"SizeDilate",config->SizeDilate); - config->MinBlobSize = tree.get(globalPrefix+"MinBlobSize",config->MinBlobSize); - config->MaxBlobSize = tree.get(globalPrefix+"MaxBlobSize",config->MaxBlobSize); - config->LearningRate = tree.get(globalPrefix+"LearningRate",config->LearningRate); - config->DoNetwork = tree.get(globalPrefix+"DoNetwork",config->DoNetwork); - config->NetworkPort = tree.get(globalPrefix+"NetworkPort",config->NetworkPort); - config->DoBackground = tree.get(globalPrefix+"DoBackground",config->DoBackground); - config->ResetBackground = tree.get(globalPrefix+"ResetBackground",config->ResetBackground); + config->EnableView = tree.get(globalPrefix + "EnableView", + config->EnableView); + config->EnableMove = tree.get(globalPrefix + "EnableMove", + config->EnableMove); + config->EnableRemove = tree.get(globalPrefix + "EnableRemove", + config->EnableRemove); + config->EnableSwap = tree.get(globalPrefix + "EnableSwap", + config->EnableSwap); + config->EnableAdd = tree.get(globalPrefix + "EnableAdd", + config->EnableAdd); + config->EnableRotate = tree.get(globalPrefix + "EnableRotate", + config->EnableRotate); + config->UseAbsoluteDifference = tree.get( + globalPrefix + "UseAbsoluteDifference", + config->UseAbsoluteDifference); + config->BinarizationThreshold = tree.get( + globalPrefix + "BinarizationThreshold", + config->BinarizationThreshold); + config->SizeErode = tree.get(globalPrefix + "SizeErode", + config->SizeErode); + config->SizeDilate = tree.get(globalPrefix + "SizeDilate", + config->SizeDilate); + config->MinBlobSize = tree.get(globalPrefix + "MinBlobSize", + config->MinBlobSize); + config->MaxBlobSize = tree.get(globalPrefix + "MaxBlobSize", + config->MaxBlobSize); + config->LearningRate = tree.get(globalPrefix + "LearningRate", + config->LearningRate); + config->DoNetwork = tree.get(globalPrefix + "DoNetwork", + config->DoNetwork); + config->NetworkPort = tree.get(globalPrefix + "NetworkPort", + config->NetworkPort); + config->DoBackground = tree.get(globalPrefix + "DoBackground", + config->DoBackground); + config->ResetBackground = tree.get(globalPrefix + "ResetBackground", + config->ResetBackground); } void Config::save(QString dir, QString file) { using namespace boost::property_tree; - auto tree = ptree{}; - Config *config = this; + auto tree = ptree{}; + Config* config = this; std::string globalPrefix = "General."; - tree.put(globalPrefix+"EnableView", config->EnableView); - tree.put(globalPrefix+"EnableMove", config->EnableMove); - tree.put(globalPrefix+"EnableRemove", config->EnableRemove); - tree.put(globalPrefix+"EnableSwap", config->EnableSwap); - tree.put(globalPrefix+"EnableAdd", config->EnableAdd); - tree.put(globalPrefix+"EnableRotate", config->EnableRotate); - tree.put(globalPrefix+"UseAbsoluteDifference", config->UseAbsoluteDifference); - tree.put(globalPrefix+"BinarizationThreshold", config->BinarizationThreshold); - tree.put(globalPrefix+"SizeErode", config->SizeErode); - tree.put(globalPrefix+"SizeDilate", config->SizeDilate); - tree.put(globalPrefix+"MinBlobSize", config->MinBlobSize); - tree.put(globalPrefix+"MaxBlobSize", config->MaxBlobSize); - tree.put(globalPrefix+"LearningRate", config->LearningRate); - tree.put(globalPrefix+"DoNetwork", config->DoNetwork); - tree.put(globalPrefix+"NetworkPort", config->NetworkPort); - tree.put(globalPrefix+"DoBackground", config->DoBackground); - tree.put(globalPrefix+"ResetBackground", config->ResetBackground); + tree.put(globalPrefix + "EnableView", config->EnableView); + tree.put(globalPrefix + "EnableMove", config->EnableMove); + tree.put(globalPrefix + "EnableRemove", config->EnableRemove); + tree.put(globalPrefix + "EnableSwap", config->EnableSwap); + tree.put(globalPrefix + "EnableAdd", config->EnableAdd); + tree.put(globalPrefix + "EnableRotate", config->EnableRotate); + tree.put(globalPrefix + "UseAbsoluteDifference", + config->UseAbsoluteDifference); + tree.put(globalPrefix + "BinarizationThreshold", + config->BinarizationThreshold); + tree.put(globalPrefix + "SizeErode", config->SizeErode); + tree.put(globalPrefix + "SizeDilate", config->SizeDilate); + tree.put(globalPrefix + "MinBlobSize", config->MinBlobSize); + tree.put(globalPrefix + "MaxBlobSize", config->MaxBlobSize); + tree.put(globalPrefix + "LearningRate", config->LearningRate); + tree.put(globalPrefix + "DoNetwork", config->DoNetwork); + tree.put(globalPrefix + "NetworkPort", config->NetworkPort); + tree.put(globalPrefix + "DoBackground", config->DoBackground); + tree.put(globalPrefix + "ResetBackground", config->ResetBackground); write_ini((dir + "/" + file).toStdString(), tree); } diff --git a/Src/Config.h b/Src/Config.h index f268060..01bb358 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -7,33 +7,33 @@ class Config : public IConfig { public: - bool UseAbsoluteDifference = true; - int BinarizationThreshold = 40; + bool UseAbsoluteDifference = true; + int BinarizationThreshold = 40; - int SizeErode = 8; - int SizeDilate = 8; - int MinBlobSize = 40; - int MaxBlobSize = 999999; + int SizeErode = 8; + int SizeDilate = 8; + int MinBlobSize = 40; + int MaxBlobSize = 999999; - double LearningRate = 0.05; + double LearningRate = 0.05; - int DoNetwork = false; - int NetworkPort = 54444; + int DoNetwork = false; + int NetworkPort = 54444; - int DoBackground = true; - int ResetBackground = false; + int DoBackground = true; + int ResetBackground = false; - int EnableView = 1; - int EnableMove = 1; + int EnableView = 1; + int EnableMove = 1; int EnableRemove = 1; - int EnableSwap = 1; - int EnableAdd = 1; + int EnableSwap = 1; + int EnableAdd = 1; int EnableRotate = 1; int NoFish = 0; void load(QString dir, QString file = "config.ini") override; void save(QString dir, QString file) override; - + static const QString DefaultArena; }; diff --git a/Src/Controller/ControllerTrackedComponent.cpp b/Src/Controller/ControllerTrackedComponent.cpp index e71f1b2..6cc4554 100644 --- a/Src/Controller/ControllerTrackedComponent.cpp +++ b/Src/Controller/ControllerTrackedComponent.cpp @@ -5,168 +5,201 @@ #include "qdebug.h" #include "qmath.h" -ControllerTrackedComponent::ControllerTrackedComponent(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) +ControllerTrackedComponent::ControllerTrackedComponent( + QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IController(parent, context, ctr) { - m_currentFrameNumber = 0; + m_currentFrameNumber = 0; } void ControllerTrackedComponent::createView() { - m_View = new TrackedElementView(0, this, m_Model); + m_View = new TrackedElementView(0, this, m_Model); } void ControllerTrackedComponent::connectModelToController() { - } void ControllerTrackedComponent::connectControllerToController() { } -void createTrajectories(int count, TrackedTrajectory* all) { +void createTrajectories(int count, TrackedTrajectory* all) +{ } void ControllerTrackedComponent::createModel() { - TrackedTrajectory *t = new TrackedTrajectory(this, "All"); - m_Model = t; + TrackedTrajectory* t = new TrackedTrajectory(this, "All"); + m_Model = t; } - -IView *ControllerTrackedComponent::getTrackingElementsWidget() +IView* ControllerTrackedComponent::getTrackingElementsWidget() { - return m_View; + return m_View; } -void ControllerTrackedComponent::receiveRemoveTrajectory(IModelTrackedTrajectory * trajectory) +void ControllerTrackedComponent::receiveRemoveTrajectory( + IModelTrackedTrajectory* trajectory) { - trajectory->setValid(false); - qDebug() << "TRACKER: Track" << trajectory->getId() << "set invalid"; + trajectory->setValid(false); + qDebug() << "TRACKER: Track" << trajectory->getId() << "set invalid"; } void ControllerTrackedComponent::receiveRemoveTrajectoryId(int id) { - TrackedTrajectory* allTraj = qobject_cast(m_Model); - if (allTraj) { - IModelTrackedComponent* traj = allTraj->getChild(id - 1); - traj->setValid(false); - qDebug() << "TRACKER: Track" << id << "set invalid"; - } + 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"; - } + 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) +void ControllerTrackedComponent::receiveValidateEntity( + IModelTrackedTrajectory* trajectory, + uint frameNumber) { - trajectory->getChild(frameNumber)->setValid(true); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "set valid"; + trajectory->getChild(frameNumber)->setValid(true); + qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" + << frameNumber << "set valid"; } -void ControllerTrackedComponent::receiveRemoveTrackEntity(IModelTrackedTrajectory * trajectory, uint frameNumber) +void ControllerTrackedComponent::receiveRemoveTrackEntity( + IModelTrackedTrajectory* trajectory, + uint frameNumber) { - trajectory->getChild(frameNumber)->setValid(false); - qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" << frameNumber << "deleted (set invalid)"; + trajectory->getChild(frameNumber)->setValid(false); + qDebug() << "TRACKER: Track " << trajectory->getId() << " entity #" + << frameNumber << "deleted (set invalid)"; } void ControllerTrackedComponent::receiveAddTrajectory(QPoint position) { - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - - cv::Point newPosPx = cv::Point(position.x(), position.y()); - cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); + std::chrono::system_clock::time_point start = + std::chrono::system_clock::now(); - BST::TrackedTrajectory* newTraj = new BST::TrackedTrajectory(); - BST::TrackedElement* firstElem = new BST::TrackedElement(newTraj, "n.a.", newTraj->getId()); + cv::Point newPosPx = cv::Point(position.x(), position.y()); + cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); - FishPose newPose = FishPose(newPosCm, newPosPx, 0, 0, 20, 20, 0.0); + BST::TrackedTrajectory* newTraj = new BST::TrackedTrajectory(); + BST::TrackedElement* firstElem = new BST::TrackedElement(newTraj, + "n.a.", + newTraj->getId()); - firstElem->setFishPose(newPose); + FishPose newPose = FishPose(newPosCm, newPosPx, 0, 0, 20, 20, 0.0); + firstElem->setFishPose(newPose); - firstElem->setTime(start); - newTraj->add(firstElem, m_currentFrameNumber); - TrackedTrajectory* allTraj = qobject_cast(m_Model); - if (allTraj) { - allTraj->add(newTraj); - qDebug() << "TRACKER: Trajectory added at" << firstElem->getXpx() << "," << firstElem->getYpx(); - } + firstElem->setTime(start); + newTraj->add(firstElem, m_currentFrameNumber); + TrackedTrajectory* allTraj = qobject_cast(m_Model); + if (allTraj) { + allTraj->add(newTraj); + qDebug() << "TRACKER: Trajectory added at" << firstElem->getXpx() + << "," << firstElem->getYpx(); + } } -void ControllerTrackedComponent::receiveMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint position) +void ControllerTrackedComponent::receiveMoveElement( + IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint position) { - BST::TrackedTrajectory* traj = dynamic_cast(trajectory); - // don't move when frame number under 0 and main trajectory (id's: 0)!! - if (!(traj->getId() == 0) && frameNumber >= 0) { - BST::TrackedElement* element = dynamic_cast(traj->getChild(frameNumber)); + BST::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) { + BST::TrackedElement* element = dynamic_cast( + traj->getChild(frameNumber)); - //TODO rewrite this when default ipose is implemented... - FishPose oldPose = element->getFishPose(); + // TODO rewrite this when default ipose is implemented... + FishPose oldPose = element->getFishPose(); - cv::Point newPosPx = cv::Point(position.x(), position.y()); - cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); - // ignore blobs outside the tracking area - if (!m_areaDescr->inTrackingArea(newPosPx)) { - qDebug() << "Attention! You moved the entity outside of the tracking area!"; - } + cv::Point newPosPx = cv::Point(position.x(), position.y()); + cv::Point2f newPosCm = m_areaDescr->pxToCm(newPosPx); + // ignore blobs outside the tracking area + if (!m_areaDescr->inTrackingArea(newPosPx)) { + qDebug() << "Attention! You moved the entity outside of the " + "tracking area!"; + } - FishPose newPose = FishPose(newPosCm, newPosPx, oldPose.orientation_rad(), oldPose.orientation_deg(), oldPose.width(), oldPose.height(), oldPose.getScore()); + FishPose newPose = FishPose(newPosCm, + newPosPx, + oldPose.orientation_rad(), + oldPose.orientation_deg(), + oldPose.width(), + oldPose.height(), + oldPose.getScore()); - element->setFishPose(newPose); - } + element->setFishPose(newPose); + } } -void ControllerTrackedComponent::receiveSwapIds(IModelTrackedTrajectory * trajectory0, IModelTrackedTrajectory * trajectory1) +void ControllerTrackedComponent::receiveSwapIds( + IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1) { - TrackedTrajectory* traj0 = dynamic_cast(trajectory0); - TrackedTrajectory* traj1 = dynamic_cast(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(); + if (traj0 && traj1) { + if (traj0->getId() != 0 && traj1->getId() != 0) { + int traj0Id = traj0->getId(); + int traj1Id = traj1->getId(); - traj0->setId(traj1Id); - traj1->setId(traj0Id); + traj0->setId(traj1Id); + traj1->setId(traj0Id); - qDebug() << "TRACKER: Swap IDs " << traj0Id << "and " << traj1Id; - } - } + qDebug() << "TRACKER: Swap IDs " << traj0Id << "and " << traj1Id; + } + } } -void ControllerTrackedComponent::receiveToggleFixTrack(IModelTrackedTrajectory * trajectory, bool toggle) +void ControllerTrackedComponent::receiveToggleFixTrack( + IModelTrackedTrajectory* trajectory, + bool toggle) { - qDebug() << "TRACKER: Fix trajectory " << trajectory->getId(); - trajectory->setFixed(toggle); + qDebug() << "TRACKER: Fix trajectory " << trajectory->getId(); + trajectory->setFixed(toggle); } -void ControllerTrackedComponent::receiveEntityRotation(IModelTrackedTrajectory * trajectory, double angle, uint frameNumber) +void ControllerTrackedComponent::receiveEntityRotation( + IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber) { - TrackedTrajectory* traj = dynamic_cast(trajectory); - if (traj) { - IModelTrackedPoint* pointLike = dynamic_cast(traj->getChild(frameNumber)); - if (pointLike) { - pointLike->setDeg(float(angle)); - pointLike->setRad(float(qDegreesToRadians(angle))); - } - } + 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; + m_currentFrameNumber = (int) framenumber; } -void ControllerTrackedComponent::receiveAreaDescriptorUpdate(IModelAreaDescriptor * areaDescr) +void ControllerTrackedComponent::receiveAreaDescriptorUpdate( + IModelAreaDescriptor* areaDescr) { - m_areaDescr = areaDescr; + m_areaDescr = areaDescr; } diff --git a/Src/Controller/ControllerTrackedComponent.h b/Src/Controller/ControllerTrackedComponent.h index 6c1e82e..8ccdbb6 100644 --- a/Src/Controller/ControllerTrackedComponent.h +++ b/Src/Controller/ControllerTrackedComponent.h @@ -9,41 +9,59 @@ class ControllerTrackedComponent : public IController { - Q_OBJECT + Q_OBJECT public: - ControllerTrackedComponent(QObject *parent = 0, IBioTrackerContext *context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COMPONENT); + ControllerTrackedComponent( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::COMPONENT); - Config *getConfig() { return _cfg;}; - void setConfig(Config *cfg) { _cfg = cfg;}; - IView *getTrackingElementsWidget(); + Config* getConfig() + { + return _cfg; + }; + void setConfig(Config* cfg) + { + _cfg = cfg; + }; + IView* getTrackingElementsWidget(); public Q_SLOTS: - void receiveAddTrajectory(QPoint position); - void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); - void receiveRemoveTrajectoryId(int id); - void receiveRemoveTrackEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void receiveValidateTrajectory(int id); - void receiveValidateEntity(IModelTrackedTrajectory* trajectory, uint frameNumber); - void receiveMoveElement(IModelTrackedTrajectory* trajectory, uint frameNumber, QPoint position); - /* TODO Swaps ID's of last elements (-> swap elements) or swap ID's of trajectories and all of its elements? - */ - void receiveSwapIds(IModelTrackedTrajectory* trajectory0, IModelTrackedTrajectory* trajectory1); - void receiveToggleFixTrack(IModelTrackedTrajectory* trajectory, bool toggle); - void receiveEntityRotation(IModelTrackedTrajectory* trajectory, double angle, uint frameNumber); - void receiveCurrentFrameNumber(uint framenumber); + void receiveAddTrajectory(QPoint position); + void receiveRemoveTrajectory(IModelTrackedTrajectory* trajectory); + void receiveRemoveTrajectoryId(int id); + void receiveRemoveTrackEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void receiveValidateTrajectory(int id); + void receiveValidateEntity(IModelTrackedTrajectory* trajectory, + uint frameNumber); + void receiveMoveElement(IModelTrackedTrajectory* trajectory, + uint frameNumber, + QPoint position); + /* TODO Swaps ID's of last elements (-> swap elements) or swap ID's of + * trajectories and all of its elements? + */ + void receiveSwapIds(IModelTrackedTrajectory* trajectory0, + IModelTrackedTrajectory* trajectory1); + void receiveToggleFixTrack(IModelTrackedTrajectory* trajectory, + bool toggle); + void receiveEntityRotation(IModelTrackedTrajectory* trajectory, + double angle, + uint frameNumber); + void receiveCurrentFrameNumber(uint framenumber); - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); - // IController interface + // IController interface protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; - Config *_cfg; + void createModel() override; + void createView() override; + void connectModelToController() override; + void connectControllerToController() override; + Config* _cfg; - //members - int m_currentFrameNumber; - IModelAreaDescriptor* m_areaDescr; + // members + int m_currentFrameNumber; + IModelAreaDescriptor* m_areaDescr; }; #endif // CONTROLLERTRACKEDCOMPONENT_H diff --git a/Src/Controller/ControllerTrackingAlgorithm.cpp b/Src/Controller/ControllerTrackingAlgorithm.cpp index 8544888..555a7f6 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.cpp +++ b/Src/Controller/ControllerTrackingAlgorithm.cpp @@ -5,37 +5,46 @@ #include "../View/TrackerParameterView.h" #include "../View/TrackedElementView.h" -ControllerTrackingAlgorithm::ControllerTrackingAlgorithm(QObject *parent, IBioTrackerContext *context, ENUMS::CONTROLLERTYPE ctr) : - IController(parent, context, ctr) +ControllerTrackingAlgorithm::ControllerTrackingAlgorithm( + QObject* parent, + IBioTrackerContext* context, + ENUMS::CONTROLLERTYPE ctr) +: IController(parent, context, ctr) { - m_BioTrackerContext = context; + m_BioTrackerContext = context; } void ControllerTrackingAlgorithm::connectControllerToController() { - IController * ctr = m_BioTrackerContext->requestController(ENUMS::CONTROLLERTYPE::COMPONENT); - QPointer< ControllerTrackedComponent > ctrComponent = qobject_cast(ctr); + IController* ctr = m_BioTrackerContext->requestController( + ENUMS::CONTROLLERTYPE::COMPONENT); + QPointer ctrComponent = + qobject_cast(ctr); - m_TrackedTrajectoryMajor = ctrComponent->getModel(); + m_TrackedTrajectoryMajor = ctrComponent->getModel(); } -void ControllerTrackingAlgorithm::doTracking(std::shared_ptr mat, uint number) +void ControllerTrackingAlgorithm::doTracking(std::shared_ptr mat, + uint number) { - qobject_cast(m_Model)->doTracking(mat, number); + qobject_cast(m_Model)->doTracking(mat, + number); } -IView *ControllerTrackingAlgorithm::getTrackingParameterWidget() +IView* ControllerTrackingAlgorithm::getTrackingParameterWidget() { return m_View; } void ControllerTrackingAlgorithm::createModel() { - connectControllerToController(); + connectControllerToController(); - m_TrackingParameter = new TrackerParameter(this); + m_TrackingParameter = new TrackerParameter(this); - m_Model = new BioTrackerTrackingAlgorithm(this, m_TrackingParameter, m_TrackedTrajectoryMajor); + m_Model = new BioTrackerTrackingAlgorithm(this, + m_TrackingParameter, + m_TrackedTrajectoryMajor); } void ControllerTrackingAlgorithm::createView() @@ -45,22 +54,45 @@ void ControllerTrackingAlgorithm::createView() void ControllerTrackingAlgorithm::connectModelToController() { - BioTrackerTrackingAlgorithm *trackingAlg = qobject_cast(m_Model); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitCvMatA, this, &ControllerTrackingAlgorithm::emitCvMat); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitTrackingDone, this, &ControllerTrackingAlgorithm::emitTrackingDone); - QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, this, &ControllerTrackingAlgorithm::emitChangeDisplayImage); - QObject::connect(this, &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, trackingAlg, &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); + BioTrackerTrackingAlgorithm* trackingAlg = + qobject_cast(m_Model); + QObject::connect(trackingAlg, + &BioTrackerTrackingAlgorithm::emitCvMatA, + this, + &ControllerTrackingAlgorithm::emitCvMat); + QObject::connect(trackingAlg, + &BioTrackerTrackingAlgorithm::emitTrackingDone, + this, + &ControllerTrackingAlgorithm::emitTrackingDone); + QObject::connect(trackingAlg, + &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, + this, + &ControllerTrackingAlgorithm::emitChangeDisplayImage); + QObject::connect( + this, + &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, + trackingAlg, + &BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate); - QObject::connect(static_cast(m_View), &TrackerParameterView::parametersChanged, - trackingAlg, &BioTrackerTrackingAlgorithm::receiveParametersChanged); + 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))); + // 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::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - Q_EMIT emitAreaDescriptorUpdate(areaDescr); +void ControllerTrackingAlgorithm::receiveAreaDescriptorUpdate( + IModelAreaDescriptor* areaDescr) +{ + Q_EMIT emitAreaDescriptorUpdate(areaDescr); } diff --git a/Src/Controller/ControllerTrackingAlgorithm.h b/Src/Controller/ControllerTrackingAlgorithm.h index 7854934..9f8af37 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.h +++ b/Src/Controller/ControllerTrackingAlgorithm.h @@ -7,15 +7,23 @@ #include "Interfaces/IModel/IModelDataExporter.h" #include "../Config.h" - class ControllerTrackingAlgorithm : public IController { Q_OBJECT public: - ControllerTrackingAlgorithm(QObject* parent = 0, IBioTrackerContext* context = 0, ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); - - Config* getConfig() { return _cfg;}; - void setConfig(Config *cfg) { _cfg = cfg;}; + ControllerTrackingAlgorithm( + QObject* parent = 0, + IBioTrackerContext* context = 0, + ENUMS::CONTROLLERTYPE ctr = ENUMS::CONTROLLERTYPE::NO_CTR); + + Config* getConfig() + { + return _cfg; + }; + void setConfig(Config* cfg) + { + _cfg = cfg; + }; // IController interface public: void connectControllerToController() override; @@ -25,7 +33,7 @@ class ControllerTrackingAlgorithm : public IController IView* getTrackingParameterWidget(); public Q_SLOTS: - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); protected: void createModel() override; @@ -35,12 +43,12 @@ public Q_SLOTS: Q_SIGNALS: void emitCvMat(std::shared_ptr mat, QString name); void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); - void emitAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void emitChangeDisplayImage(QString str); + void emitAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); private: IModel* m_TrackingParameter; - IModel* m_TrackedTrajectoryMajor; + IModel* m_TrackedTrajectoryMajor; Config* _cfg; }; diff --git a/Src/Controller/null_Controller.cpp b/Src/Controller/null_Controller.cpp deleted file mode 100644 index 612c02f..0000000 --- a/Src/Controller/null_Controller.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "null_Controller.h" - -null_Controller::null_Controller() -{ - -} - -void null_Controller::createModel() -{ - -} - -void null_Controller::createView() -{ - -} - -void null_Controller::connectModelToController() -{ - -} - -void null_Controller::connectControllerToController() -{ - -} diff --git a/Src/Controller/null_Controller.h b/Src/Controller/null_Controller.h deleted file mode 100644 index a0fcc21..0000000 --- a/Src/Controller/null_Controller.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NULL_CONTROLLER_H -#define NULL_CONTROLLER_H - -#include "Interfaces/IController/IController.h" -class null_Controller : public IController -{ -public: - null_Controller(); - - // IController interface -protected: - void createModel() override; - void createView() override; - void connectModelToController() override; - void connectControllerToController() override; -}; - -#endif // NULL_CONTROLLER_H diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 52a3788..e0efb86 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -3,72 +3,85 @@ #include "TrackedComponents/TrackedComponentFactory.h" #include -BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController *parent, IModel* parameter, IModel* trajectory) +BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController* parent, + IModel* parameter, + IModel* trajectory) : IModelTrackingAlgorithm(parent) , _ipp((TrackerParameter*) parameter) { - _cfg = static_cast(parent)->getConfig(); - _TrackingParameter = (TrackerParameter*)parameter; - _TrackedTrajectoryMajor = (BST::TrackedTrajectory*)trajectory; - _nn2d = std::make_shared(_TrackedTrajectoryMajor); - - _bd = BlobsDetector(); - - _noFish = -1; - - if (_cfg->DoNetwork) { - _listener = new TcpListener(this); - _listener->listen(QHostAddress::Any, _cfg->NetworkPort); - QObject::connect(_listener, SIGNAL(newConnection()), _listener, SLOT(acceptConnection())); - } - + _cfg = static_cast(parent)->getConfig(); + _TrackingParameter = (TrackerParameter*) parameter; + _TrackedTrajectoryMajor = (BST::TrackedTrajectory*) trajectory; + _nn2d = std::make_shared(_TrackedTrajectoryMajor); + + _bd = BlobsDetector(); + + _noFish = -1; + + if (_cfg->DoNetwork) { + _listener = new TcpListener(this); + _listener->listen(QHostAddress::Any, _cfg->NetworkPort); + QObject::connect(_listener, + SIGNAL(newConnection()), + _listener, + SLOT(acceptConnection())); + } - _lastImage = nullptr; + _lastImage = nullptr; _lastFramenumber = -1; } - -void BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr) { - _AreaInfo = areaDescr; - _bd.setAreaInfo(_AreaInfo); +void BioTrackerTrackingAlgorithm::receiveAreaDescriptorUpdate( + IModelAreaDescriptor* areaDescr) +{ + _AreaInfo = areaDescr; + _bd.setAreaInfo(_AreaInfo); } BioTrackerTrackingAlgorithm::~BioTrackerTrackingAlgorithm() { } -std::vector 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++) { - BST::TrackedTrajectory *t = dynamic_cast(_TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - BST::TrackedElement *e = (BST::TrackedElement *)t->getLastChild(); - last.push_back(e->getFishPose()); - } - } - return last; +std::vector 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++) { + BST::TrackedTrajectory* t = dynamic_cast( + _TrackedTrajectoryMajor->getChild(i)); + if (t && t->getValid() && !t->getFixed()) { + BST::TrackedElement* e = (BST::TrackedElement*) t->getLastChild(); + last.push_back(e->getFishPose()); + } + } + return last; } -void BioTrackerTrackingAlgorithm::refreshPolygon() { - +void BioTrackerTrackingAlgorithm::refreshPolygon() +{ } -void BioTrackerTrackingAlgorithm::receiveParametersChanged() { +void BioTrackerTrackingAlgorithm::receiveParametersChanged() +{ if (_lastFramenumber >= 0 && _lastImage && !_lastImage->empty()) { doTracking(_lastImage, _lastFramenumber); } } -void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map> *images) { +void BioTrackerTrackingAlgorithm::sendSelectedImage( + std::map>* images) +{ std::shared_ptr sendImage; - //Send forth whatever the user selected + // Send forth whatever the user selected switch (_TrackingParameter->getSendImage()) { - case 0: //Send none + case 0: // Send none Q_EMIT emitChangeDisplayImage("Original"); break; case 1: @@ -94,123 +107,148 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage(std::map BioTrackerTrackingAlgorithm::getContourCentroids(cv::Mat& image, int minSize){ - - std::vector > contours; - std::vector hierarchy; - std::vector centroids; - - findContours( image, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0) ); - for(auto x: contours){ - cv::Point2f c(0,0); - float i=0; - for(auto y: x){ +std::vector BioTrackerTrackingAlgorithm::getContourCentroids( + cv::Mat& image, + int minSize) +{ + + std::vector> contours; + std::vector hierarchy; + std::vector centroids; + + findContours(image, + contours, + hierarchy, + cv::RETR_TREE, + cv::CHAIN_APPROX_SIMPLE, + cv::Point(0, 0)); + for (auto x : contours) { + cv::Point2f c(0, 0); + float i = 0; + for (auto y : x) { c += cv::Point2f(y); i++; } c.x = c.x / i; c.y = c.y / i; - - //cv::RotatedRect minEllipse; - cv::RotatedRect bb = minAreaRect( x ); - //check if blob is in tracking area --> this can be optimized by checking earlier (only search blobs in tracking area) - if(!_AreaInfo->inTrackingArea(c)){ - continue; - } + // cv::RotatedRect minEllipse; + cv::RotatedRect bb = minAreaRect(x); - BlobPose bc(_AreaInfo->pxToCm(c), c, bb.angle, bb.size.width, bb.size.height); + // check if blob is in tracking area --> this can be optimized by + // checking earlier (only search blobs in tracking area) + if (!_AreaInfo->inTrackingArea(c)) { + continue; + } + + BlobPose bc(_AreaInfo->pxToCm(c), + c, + bb.angle, + bb.size.width, + bb.size.height); centroids.push_back(bc); } - + return centroids; } -void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr p_image, uint framenumber) +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; - } + _ipp.m_TrackingParameter = _TrackingParameter; + _lastImage = p_image; + _lastFramenumber = framenumber; - if (_imageX != p_image->size().width || _imageY != p_image->size().height) { - _imageX = p_image->size().width; - _imageY = p_image->size().height; - Q_EMIT emitDimensionUpdate(_imageX, _imageY); - } + // dont do nothing if we ain't got an image + if (p_image->empty()) { + return; + } - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + if (_imageX != p_image->size().width || + _imageY != p_image->size().height) { + _imageX = p_image->size().width; + _imageY = p_image->size().height; + Q_EMIT emitDimensionUpdate(_imageX, _imageY); + } - //Refuse to run tracking if we have no area info... - if (_AreaInfo == nullptr) { - Q_EMIT emitTrackingDone(framenumber); - return; - } + std::chrono::system_clock::time_point start = + std::chrono::system_clock::now(); + // Refuse to run tracking if we have no area info... + if (_AreaInfo == nullptr) { + Q_EMIT emitTrackingDone(framenumber); + return; + } - //The user changed the # of fish. Reset the history and start over! - if (_noFish != _TrackedTrajectoryMajor->validCount()) { - _noFish = _TrackedTrajectoryMajor->validCount(); - _nn2d = std::make_shared(_TrackedTrajectoryMajor); - } + // The user changed the # of fish. Reset the history and start over! + if (_noFish != _TrackedTrajectoryMajor->validCount()) { + _noFish = _TrackedTrajectoryMajor->validCount(); + _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); + // 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); std::vector blobs = getContourCentroids(*dilated, 111); - // Never switch the position of the trajectories. The NN2d mapper relies on this! - // If you mess up the order, add or remove some t, then create a new mapper. - std::vector fish = getLastPositionsAsPose(); - - //Find new positions using 2D nearest neighbor - 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++) { - BST::TrackedTrajectory *t = dynamic_cast(_TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - BST::TrackedElement *e = new BST::TrackedElement(t, "n.a.", t->getId()); - - e->setFishPose(std::get<0>(poses)[trajNumber]); - e->setTime(start); - t->add(e, framenumber); - trajNumber++; - } - } - - //Send forth new positions to the robotracker, if networking is enabled - if (_TrackingParameter->getDoNetwork()){ - std::vector ps = std::get<0>(poses); - _listener->sendPositions(framenumber, ps, std::vector(), start); - } + // Never switch the position of the trajectories. The NN2d mapper relies on + // this! If you mess up the order, add or remove some t, then create a new + // mapper. + std::vector fish = getLastPositionsAsPose(); + + // Find new positions using 2D nearest neighbor + 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++) { + BST::TrackedTrajectory* t = dynamic_cast( + _TrackedTrajectoryMajor->getChild(i)); + if (t && t->getValid() && !t->getFixed()) { + BST::TrackedElement* e = new BST::TrackedElement(t, + "n.a.", + t->getId()); + + e->setFishPose(std::get<0>(poses)[trajNumber]); + e->setTime(start); + t->add(e, framenumber); + trajNumber++; + } + } + + // Send forth new positions to the robotracker, if networking is enabled + if (_TrackingParameter->getDoNetwork()) { + std::vector 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"); - } + // First the user still wants to see the original image, right? + if (framenumber == 1) { + Q_EMIT emitChangeDisplayImage("Original"); + } - std::string newSel = _TrackingParameter->getNewSelection(); + std::string newSel = _TrackingParameter->getNewSelection(); - Q_EMIT emitTrackingDone(framenumber); + Q_EMIT emitTrackingDone(framenumber); } diff --git a/Src/Model/BioTrackerTrackingAlgorithm.h b/Src/Model/BioTrackerTrackingAlgorithm.h index 8518aa0..ca456fe 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.h +++ b/Src/Model/BioTrackerTrackingAlgorithm.h @@ -1,7 +1,6 @@ #ifndef BIOTRACKERTRACKINGALGORITHM_H #define BIOTRACKERTRACKINGALGORITHM_H - #include "Interfaces/IModel/IModel.h" #include "TrackerParameter.h" @@ -25,47 +24,50 @@ class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm { Q_OBJECT public: - BioTrackerTrackingAlgorithm(IController *parent, IModel* parameter, IModel* trajectory); - ~BioTrackerTrackingAlgorithm(); + BioTrackerTrackingAlgorithm(IController* parent, + IModel* parameter, + IModel* trajectory); + ~BioTrackerTrackingAlgorithm(); Q_SIGNALS: void emitCvMatA(std::shared_ptr image, QString name); - void emitDimensionUpdate(int x, int y); - void emitTrackingDone(uint framenumber); + void emitDimensionUpdate(int x, int y); + void emitTrackingDone(uint framenumber); // ITrackingAlgorithm interface public Q_SLOTS: - void doTracking(std::shared_ptr image, uint framenumber) override; - void receiveAreaDescriptorUpdate(IModelAreaDescriptor *areaDescr); + void doTracking(std::shared_ptr image, uint framenumber) override; + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); void receiveParametersChanged(); private: -std::vector getContourCentroids(cv::Mat& image, int minSize); - void refreshPolygon(); - void sendSelectedImage(std::map>* images); + std::vector getContourCentroids(cv::Mat& image, int minSize); + void refreshPolygon(); + void sendSelectedImage( + std::map>* images); - std::vector getLastPositionsAsPose(); + std::vector getLastPositionsAsPose(); BST::TrackedTrajectory* _TrackedTrajectoryMajor; - TrackerParameter* _TrackingParameter; - IModelAreaDescriptor* _AreaInfo; + TrackerParameter* _TrackingParameter; + IModelAreaDescriptor* _AreaInfo; - TcpListener* _listener; + TcpListener* _listener; - ImagePreProcessor _ipp; - BlobsDetector _bd; - std::shared_ptr _nn2d; + ImagePreProcessor _ipp; + BlobsDetector _bd; + std::shared_ptr _nn2d; - int _noFish; + int _noFish; - //std::ofstream _ofs; + // std::ofstream _ofs; - int _imageX; - int _imageY; + int _imageX; + int _imageY; std::shared_ptr _lastImage; - uint _lastFramenumber; - Config *_cfg; + uint _lastFramenumber; + Config* _cfg; }; #endif // BIOTRACKERTRACKINGALGORITHM_H diff --git a/Src/Model/Network/TcpListener.cpp b/Src/Model/Network/TcpListener.cpp index 4f76136..6a6f5fb 100644 --- a/Src/Model/Network/TcpListener.cpp +++ b/Src/Model/Network/TcpListener.cpp @@ -2,68 +2,74 @@ #include -TcpListener::TcpListener(QObject *parent) : QTcpServer(parent) +TcpListener::TcpListener(QObject* parent) +: QTcpServer(parent) { } void TcpListener::acceptConnection() { - while (this->hasPendingConnections()) - { - QTcpSocket *socket = this->nextPendingConnection(); - _sockets.insert(socket); - QObject::connect(socket, &QTcpSocket::disconnected, [this, socket](){ - _sockets.erase(socket); - }); - } + while (this->hasPendingConnections()) { + QTcpSocket* socket = this->nextPendingConnection(); + _sockets.insert(socket); + QObject::connect(socket, &QTcpSocket::disconnected, [this, socket]() { + _sockets.erase(socket); + }); + } } void TcpListener::sendPositionsToSocket(std::string packet) { - for (auto const& socket : _sockets) { - socket->write(packet.c_str()); - } + for (auto const& socket : _sockets) { + socket->write(packet.c_str()); + } } std::string TcpListener::sendPositions( - int frameNo, - const std::vector& poses, - const std::vector& polygon, - std::chrono::system_clock::time_point ts) + int frameNo, + const std::vector& poses, + const std::vector& polygon, + std::chrono::system_clock::time_point ts) { - std::stringstream str; - str << "frame:" << frameNo << ";"; + std::stringstream str; + str << "frame:" << frameNo << ";"; - str << "polygon:" << polygon.size() << ";"; - for (auto vertex = polygon.cbegin(); vertex != polygon.cend(); ++vertex) - { - str << vertex->x << "x" << vertex->y << ";"; - } + str << "polygon:" << polygon.size() << ";"; + for (auto vertex = polygon.cbegin(); vertex != polygon.cend(); ++vertex) { + str << vertex->x << "x" << vertex->y << ";"; + } - int fishCount = poses.size(); - int fi = 0; - str << "fishcount:" << fishCount << ";"; + int fishCount = poses.size(); + int fi = 0; + str << "fishcount:" << fishCount << ";"; - for (int i=0; i < poses.size(); i++) - { + for (int i = 0; i < poses.size(); i++) { - str << i+1 << "," // the id of the fish - << poses[i].position_cm().x << "," // real position in cm - x-coordinate - << poses[i].position_cm().y << "," // real position in cm - y-coordinate - << poses[i].orientation_rad() << "," // orientation in radian - << poses[i].orientation_deg() << "," // orientation in degree - << poses[i].width() << "," // size of the fish blob: width - << poses[i].height() << "," // size of the fish blob: height - << long(std::chrono::duration_cast(ts.time_since_epoch()).count()) << "," // the time stamp - << "F" << (((i + 1) == poses.size()) ? ";" : "&"); // F: obsolete "isRobofish" flag (F: not a robofish) - } - str << "end\n"; + str << i + 1 << "," // the id of the fish + << poses[i].position_cm().x + << "," // real position in cm - x-coordinate + << poses[i].position_cm().y + << "," // real position in cm - y-coordinate + << poses[i].orientation_rad() << "," // orientation in radian + << poses[i].orientation_deg() << "," // orientation in degree + << poses[i].width() << "," // size of the fish blob: width + << poses[i].height() << "," // size of the fish blob: height + << long(std::chrono::duration_cast( + ts.time_since_epoch()) + .count()) + << "," // the time stamp + << "F" + << (((i + 1) == poses.size()) ? ";" + : "&"); // F: obsolete "isRobofish" + // flag (F: not a robofish) + } + str << "end\n"; - std::cout << str.str() << std::endl; + std::cout << str.str() << std::endl; #ifdef SAVETRACKINGPACKAGES - _trackingInfoOutputFile4Simulation << str.str(); + _trackingInfoOutputFile4Simulation << str.str(); #endif - sendPositionsToSocket(str.str()); - return str.str(); + sendPositionsToSocket(str.str()); + return str.str(); } diff --git a/Src/Model/Network/TcpListener.h b/Src/Model/Network/TcpListener.h index d53d30f..e3fbfd5 100644 --- a/Src/Model/Network/TcpListener.h +++ b/Src/Model/Network/TcpListener.h @@ -13,19 +13,19 @@ class TcpListener : public QTcpServer { - Q_OBJECT + Q_OBJECT public: - TcpListener(QObject *parent = 0); + TcpListener(QObject* parent = 0); public slots: - void acceptConnection(); - void sendPositionsToSocket(std::string packet); - std::string sendPositions(int frameNo, - const std::vector& poses, - const std::vector& polygon, - std::chrono::system_clock::time_point ts); + 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::unordered_set _sockets; + std::unordered_set _sockets; }; diff --git a/Src/Model/TrackedComponents/TrackedComponentFactory.cpp b/Src/Model/TrackedComponents/TrackedComponentFactory.cpp index d2e92cd..b83c7ed 100644 --- a/Src/Model/TrackedComponents/TrackedComponentFactory.cpp +++ b/Src/Model/TrackedComponents/TrackedComponentFactory.cpp @@ -3,37 +3,40 @@ #include "TrackedTrajectory.h" #include "TrackedElement.h" -namespace BST{ - - TrackedComponentFactory::TrackedComponentFactory() - { - - } - - TrackedComponentFactory::~TrackedComponentFactory() - { - - } - - QList TrackedComponentFactory::getElementTypes() { - return QList{ "TrackedElement" }; - } - - IModelTrackedComponent *TrackedComponentFactory::createTrackedElement(QString name) - { - return new BST::TrackedElement(this, "n.a."); - } - - IModelTrackedComponent *TrackedComponentFactory::createTrackedObject(QString name) - { - BST::TrackedTrajectory *t = new BST::TrackedTrajectory(); - BST::TrackedElement *e = new BST::TrackedElement(this, "n.a.", 0); - t->add(e, 0); - return t; - } - - IModelTrackedComponent *TrackedComponentFactory::createTrackedTrajectory(QString name) - { - return new BST::TrackedTrajectory(); - } +namespace BST +{ + + TrackedComponentFactory::TrackedComponentFactory() + { + } + + TrackedComponentFactory::~TrackedComponentFactory() + { + } + + QList TrackedComponentFactory::getElementTypes() + { + return QList{"TrackedElement"}; + } + + IModelTrackedComponent* TrackedComponentFactory::createTrackedElement( + QString name) + { + return new BST::TrackedElement(this, "n.a."); + } + + IModelTrackedComponent* TrackedComponentFactory::createTrackedObject( + QString name) + { + BST::TrackedTrajectory* t = new BST::TrackedTrajectory(); + BST::TrackedElement* e = new BST::TrackedElement(this, "n.a.", 0); + t->add(e, 0); + return t; + } + + IModelTrackedComponent* TrackedComponentFactory::createTrackedTrajectory( + QString name) + { + return new BST::TrackedTrajectory(); + } } diff --git a/Src/Model/TrackedComponents/TrackedComponentFactory.h b/Src/Model/TrackedComponents/TrackedComponentFactory.h index 26455a2..3d009ab 100644 --- a/Src/Model/TrackedComponents/TrackedComponentFactory.h +++ b/Src/Model/TrackedComponents/TrackedComponentFactory.h @@ -2,22 +2,22 @@ #include "Interfaces/IModel/IModelTrackedComponentFactory.h" -namespace BST{ - -class TrackedComponentFactory : public IModelTrackedComponentFactory +namespace BST { - Q_OBJECT -public: - TrackedComponentFactory(); - ~TrackedComponentFactory(); - QList getElementTypes() override; + class TrackedComponentFactory : public IModelTrackedComponentFactory + { + Q_OBJECT + public: + TrackedComponentFactory(); + ~TrackedComponentFactory(); - // ITrackedComponentFactory interface -protected: - IModelTrackedComponent *createTrackedElement(QString name) override; - IModelTrackedComponent *createTrackedObject(QString name) override; - IModelTrackedComponent *createTrackedTrajectory(QString name) override; -}; -} + QList getElementTypes() override; + // ITrackedComponentFactory interface + protected: + IModelTrackedComponent* createTrackedElement(QString name) override; + IModelTrackedComponent* createTrackedObject(QString name) override; + IModelTrackedComponent* createTrackedTrajectory(QString name) override; + }; +} diff --git a/Src/Model/TrackedComponents/TrackedElement.cpp b/Src/Model/TrackedComponents/TrackedElement.cpp index ae313ac..7f9904d 100644 --- a/Src/Model/TrackedComponents/TrackedElement.cpp +++ b/Src/Model/TrackedComponents/TrackedElement.cpp @@ -6,182 +6,233 @@ #include "QPainter" #include "QtMath" - namespace BST { - TrackedElement::TrackedElement(QObject *parent, QString name, int id) : - IModelTrackedPoint(parent) - { - _x = 0; - _y = 0; - _id = id; - _deg = 0; - _rad = 0; - _valid = false; - _fixed = false; - } - - void TrackedElement::setValid(bool v) - { - _valid = v; - if (_parentNode) { - TrackedTrajectory* n = dynamic_cast(_parentNode); - if (n) - n->triggerRecalcValid(); - } - } - - - QString TrackedElement::getName() - { - return ""; - } - - void TrackedElement::setFishPose(FishPose p) - { - _pose = p; - _x = p.position_cm().x; - _y = p.position_cm().y; - _deg = p.orientation_deg(); - _rad = p.orientation_rad(); - _ypx = p.position_px().y; - _xpx = p.position_px().x; - _valid = true; - Q_EMIT notifyView(); - } - - void TrackedElement::setTime(std::chrono::system_clock::time_point t) { - _timeSysclck = t; - }; - - void TrackedElement::setTime(qint64 t) { - std::string::size_type sz = 0; - long long ll = t / 1000; - long long remainder = t % 1000; - std::time_t tm(ll); - - _timeSysclck = std::chrono::system_clock::from_time_t(tm); - std::chrono::duration 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; - } + 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) + { + 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/Src/Model/TrackedComponents/TrackedElement.h b/Src/Model/TrackedComponents/TrackedElement.h index 1dfaa69..d799059 100644 --- a/Src/Model/TrackedComponents/TrackedElement.h +++ b/Src/Model/TrackedComponents/TrackedElement.h @@ -9,86 +9,160 @@ namespace BST { - /** - * This class is an example of how a TrackedComponent could be defined. - * This class inherits from the IModelTrackedComponent class and is therefor part of the Composite Pattern. - * This class represents the Leaf class in the Composite Pattern. - * Objects of this class have a QObject as parent. - */ - class TrackedElement : public IModelTrackedPoint - { - Q_OBJECT + /** + * This class is an example of how a TrackedComponent could be defined. + * This class inherits from the IModelTrackedComponent class and is + * therefor part of the Composite Pattern. This class represents the Leaf + * class in the Composite Pattern. Objects of this class have a QObject as + * parent. + */ + class TrackedElement : public IModelTrackedPoint + { + Q_OBJECT - public: - TrackedElement(QObject *parent = 0, QString name = "n.a.", int id = 0); + public: + TrackedElement(QObject* parent = 0, QString name = "n.a.", int id = 0); - QString getName(); - QString getCoordinateUnit() override { return _unit; }; - void setCoordinateUnit(QString str) override { _unit = str; }; + QString getName(); + QString getCoordinateUnit() override + { + return _unit; + }; + void setCoordinateUnit(QString str) override + { + _unit = str; + }; - void setX(float val); - void setY(float val); - void setW(float w); - void setH(float h); - void setXpx(float val); - void setYpx(float val); - void setWpx(float w); - void setHpx(float h); - void setRad(float r); - void setDeg(float d); - void setId(int val) { _id = val; }; - void setTime(std::chrono::system_clock::time_point t); - void setTime(qint64 t); - void setTimeString(QString t) { _timeString = t; }; - void setValid(bool v); - void setFixed(bool f) { _fixed = f; }; + void setX(float val); + void setY(float val); + void setW(float w); + void setH(float h); + void setXpx(float val); + void setYpx(float val); + void setWpx(float w); + void setHpx(float h); + void setRad(float r); + void setDeg(float d); + void setId(int val) + { + _id = val; + }; + void setTime(std::chrono::system_clock::time_point t); + void setTime(qint64 t); + void setTimeString(QString t) + { + _timeString = t; + }; + void setValid(bool v); + void setFixed(bool f) + { + _fixed = f; + }; + float getX(); + float getY(); + float getXpx(); + float getYpx(); + float getW() + { + return _w; + }; + float getH() + { + return _h; + }; + float getWpx() + { + return _w; + }; + float getHpx() + { + return _h; + }; + float getRad() + { + return _rad; + }; + float getDeg(); + int getId() + { + return _id; + }; + qint64 getTime(); + QString getTimeString(); + bool getValid() + { + return _valid; + }; + bool getFixed() + { + return _fixed; + }; - float getX(); - float getY(); - float getXpx(); - float getYpx(); - float getW() { return _w; }; - float getH() { return _h; }; - float getWpx() { return _w; }; - float getHpx() { return _h; }; - float getRad() { return _rad; }; - float getDeg(); - int getId() { return _id; }; - qint64 getTime(); - QString getTimeString(); - bool getValid() { return _valid; }; - bool getFixed() { return _fixed; }; + bool hasX() + { + return true; + }; + bool hasY() + { + return true; + }; + bool hasW() + { + return false; + }; + bool hasH() + { + return false; + }; + bool hasXpx() + { + return true; + }; + bool hasYpx() + { + return true; + }; + bool hasWpx() + { + return false; + }; + bool hasHpx() + { + return false; + }; + bool hasRad() + { + return true; + }; + bool hasDeg() + { + return true; + }; + bool hasTime() + { + return true; + }; + bool hasTimeString() + { + return true; + }; - bool hasX() { return true; }; - bool hasY() { return true; }; - bool hasW() { return false; }; - bool hasH() { return false; }; - bool hasXpx() { return true; }; - bool hasYpx() { return true; }; - bool hasWpx() { return false; }; - bool hasHpx() { return false; }; - bool hasRad() { return true; }; - bool hasDeg() { return true; }; - bool hasTime() { return true; }; - bool hasTimeString() { return true; }; + void pressed(); + void notPressed(); + bool getPressedStatus(); - void pressed(); - void notPressed(); - bool getPressedStatus(); + void setFishPose(FishPose p); + FishPose getFishPose(); - void setFishPose(FishPose p); - FishPose getFishPose(); + // ITrackedPoint interface + public: + void operate(); - // ITrackedPoint interface - public: - void operate(); - - private: - std::chrono::system_clock::time_point _timeSysclck; - QString _unit = "cm"; - FishPose _pose; - QString _timeString; - }; + private: + std::chrono::system_clock::time_point _timeSysclck; + QString _unit = "cm"; + FishPose _pose; + QString _timeString; + }; } - diff --git a/Src/Model/TrackedComponents/TrackedTrajectory.cpp b/Src/Model/TrackedComponents/TrackedTrajectory.cpp index e4dd321..9fd38d6 100644 --- a/Src/Model/TrackedComponents/TrackedTrajectory.cpp +++ b/Src/Model/TrackedComponents/TrackedTrajectory.cpp @@ -2,43 +2,49 @@ #include "QDebug" #include "TrackedElement.h" -namespace BST{ - - void TrackedTrajectory::triggerRecalcValid() { +namespace BST +{ + + void TrackedTrajectory::triggerRecalcValid() + { g_calcValid = 1; } - void TrackedTrajectory::setValid(bool v) { + void TrackedTrajectory::setValid(bool v) + { _valid = v; if (_parentNode) { - TrackedTrajectory* n = dynamic_cast(_parentNode); + TrackedTrajectory* n = dynamic_cast( + _parentNode); if (n) n->triggerRecalcValid(); } } - TrackedTrajectory::TrackedTrajectory(QObject *parent, QString name) : - ::TrackedTrajectory(parent), - name(name) + TrackedTrajectory::TrackedTrajectory(QObject* parent, QString name) + : ::TrackedTrajectory(parent) + , name(name) { setFixed(false); - g_calcValid = 1; + g_calcValid = 1; g_validCount = 0; - _size = 0; - _valid = true; + _size = 0; + _valid = true; } void TrackedTrajectory::operate() { - qDebug() << "Printing all TrackedElements in TrackedObject " << name; - qDebug() << "========================= Begin =========================="; + qDebug() << "Printing all TrackedElements in TrackedObject " << name; + qDebug() + << "========================= Begin =========================="; for (int i = 0; i < _TrackedComponents.size(); ++i) { - dynamic_cast(_TrackedComponents.at(i))->operate(); + dynamic_cast(_TrackedComponents.at(i))->operate(); } - qDebug() << "======================== End ========================="; + qDebug() + << "======================== End ========================="; } - void TrackedTrajectory::add(IModelTrackedComponent *comp, int pos) + void TrackedTrajectory::add(IModelTrackedComponent* comp, int pos) { comp->setParent(this); @@ -47,10 +53,8 @@ namespace BST{ _TrackedComponents.append(comp); _size++; g_validCount++; - } - else if (_size <= pos) { - while (_size < pos) - { + } else if (_size <= pos) { + while (_size < pos) { _TrackedComponents.append(nullptr); _size++; } @@ -58,13 +62,12 @@ namespace BST{ _TrackedComponents.append(comp); _size++; g_validCount++; - } - else { + } else { _TrackedComponents[pos] = comp; } } - bool TrackedTrajectory::remove(IModelTrackedComponent *comp) + bool TrackedTrajectory::remove(IModelTrackedComponent* comp) { g_calcValid = 1; comp->setValid(false); @@ -74,7 +77,7 @@ namespace BST{ void TrackedTrajectory::clear() { g_calcValid = 1; - foreach(IModelTrackedComponent* el, _TrackedComponents) { + foreach (IModelTrackedComponent* el, _TrackedComponents) { if (dynamic_cast(el)) dynamic_cast(el)->clear(); } @@ -97,8 +100,8 @@ namespace BST{ IModelTrackedComponent* TrackedTrajectory::getValidChild(int index) { int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { - if (el){ + foreach (IModelTrackedComponent* el, _TrackedComponents) { + if (el) { if (c == index && el->getValid()) return el; c += el->getValid() ? 1 : 0; @@ -124,16 +127,15 @@ namespace BST{ { if (g_calcValid == 1) { int c = 0; - foreach(IModelTrackedComponent* el, _TrackedComponents) { + foreach (IModelTrackedComponent* el, _TrackedComponents) { if (el) c += el->getValid() ? 1 : 0; } g_validCount = c; - g_calcValid = 0; + g_calcValid = 0; return c; - } - else { + } else { return g_validCount; } } diff --git a/Src/Model/TrackedComponents/TrackedTrajectory.h b/Src/Model/TrackedComponents/TrackedTrajectory.h index 867e476..7459e9e 100644 --- a/Src/Model/TrackedComponents/TrackedTrajectory.h +++ b/Src/Model/TrackedComponents/TrackedTrajectory.h @@ -6,44 +6,44 @@ namespace BST { - /** - * This class inherits from the IModelTrackedTrajectory class and is therefor part of the Composite Pattern. - * This class represents the Composite class. - * This class is responsibility for the handling of Leaf objects. - * Internaly this class uses a QList for storing Leaf object. - * - * Objects of this class have a QObject as parent. - */ - class TrackedTrajectory : public ::TrackedTrajectory { - Q_OBJECT - - public: - TrackedTrajectory(QObject *parent = 0, QString name = "n.a."); - ~TrackedTrajectory()override{}; - - // ITrackedComponent interface - public: - void operate(); - - // ITrackedObject interface - public: - void add(IModelTrackedComponent *comp, int pos = -1) override; - bool remove(IModelTrackedComponent *comp) override; - void clear() override; - IModelTrackedComponent *getChild(int index) override; - IModelTrackedComponent* getValidChild(int index) override; - IModelTrackedComponent *getLastChild() override; - int size() override; - int validCount() override; - void setValid(bool v) override; - void triggerRecalcValid(); - - private: - int g_calcValid = 1; - int g_validCount = 0; - int _size = 0; - QString name; - }; - + /** + * This class inherits from the IModelTrackedTrajectory class and is + * therefor part of the Composite Pattern. This class represents the + * Composite class. This class is responsibility for the handling of Leaf + * objects. Internaly this class uses a QList for storing Leaf object. + * + * Objects of this class have a QObject as parent. + */ + class TrackedTrajectory : public ::TrackedTrajectory + { + Q_OBJECT + + public: + TrackedTrajectory(QObject* parent = 0, QString name = "n.a."); + ~TrackedTrajectory() override{}; + + // ITrackedComponent interface + public: + void operate(); + + // ITrackedObject interface + public: + void add(IModelTrackedComponent* comp, int pos = -1) override; + bool remove(IModelTrackedComponent* comp) override; + void clear() override; + IModelTrackedComponent* getChild(int index) override; + IModelTrackedComponent* getValidChild(int index) override; + IModelTrackedComponent* getLastChild() override; + int size() override; + int validCount() override; + void setValid(bool v) override; + void triggerRecalcValid(); + + private: + int g_calcValid = 1; + int g_validCount = 0; + int _size = 0; + QString name; + }; } diff --git a/Src/Model/TrackedComponents/pose/FishPose.cpp b/Src/Model/TrackedComponents/pose/FishPose.cpp index af0bfcc..7442b3c 100644 --- a/Src/Model/TrackedComponents/pose/FishPose.cpp +++ b/Src/Model/TrackedComponents/pose/FishPose.cpp @@ -1,33 +1,44 @@ #include "FishPose.h" #include "../../../helper/CvHelper.h" -FishPose::FishPose(cv::Point2f pos_cm , cv::Point pos_px, float rad, float deg, float width, float height, float score) : - _position_cm(pos_cm), - _position_px(pos_px), - _radAngle(rad), - _degAngle(deg), - _width(width), - _height(height), - _score(score) +FishPose::FishPose(cv::Point2f pos_cm, + cv::Point pos_px, + float rad, + float deg, + float width, + float height, + float score) +: _position_cm(pos_cm) +, _position_px(pos_px) +, _radAngle(rad) +, _degAngle(deg) +, _width(width) +, _height(height) +, _score(score) { - assert(_degAngle >= -360.0f && _degAngle <= 360.0f); - time(&_timev); + assert(_degAngle >= -360.0f && _degAngle <= 360.0f); + time(&_timev); } - std::string FishPose::toString(bool rectified) { - std::ostringstream out; - if(rectified == false) - out << _position_px.x << ";" << _position_px.y << ";" << _degAngle << ";" << _radAngle; - else - out << _position_cm.x << ";" << _position_cm.y << ";" << _degAngle << ";" << _radAngle; - return out.str(); + std::ostringstream out; + if (rectified == false) + out << _position_px.x << ";" << _position_px.y << ";" << _degAngle + << ";" << _radAngle; + else + out << _position_cm.x << ";" << _position_cm.y << ";" << _degAngle + << ";" << _radAngle; + return out.str(); } -float FishPose::calculateProbabilityOfIdentity(const FishPose &first, const FishPose &second, float angleImportance) +float FishPose::calculateProbabilityOfIdentity(const FishPose& first, + const FishPose& second, + float angleImportance) { - //Preliminary method for calculating identity of entities. See Issue biotracker_core/issues/130 for a discussion of this topic. - float distance = CvHelper::getDistance(first.position_cm(), second.position_cm()); - return distance <= 0 ? std::numeric_limits::max() : 1.0/distance; + // Preliminary method for calculating identity of entities. See Issue + // biotracker_core/issues/130 for a discussion of this topic. + float distance = CvHelper::getDistance(first.position_cm(), + second.position_cm()); + return distance <= 0 ? std::numeric_limits::max() : 1.0 / distance; } diff --git a/Src/Model/TrackedComponents/pose/FishPose.h b/Src/Model/TrackedComponents/pose/FishPose.h index 39778f8..57f19e2 100644 --- a/Src/Model/TrackedComponents/pose/FishPose.h +++ b/Src/Model/TrackedComponents/pose/FishPose.h @@ -7,127 +7,186 @@ class FishPose : public IPose { public: - /** - * The standard constructor. - */ - FishPose(cv::Point2f pos_cm = cv::Point2f(-1,-1), cv::Point pos_px = cv::Point(-1,-1), float rad = 0, float deg = 0, float width = 0, float height = 0, float score = 0.0); - - /** - * Copy constructor. - */ - FishPose(const FishPose &other) : FishPose(other._position_cm, other._position_px, other._radAngle, other._degAngle, other._width, other._height, other._score) - { - time(&_timev); - } - - /* Simple identity of fish poses, based on orientation, position and dimensions - */ - inline bool operator == (const FishPose &b) const{ - if (b.orientation_rad() == orientation_rad() && - b.position_cm() == position_cm() && - b.width() == width() && - b.height() == height()) - return true; - return false; - } - - /** - * Gets the position of the pose in cm. - * @return: position in cm. - */ - cv::Point2f position_cm() const { return _position_cm; } - - /** - * Gets the position of the pose in pixel. - * @return: position in px. - */ - cv::Point position_px() const { return _position_px; } - - /** - * Gets the position of the pose in pixel as floating point values. - * @return: position in px. - */ - cv::Point2f position_pxf() const { return cv::Point2f(_position_px.x, _position_px.y); } - - - /** - * Gets the orientation of the pose as degree. - * @return: orientation angle. - */ - float orientation_deg() const { return _degAngle; } - - /** - * Sets the orientation of the pose as degree. - * @param: degAngle, the orientation angle to set. - */ - void set_orientation_deg(float degAngle) { _degAngle = degAngle; time(&_timev); assert(_degAngle >= -360.0f && _degAngle <= 360.0f); } - - /** - * Gets the orientation of the pose as radian. - * @return: orientation angle. - */ - float orientation_rad() const { return _radAngle; } - - /** - * Sets the orientation of the pose as radian. - * @param: radAngle, the orientation angle to set. - */ - void set_orientation_rad(float radAngle) { _radAngle = radAngle; time(&_timev); } - - /** - * Gets the width pose. - * @return: width of the pose - */ - float width() const { return _width; } - - /** - * Gets the height pose. - * @return: height of the pose - */ - float height() const { return _height; } - - /** - * Checks if the fish pose is valid. Means, x-pos != -1 and y-pose != -1. - * @return: true if position is valid, false otherwise. - */ - bool isValid() { return (_position_px.x != -1 && _position_px.y != -1) ? true : false; } - - /** - * @return: the score of the fish that comes from the mapper - usually between 0 and 1 - */ - float getScore() { return _score; } - - /** - * Sets the score of the fish pose. Conventionally, it should be between 0 and 1. - */ - void setScore(float score) { _score = score; } - /** - * Gets the time stamp. - * - */ - time_t ts() { return _timev; } - - /** - * Converts a pose to standard string. - * @param: rectified, specified whether the position is rectified. - * @return: a position as a standard string. - */ - std::string toString(bool rectified = false); - - /** - * Calculates the probability that two poses are the same. - * The influence of the angle can be set by the parameter angleImportance. - * @return probability between 0 and 1 - */ - static float calculateProbabilityOfIdentity(const FishPose &first, const FishPose &second, float angleImportance = 0.2f); + /** + * The standard constructor. + */ + FishPose(cv::Point2f pos_cm = cv::Point2f(-1, -1), + cv::Point pos_px = cv::Point(-1, -1), + float rad = 0, + float deg = 0, + float width = 0, + float height = 0, + float score = 0.0); + + /** + * Copy constructor. + */ + FishPose(const FishPose& other) + : FishPose(other._position_cm, + other._position_px, + other._radAngle, + other._degAngle, + other._width, + other._height, + other._score) + { + time(&_timev); + } + + /* Simple identity of fish poses, based on orientation, position and + * dimensions + */ + inline bool operator==(const FishPose& b) const + { + if (b.orientation_rad() == orientation_rad() && + b.position_cm() == position_cm() && b.width() == width() && + b.height() == height()) + return true; + return false; + } + + /** + * Gets the position of the pose in cm. + * @return: position in cm. + */ + cv::Point2f position_cm() const + { + return _position_cm; + } + + /** + * Gets the position of the pose in pixel. + * @return: position in px. + */ + cv::Point position_px() const + { + return _position_px; + } + + /** + * Gets the position of the pose in pixel as floating point values. + * @return: position in px. + */ + cv::Point2f position_pxf() const + { + return cv::Point2f(_position_px.x, _position_px.y); + } + + /** + * Gets the orientation of the pose as degree. + * @return: orientation angle. + */ + float orientation_deg() const + { + return _degAngle; + } + + /** + * Sets the orientation of the pose as degree. + * @param: degAngle, the orientation angle to set. + */ + void set_orientation_deg(float degAngle) + { + _degAngle = degAngle; + time(&_timev); + assert(_degAngle >= -360.0f && _degAngle <= 360.0f); + } + + /** + * Gets the orientation of the pose as radian. + * @return: orientation angle. + */ + float orientation_rad() const + { + return _radAngle; + } + + /** + * Sets the orientation of the pose as radian. + * @param: radAngle, the orientation angle to set. + */ + void set_orientation_rad(float radAngle) + { + _radAngle = radAngle; + time(&_timev); + } + + /** + * Gets the width pose. + * @return: width of the pose + */ + float width() const + { + return _width; + } + + /** + * Gets the height pose. + * @return: height of the pose + */ + float height() const + { + return _height; + } + + /** + * Checks if the fish pose is valid. Means, x-pos != -1 and y-pose != -1. + * @return: true if position is valid, false otherwise. + */ + bool isValid() + { + return (_position_px.x != -1 && _position_px.y != -1) ? true : false; + } + + /** + * @return: the score of the fish that comes from the mapper - usually + * between 0 and 1 + */ + float getScore() + { + return _score; + } + + /** + * Sets the score of the fish pose. Conventionally, it should be between 0 + * and 1. + */ + void setScore(float score) + { + _score = score; + } + /** + * Gets the time stamp. + * + */ + time_t ts() + { + return _timev; + } + + /** + * Converts a pose to standard string. + * @param: rectified, specified whether the position is rectified. + * @return: a position as a standard string. + */ + std::string toString(bool rectified = false); + + /** + * Calculates the probability that two poses are the same. + * The influence of the angle can be set by the parameter angleImportance. + * @return probability between 0 and 1 + */ + static float calculateProbabilityOfIdentity(const FishPose& first, + const FishPose& second, + float angleImportance = 0.2f); private: - cv::Point2f _position_cm; - cv::Point _position_px; - float _radAngle; - float _degAngle; - float _width; - float _height; - float _score; - time_t _timev; + cv::Point2f _position_cm; + cv::Point _position_px; + float _radAngle; + float _degAngle; + float _width; + float _height; + float _score; + time_t _timev; }; diff --git a/Src/Model/TrackedComponents/pose/IPose.h b/Src/Model/TrackedComponents/pose/IPose.h index 1d315ab..71c0752 100644 --- a/Src/Model/TrackedComponents/pose/IPose.h +++ b/Src/Model/TrackedComponents/pose/IPose.h @@ -5,25 +5,27 @@ class IPose { public: - virtual ~IPose() {} + virtual ~IPose() + { + } - /** - * Gets the fish position as centimeter metric. - */ - virtual cv::Point2f position_cm() const = 0; + /** + * Gets the fish position as centimeter metric. + */ + virtual cv::Point2f position_cm() const = 0; - /** - * Gets the fish position as pixel metric. - */ - virtual cv::Point position_px() const = 0; + /** + * Gets the fish position as pixel metric. + */ + virtual cv::Point position_px() const = 0; - /** - * Gets the fish orientation in degree. - */ - virtual float orientation_deg() const = 0; + /** + * Gets the fish orientation in degree. + */ + virtual float orientation_deg() const = 0; - /** - * Gets the fish orientation in radian. - */ - virtual float orientation_rad() const = 0; + /** + * Gets the fish orientation in radian. + */ + virtual float orientation_rad() const = 0; }; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 645159c..365bc9e 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -1,54 +1,53 @@ #include "TrackerParameter.h" #include "../Controller/ControllerTrackingAlgorithm.h" -TrackerParameter::TrackerParameter(QObject *parent) : - IModel(parent) +TrackerParameter::TrackerParameter(QObject* parent) +: IModel(parent) { - - _cfg = static_cast(parent)->getConfig(); - - _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; - _BinarizationThreshold = _cfg->BinarizationThreshold; - _SizeErode = _cfg->SizeErode; - _SizeDilate = _cfg->SizeDilate; - _MinBlobSize = _cfg->MinBlobSize; - _MaxBlobSize = _cfg->MaxBlobSize; - _LearningRate = _cfg->LearningRate; + _cfg = static_cast(parent)->getConfig(); - _doNetwork = _cfg->DoNetwork; - _networkPort = _cfg->NetworkPort; + _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; + _BinarizationThreshold = _cfg->BinarizationThreshold; + _SizeErode = _cfg->SizeErode; + _SizeDilate = _cfg->SizeDilate; + _MinBlobSize = _cfg->MinBlobSize; + _MaxBlobSize = _cfg->MaxBlobSize; - _doBackground = true; - _sendImage = 0; //Send no image - _resetBackground = false; + _LearningRate = _cfg->LearningRate; - _algorithm = "Custom"; + _doNetwork = _cfg->DoNetwork; + _networkPort = _cfg->NetworkPort; + + _doBackground = true; + _sendImage = 0; // Send no image + _resetBackground = false; + + _algorithm = "Custom"; Q_EMIT notifyView(); } void TrackerParameter::setBinarizationThreshold(int x) { - _BinarizationThreshold = x; - _cfg->BinarizationThreshold = x; - Q_EMIT notifyView(); + _BinarizationThreshold = x; + _cfg->BinarizationThreshold = x; + Q_EMIT notifyView(); } int TrackerParameter::getBinarizationThreshold() { - return _BinarizationThreshold; + return _BinarizationThreshold; } - void TrackerParameter::setUseAbsoluteDifference(bool value) { - _UseAbsoluteDifference = value; - _cfg->UseAbsoluteDifference = value; - Q_EMIT notifyView(); + _UseAbsoluteDifference = value; + _cfg->UseAbsoluteDifference = value; + Q_EMIT notifyView(); } bool TrackerParameter::getUseAbsoluteDifference() { - return _UseAbsoluteDifference; + return _UseAbsoluteDifference; } \ No newline at end of file diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 5ad37d1..4ee2f4b 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -1,7 +1,6 @@ #ifndef TRACKERPARAMETER_H #define TRACKERPARAMETER_H - #include "Interfaces/IModel/IModel.h" #include "../Config.h" @@ -9,117 +8,164 @@ class TrackerParameter : public IModel { Q_OBJECT public: - TrackerParameter(QObject *parent = 0); + TrackerParameter(QObject* parent = 0); public slots: - QString getAlgorithm() { return _algorithm; } - void setAlgorithm(QString algorithm) { - _algorithm = algorithm; - } - - void setUseAbsoluteDifference(bool x); - bool getUseAbsoluteDifference(); - - void setBinarizationThreshold(int x); - int getBinarizationThreshold(); - - int getSizeErode() { return _SizeErode; }; - void setSizeErode(int x) { - _SizeErode = x; - _cfg->SizeErode = x; - Q_EMIT notifyView(); - }; - - int getSizeDilate() { return _SizeDilate; }; - void setSizeDilate(int x) { - _SizeDilate = x; - _cfg->SizeDilate = x; - Q_EMIT notifyView(); - }; - - double getLearningRate() { return _LearningRate; }; - void setLearningRate(double x) { - _LearningRate = x; - _cfg->LearningRate = x; - Q_EMIT notifyView(); - }; - - double getMinBlobSize() { return _MinBlobSize; }; - void setMinBlobSize(double x) { - _MinBlobSize = x; - _cfg->MinBlobSize = x; - Q_EMIT notifyView(); - }; - - double getMaxBlobSize() { return _MaxBlobSize; }; - void setMaxBlobSize(double x) { - _MaxBlobSize = x; - _cfg->MaxBlobSize = x; - Q_EMIT notifyView(); - }; - - bool getDoBackground() { return _doBackground; }; - void setDoBackground(bool x) { - _doBackground = x; - _cfg->DoBackground = x; - Q_EMIT notifyView(); - }; - - bool getDoNetwork() { return _doNetwork; }; - void setDoNetwork(bool x) { - _doNetwork = x; - _cfg->DoNetwork = x; - Q_EMIT notifyView(); - }; - - int getSendImage() { return _sendImage; }; - void setSendImage(int x) { - _sendImage = x; - Q_EMIT notifyView(); - }; - - bool getResetBackground() { return _resetBackground; }; - void setResetBackground(bool x) { - _resetBackground = x; - Q_EMIT notifyView(); - }; - - int getNoFish() { return _noFish; }; - void setNoFish(int x) { - _noFish = x; - _cfg->NoFish = x; - Q_EMIT notifyView(); - }; - - std::string getNewSelection() { return _newSelection; }; - void setNewSelection(std::string x) { - _newSelection = x; - } + QString getAlgorithm() + { + return _algorithm; + } + void setAlgorithm(QString algorithm) + { + _algorithm = algorithm; + } + + void setUseAbsoluteDifference(bool x); + bool getUseAbsoluteDifference(); + + void setBinarizationThreshold(int x); + int getBinarizationThreshold(); + + int getSizeErode() + { + return _SizeErode; + }; + void setSizeErode(int x) + { + _SizeErode = x; + _cfg->SizeErode = x; + Q_EMIT notifyView(); + }; + + int getSizeDilate() + { + return _SizeDilate; + }; + void setSizeDilate(int x) + { + _SizeDilate = x; + _cfg->SizeDilate = x; + Q_EMIT notifyView(); + }; + + double getLearningRate() + { + return _LearningRate; + }; + void setLearningRate(double x) + { + _LearningRate = x; + _cfg->LearningRate = x; + Q_EMIT notifyView(); + }; + + double getMinBlobSize() + { + return _MinBlobSize; + }; + void setMinBlobSize(double x) + { + _MinBlobSize = x; + _cfg->MinBlobSize = x; + Q_EMIT notifyView(); + }; + + double getMaxBlobSize() + { + return _MaxBlobSize; + }; + void setMaxBlobSize(double x) + { + _MaxBlobSize = x; + _cfg->MaxBlobSize = x; + Q_EMIT notifyView(); + }; + + bool getDoBackground() + { + return _doBackground; + }; + void setDoBackground(bool x) + { + _doBackground = x; + _cfg->DoBackground = x; + Q_EMIT notifyView(); + }; + + bool getDoNetwork() + { + return _doNetwork; + }; + void setDoNetwork(bool x) + { + _doNetwork = x; + _cfg->DoNetwork = x; + Q_EMIT notifyView(); + }; + + int getSendImage() + { + return _sendImage; + }; + void setSendImage(int x) + { + _sendImage = x; + Q_EMIT notifyView(); + }; + + bool getResetBackground() + { + return _resetBackground; + }; + void setResetBackground(bool x) + { + _resetBackground = x; + Q_EMIT notifyView(); + }; + + int getNoFish() + { + return _noFish; + }; + void setNoFish(int x) + { + _noFish = x; + _cfg->NoFish = x; + Q_EMIT notifyView(); + }; + + std::string getNewSelection() + { + return _newSelection; + }; + void setNewSelection(std::string x) + { + _newSelection = x; + } private: + QString _algorithm; - QString _algorithm; - - bool _UseAbsoluteDifference; - int _BinarizationThreshold; + bool _UseAbsoluteDifference; + int _BinarizationThreshold; - int _SizeErode; - int _SizeDilate; - double _LearningRate; - int _MinBlobSize; - int _MaxBlobSize; + int _SizeErode; + int _SizeDilate; + double _LearningRate; + int _MinBlobSize; + int _MaxBlobSize; - bool _doBackground; - int _sendImage; - bool _resetBackground; - int _noFish; + bool _doBackground; + int _sendImage; + bool _resetBackground; + int _noFish; - int _networkPort; - bool _doNetwork; + int _networkPort; + bool _doNetwork; - std::string _newSelection; - Config *_cfg; + std::string _newSelection; + Config* _cfg; }; #endif // TRACKERPARAMETER_H diff --git a/Src/Model/TrackingAlgorithm/NN2dMapper.cpp b/Src/Model/TrackingAlgorithm/NN2dMapper.cpp index 447db50..dc379a2 100644 --- a/Src/Model/TrackingAlgorithm/NN2dMapper.cpp +++ b/Src/Model/TrackingAlgorithm/NN2dMapper.cpp @@ -5,322 +5,376 @@ #include #include -float dif(float a, float b) { - return fmod((std::abs(b - a)), CV_PI); +float dif(float a, float b) +{ + return fmod((std::abs(b - a)), CV_PI); } -NN2dMapper::NN2dMapper(BST::TrackedTrajectory *tree) { - _tree = tree; - - //Looks kinda complicated but is a rather simple thing: - //For every true trajectory below the tree's root (which are in fact, fish trajectories in out case) - //we want to arr a last confident angle to the map. - int cid = 0; - for (int i = 0; i < _tree->size(); i++) - { - TrackedTrajectory *t = dynamic_cast(_tree->getChild(i)); - if (t && t->getValid()){ - _mapLastConfidentAngle.insert(std::pair(cid, std::numeric_limits::quiet_NaN())); - cid++; - } - } +NN2dMapper::NN2dMapper(BST::TrackedTrajectory* tree) +{ + _tree = tree; + + // Looks kinda complicated but is a rather simple thing: + // For every true trajectory below the tree's root (which are in fact, fish + // trajectories in out case) we want to arr a last confident angle to the + // map. + int cid = 0; + for (int i = 0; i < _tree->size(); i++) { + TrackedTrajectory* t = dynamic_cast( + _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 +// 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); - } - + bool operator()(std::tuple a, + std::tuple b) const + { + return std::get<0>(a) > std::get<0>(b); + } }; -FishPose getFishpose(BST::TrackedTrajectory* traj, uint frameid, uint id) { +FishPose getFishpose(BST::TrackedTrajectory* traj, uint frameid, uint id) +{ IModelTrackedComponent* comp = traj->getValidChild(id); - BST::TrackedTrajectory* ct = dynamic_cast(comp); + BST::TrackedTrajectory* ct = dynamic_cast(comp); if (ct) { - BST::TrackedElement *el = dynamic_cast(ct->getChild(frameid-1)); + BST::TrackedElement* el = dynamic_cast( + ct->getChild(frameid - 1)); if (el) return el->getFishPose(); } return FishPose(); } -std::tuple, std::vector> NN2dMapper::getNewPoses(BST::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; +std::tuple, std::vector> NN2dMapper::getNewPoses( + BST::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 + 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(); + double lookBack = 10; + cv::Point2f p = + getFishpose(traj, frameid - lookBack, i).position_cm(); cv::Point2f pnow = bestMatchesPoses[i].position_cm(); while (CvHelper::getDistance(p, pnow) < 0.1 && lookBack < 100) { lookBack += 10; - cv::Point2f p = getFishpose(traj, frameid - lookBack, i).position_cm(); + cv::Point2f p = + getFishpose(traj, frameid - lookBack, i).position_cm(); cv::Point2f pnow = bestMatchesPoses[i].position_cm(); } double dir = CvHelper::getAngleToTarget(p, pnow); - //correct some weird angle definition + // correct some weird angle definition historyDir = dir + CV_PI / 2; } - //The blob detection will come up with an ellipse orientation, where front and back are ambigious. - //So check the history for movement direction. Use the history as an indicator where front and back are. - //This might be unstable iff the fish didn't move at all. - double dif = CvHelper::angleDifference(bestMatchesPoses[i].orientation_rad(), historyDir); + // The blob detection will come up with an ellipse orientation, where + // front and back are ambigious. So check the history for movement + // direction. Use the history as an indicator where front and back are. + // This might be unstable iff the fish didn't move at all. + double dif = CvHelper::angleDifference( + bestMatchesPoses[i].orientation_rad(), + historyDir); if (std::abs(dif) > CV_PI / 2) { double dir = bestMatchesPoses[i].orientation_rad() + CV_PI; - while (dir > 2 * CV_PI) dir -= 2 * CV_PI; - while (dir < -2 * CV_PI) dir += 2 * CV_PI; + while (dir > 2 * CV_PI) + dir -= 2 * CV_PI; + while (dir < -2 * CV_PI) + dir += 2 * CV_PI; bestMatchesPoses[i].set_orientation_rad(dir); bestMatchesPoses[i].set_orientation_deg(dir * 180.0f / CV_PI); } - - //TODO move this to algorithm because this does not really take user manipulation into consideration - //TODO include difference between estimated and current - //simple smoothing out big angle jumps - float lastConfidentAngle = _mapLastConfidentAngle.at(i); //this is mot really working if we jump some frmae back/fwd - double dir = bestMatchesPoses[i].orientation_rad(); - if(!std::isnan(lastConfidentAngle)){ - const float deviationFromLast = CvHelper::angleDifference(lastConfidentAngle, dir); - if (std::abs(deviationFromLast) > CV_PI * 0.2 ){ // 36° - dir += deviationFromLast * 0.5; //reduce big jumps - } - else{ - dir += deviationFromLast * 0.1;//smooth out small changes - } - while (dir > 2 * CV_PI) dir -= 2 * CV_PI; - while (dir < -2 * CV_PI) dir += 2 * CV_PI; - bestMatchesPoses[i].set_orientation_rad(dir); + // TODO move this to algorithm because this does not really take user + // manipulation into consideration + // TODO include difference between estimated and current + // simple smoothing out big angle jumps + float lastConfidentAngle = _mapLastConfidentAngle.at( + i); // this is mot really working if we jump some frmae back/fwd + double dir = bestMatchesPoses[i].orientation_rad(); + if (!std::isnan(lastConfidentAngle)) { + const float deviationFromLast = CvHelper::angleDifference( + lastConfidentAngle, + dir); + if (std::abs(deviationFromLast) > CV_PI * 0.2) { // 36° + dir += deviationFromLast * 0.5; // reduce big jumps + } else { + dir += deviationFromLast * 0.1; // smooth out small changes + } + while (dir > 2 * CV_PI) + dir -= 2 * CV_PI; + while (dir < -2 * CV_PI) + dir += 2 * CV_PI; + bestMatchesPoses[i].set_orientation_rad(dir); bestMatchesPoses[i].set_orientation_deg(dir * 180.0f / CV_PI); - } - _mapLastConfidentAngle[i] = dir; - } - return std::tuple, std::vector>(bestMatchesPoses,bestMatchesProps); + } + _mapLastConfidentAngle[i] = dir; + } + return std::tuple, std::vector>( + bestMatchesPoses, + bestMatchesProps); } -bool NN2dMapper::correctAngle(int trackid, FishPose &pose) +bool NN2dMapper::correctAngle(int trackid, FishPose& pose) { - // the current angle is a decent estimation of the direction; however, it might point into the wrong hemisphere - const float poseOrientation = pose.orientation_rad(); - - // start with the pose orientation for our estimate - float proposedAngle = poseOrientation; - - // we have more historical data to correct the new angle to at least be more plausible - float confidence = 0.0f; - const float historyAngle = estimateOrientationRad(trackid, &confidence); - //const float lastConfidentAngle = fish.getLastConfidentOrientationRad(); - float lastConfidentAngle = _mapLastConfidentAngle.at(trackid); //TODO Hauke check if this is an ok thing to do... - - // the current history orientation has a stronger meaning and is preferred - const float comparisonOrientation = std::isnan(historyAngle) ? lastConfidentAngle : historyAngle; - // can't correct the angle? - if (std::isnan(comparisonOrientation)) return false; - - // panic mode - what if nothing was measured? - if (std::isnan(poseOrientation)) - { - pose.set_orientation_rad(comparisonOrientation); - pose.set_orientation_deg(comparisonOrientation * 180.0f / CV_PI); - return false; - } - - const float angleDifference = CvHelper::angleDifference(proposedAngle, comparisonOrientation); - - // if the angles do not lie on the same hemisphere, mirror the proposed angle - if (!std::isnan(angleDifference) && std::abs(angleDifference) > 0.5f * CV_PI) - { - proposedAngle += CV_PI; - } - - // the angle is corrected into the correct hemisphere now; - // now smooth the angle to reduce the impact of outliers or directly remove a zero-measurement. - - if (std::isnan(lastConfidentAngle)) // nothing to smooth? Then simply assume the movement-angle to be a good first estimate - proposedAngle = historyAngle; - else - { - // smooth the change in the angle iff the new angle deviates too much from the last one - const float deviationFromLast = CvHelper::angleDifference(lastConfidentAngle, proposedAngle); - assert(!std::isnan(deviationFromLast)); - - if (std::abs(deviationFromLast) > 0.2f * CV_PI) - { - if (poseOrientation == 0.0f) // deviation AND zero-angle? Most likely not a decent estimation. - proposedAngle = lastConfidentAngle; - else // smooth outliers by a fixed margin - proposedAngle = lastConfidentAngle - 0.1f * deviationFromLast; - } - } - // angle should be between 0� and 360� - if (proposedAngle > 2.0f * CV_PI) proposedAngle -= 2.0f * CV_PI; - else if (proposedAngle < 0.0f) proposedAngle += 2.0f * CV_PI; - assert(!std::isnan(proposedAngle)); - - pose.set_orientation_rad(proposedAngle); - pose.set_orientation_deg(proposedAngle * 180.0f / CV_PI); - - // did we have ANY confident correction? - if (!std::isnan(lastConfidentAngle)) // if we simply adjusted the last position, assume to be confident - return true; - // otherwise, we need to intialize the confident angle. - // do that when we really are "confident" for the first time.. - const float differenceToHistoryAngle = std::abs(CvHelper::angleDifference(proposedAngle, historyAngle)); - assert(!std::isnan(differenceToHistoryAngle)); - if (differenceToHistoryAngle < 0.25f * CV_PI) - return true; - // neither updating nor a good initialization? - return false; + // the current angle is a decent estimation of the direction; however, it + // might point into the wrong hemisphere + const float poseOrientation = pose.orientation_rad(); + + // start with the pose orientation for our estimate + float proposedAngle = poseOrientation; + + // we have more historical data to correct the new angle to at least be + // more plausible + float confidence = 0.0f; + const float historyAngle = estimateOrientationRad(trackid, &confidence); + // const float lastConfidentAngle = fish.getLastConfidentOrientationRad(); + float lastConfidentAngle = _mapLastConfidentAngle.at( + trackid); // TODO Hauke check if this is an ok thing to do... + + // the current history orientation has a stronger meaning and is preferred + const float comparisonOrientation = std::isnan(historyAngle) + ? lastConfidentAngle + : historyAngle; + // can't correct the angle? + if (std::isnan(comparisonOrientation)) + return false; + + // panic mode - what if nothing was measured? + if (std::isnan(poseOrientation)) { + pose.set_orientation_rad(comparisonOrientation); + pose.set_orientation_deg(comparisonOrientation * 180.0f / CV_PI); + return false; + } + + const float angleDifference = CvHelper::angleDifference( + proposedAngle, + comparisonOrientation); + + // if the angles do not lie on the same hemisphere, mirror the proposed + // angle + if (!std::isnan(angleDifference) && + std::abs(angleDifference) > 0.5f * CV_PI) { + proposedAngle += CV_PI; + } + + // the angle is corrected into the correct hemisphere now; + // now smooth the angle to reduce the impact of outliers or directly remove + // a zero-measurement. + + if (std::isnan( + lastConfidentAngle)) // nothing to smooth? Then simply assume the + // movement-angle to be a good first estimate + proposedAngle = historyAngle; + else { + // smooth the change in the angle iff the new angle deviates too much + // from the last one + const float deviationFromLast = CvHelper::angleDifference( + lastConfidentAngle, + proposedAngle); + assert(!std::isnan(deviationFromLast)); + + if (std::abs(deviationFromLast) > 0.2f * CV_PI) { + if (poseOrientation == 0.0f) // deviation AND zero-angle? Most + // likely not a decent estimation. + proposedAngle = lastConfidentAngle; + else // smooth outliers by a fixed margin + proposedAngle = lastConfidentAngle - 0.1f * deviationFromLast; + } + } + // angle should be between 0� and 360� + if (proposedAngle > 2.0f * CV_PI) + proposedAngle -= 2.0f * CV_PI; + else if (proposedAngle < 0.0f) + proposedAngle += 2.0f * CV_PI; + assert(!std::isnan(proposedAngle)); + + pose.set_orientation_rad(proposedAngle); + pose.set_orientation_deg(proposedAngle * 180.0f / CV_PI); + + // did we have ANY confident correction? + if (!std::isnan(lastConfidentAngle)) // if we simply adjusted the last + // position, assume to be confident + return true; + // otherwise, we need to intialize the confident angle. + // do that when we really are "confident" for the first time.. + const float differenceToHistoryAngle = std::abs( + CvHelper::angleDifference(proposedAngle, historyAngle)); + assert(!std::isnan(differenceToHistoryAngle)); + if (differenceToHistoryAngle < 0.25f * CV_PI) + return true; + // neither updating nor a good initialization? + return false; } -BST::TrackedTrajectory* getChildOfType(BST::TrackedTrajectory* tree, int tid) { - int cid = 0; - for (int i = 0; i < tree->size(); i++) { - BST::TrackedTrajectory* t = dynamic_cast(tree->getChild(i)); - if (t && cid==tid && t->getValid()) { - return t; - }else if (t && t->getValid()) - cid++; - } - return 0; +BST::TrackedTrajectory* getChildOfType(BST::TrackedTrajectory* tree, int tid) +{ + int cid = 0; + for (int i = 0; i < tree->size(); i++) { + BST::TrackedTrajectory* t = dynamic_cast( + tree->getChild(i)); + if (t && cid == tid && t->getValid()) { + return t; + } else if (t && t->getValid()) + cid++; + } + return 0; } -float NN2dMapper::estimateOrientationRad(int trackid, float *confidence) +float NN2dMapper::estimateOrientationRad(int trackid, float* confidence) { - //Get corresponding trajectory - BST::TrackedTrajectory* t = getChildOfType((BST::TrackedTrajectory*)_tree, trackid); - //return 0; - - // can't give estimate if not enough poses available - if (t->size() < 3) return std::numeric_limits::quiet_NaN(); - - //std::deque::const_reverse_iterator iter = _histComponents.rbegin(); - int start = std::max(t->size()-20, 0); - BST::TrackedElement* e = (BST::TrackedElement*)t->getChild(start); - if (!e) - return std::numeric_limits::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++) - { - BST::TrackedElement* ecur = (BST::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); + // Get corresponding trajectory + BST::TrackedTrajectory* t = getChildOfType((BST::TrackedTrajectory*) _tree, + trackid); + // return 0; + + // can't give estimate if not enough poses available + if (t->size() < 3) + return std::numeric_limits::quiet_NaN(); + + // std::deque::const_reverse_iterator iter = + // _histComponents.rbegin(); + int start = std::max(t->size() - 20, 0); + BST::TrackedElement* e = (BST::TrackedElement*) t->getChild(start); + if (!e) + return std::numeric_limits::quiet_NaN(); + cv::Point2f nextPoint = e->getFishPose().position_cm(); + cv::Point2f positionDerivative(0.0f, 0.0f); + + // weights the last poses with falloff^k * pose[end - k] until falloff^k < + // falloffMargin + int posesUsed = 0; + float currentWeight = 1.0f; + float weightSum = 0.0f; + const float falloff = 0.9f; + const float falloffMargin = 0.4f; + + for (int i = start + 1; i < t->size(); i++) { + BST::TrackedElement* ecur = (BST::TrackedElement*) t->getChild(i); + if (!ecur) + return std::numeric_limits::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 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; + 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/Src/Model/TrackingAlgorithm/NN2dMapper.h b/Src/Model/TrackingAlgorithm/NN2dMapper.h index 9851c63..5bb7786 100644 --- a/Src/Model/TrackingAlgorithm/NN2dMapper.h +++ b/Src/Model/TrackingAlgorithm/NN2dMapper.h @@ -13,23 +13,24 @@ class NN2dMapper { public: + /** + * The contructor with parameters. + */ + NN2dMapper(BST::TrackedTrajectory* tree); - /** - * The contructor with parameters. - */ - NN2dMapper(BST::TrackedTrajectory *tree); - - ~NN2dMapper(void) {}; - - std::tuple, std::vector> getNewPoses(BST::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; - BST::TrackedTrajectory *_tree; + ~NN2dMapper(void){}; -protected: + std::tuple, std::vector> getNewPoses( + BST::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; + BST::TrackedTrajectory* _tree; +protected: +}; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp index c2a0cbc..6865980 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.cpp @@ -4,159 +4,152 @@ CBlobContour::CBlobContour() { - m_startPoint.x = 0; - m_startPoint.y = 0; - m_area = -1; - m_perimeter = -1; - m_contourPoints = NULL; - m_moments.m00 = -1; - m_contour = NULL; - m_parentStorage = NULL; + m_startPoint.x = 0; + m_startPoint.y = 0; + m_area = -1; + m_perimeter = -1; + m_contourPoints = NULL; + m_moments.m00 = -1; + m_contour = NULL; + m_parentStorage = NULL; } -CBlobContour::CBlobContour(cv::Point startPoint, CvMemStorage *storage ) +CBlobContour::CBlobContour(cv::Point startPoint, CvMemStorage* storage) { - m_startPoint.x = startPoint.x; - m_startPoint.y = startPoint.y; - m_area = -1; - m_perimeter = -1; - m_moments.m00 = -1; - - m_parentStorage = storage; - - m_contourPoints = NULL; - - // contour sequence: must be compatible with opencv functions - m_contour = cvCreateSeq( CV_SEQ_ELTYPE_CODE | CV_SEQ_KIND_CURVE | CV_SEQ_FLAG_CLOSED, - sizeof(CvContour), - sizeof(t_chainCode),m_parentStorage); - + m_startPoint.x = startPoint.x; + m_startPoint.y = startPoint.y; + m_area = -1; + m_perimeter = -1; + m_moments.m00 = -1; + + m_parentStorage = storage; + + m_contourPoints = NULL; + + // contour sequence: must be compatible with opencv functions + m_contour = cvCreateSeq(CV_SEQ_ELTYPE_CODE | CV_SEQ_KIND_CURVE | + CV_SEQ_FLAG_CLOSED, + sizeof(CvContour), + sizeof(t_chainCode), + m_parentStorage); } - //! Copy constructor -CBlobContour::CBlobContour( CBlobContour *source ) +CBlobContour::CBlobContour(CBlobContour* source) { - if (source != NULL ) - { - *this = *source; - } + if (source != NULL) { + *this = *source; + } } CBlobContour::~CBlobContour() { - // let parent blob deallocate all contour and contour point memory - m_contour = NULL; - m_contourPoints = NULL; + // let parent blob deallocate all contour and contour point memory + m_contour = NULL; + m_contourPoints = NULL; } - //! Copy operator -CBlobContour& CBlobContour::operator=( const CBlobContour &source ) +CBlobContour& CBlobContour::operator=(const CBlobContour& source) { - if( this != &source ) - { - m_startPoint = source.m_startPoint; - - m_parentStorage = source.m_parentStorage; - - if (m_contour) - { - cvClearSeq( m_contour ); - } - - if (source.m_contour) - { - m_contour = cvCloneSeq( source.m_contour, m_parentStorage); - } - - if( source.m_contourPoints ) - { - if( m_contourPoints ) - cvClearSeq( m_contourPoints ); - m_contourPoints = cvCloneSeq( source.m_contourPoints, m_parentStorage); - } - - m_area = source.m_area; - m_perimeter = source.m_area; - m_moments = source.m_moments; - } - return *this; + if (this != &source) { + m_startPoint = source.m_startPoint; + + m_parentStorage = source.m_parentStorage; + + if (m_contour) { + cvClearSeq(m_contour); + } + + if (source.m_contour) { + m_contour = cvCloneSeq(source.m_contour, m_parentStorage); + } + + if (source.m_contourPoints) { + if (m_contourPoints) + cvClearSeq(m_contourPoints); + m_contourPoints = cvCloneSeq(source.m_contourPoints, + m_parentStorage); + } + + m_area = source.m_area; + m_perimeter = source.m_area; + m_moments = source.m_moments; + } + return *this; } - /** - FUNCI�: AddChainCode - FUNCIONALITAT: Add chain code to contour - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ void CBlobContour::AddChainCode(t_chainCode chaincode) { - cvSeqPush(m_contour, &chaincode); + cvSeqPush(m_contour, &chaincode); } //! Clears chain code contour and points void CBlobContour::ResetChainCode() { - if( m_contour ) - { - cvClearSeq( m_contour ); - m_contour = NULL; - } - if( m_contourPoints ) - { - cvClearSeq( m_contourPoints ); - m_contourPoints = NULL; - } + if (m_contour) { + cvClearSeq(m_contour); + m_contour = NULL; + } + if (m_contourPoints) { + cvClearSeq(m_contourPoints); + m_contourPoints = NULL; + } } /** - FUNCI�: GetPerimeter -- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and horizontal and vertical codes 1 +- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and +horizontal and vertical codes 1 - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: Algorithm derived from "Methods to estimate area and perimeters of blob-like objects: A comparison", L.Yang +- NOTA: Algorithm derived from "Methods to estimate area and perimeters of +blob-like objects: A comparison", L.Yang */ double CBlobContour::GetPerimeter() { - // is calculated? - if (m_perimeter != -1) - { - return m_perimeter; - } + // is calculated? + if (m_perimeter != -1) { + return m_perimeter; + } - if( IsEmpty() ) - return 0; + if (IsEmpty()) + return 0; - m_perimeter = cvContourPerimeter( GetContourPoints() ); + m_perimeter = cvContourPerimeter(GetContourPoints()); - return m_perimeter; + return m_perimeter; } /** - FUNCI�: GetArea - FUNCIONALITAT: Computes area from chain code - PAR�METRES: - - + - - RESULTAT: - - May give negative areas for clock wise contours + - May give negative areas for clock wise contours - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. @@ -164,97 +157,93 @@ double CBlobContour::GetPerimeter() */ double CBlobContour::GetArea() { - // is calculated? - if (m_area != -1) - { - return m_area; - } - - if( IsEmpty() ) - return 0; - - m_area = fabs( cvContourArea( GetContourPoints() )); - - return m_area; + // is calculated? + if (m_area != -1) { + return m_area; + } + + if (IsEmpty()) + return 0; + + m_area = fabs(cvContourArea(GetContourPoints())); + + return m_area; } //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) double CBlobContour::GetMoment(int p, int q) { - // is a valid moment? - if ( p < 0 || q < 0 || p > MAX_MOMENTS_ORDER || q > MAX_MOMENTS_ORDER ) - { - return -1; - } - - if( IsEmpty() ) - return 0; - - // it is calculated? - if( m_moments.m00 == -1) - { - cvMoments( GetContourPoints(), &m_moments ); - } - - return cvGetSpatialMoment( &m_moments, p, q ); - - + // is a valid moment? + if (p < 0 || q < 0 || p > MAX_MOMENTS_ORDER || q > MAX_MOMENTS_ORDER) { + return -1; + } + + if (IsEmpty()) + return 0; + + // it is calculated? + if (m_moments.m00 == -1) { + cvMoments(GetContourPoints(), &m_moments); + } + + return cvGetSpatialMoment(&m_moments, p, q); } //! Calculate contour points from crack codes t_PointList CBlobContour::GetContourPoints() { - // it is calculated? - if( m_contourPoints != NULL ) - return m_contourPoints; - - if ( m_contour == NULL || m_contour->total <= 0 ) - { - return NULL; - } - - CvSeq *tmpPoints; - CvSeqReader reader; - CvSeqWriter writer; - cv::Point actualPoint; - CvRect boundingBox; - - // if aproximation is different than simple extern perimeter will not work - tmpPoints = cvApproxChains( m_contour, m_parentStorage, CV_CHAIN_APPROX_NONE); - - - // apply an offset to contour points to recover real coordinates - - cvStartReadSeq( tmpPoints, &reader); - - m_contourPoints = cvCreateSeq( tmpPoints->flags, tmpPoints->header_size, tmpPoints->elem_size, m_parentStorage ); - cvStartAppendToSeq(m_contourPoints, &writer ); - - // also calculate bounding box of the contour to allow cvPointPolygonTest - // work correctly on the generated polygon - boundingBox.x = boundingBox.y = 10000; - boundingBox.width = boundingBox.height = 0; - - for( int i=0; i< tmpPoints->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - actualPoint.x += m_startPoint.x; - actualPoint.y += m_startPoint.y; - - boundingBox.x = MIN( boundingBox.x, actualPoint.x ); - boundingBox.y = MIN( boundingBox.y, actualPoint.y ); - boundingBox.width = MAX( boundingBox.width, actualPoint.x ); - boundingBox.height = MAX( boundingBox.height, actualPoint.y ); - - CV_WRITE_SEQ_ELEM( actualPoint, writer ); - } - cvEndWriteSeq( &writer ); - cvClearSeq( tmpPoints ); - - // assign calculated bounding box - ((CvContour*)m_contourPoints)->rect = boundingBox; - - - return m_contourPoints; + // it is calculated? + if (m_contourPoints != NULL) + return m_contourPoints; + + if (m_contour == NULL || m_contour->total <= 0) { + return NULL; + } + + CvSeq* tmpPoints; + CvSeqReader reader; + CvSeqWriter writer; + cv::Point actualPoint; + CvRect boundingBox; + + // if aproximation is different than simple extern perimeter will not work + tmpPoints = cvApproxChains(m_contour, + m_parentStorage, + CV_CHAIN_APPROX_NONE); + + // apply an offset to contour points to recover real coordinates + + cvStartReadSeq(tmpPoints, &reader); + + m_contourPoints = cvCreateSeq(tmpPoints->flags, + tmpPoints->header_size, + tmpPoints->elem_size, + m_parentStorage); + cvStartAppendToSeq(m_contourPoints, &writer); + + // also calculate bounding box of the contour to allow cvPointPolygonTest + // work correctly on the generated polygon + boundingBox.x = boundingBox.y = 10000; + boundingBox.width = boundingBox.height = 0; + + for (int i = 0; i < tmpPoints->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + actualPoint.x += m_startPoint.x; + actualPoint.y += m_startPoint.y; + + boundingBox.x = MIN(boundingBox.x, actualPoint.x); + boundingBox.y = MIN(boundingBox.y, actualPoint.y); + boundingBox.width = MAX(boundingBox.width, actualPoint.x); + boundingBox.height = MAX(boundingBox.height, actualPoint.y); + + CV_WRITE_SEQ_ELEM(actualPoint, writer); + } + cvEndWriteSeq(&writer); + cvClearSeq(tmpPoints); + + // assign calculated bounding box + ((CvContour*) m_contourPoints)->rect = boundingBox; + + return m_contourPoints; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h index 83d2eb9..982349b 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobContour.h @@ -12,86 +12,77 @@ typedef CvSeq* t_chainCodeList; //! Type of list of points typedef CvSeq* t_PointList; - //! Max order of calculated moments -#define MAX_MOMENTS_ORDER 3 - +#define MAX_MOMENTS_ORDER 3 //! Blob contour class (in crack code) class CBlobContour { - friend class CBlob; - friend class CBlobProperties; //AO - + friend class CBlob; + friend class CBlobProperties; // AO + public: - //! Constructors - CBlobContour(); - CBlobContour(cv::Point startPoint, CvMemStorage *storage ); - //! Copy constructor - CBlobContour( CBlobContour *source ); - - ~CBlobContour(); - //! Assigment operator - CBlobContour& operator=( const CBlobContour &source ); - - //! Add chain code to contour - void AddChainCode(t_chainCode code); - - //! Return freeman chain coded contour - t_chainCodeList GetChainCode() - { - return m_contour; - } - - bool IsEmpty() - { - return m_contour == NULL || m_contour->total == 0; - } - - //! Return all contour points - t_chainCodeList GetContourPoints(); - -protected: - - cv::Point GetStartPoint() const - { - return m_startPoint; - } - - //! Clears chain code contour - void ResetChainCode(); - - - - //! Computes area from contour - double GetArea(); - //! Computes perimeter from contour - double GetPerimeter(); - //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) - double GetMoment(int p, int q); - - //! Crack code list - t_chainCodeList m_contour; + //! Constructors + CBlobContour(); + CBlobContour(cv::Point startPoint, CvMemStorage* storage); + //! Copy constructor + CBlobContour(CBlobContour* source); + + ~CBlobContour(); + //! Assigment operator + CBlobContour& operator=(const CBlobContour& source); + + //! Add chain code to contour + void AddChainCode(t_chainCode code); + + //! Return freeman chain coded contour + t_chainCodeList GetChainCode() + { + return m_contour; + } + + bool IsEmpty() + { + return m_contour == NULL || m_contour->total == 0; + } + + //! Return all contour points + t_chainCodeList GetContourPoints(); + +protected: + cv::Point GetStartPoint() const + { + return m_startPoint; + } + + //! Clears chain code contour + void ResetChainCode(); + + //! Computes area from contour + double GetArea(); + //! Computes perimeter from contour + double GetPerimeter(); + //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) + double GetMoment(int p, int q); + + //! Crack code list + t_chainCodeList m_contour; private: - //! Starting point of the contour - cv::Point m_startPoint; - //! All points from the contour - t_PointList m_contourPoints; - - - - //! Computed area from contour - double m_area; - //! Computed perimeter from contour - double m_perimeter; - //! Computed moments from contour - CvMoments m_moments; - - //! Pointer to storage - CvMemStorage *m_parentStorage; + //! Starting point of the contour + cv::Point m_startPoint; + //! All points from the contour + t_PointList m_contourPoints; + + //! Computed area from contour + double m_area; + //! Computed perimeter from contour + double m_perimeter; + //! Computed moments from contour + CvMoments m_moments; + + //! Pointer to storage + CvMemStorage* m_parentStorage; }; -#endif //!BLOBCONTOUR_H_INCLUDED - - +#endif //! BLOBCONTOUR_H_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h index f1a02a7..158d2f7 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobLibraryConfiguration.h @@ -1,6 +1,6 @@ /************************************************************************ - BlobLibraryConfiguration.h - + BlobLibraryConfiguration.h + FUNCIONALITAT: Configuraci� del comportament global de la llibreria AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp index cfdae2d..0c3cb10 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.cpp @@ -15,28 +15,28 @@ - FUNCTIONALITY: Calculates the pq moment of the blob - PARAMETERS: - RESULT: - - returns the pq moment or 0 if the moment it is not implemented + - returns the pq moment or 0 if the moment it is not implemented - RESTRICTIONS: - - Currently, implemented moments up to 3 + - Currently, implemented moments up to 3 - AUTHOR: Ricard Borr�s - CREATION DATE: 20-07-2004. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMoment::operator()(CBlob &blob) +double CBlobGetMoment::operator()(CBlob& blob) { - return blob.Moment(m_p, m_q); + return blob.Moment(m_p, m_q); } /** - FUNCI�: HullPerimeter - FUNCIONALITAT: Calcula la longitud del perimetre convex del blob. - Fa servir la funci� d'OpenCV cvConvexHull2 per a - calcular el perimetre convex. - + Fa servir la funci� d'OpenCV cvConvexHull2 per a + calcular el perimetre convex. + - PAR�METRES: - RESULTAT: - - retorna la longitud del per�metre convex del blob. Si el blob no t� coordenades - associades retorna el per�metre normal del blob. + - retorna la longitud del per�metre convex del blob. Si el blob no t� +coordenades associades retorna el per�metre normal del blob. - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 20-07-2004. @@ -47,45 +47,45 @@ double CBlobGetMoment::operator()(CBlob &blob) - FUNCTIONALITY: Calculates the convex hull perimeter of the blob - PARAMETERS: - RESULT: - - returns the convex hull perimeter of the blob or the perimeter if the - blob edges could not be retrieved + - returns the convex hull perimeter of the blob or the perimeter if the + blob edges could not be retrieved - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetHullPerimeter::operator()(CBlob &blob) +double CBlobGetHullPerimeter::operator()(CBlob& blob) { - CvSeq *convexHull; - double perimeter; + CvSeq* convexHull; + double perimeter; - convexHull = blob.GetConvexHull(); + convexHull = blob.GetConvexHull(); - if( convexHull ) - perimeter = fabs(cvArcLength(convexHull,CV_WHOLE_SEQ,1)); - else - return 0; + if (convexHull) + perimeter = fabs(cvArcLength(convexHull, CV_WHOLE_SEQ, 1)); + else + return 0; - cvClearSeq(convexHull); + cvClearSeq(convexHull); - return perimeter; + return perimeter; } -double CBlobGetHullArea::operator()(CBlob &blob) +double CBlobGetHullArea::operator()(CBlob& blob) { - CvSeq *convexHull; - double area; + CvSeq* convexHull; + double area; - convexHull = blob.GetConvexHull(); + convexHull = blob.GetConvexHull(); - if( convexHull ) - area = fabs(cvContourArea(convexHull)); - else - return 0; + if (convexHull) + area = fabs(cvContourArea(convexHull)); + else + return 0; - cvClearSeq(convexHull); + cvClearSeq(convexHull); - return area; + return area; } /** @@ -98,29 +98,28 @@ double CBlobGetHullArea::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMinXatMinY::operator()(CBlob &blob) +double CBlobGetMinXatMinY::operator()(CBlob& blob) { - double result = LONG_MAX; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - cvStartReadSeq( externContour, &reader); - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.y == blob.MinY()) && (actualPoint.x < result) ) - { - result = actualPoint.x; - } - } - - return result; + double result = LONG_MAX; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.y == blob.MinY()) && (actualPoint.x < result)) { + result = actualPoint.x; + } + } + + return result; } /** @@ -133,29 +132,28 @@ double CBlobGetMinXatMinY::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMinYatMaxX::operator()(CBlob &blob) +double CBlobGetMinYatMaxX::operator()(CBlob& blob) { - double result = LONG_MAX; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - cvStartReadSeq( externContour, &reader); - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.x == blob.MaxX()) && (actualPoint.y < result) ) - { - result = actualPoint.y; - } - } - - return result; + double result = LONG_MAX; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.x == blob.MaxX()) && (actualPoint.y < result)) { + result = actualPoint.y; + } + } + + return result; } /** @@ -168,30 +166,29 @@ double CBlobGetMinYatMaxX::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMaxXatMaxY::operator()(CBlob &blob) +double CBlobGetMaxXatMaxY::operator()(CBlob& blob) { - double result = LONG_MIN; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - - cvStartReadSeq( externContour, &reader); - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.y == blob.MaxY()) && (actualPoint.x > result) ) - { - result = actualPoint.x; - } - } - - return result; + double result = LONG_MIN; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.y == blob.MaxY()) && (actualPoint.x > result)) { + result = actualPoint.x; + } + } + + return result; } /** @@ -204,33 +201,30 @@ double CBlobGetMaxXatMaxY::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetMaxYatMinX::operator()(CBlob &blob) +double CBlobGetMaxYatMinX::operator()(CBlob& blob) { - double result = LONG_MIN; - - CvSeqReader reader; - cv::Point actualPoint; - t_PointList externContour; - - externContour = blob.GetExternalContour()->GetContourPoints(); - if( !externContour ) return result; - - cvStartReadSeq( externContour, &reader); - - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - if( (actualPoint.x == blob.MinX()) && (actualPoint.y > result) ) - { - result = actualPoint.y; - } - } - - return result; -} + double result = LONG_MIN; + + CvSeqReader reader; + cv::Point actualPoint; + t_PointList externContour; + + externContour = blob.GetExternalContour()->GetContourPoints(); + if (!externContour) + return result; + cvStartReadSeq(externContour, &reader); + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + if ((actualPoint.x == blob.MinX()) && (actualPoint.y > result)) { + result = actualPoint.y; + } + } + + return result; +} /** - FUNCTION: CBlobGetElongation @@ -238,41 +232,42 @@ double CBlobGetMaxYatMinX::operator()(CBlob &blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - - See below to see how the lenght and the breadth are aproximated + - See below to see how the lenght and the breadth are aproximated - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetElongation::operator()(CBlob &blob) +double CBlobGetElongation::operator()(CBlob& blob) { - double ampladaC,longitudC,amplada,longitud; + double ampladaC, longitudC, amplada, longitud; - double tmp; + double tmp; - tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); + tmp = blob.Perimeter() * blob.Perimeter() - 16 * blob.Area(); - if( tmp > 0.0 ) - ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; - // error intr�nsec en els c�lculs de l'�rea i el per�metre - else - ampladaC = (double) (blob.Perimeter())/4; + if (tmp > 0.0) + ampladaC = (double) (blob.Perimeter() + sqrt(tmp)) / 4; + // error intr�nsec en els c�lculs de l'�rea i el per�metre + else + ampladaC = (double) (blob.Perimeter()) / 4; - if(ampladaC<=0.0) return 0; - longitudC=(double) blob.Area()/ampladaC; + if (ampladaC <= 0.0) + return 0; + longitudC = (double) blob.Area() / ampladaC; - longitud=MAX( longitudC , ampladaC ); - amplada=MIN( longitudC , ampladaC ); + longitud = MAX(longitudC, ampladaC); + amplada = MIN(longitudC, ampladaC); - return (double) longitud/amplada; + return (double) longitud / amplada; } /** - Retorna la compacitat del blob + Retorna la compacitat del blob */ /** - FUNCTION: CBlobGetCompactness -- FUNCTIONALITY: Calculates the compactness of the blob - ( maximum for circle shaped blobs, minimum for the rest) +- FUNCTIONALITY: Calculates the compactness of the blob + ( maximum for circle shaped blobs, minimum for the rest) - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -280,21 +275,21 @@ double CBlobGetElongation::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetCompactness::operator()(CBlob &blob) +double CBlobGetCompactness::operator()(CBlob& blob) { - if( blob.Area() != 0.0 ) - return (double) pow(blob.Perimeter(),2)/(4*CV_PI*blob.Area()); - else - return 0.0; + if (blob.Area() != 0.0) + return (double) pow(blob.Perimeter(), 2) / (4 * CV_PI * blob.Area()); + else + return 0.0; } /** - Retorna la rugositat del blob + Retorna la rugositat del blob */ /** - FUNCTION: CBlobGetRoughness -- FUNCTIONALITY: Calculates the roughness of the blob - ( ratio between perimeter and convex hull perimeter) +- FUNCTIONALITY: Calculates the roughness of the blob + ( ratio between perimeter and convex hull perimeter) - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -302,91 +297,95 @@ double CBlobGetCompactness::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetRoughness::operator()(CBlob &blob) +double CBlobGetRoughness::operator()(CBlob& blob) { - CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter(); - - double hullPerimeter = getHullPerimeter(blob); + CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter(); + + double hullPerimeter = getHullPerimeter(blob); - if( hullPerimeter != 0.0 ) - return blob.Perimeter() / hullPerimeter;//HullPerimeter(); + if (hullPerimeter != 0.0) + return blob.Perimeter() / hullPerimeter; // HullPerimeter(); - return 0.0; + return 0.0; } /** - Retorna la longitud del blob + Retorna la longitud del blob */ /** - FUNCTION: CBlobGetLength -- FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the blob) +- FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the +blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - - The lenght is an aproximation to the real lenght + - The lenght is an aproximation to the real lenght - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetLength::operator()(CBlob &blob) +double CBlobGetLength::operator()(CBlob& blob) { - double ampladaC,longitudC; - double tmp; + double ampladaC, longitudC; + double tmp; - tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); + tmp = blob.Perimeter() * blob.Perimeter() - 16 * blob.Area(); - if( tmp > 0.0 ) - ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; - // error intr�nsec en els c�lculs de l'�rea i el per�metre - else - ampladaC = (double) (blob.Perimeter())/4; + if (tmp > 0.0) + ampladaC = (double) (blob.Perimeter() + sqrt(tmp)) / 4; + // error intr�nsec en els c�lculs de l'�rea i el per�metre + else + ampladaC = (double) (blob.Perimeter()) / 4; - if(ampladaC<=0.0) return 0; - longitudC=(double) blob.Area()/ampladaC; + if (ampladaC <= 0.0) + return 0; + longitudC = (double) blob.Area() / ampladaC; - return MAX( longitudC , ampladaC ); + return MAX(longitudC, ampladaC); } /** - Retorna l'amplada del blob + Retorna l'amplada del blob */ /** - FUNCTION: CBlobGetBreadth -- FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the blob) +- FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the +blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - - The breadth is an aproximation to the real breadth + - The breadth is an aproximation to the real breadth - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetBreadth::operator()(CBlob &blob) +double CBlobGetBreadth::operator()(CBlob& blob) { - double ampladaC,longitudC; - double tmp; + double ampladaC, longitudC; + double tmp; - tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); + tmp = blob.Perimeter() * blob.Perimeter() - 16 * blob.Area(); - if( tmp > 0.0 ) - ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; - // error intr�nsec en els c�lculs de l'�rea i el per�metre - else - ampladaC = (double) (blob.Perimeter())/4; + if (tmp > 0.0) + ampladaC = (double) (blob.Perimeter() + sqrt(tmp)) / 4; + // error intr�nsec en els c�lculs de l'�rea i el per�metre + else + ampladaC = (double) (blob.Perimeter()) / 4; - if(ampladaC<=0.0) return 0; - longitudC = (double) blob.Area()/ampladaC; + if (ampladaC <= 0.0) + return 0; + longitudC = (double) blob.Area() / ampladaC; - return MIN( longitudC , ampladaC ); + return MIN(longitudC, ampladaC); } /** - Calcula la dist�ncia entre un punt i el centre del blob + Calcula la dist�ncia entre un punt i el centre del blob */ /** - FUNCTION: CBlobGetDistanceFromPoint -- FUNCTIONALITY: Calculates the euclidean distance between the blob center and - the point specified in the constructor +- FUNCTIONALITY: Calculates the euclidean distance between the blob center and + the point specified in the constructor - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -394,16 +393,16 @@ double CBlobGetBreadth::operator()(CBlob &blob) - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobGetDistanceFromPoint::operator()(CBlob &blob) +double CBlobGetDistanceFromPoint::operator()(CBlob& blob) { - double xmitjana, ymitjana; - CBlobGetXCenter getXCenter; - CBlobGetYCenter getYCenter; + double xmitjana, ymitjana; + CBlobGetXCenter getXCenter; + CBlobGetYCenter getYCenter; - xmitjana = m_x - getXCenter( blob ); - ymitjana = m_y - getYCenter( blob ); + xmitjana = m_x - getXCenter(blob); + ymitjana = m_y - getYCenter(blob); - return sqrt((xmitjana*xmitjana)+(ymitjana*ymitjana)); + return sqrt((xmitjana * xmitjana) + (ymitjana * ymitjana)); } /** @@ -412,18 +411,20 @@ double CBlobGetDistanceFromPoint::operator()(CBlob &blob) rectangular bounding box of a blob - PARAMETERS: - RESULT: - - returns 1 if it is inside; o if not + - returns 1 if it is inside; o if not - RESTRICTIONS: - AUTHOR: Francesc Pinyol Margalef - CREATION DATE: 16-01-2006. - MODIFICATION: Date. Author. Description. */ -double CBlobGetXYInside::operator()(CBlob &blob) +double CBlobGetXYInside::operator()(CBlob& blob) { - if( blob.GetExternalContour()->GetContourPoints() ) - { - return cvPointPolygonTest( blob.GetExternalContour()->GetContourPoints(), m_p,0) >= 0; - } - - return 0; + if (blob.GetExternalContour()->GetContourPoints()) { + return cvPointPolygonTest( + blob.GetExternalContour()->GetContourPoints(), + m_p, + 0) >= 0; + } + + return 0; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h index fbe233f..4c8b435 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobOperators.h @@ -4,731 +4,739 @@ #include "blob.h" /************************************************************************** - Definici� de les classes per a fer operacions sobre els blobs + Definici� de les classes per a fer operacions sobre els blobs - Helper classes to perform operations on blobs + Helper classes to perform operations on blobs **************************************************************************/ //! Factor de conversi� de graus a radians -#define DEGREE2RAD (CV_PI / 180.0) - +#define DEGREE2RAD (CV_PI / 180.0) //! Classe d'on derivarem totes les operacions sobre els blobs //! Interface to derive all blob operations class COperadorBlob { public: - virtual ~COperadorBlob(){}; + virtual ~COperadorBlob(){}; - //! Aply operator to blob - virtual double operator()(CBlob &blob) = 0; - //! Get operator name - virtual const char *GetNom() = 0; + //! Aply operator to blob + virtual double operator()(CBlob& blob) = 0; + //! Get operator name + virtual const char* GetNom() = 0; - operator COperadorBlob*() - { - return (COperadorBlob*)this; - } + operator COperadorBlob*() + { + return (COperadorBlob*) this; + } }; typedef COperadorBlob funcio_calculBlob; - //! Classe per calcular l'etiqueta d'un blob //! Class to get ID of a blob class CBlobGetID : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.GetID(); - } - const char *GetNom() - { - return "CBlobGetID"; - } + double operator()(CBlob& blob) + { + return blob.GetID(); + } + const char* GetNom() + { + return "CBlobGetID"; + } }; - //! Classe per calcular l'�rea d'un blob //! Class to get the area of a blob class CBlobGetArea : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.Area(); - } - const char *GetNom() - { - return "CBlobGetArea"; - } + double operator()(CBlob& blob) + { + return blob.Area(); + } + const char* GetNom() + { + return "CBlobGetArea"; + } }; //! Classe per calcular el perimetre d'un blob //! Class to get the perimeter of a blob -class CBlobGetPerimeter: public COperadorBlob +class CBlobGetPerimeter : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.Perimeter(); - } - const char *GetNom() - { - return "CBlobGetPerimeter"; - } + double operator()(CBlob& blob) + { + return blob.Perimeter(); + } + const char* GetNom() + { + return "CBlobGetPerimeter"; + } }; //! Classe que diu si un blob �s extern o no //! Class to get the extern flag of a blob -class CBlobGetExterior: public COperadorBlob -{ -public: - CBlobGetExterior() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExterior(IplImage *mask, bool xBorder = true, bool yBorder = true) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - return blob.Exterior(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExterior"; - } +class CBlobGetExterior : public COperadorBlob +{ +public: + CBlobGetExterior() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExterior(IplImage* mask, bool xBorder = true, bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + return blob.Exterior(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExterior"; + } + private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; //! Classe per calcular la mitjana de nivells de gris d'un blob //! Class to get the mean grey level of a blob -class CBlobGetMean: public COperadorBlob -{ -public: - CBlobGetMean() - { - m_image = NULL; - } - CBlobGetMean( IplImage *image ) - { - m_image = image; - }; - - double operator()(CBlob &blob) - { - return blob.Mean(m_image); - } - const char *GetNom() - { - return "CBlobGetMean"; - } -private: +class CBlobGetMean : public COperadorBlob +{ +public: + CBlobGetMean() + { + m_image = NULL; + } + CBlobGetMean(IplImage* image) + { + m_image = image; + }; + + double operator()(CBlob& blob) + { + return blob.Mean(m_image); + } + const char* GetNom() + { + return "CBlobGetMean"; + } - IplImage *m_image; +private: + IplImage* m_image; }; //! Classe per calcular la desviaci� est�ndard dels nivells de gris d'un blob //! Class to get the standard deviation of the grey level values of a blob -class CBlobGetStdDev: public COperadorBlob -{ -public: - CBlobGetStdDev() - { - m_image = NULL; - } - CBlobGetStdDev( IplImage *image ) - { - m_image = image; - }; - double operator()(CBlob &blob) - { - return blob.StdDev(m_image); - } - const char *GetNom() - { - return "CBlobGetStdDev"; - } -private: - - IplImage *m_image; +class CBlobGetStdDev : public COperadorBlob +{ +public: + CBlobGetStdDev() + { + m_image = NULL; + } + CBlobGetStdDev(IplImage* image) + { + m_image = image; + }; + double operator()(CBlob& blob) + { + return blob.StdDev(m_image); + } + const char* GetNom() + { + return "CBlobGetStdDev"; + } +private: + IplImage* m_image; }; //! Classe per calcular la compacitat d'un blob //! Class to calculate the compactness of a blob -class CBlobGetCompactness: public COperadorBlob +class CBlobGetCompactness : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetCompactness"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetCompactness"; + } }; //! Classe per calcular la longitud d'un blob //! Class to calculate the length of a blob -class CBlobGetLength: public COperadorBlob +class CBlobGetLength : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetLength"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetLength"; + } }; //! Classe per calcular l'amplada d'un blob //! Class to calculate the breadth of a blob -class CBlobGetBreadth: public COperadorBlob +class CBlobGetBreadth : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetBreadth"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetBreadth"; + } }; //! Classe per calcular la difer�ncia en X del blob -class CBlobGetDiffX: public COperadorBlob +class CBlobGetDiffX : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.GetBoundingBox().width; - } - const char *GetNom() - { - return "CBlobGetDiffX"; - } + double operator()(CBlob& blob) + { + return blob.GetBoundingBox().width; + } + const char* GetNom() + { + return "CBlobGetDiffX"; + } }; //! Classe per calcular la difer�ncia en X del blob -class CBlobGetDiffY: public COperadorBlob +class CBlobGetDiffY : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.GetBoundingBox().height; - } - const char *GetNom() - { - return "CBlobGetDiffY"; - } + double operator()(CBlob& blob) + { + return blob.GetBoundingBox().height; + } + const char* GetNom() + { + return "CBlobGetDiffY"; + } }; //! Classe per calcular el moment PQ del blob //! Class to calculate the P,Q moment of a blob -class CBlobGetMoment: public COperadorBlob -{ -public: - //! Constructor est�ndard - //! Standard constructor (gets the 00 moment) - CBlobGetMoment() - { - m_p = m_q = 0; - } - //! Constructor: indiquem el moment p,q a calcular - //! Constructor: gets the PQ moment - CBlobGetMoment( int p, int q ) - { - m_p = p; - m_q = q; - }; - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMoment"; - } +class CBlobGetMoment : public COperadorBlob +{ +public: + //! Constructor est�ndard + //! Standard constructor (gets the 00 moment) + CBlobGetMoment() + { + m_p = m_q = 0; + } + //! Constructor: indiquem el moment p,q a calcular + //! Constructor: gets the PQ moment + CBlobGetMoment(int p, int q) + { + m_p = p; + m_q = q; + }; + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMoment"; + } private: - //! moment que volem calcular - int m_p, m_q; + //! moment que volem calcular + int m_p, m_q; }; //! Classe per calcular el perimetre del poligon convex d'un blob //! Class to calculate the convex hull perimeter of a blob -class CBlobGetHullPerimeter: public COperadorBlob +class CBlobGetHullPerimeter : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetHullPerimeter"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetHullPerimeter"; + } }; //! Classe per calcular l'�rea del poligon convex d'un blob //! Class to calculate the convex hull area of a blob -class CBlobGetHullArea: public COperadorBlob +class CBlobGetHullArea : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetHullArea"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetHullArea"; + } }; //! Classe per calcular la x minima en la y minima //! Class to calculate the minimum x on the minimum y -class CBlobGetMinXatMinY: public COperadorBlob +class CBlobGetMinXatMinY : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMinXatMinY"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMinXatMinY"; + } }; //! Classe per calcular la y minima en la x maxima //! Class to calculate the minimum y on the maximum x -class CBlobGetMinYatMaxX: public COperadorBlob +class CBlobGetMinYatMaxX : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMinYatMaxX"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMinYatMaxX"; + } }; //! Classe per calcular la x maxima en la y maxima //! Class to calculate the maximum x on the maximum y -class CBlobGetMaxXatMaxY: public COperadorBlob +class CBlobGetMaxXatMaxY : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMaxXatMaxY"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMaxXatMaxY"; + } }; //! Classe per calcular la y maxima en la x minima //! Class to calculate the maximum y on the minimum y -class CBlobGetMaxYatMinX: public COperadorBlob +class CBlobGetMaxYatMinX : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetMaxYatMinX"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetMaxYatMinX"; + } }; //! Classe per a calcular la x m�nima //! Class to get the minimum x -class CBlobGetMinX: public COperadorBlob +class CBlobGetMinX : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinX(); - } - const char *GetNom() - { - return "CBlobGetMinX"; - } + double operator()(CBlob& blob) + { + return blob.MinX(); + } + const char* GetNom() + { + return "CBlobGetMinX"; + } }; //! Classe per a calcular la x m�xima //! Class to get the maximum x -class CBlobGetMaxX: public COperadorBlob +class CBlobGetMaxX : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MaxX(); - } - const char *GetNom() - { - return "CBlobGetMaxX"; - } + double operator()(CBlob& blob) + { + return blob.MaxX(); + } + const char* GetNom() + { + return "CBlobGetMaxX"; + } }; //! Classe per a calcular la y m�nima //! Class to get the minimum y -class CBlobGetMinY: public COperadorBlob +class CBlobGetMinY : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinY(); - } - const char *GetNom() - { - return "CBlobGetMinY"; - } + double operator()(CBlob& blob) + { + return blob.MinY(); + } + const char* GetNom() + { + return "CBlobGetMinY"; + } }; //! Classe per a calcular la y m�xima //! Class to get the maximum y -class CBlobGetMaxY: public COperadorBlob +class CBlobGetMaxY : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MaxY(); - } - const char *GetNom() - { - return "CBlobGetMaxY"; - } + double operator()(CBlob& blob) + { + return blob.MaxY(); + } + const char* GetNom() + { + return "CBlobGetMaxY"; + } }; - //! Classe per calcular l'elongacio d'un blob //! Class to calculate the elongation of the blob -class CBlobGetElongation: public COperadorBlob +class CBlobGetElongation : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetElongation"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetElongation"; + } }; //! Classe per calcular la rugositat d'un blob //! Class to calculate the roughness of the blob -class CBlobGetRoughness: public COperadorBlob +class CBlobGetRoughness : public COperadorBlob { public: - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetRoughness"; - } + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetRoughness"; + } }; //! Classe per calcular la dist�ncia entre el centre del blob i un punt donat -//! Class to calculate the euclidean distance between the center of a blob and a given point -class CBlobGetDistanceFromPoint: public COperadorBlob -{ -public: - //! Standard constructor (distance to point 0,0) - CBlobGetDistanceFromPoint() - { - m_x = m_y = 0.0; - } - //! Constructor (distance to point x,y) - CBlobGetDistanceFromPoint( const double x, const double y ) - { - m_x = x; - m_y = y; - } - - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetDistanceFromPoint"; - } +//! Class to calculate the euclidean distance between the center of a blob and +//! a given point +class CBlobGetDistanceFromPoint : public COperadorBlob +{ +public: + //! Standard constructor (distance to point 0,0) + CBlobGetDistanceFromPoint() + { + m_x = m_y = 0.0; + } + //! Constructor (distance to point x,y) + CBlobGetDistanceFromPoint(const double x, const double y) + { + m_x = x; + m_y = y; + } + + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetDistanceFromPoint"; + } private: - // coordenades del punt on volem calcular la dist�ncia - double m_x, m_y; + // coordenades del punt on volem calcular la dist�ncia + double m_x, m_y; }; //! Classe per calcular el nombre de pixels externs d'un blob //! Class to get the number of extern pixels of a blob -class CBlobGetExternPerimeter: public COperadorBlob -{ -public: - CBlobGetExternPerimeter() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExternPerimeter( IplImage *mask, bool xBorder = true, bool yBorder = true ) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExternPerimeter"; - } +class CBlobGetExternPerimeter : public COperadorBlob +{ +public: + CBlobGetExternPerimeter() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExternPerimeter(IplImage* mask, + bool xBorder = true, + bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExternPerimeter"; + } + private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; //! Classe per calcular el ratio entre el perimetre i nombre pixels externs //! valors propers a 0 indiquen que la majoria del blob �s intern //! valors propers a 1 indiquen que la majoria del blob �s extern -//! Class to calculate the ratio between the perimeter and the number of extern pixels -class CBlobGetExternPerimeterRatio: public COperadorBlob -{ -public: - CBlobGetExternPerimeterRatio() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExternPerimeterRatio( IplImage *mask, bool xBorder = true, bool yBorder = true ) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - if( blob.Perimeter() != 0 ) - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / blob.Perimeter(); - else - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExternPerimeterRatio"; - } +//! Class to calculate the ratio between the perimeter and the number of extern +//! pixels +class CBlobGetExternPerimeterRatio : public COperadorBlob +{ +public: + CBlobGetExternPerimeterRatio() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExternPerimeterRatio(IplImage* mask, + bool xBorder = true, + bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + if (blob.Perimeter() != 0) + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / + blob.Perimeter(); + else + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExternPerimeterRatio"; + } + private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; -//! Classe per calcular el ratio entre el perimetre convex i nombre pixels externs -//! valors propers a 0 indiquen que la majoria del blob �s intern +//! Classe per calcular el ratio entre el perimetre convex i nombre pixels +//! externs valors propers a 0 indiquen que la majoria del blob �s intern //! valors propers a 1 indiquen que la majoria del blob �s extern -//! Class to calculate the ratio between the perimeter and the number of extern pixels -class CBlobGetExternHullPerimeterRatio: public COperadorBlob -{ -public: - CBlobGetExternHullPerimeterRatio() - { - m_mask = NULL; - m_xBorder = false; - m_yBorder = false; - } - CBlobGetExternHullPerimeterRatio( IplImage *mask, bool xBorder = true, bool yBorder = true ) - { - m_mask = mask; - m_xBorder = xBorder; - m_yBorder = yBorder; - } - double operator()(CBlob &blob) - { - CBlobGetHullPerimeter getHullPerimeter; - double hullPerimeter; - - if( (hullPerimeter = getHullPerimeter( blob ) ) != 0 ) - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / hullPerimeter; - else - return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); - } - const char *GetNom() - { - return "CBlobGetExternHullPerimeterRatio"; - } -private: - IplImage *m_mask; - bool m_xBorder, m_yBorder; +//! Class to calculate the ratio between the perimeter and the number of extern +//! pixels +class CBlobGetExternHullPerimeterRatio : public COperadorBlob +{ +public: + CBlobGetExternHullPerimeterRatio() + { + m_mask = NULL; + m_xBorder = false; + m_yBorder = false; + } + CBlobGetExternHullPerimeterRatio(IplImage* mask, + bool xBorder = true, + bool yBorder = true) + { + m_mask = mask; + m_xBorder = xBorder; + m_yBorder = yBorder; + } + double operator()(CBlob& blob) + { + CBlobGetHullPerimeter getHullPerimeter; + double hullPerimeter; + + if ((hullPerimeter = getHullPerimeter(blob)) != 0) + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder) / + hullPerimeter; + else + return blob.ExternPerimeter(m_mask, m_xBorder, m_yBorder); + } + const char* GetNom() + { + return "CBlobGetExternHullPerimeterRatio"; + } +private: + IplImage* m_mask; + bool m_xBorder, m_yBorder; }; //! Classe per calcular el centre en el eix X d'un blob //! Class to calculate the center in the X direction -class CBlobGetXCenter: public COperadorBlob +class CBlobGetXCenter : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinX() + (( blob.MaxX() - blob.MinX() ) / 2.0); - } - const char *GetNom() - { - return "CBlobGetXCenter"; - } + double operator()(CBlob& blob) + { + return blob.MinX() + ((blob.MaxX() - blob.MinX()) / 2.0); + } + const char* GetNom() + { + return "CBlobGetXCenter"; + } }; //! Classe per calcular el centre en el eix Y d'un blob //! Class to calculate the center in the Y direction -class CBlobGetYCenter: public COperadorBlob +class CBlobGetYCenter : public COperadorBlob { public: - double operator()(CBlob &blob) - { - return blob.MinY() + (( blob.MaxY() - blob.MinY() ) / 2.0); - } - const char *GetNom() - { - return "CBlobGetYCenter"; - } + double operator()(CBlob& blob) + { + return blob.MinY() + ((blob.MaxY() - blob.MinY()) / 2.0); + } + const char* GetNom() + { + return "CBlobGetYCenter"; + } }; //! Classe per calcular la longitud de l'eix major d'un blob -//! Class to calculate the length of the major axis of the ellipse that fits the blob edges -class CBlobGetMajorAxisLength: public COperadorBlob +//! Class to calculate the length of the major axis of the ellipse that fits +//! the blob edges +class CBlobGetMajorAxisLength : public COperadorBlob { public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); + double operator()(CBlob& blob) + { + CvBox2D elipse = blob.GetEllipse(); - return elipse.size.width; - } - const char *GetNom() - { - return "CBlobGetMajorAxisLength"; - } + return elipse.size.width; + } + const char* GetNom() + { + return "CBlobGetMajorAxisLength"; + } }; //! Classe per calcular el ratio entre l'area de la elipse i la de la taca -//! Class -class CBlobGetAreaElipseRatio: public COperadorBlob +//! Class +class CBlobGetAreaElipseRatio : public COperadorBlob { public: - double operator()(CBlob &blob) - { - if( blob.Area()==0.0 ) return 0.0; + double operator()(CBlob& blob) + { + if (blob.Area() == 0.0) + return 0.0; - CvBox2D elipse = blob.GetEllipse(); - double ratioAreaElipseAreaTaca = ( (elipse.size.width/2.0) - * - (elipse.size.height/2.0) - *CV_PI - ) - / - blob.Area(); + CvBox2D elipse = blob.GetEllipse(); + double ratioAreaElipseAreaTaca = ((elipse.size.width / 2.0) * + (elipse.size.height / 2.0) * CV_PI) / + blob.Area(); - return ratioAreaElipseAreaTaca; - } - const char *GetNom() - { - return "CBlobGetAreaElipseRatio"; - } + return ratioAreaElipseAreaTaca; + } + const char* GetNom() + { + return "CBlobGetAreaElipseRatio"; + } }; //! Classe per calcular la longitud de l'eix menor d'un blob -//! Class to calculate the length of the minor axis of the ellipse that fits the blob edges -class CBlobGetMinorAxisLength: public COperadorBlob +//! Class to calculate the length of the minor axis of the ellipse that fits +//! the blob edges +class CBlobGetMinorAxisLength : public COperadorBlob { public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); + double operator()(CBlob& blob) + { + CvBox2D elipse = blob.GetEllipse(); - return elipse.size.height; - } - const char *GetNom() - { - return "CBlobGetMinorAxisLength"; - } + return elipse.size.height; + } + const char* GetNom() + { + return "CBlobGetMinorAxisLength"; + } }; //! Classe per calcular l'orientaci� de l'ellipse del blob en radians -//! Class to calculate the orientation of the ellipse that fits the blob edges in radians -class CBlobGetOrientation: public COperadorBlob -{ -public: - double operator()(CBlob &blob) - { - CvBox2D elipse = blob.GetEllipse(); -/* - if( elipse.angle > 180.0 ) - return (( elipse.angle - 180.0 )* DEGREE2RAD); - else - return ( elipse.angle * DEGREE2RAD); -*/ - return elipse.angle; - } - const char *GetNom() - { - return "CBlobGetOrientation"; - } +//! Class to calculate the orientation of the ellipse that fits the blob edges +//! in radians +class CBlobGetOrientation : public COperadorBlob +{ +public: + double operator()(CBlob& blob) + { + CvBox2D elipse = blob.GetEllipse(); + /* + if( elipse.angle > 180.0 ) + return (( elipse.angle - 180.0 )* DEGREE2RAD); + else + return ( elipse.angle * DEGREE2RAD); + */ + return elipse.angle; + } + const char* GetNom() + { + return "CBlobGetOrientation"; + } }; //! Classe per calcular el cosinus de l'orientaci� de l'ellipse del blob -//! Class to calculate the cosinus of the orientation of the ellipse that fits the blob edges -class CBlobGetOrientationCos: public COperadorBlob +//! Class to calculate the cosinus of the orientation of the ellipse that fits +//! the blob edges +class CBlobGetOrientationCos : public COperadorBlob { public: - double operator()(CBlob &blob) - { - CBlobGetOrientation getOrientation; - return fabs( cos( getOrientation(blob)*DEGREE2RAD )); - } - const char *GetNom() - { - return "CBlobGetOrientationCos"; - } + double operator()(CBlob& blob) + { + CBlobGetOrientation getOrientation; + return fabs(cos(getOrientation(blob) * DEGREE2RAD)); + } + const char* GetNom() + { + return "CBlobGetOrientationCos"; + } }; - //! Classe per calcular el ratio entre l'eix major i menor de la el�lipse //! Class to calculate the ratio between both axes of the ellipse -class CBlobGetAxisRatio: public COperadorBlob +class CBlobGetAxisRatio : public COperadorBlob { public: - double operator()(CBlob &blob) - { - double major,minor; - CBlobGetMajorAxisLength getMajor; - CBlobGetMinorAxisLength getMinor; + double operator()(CBlob& blob) + { + double major, minor; + CBlobGetMajorAxisLength getMajor; + CBlobGetMinorAxisLength getMinor; - major = getMajor(blob); - minor = getMinor(blob); + major = getMajor(blob); + minor = getMinor(blob); - if( major != 0 ) - return minor / major; - else - return 0; - } - const char *GetNom() - { - return "CBlobGetAxisRatio"; - } + if (major != 0) + return minor / major; + else + return 0; + } + const char* GetNom() + { + return "CBlobGetAxisRatio"; + } }; - //! Classe per calcular si un punt cau dins del blob //! Class to calculate whether a point is inside a blob -class CBlobGetXYInside: public COperadorBlob -{ -public: - //! Constructor est�ndard - //! Standard constructor - CBlobGetXYInside() - { - m_p.x = 0; - m_p.y = 0; - } - //! Constructor: indiquem el punt - //! Constructor: sets the point - CBlobGetXYInside( CvPoint2D32f p ) - { - m_p = p; - }; - double operator()(CBlob &blob); - const char *GetNom() - { - return "CBlobGetXYInside"; - } +class CBlobGetXYInside : public COperadorBlob +{ +public: + //! Constructor est�ndard + //! Standard constructor + CBlobGetXYInside() + { + m_p.x = 0; + m_p.y = 0; + } + //! Constructor: indiquem el punt + //! Constructor: sets the point + CBlobGetXYInside(CvPoint2D32f p) + { + m_p = p; + }; + double operator()(CBlob& blob); + const char* GetNom() + { + return "CBlobGetXYInside"; + } private: - //! punt que considerem - //! point to be considered - CvPoint2D32f m_p; + //! punt que considerem + //! point to be considered + CvPoint2D32f m_p; }; -#endif //!BLOB_OPERATORS_H_INCLUDED +#endif //! BLOB_OPERATORS_H_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp index 64b7265..dd1e495 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.cpp @@ -1,31 +1,33 @@ #include "BlobProperties.h" - /** - FUNCIÓ: GetPerimeter -- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and horizontal and vertical codes 1 +- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and +horizontal and vertical codes 1 - PARÀMETRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACIÓ: 2008/04/30 - MODIFICACIÓ: Data. Autor. Descripció. -- NOTA: Algorithm derived from "Methods to estimate area and perimeters of blob-like objects: A comparison", L.Yang +- NOTA: Algorithm derived from "Methods to estimate area and perimeters of +blob-like objects: A comparison", L.Yang */ #define SQRT2 1.414213562 /** - FUNCIÓ: GetPerimeter -- FUNCIONALITAT: Get blob area, ie. external contour area minus internal contours area +- FUNCIONALITAT: Get blob area, ie. external contour area minus internal +contours area - PARÀMETRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACIÓ: 2008/04/30 - MODIFICACIÓ: Data. Autor. Descripció. @@ -33,49 +35,45 @@ double CBlobProperties::GetArea() { - double area; - t_contourList::iterator itContour; + double area; + t_contourList::iterator itContour; + + area = m_externalContour.GetArea(); - area = m_externalContour.GetArea(); + itContour = m_internalContours.begin(); - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - area += (*itContour).GetArea(); - itContour++; - } - return area; + while (itContour != m_internalContours.end()) { + area += (*itContour).GetArea(); + itContour++; + } + return area; } /** - FUNCIÓ: GetPerimeter - FUNCIONALITAT: Get blob perimeter, ie. sum of the lenght of all the contours - PARÀMETRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACIÓ: 2008/04/30 - MODIFICACIÓ: Data. Autor. Descripció. */ double CBlobProperties::GetPerimeter() { - double perimeter; - t_contourList::iterator itContour; + double perimeter; + t_contourList::iterator itContour; - perimeter = m_externalContour.GetPerimeter(); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - perimeter += (*itContour).GetPerimeter(); - itContour++; - } - return perimeter; -} + perimeter = m_externalContour.GetPerimeter(); + itContour = m_internalContours.begin(); + while (itContour != m_internalContours.end()) { + perimeter += (*itContour).GetPerimeter(); + itContour++; + } + return perimeter; +} diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h index 97d028a..46f3e1e 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobProperties.h @@ -1,67 +1,59 @@ //! Disable warnings referred to 255 character truncation for the std:map -#pragma warning( disable : 4786 ) +#pragma warning(disable : 4786) #ifndef BLOB_PROPERTIES_H_INCLUDED -#define BLOB_PROPERTIES_H_INCLUDED + #define BLOB_PROPERTIES_H_INCLUDED -#include + #include -#include - -#include "BlobLibraryConfiguration.h" -#include "BlobContour.h" + #include + #include "BlobLibraryConfiguration.h" + #include "BlobContour.h" //! Type of labelled images typedef unsigned int t_labelType; -//! Max order of calculated moments -#define MAX_MOMENTS_ORDER 3 - + //! Max order of calculated moments + #define MAX_MOMENTS_ORDER 3 //! Blob class class CBlobProperties { - typedef std::list t_contourList; + typedef std::list t_contourList; public: + CBlobProperties(); + virtual ~CBlobProperties(); - CBlobProperties(); - virtual ~CBlobProperties(); - - //! Get blob area - double GetArea(); + //! Get blob area + double GetArea(); - //! Get blob perimeter - double GetPerimeter(); + //! Get blob perimeter + double GetPerimeter(); - //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) - double GetMoment(int p, int q); - + //! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS) + double GetMoment(int p, int q); - ////////////////////////////////////////////////////////////////////////// - // Blob contours - ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // Blob contours + ////////////////////////////////////////////////////////////////////////// - - //! Contour storage memory - CvMemStorage *m_storage; - //! External contour of the blob (crack codes) - CBlobContour m_externalContour; - //! Internal contours (crack codes) - t_contourList m_internalContours; + //! Contour storage memory + CvMemStorage* m_storage; + //! External contour of the blob (crack codes) + CBlobContour m_externalContour; + //! Internal contours (crack codes) + t_contourList m_internalContours; private: - - //! Computed area from blob - double m_area; - //! Computed perimeter from blob - double m_perimeter; - // Computed moment from the blob - double m_moment[MAX_MOMENTS_ORDER*MAX_MOMENTS_ORDER]; - + //! Computed area from blob + double m_area; + //! Computed perimeter from blob + double m_perimeter; + // Computed moment from the blob + double m_moment[MAX_MOMENTS_ORDER * MAX_MOMENTS_ORDER]; }; -#endif //!BLOB_PROPERTIES_H_INCLUDED - +#endif //! BLOB_PROPERTIES_H_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp index 7e84c53..02b23e9 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp @@ -1,10 +1,10 @@ /************************************************************************ - BlobResult.cpp - + BlobResult.cpp + FUNCIONALITAT: Implementaci� de la classe CBlobResult AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): - + **************************************************************************/ #include @@ -14,10 +14,9 @@ MODIFICACIONS (Modificaci�, Autor, Data): #include "BlobResult.h" /************************************************************************** - Constructors / Destructors + Constructors / Destructors **************************************************************************/ - /** - FUNCI�: CBlobResult - FUNCIONALITAT: Constructor estandard. @@ -34,7 +33,7 @@ MODIFICACIONS (Modificaci�, Autor, Data): - FUNCTIONALITY: Standard constructor - PARAMETERS: - RESULT: - - creates an empty set of blobs + - creates an empty set of blobs - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. @@ -42,25 +41,27 @@ MODIFICACIONS (Modificaci�, Autor, Data): */ CBlobResult::CBlobResult() { - m_blobs = Blob_vector(); + m_blobs = Blob_vector(); } /** - FUNCI�: CBlobResult -- FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seq��ncia de blobs - amb els blobs resultants de l'an�lisi de blobs de la imatge. +- FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seq��ncia de +blobs amb els blobs resultants de l'an�lisi de blobs de la imatge. - PAR�METRES: - - source: imatge d'on s'extreuran els blobs - - mask: m�scara a aplicar. Nom�s es calcularan els blobs on la m�scara sigui - diferent de 0. Els blobs que toquin a un pixel 0 de la m�scara seran - considerats exteriors. - - threshold: llindar que s'aplicar� a la imatge source abans de calcular els blobs - - findmoments: indica si s'han de calcular els moments de cada blob - - blackBlobs: true per buscar blobs negres a la binaritzazi� (it will join all extern white blobs). - false per buscar blobs negres a la binaritzazi� (it will join all extern black blobs). + - source: imatge d'on s'extreuran els blobs + - mask: m�scara a aplicar. Nom�s es calcularan els blobs on la m�scara +sigui diferent de 0. Els blobs que toquin a un pixel 0 de la m�scara seran + considerats exteriors. + - threshold: llindar que s'aplicar� a la imatge source abans de calcular +els blobs + - findmoments: indica si s'han de calcular els moments de cada blob + - blackBlobs: true per buscar blobs negres a la binaritzazi� (it will join +all extern white blobs). false per buscar blobs negres a la binaritzazi� (it +will join all extern black blobs). - RESULTAT: - - objecte CBlobResult amb els blobs de la imatge source + - objecte CBlobResult amb els blobs de la imatge source - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -68,48 +69,48 @@ CBlobResult::CBlobResult() */ /** - FUNCTION: CBlob -- FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs in - the image +- FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs +in the image - PARAMETERS: - - source: image to extract the blobs from - - mask: optional mask to apply. The blobs will be extracted where the mask is - not 0. All the neighboring blobs where the mask is 0 will be extern blobs - - threshold: threshold level to apply to the image before computing blobs - - findmoments: true to calculate the blob moments (slower) (needed to calculate elipses!) - - blackBlobs: true to search for black blobs in the binarization (it will join all extern white blobs). - false to search for white blobs in the binarization (it will join all extern black blobs). + - source: image to extract the blobs from + - mask: optional mask to apply. The blobs will be extracted where the mask +is not 0. All the neighboring blobs where the mask is 0 will be extern blobs + - threshold: threshold level to apply to the image before computing blobs + - findmoments: true to calculate the blob moments (slower) (needed to +calculate elipses!) + - blackBlobs: true to search for black blobs in the binarization (it will +join all extern white blobs). false to search for white blobs in the +binarization (it will join all extern black blobs). - RESULT: - - object with all the blobs in the image. It throws an EXCEPCIO_CALCUL_BLOBS - if some error appears in the BlobAnalysis function + - object with all the blobs in the image. It throws an +EXCEPCIO_CALCUL_BLOBS if some error appears in the BlobAnalysis function - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -CBlobResult::CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor ) +CBlobResult::CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor) { - bool success; - - try - { - success = ComponentLabeling( source, mask, backgroundColor, m_blobs ); - } - catch(...) - { - success = false; - } - - if( !success ) throw EXCEPCIO_CALCUL_BLOBS; + bool success; + + try { + success = ComponentLabeling(source, mask, backgroundColor, m_blobs); + } catch (...) { + success = false; + } + + if (!success) + throw EXCEPCIO_CALCUL_BLOBS; } /** - FUNCI�: CBlobResult -- FUNCIONALITAT: Constructor de c�pia. Inicialitza la seq��ncia de blobs - amb els blobs del par�metre. +- FUNCIONALITAT: Constructor de c�pia. Inicialitza la seq��ncia de blobs + amb els blobs del par�metre. - PAR�METRES: - - source: objecte que es copiar� + - source: objecte que es copiar� - RESULTAT: - - objecte CBlobResult amb els blobs de l'objecte source + - objecte CBlobResult amb els blobs de l'objecte source - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -119,42 +120,39 @@ CBlobResult::CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor ) - FUNCTION: CBlobResult - FUNCTIONALITY: Copy constructor - PARAMETERS: - - source: object to copy + - source: object to copy - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -CBlobResult::CBlobResult( const CBlobResult &source ) +CBlobResult::CBlobResult(const CBlobResult& source) { - m_blobs = Blob_vector( source.GetNumBlobs() ); - - // creem el nou a partir del passat com a par�metre - m_blobs = Blob_vector( source.GetNumBlobs() ); - // copiem els blobs de l'origen a l'actual - Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); - Blob_vector::iterator pBlobsDst = m_blobs.begin(); - - while( pBlobsSrc != source.m_blobs.end() ) - { - // no podem cridar a l'operador = ja que Blob_vector �s un - // vector de CBlob*. Per tant, creem un blob nou a partir del - // blob original - *pBlobsDst = new CBlob(**pBlobsSrc); - pBlobsSrc++; - pBlobsDst++; - } + m_blobs = Blob_vector(source.GetNumBlobs()); + + // creem el nou a partir del passat com a par�metre + m_blobs = Blob_vector(source.GetNumBlobs()); + // copiem els blobs de l'origen a l'actual + Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); + Blob_vector::iterator pBlobsDst = m_blobs.begin(); + + while (pBlobsSrc != source.m_blobs.end()) { + // no podem cridar a l'operador = ja que Blob_vector �s un + // vector de CBlob*. Per tant, creem un blob nou a partir del + // blob original + *pBlobsDst = new CBlob(**pBlobsSrc); + pBlobsSrc++; + pBlobsDst++; + } } - - /** - FUNCI�: ~CBlobResult - FUNCIONALITAT: Destructor estandard. - PAR�METRES: - RESULTAT: - - Allibera la mem�ria reservada de cadascun dels blobs de la classe + - Allibera la mem�ria reservada de cadascun dels blobs de la classe - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -172,21 +170,20 @@ CBlobResult::CBlobResult( const CBlobResult &source ) */ CBlobResult::~CBlobResult() { - ClearBlobs(); + ClearBlobs(); } /************************************************************************** - Operadors / Operators + Operadors / Operators **************************************************************************/ - /** - FUNCI�: operador = - FUNCIONALITAT: Assigna un objecte source a l'actual - PAR�METRES: - - source: objecte a assignar + - source: objecte a assignar - RESULTAT: - - Substitueix els blobs actuals per els de l'objecte source + - Substitueix els blobs actuals per els de l'objecte source - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -194,7 +191,7 @@ CBlobResult::~CBlobResult() */ /** - FUNCTION: Assigment operator -- FUNCTIONALITY: +- FUNCTIONALITY: - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -204,42 +201,38 @@ CBlobResult::~CBlobResult() */ CBlobResult& CBlobResult::operator=(const CBlobResult& source) { - // si ja s�n el mateix, no cal fer res - if (this != &source) - { - // alliberem el conjunt de blobs antic - for( int i = 0; i < GetNumBlobs(); i++ ) - { - delete m_blobs[i]; - } - m_blobs.clear(); - // creem el nou a partir del passat com a par�metre - m_blobs = Blob_vector( source.GetNumBlobs() ); - // copiem els blobs de l'origen a l'actual - Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); - Blob_vector::iterator pBlobsDst = m_blobs.begin(); - - while( pBlobsSrc != source.m_blobs.end() ) - { - // no podem cridar a l'operador = ja que Blob_vector �s un - // vector de CBlob*. Per tant, creem un blob nou a partir del - // blob original - *pBlobsDst = new CBlob(**pBlobsSrc); - pBlobsSrc++; - pBlobsDst++; - } - } - return *this; + // si ja s�n el mateix, no cal fer res + if (this != &source) { + // alliberem el conjunt de blobs antic + for (int i = 0; i < GetNumBlobs(); i++) { + delete m_blobs[i]; + } + m_blobs.clear(); + // creem el nou a partir del passat com a par�metre + m_blobs = Blob_vector(source.GetNumBlobs()); + // copiem els blobs de l'origen a l'actual + Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); + Blob_vector::iterator pBlobsDst = m_blobs.begin(); + + while (pBlobsSrc != source.m_blobs.end()) { + // no podem cridar a l'operador = ja que Blob_vector �s un + // vector de CBlob*. Per tant, creem un blob nou a partir del + // blob original + *pBlobsDst = new CBlob(**pBlobsSrc); + pBlobsSrc++; + pBlobsDst++; + } + } + return *this; } - /** - FUNCI�: operador + - FUNCIONALITAT: Concatena els blobs de dos CBlobResult - PAR�METRES: - - source: d'on s'agafaran els blobs afegits a l'actual + - source: d'on s'agafaran els blobs afegits a l'actual - RESULTAT: - - retorna un nou CBlobResult amb els dos CBlobResult concatenats + - retorna un nou CBlobResult amb els dos CBlobResult concatenats - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -250,67 +243,66 @@ CBlobResult& CBlobResult::operator=(const CBlobResult& source) - FUNCTION: + operator - FUNCTIONALITY: Joins the blobs in source with the current ones - PARAMETERS: - - source: object to copy the blobs + - source: object to copy the blobs - RESULT: - - object with the actual blobs and the source blobs + - object with the actual blobs and the source blobs - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -CBlobResult CBlobResult::operator+( const CBlobResult& source ) const -{ - //creem el resultat a partir dels blobs actuals - CBlobResult resultat( *this ); - - // reservem mem�ria per als nous blobs - resultat.m_blobs.resize( resultat.GetNumBlobs() + source.GetNumBlobs() ); - - // declarem els iterador per rec�rrer els blobs d'origen i desti - Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); - Blob_vector::iterator pBlobsDst = resultat.m_blobs.end(); - - // insertem els blobs de l'origen a l'actual - while( pBlobsSrc != source.m_blobs.end() ) - { - pBlobsDst--; - *pBlobsDst = new CBlob(**pBlobsSrc); - pBlobsSrc++; - } - - return resultat; +CBlobResult CBlobResult::operator+(const CBlobResult& source) const +{ + // creem el resultat a partir dels blobs actuals + CBlobResult resultat(*this); + + // reservem mem�ria per als nous blobs + resultat.m_blobs.resize(resultat.GetNumBlobs() + source.GetNumBlobs()); + + // declarem els iterador per rec�rrer els blobs d'origen i desti + Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); + Blob_vector::iterator pBlobsDst = resultat.m_blobs.end(); + + // insertem els blobs de l'origen a l'actual + while (pBlobsSrc != source.m_blobs.end()) { + pBlobsDst--; + *pBlobsDst = new CBlob(**pBlobsSrc); + pBlobsSrc++; + } + + return resultat; } /************************************************************************** - Operacions / Operations + Operacions / Operations **************************************************************************/ /** - FUNCI�: AddBlob - FUNCIONALITAT: Afegeix un blob al conjunt - PAR�METRES: - - blob: blob a afegir + - blob: blob a afegir - RESULTAT: - - modifica el conjunt de blobs actual + - modifica el conjunt de blobs actual - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 2006/03/01 - MODIFICACI�: Data. Autor. Descripci�. */ -void CBlobResult::AddBlob( CBlob *blob ) +void CBlobResult::AddBlob(CBlob* blob) { - if( blob != NULL ) - m_blobs.push_back( new CBlob( blob ) ); + if (blob != NULL) + m_blobs.push_back(new CBlob(blob)); } - /** - FUNCI�: GetSTLResult -- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe +- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la +classe - PAR�METRES: - - evaluador: Qualsevol objecte derivat de COperadorBlob + - evaluador: Qualsevol objecte derivat de COperadorBlob - RESULTAT: - - Retorna un array de double's STL amb el resultat per cada blob + - Retorna un array de double's STL amb el resultat per cada blob - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -319,48 +311,47 @@ void CBlobResult::AddBlob( CBlob *blob ) /** - FUNCTION: GetResult - FUNCTIONALITY: Computes the function evaluador on all the blobs of the class - and returns a vector with the result + and returns a vector with the result - PARAMETERS: - - evaluador: function to apply to each blob (any object derived from the - COperadorBlob class ) + - evaluador: function to apply to each blob (any object derived from the + COperadorBlob class ) - RESULT: - - vector with all the results in the same order as the blobs + - vector with all the results in the same order as the blobs - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double_stl_vector CBlobResult::GetSTLResult( funcio_calculBlob *evaluador ) const +double_stl_vector CBlobResult::GetSTLResult(funcio_calculBlob* evaluador) const { - if( GetNumBlobs() <= 0 ) - { - return double_stl_vector(); - } - - // definim el resultat - double_stl_vector result = double_stl_vector( GetNumBlobs() ); - // i iteradors sobre els blobs i el resultat - double_stl_vector::iterator itResult = result.begin(); - Blob_vector::const_iterator itBlobs = m_blobs.begin(); - - // avaluem la funci� en tots els blobs - while( itBlobs != m_blobs.end() ) - { - *itResult = (*evaluador)(**itBlobs); - itBlobs++; - itResult++; - } - return result; + if (GetNumBlobs() <= 0) { + return double_stl_vector(); + } + + // definim el resultat + double_stl_vector result = double_stl_vector(GetNumBlobs()); + // i iteradors sobre els blobs i el resultat + double_stl_vector::iterator itResult = result.begin(); + Blob_vector::const_iterator itBlobs = m_blobs.begin(); + + // avaluem la funci� en tots els blobs + while (itBlobs != m_blobs.end()) { + *itResult = (*evaluador)(**itBlobs); + itBlobs++; + itResult++; + } + return result; } /** - FUNCI�: GetNumber -- FUNCIONALITAT: Calcula el resultat especificat sobre un �nic blob de la classe +- FUNCIONALITAT: Calcula el resultat especificat sobre un �nic blob de la +classe - PAR�METRES: - - evaluador: Qualsevol objecte derivat de COperadorBlob - - indexblob: n�mero de blob del que volem calcular el resultat. + - evaluador: Qualsevol objecte derivat de COperadorBlob + - indexblob: n�mero de blob del que volem calcular el resultat. - RESULTAT: - - Retorna un double amb el resultat + - Retorna un double amb el resultat - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -370,46 +361,50 @@ double_stl_vector CBlobResult::GetSTLResult( funcio_calculBlob *evaluador ) cons - FUNCTION: GetNumber - FUNCTIONALITY: Computes the function evaluador on a blob of the class - PARAMETERS: - - indexBlob: index of the blob to compute the function - - evaluador: function to apply to each blob (any object derived from the - COperadorBlob class ) + - indexBlob: index of the blob to compute the function + - evaluador: function to apply to each blob (any object derived from the + COperadorBlob class ) - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -double CBlobResult::GetNumber( int indexBlob, funcio_calculBlob *evaluador ) const +double CBlobResult::GetNumber(int indexBlob, + funcio_calculBlob* evaluador) const { - if( indexBlob < 0 || indexBlob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); - return (*evaluador)( *m_blobs[indexBlob] ); + if (indexBlob < 0 || indexBlob >= GetNumBlobs()) + RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS); + return (*evaluador)(*m_blobs[indexBlob]); } -/////////////////////////// FILTRAT DE BLOBS //////////////////////////////////// +/////////////////////////// FILTRAT DE BLOBS +/////////////////////////////////////// /** - FUNCI�: Filter -- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s - els blobs que han passat el filtre. - El filtrat es basa en especificar condicions sobre un resultat dels blobs - i seleccionar (o excloure) aquells blobs que no compleixen una determinada - condicio +- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s + els blobs que han passat el filtre. + El filtrat es basa en especificar condicions sobre un resultat +dels blobs i seleccionar (o excloure) aquells blobs que no compleixen una +determinada condicio - PAR�METRES: - - dst: variable per deixar els blobs filtrats - - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), - o excloure els blobs trobats (B_EXCLUDE) - - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de COperadorBlob - - Condition: tipus de condici� que ha de superar la mesura (FilterType) - sobre cada blob per a ser considerat. - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - (nom�s t� sentit per a aquelles condicions que tenen dos valors - (B_INSIDE, per exemple). + - dst: variable per deixar els blobs filtrats + - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), + o excloure els blobs trobats (B_EXCLUDE) + - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de +COperadorBlob + - Condition: tipus de condici� que ha de superar la mesura (FilterType) + sobre cada blob per a ser considerat. + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) + - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) (nom�s t� sentit per a aquelles condicions que tenen dos valors + (B_INSIDE, per exemple). - RESULTAT: - - Deixa els blobs resultants del filtrat a destination + - Deixa els blobs resultants del filtrat a destination - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -418,60 +413,63 @@ double CBlobResult::GetNumber( int indexBlob, funcio_calculBlob *evaluador ) con /** - FUNCTION: Filter - FUNCTIONALITY: Get some blobs from the class based on conditions on measures - of the blobs. + of the blobs. - PARAMETERS: - - dst: where to store the selected blobs - - filterAction: B_INCLUDE: include the blobs which pass the filter in the result - B_EXCLUDE: exclude the blobs which pass the filter in the result - - evaluador: Object to evaluate the blob - - Condition: How to decide if the result returned by evaluador on each blob - is included or not. It can be: - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: numerical value to evaluate the Condition on evaluador(blob) - - HighLimit: numerical value to evaluate the Condition on evaluador(blob). - Only useful for B_INSIDE and B_OUTSIDE + - dst: where to store the selected blobs + - filterAction: B_INCLUDE: include the blobs which pass the filter in the +result B_EXCLUDE: exclude the blobs which pass the filter in the result + - evaluador: Object to evaluate the blob + - Condition: How to decide if the result returned by evaluador on each +blob is included or not. It can be: + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: numerical value to evaluate the Condition on evaluador(blob) + - HighLimit: numerical value to evaluate the Condition on evaluador(blob). + Only useful for B_INSIDE and B_OUTSIDE - RESULT: - - It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE) - the Condition on the result returned by evaluador on each blob + - It returns on dst the blobs that accomplish (B_INCLUDE) or discards +(B_EXCLUDE) the Condition on the result returned by evaluador on each blob - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::Filter(CBlobResult &dst, - int filterAction, - funcio_calculBlob *evaluador, - int condition, - double lowLimit, double highLimit /*=0*/) const - +void CBlobResult::Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit /*=0*/) const + { - // do the job - DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit ); + // do the job + DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit); } /** - FUNCI�: Filter (const version) -- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s - els blobs que han passat el filtre. - El filtrat es basa en especificar condicions sobre un resultat dels blobs - i seleccionar (o excloure) aquells blobs que no compleixen una determinada - condicio +- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom�s + els blobs que han passat el filtre. + El filtrat es basa en especificar condicions sobre un resultat +dels blobs i seleccionar (o excloure) aquells blobs que no compleixen una +determinada condicio - PAR�METRES: - - dst: variable per deixar els blobs filtrats - - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), - o excloure els blobs trobats (B_EXCLUDE) - - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de COperadorBlob - - Condition: tipus de condici� que ha de superar la mesura (FilterType) - sobre cada blob per a ser considerat. - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura (FilterType) - (nom�s t� sentit per a aquelles condicions que tenen dos valors - (B_INSIDE, per exemple). + - dst: variable per deixar els blobs filtrats + - filterAction: acci� de filtrat. Incloure els blobs trobats (B_INCLUDE), + o excloure els blobs trobats (B_EXCLUDE) + - evaluador: Funci� per evaluar els blobs (qualsevol objecte derivat de +COperadorBlob + - Condition: tipus de condici� que ha de superar la mesura (FilterType) + sobre cada blob per a ser considerat. + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) + - HighLimit: valor num�ric per a la comparaci� (Condition) de la mesura +(FilterType) (nom�s t� sentit per a aquelles condicions que tenen dos valors + (B_INSIDE, per exemple). - RESULTAT: - - Deixa els blobs resultants del filtrat a destination + - Deixa els blobs resultants del filtrat a destination - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -480,167 +478,156 @@ void CBlobResult::Filter(CBlobResult &dst, /** - FUNCTION: Filter (const version) - FUNCTIONALITY: Get some blobs from the class based on conditions on measures - of the blobs. + of the blobs. - PARAMETERS: - - dst: where to store the selected blobs - - filterAction: B_INCLUDE: include the blobs which pass the filter in the result - B_EXCLUDE: exclude the blobs which pass the filter in the result - - evaluador: Object to evaluate the blob - - Condition: How to decide if the result returned by evaluador on each blob - is included or not. It can be: - B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, - B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE - - LowLimit: numerical value to evaluate the Condition on evaluador(blob) - - HighLimit: numerical value to evaluate the Condition on evaluador(blob). - Only useful for B_INSIDE and B_OUTSIDE + - dst: where to store the selected blobs + - filterAction: B_INCLUDE: include the blobs which pass the filter in the +result B_EXCLUDE: exclude the blobs which pass the filter in the result + - evaluador: Object to evaluate the blob + - Condition: How to decide if the result returned by evaluador on each +blob is included or not. It can be: + B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL, + B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE + - LowLimit: numerical value to evaluate the Condition on evaluador(blob) + - HighLimit: numerical value to evaluate the Condition on evaluador(blob). + Only useful for B_INSIDE and B_OUTSIDE - RESULT: - - It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE) - the Condition on the result returned by evaluador on each blob + - It returns on dst the blobs that accomplish (B_INCLUDE) or discards +(B_EXCLUDE) the Condition on the result returned by evaluador on each blob - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::Filter(CBlobResult &dst, - int filterAction, - funcio_calculBlob *evaluador, - int condition, - double lowLimit, double highLimit /*=0*/) - +void CBlobResult::Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit /*=0*/) + { - int numBlobs = GetNumBlobs(); - - // do the job - DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit ); - - // inline operation: remove previous blobs - if( &dst == this ) - { - // esborrem els primers blobs ( que s�n els originals ) - // ja que els tindrem replicats al final si passen el filtre - Blob_vector::iterator itBlobs = m_blobs.begin(); - for( int i = 0; i < numBlobs; i++ ) - { - delete *itBlobs; - itBlobs++; - } - m_blobs.erase( m_blobs.begin(), itBlobs ); - } + int numBlobs = GetNumBlobs(); + + // do the job + DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit); + + // inline operation: remove previous blobs + if (&dst == this) { + // esborrem els primers blobs ( que s�n els originals ) + // ja que els tindrem replicats al final si passen el filtre + Blob_vector::iterator itBlobs = m_blobs.begin(); + for (int i = 0; i < numBlobs; i++) { + delete *itBlobs; + itBlobs++; + } + m_blobs.erase(m_blobs.begin(), itBlobs); + } } - //! Does the Filter method job -void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit/* = 0*/) const +void CBlobResult::DoFilter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit /* = 0*/) const { - int i, numBlobs; - bool resultavaluacio; - double_stl_vector avaluacioBlobs; - double_stl_vector::iterator itavaluacioBlobs; - - if( GetNumBlobs() <= 0 ) return; - if( !evaluador ) return; - //avaluem els blobs amb la funci� pertinent - avaluacioBlobs = GetSTLResult(evaluador); - itavaluacioBlobs = avaluacioBlobs.begin(); - numBlobs = GetNumBlobs(); - switch(condition) - { - case B_EQUAL: - for(i=0;i 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; - } + int i, numBlobs; + bool resultavaluacio; + double_stl_vector avaluacioBlobs; + double_stl_vector::iterator itavaluacioBlobs; + + if (GetNumBlobs() <= 0) + return; + if (!evaluador) + return; + // avaluem els blobs amb la funci� pertinent + avaluacioBlobs = GetSTLResult(evaluador); + itavaluacioBlobs = avaluacioBlobs.begin(); + numBlobs = GetNumBlobs(); + switch (condition) { + case B_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs == lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_NOT_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs != lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_GREATER: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs > lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_LESS: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs < lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_GREATER_OR_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs >= lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_LESS_OR_EQUAL: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = *itavaluacioBlobs <= lowLimit; + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_INSIDE: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = (*itavaluacioBlobs >= lowLimit) && + (*itavaluacioBlobs <= highLimit); + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + case B_OUTSIDE: + for (i = 0; i < numBlobs; i++, itavaluacioBlobs++) { + resultavaluacio = (*itavaluacioBlobs < lowLimit) || + (*itavaluacioBlobs > highLimit); + if ((resultavaluacio && filterAction == B_INCLUDE) || + (!resultavaluacio && filterAction == B_EXCLUDE)) { + dst.m_blobs.push_back(new CBlob(GetBlob(i))); + } + } + break; + } } /** - FUNCI�: GetBlob - FUNCIONALITAT: Retorna un blob si aquest existeix (index != -1) - PAR�METRES: - - indexblob: index del blob a retornar + - indexblob: index del blob a retornar - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borr�s @@ -651,7 +638,7 @@ void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob - FUNCTION: GetBlob - FUNCTIONALITY: Gets the n-th blob (without ordering the blobs) - PARAMETERS: - - indexblob: index in the blob array + - indexblob: index in the blob array - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s @@ -659,32 +646,33 @@ void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob - MODIFICATION: Date. Author. Description. */ CBlob CBlobResult::GetBlob(int indexblob) const -{ - if( indexblob < 0 || indexblob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); +{ + if (indexblob < 0 || indexblob >= GetNumBlobs()) + RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS); - return *m_blobs[indexblob]; + return *m_blobs[indexblob]; } -CBlob *CBlobResult::GetBlob(int indexblob) -{ - if( indexblob < 0 || indexblob >= GetNumBlobs() ) - RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); +CBlob* CBlobResult::GetBlob(int indexblob) +{ + if (indexblob < 0 || indexblob >= GetNumBlobs()) + RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS); - return m_blobs[indexblob]; + return m_blobs[indexblob]; } /** - FUNCI�: GetNthBlob - FUNCIONALITAT: Retorna l'en�ssim blob segons un determinat criteri - PAR�METRES: - - criteri: criteri per ordenar els blobs (objectes derivats de COperadorBlob) - - nBlob: index del blob a retornar - - dst: on es retorna el resultat + - criteri: criteri per ordenar els blobs (objectes derivats de +COperadorBlob) + - nBlob: index del blob a retornar + - dst: on es retorna el resultat - RESULTAT: - - retorna el blob nBlob a dst ordenant els blobs de la classe segons el criteri - en ordre DESCENDENT. Per exemple, per obtenir el blob major: - GetNthBlob( CBlobGetArea(), 0, blobMajor ); - GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob m�s gran) + - retorna el blob nBlob a dst ordenant els blobs de la classe segons el +criteri en ordre DESCENDENT. Per exemple, per obtenir el blob major: + GetNthBlob( CBlobGetArea(), 0, blobMajor ); + GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob m�s gran) - RESTRICCIONS: - AUTOR: Ricard Borr�s - DATA DE CREACI�: 25-05-2005. @@ -694,65 +682,64 @@ CBlob *CBlobResult::GetBlob(int indexblob) - FUNCTION: GetNthBlob - FUNCTIONALITY: Gets the n-th blob ordering first the blobs with some criteria - PARAMETERS: - - criteri: criteria to order the blob array - - nBlob: index of the returned blob in the ordered blob array - - dst: where to store the result + - criteri: criteria to order the blob array + - nBlob: index of the returned blob in the ordered blob array + - dst: where to store the result - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst ) const +void CBlobResult::GetNthBlob(funcio_calculBlob* criteri, + int nBlob, + CBlob& dst) const { - // verifiquem que no estem accedint fora el vector de blobs - if( nBlob < 0 || nBlob >= GetNumBlobs() ) - { - //RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); - dst = CBlob(); - return; - } - - double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat; - double valorEnessim; - - //avaluem els blobs amb la funci� pertinent - avaluacioBlobs = GetSTLResult(criteri); - - avaluacioBlobsOrdenat = double_stl_vector( GetNumBlobs() ); - - // obtenim els nBlob primers resultats (en ordre descendent) - std::partial_sort_copy( avaluacioBlobs.begin(), - avaluacioBlobs.end(), - avaluacioBlobsOrdenat.begin(), - avaluacioBlobsOrdenat.end(), - std::greater() ); - - valorEnessim = avaluacioBlobsOrdenat[nBlob]; - - // busquem el primer blob que t� el valor n-ssim - double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin(); - - bool trobatBlob = false; - int indexBlob = 0; - while( itAvaluacio != avaluacioBlobs.end() && !trobatBlob ) - { - if( *itAvaluacio == valorEnessim ) - { - trobatBlob = true; - dst = CBlob( GetBlob(indexBlob)); - } - itAvaluacio++; - indexBlob++; - } + // verifiquem que no estem accedint fora el vector de blobs + if (nBlob < 0 || nBlob >= GetNumBlobs()) { + // RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); + dst = CBlob(); + return; + } + + double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat; + double valorEnessim; + + // avaluem els blobs amb la funci� pertinent + avaluacioBlobs = GetSTLResult(criteri); + + avaluacioBlobsOrdenat = double_stl_vector(GetNumBlobs()); + + // obtenim els nBlob primers resultats (en ordre descendent) + std::partial_sort_copy(avaluacioBlobs.begin(), + avaluacioBlobs.end(), + avaluacioBlobsOrdenat.begin(), + avaluacioBlobsOrdenat.end(), + std::greater()); + + valorEnessim = avaluacioBlobsOrdenat[nBlob]; + + // busquem el primer blob que t� el valor n-ssim + double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin(); + + bool trobatBlob = false; + int indexBlob = 0; + while (itAvaluacio != avaluacioBlobs.end() && !trobatBlob) { + if (*itAvaluacio == valorEnessim) { + trobatBlob = true; + dst = CBlob(GetBlob(indexBlob)); + } + itAvaluacio++; + indexBlob++; + } } /** - FUNCI�: ClearBlobs - FUNCIONALITAT: Elimina tots els blobs de l'objecte - PAR�METRES: -- RESULTAT: - - Allibera tota la mem�ria dels blobs +- RESULTAT: + - Allibera tota la mem�ria dels blobs - RESTRICCIONS: - AUTOR: Ricard Borr�s Navarra - DATA DE CREACI�: 25-05-2005. @@ -760,7 +747,8 @@ void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst */ /* - FUNCTION: ClearBlobs -- FUNCTIONALITY: Clears all the blobs from the object and releases all its memory +- FUNCTIONALITY: Clears all the blobs from the object and releases all its +memory - PARAMETERS: - RESULT: - RESTRICTIONS: @@ -770,24 +758,23 @@ void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst */ void CBlobResult::ClearBlobs() { - Blob_vector::iterator itBlobs = m_blobs.begin(); - while( itBlobs != m_blobs.end() ) - { - delete *itBlobs; - itBlobs++; - } - - m_blobs.clear(); + Blob_vector::iterator itBlobs = m_blobs.begin(); + while (itBlobs != m_blobs.end()) { + delete *itBlobs; + itBlobs++; + } + + m_blobs.clear(); } /** - FUNCI�: RaiseError - FUNCIONALITAT: Funci� per a notificar errors al l'usuari (en debug) i llen�a - les excepcions + les excepcions - PAR�METRES: - - errorCode: codi d'error -- RESULTAT: - - Ensenya un missatge a l'usuari (en debug) i llen�a una excepci� + - errorCode: codi d'error +- RESULTAT: + - Ensenya un missatge a l'usuari (en debug) i llen�a una excepci� - RESTRICCIONS: - AUTOR: Ricard Borr�s Navarra - DATA DE CREACI�: 25-05-2005. @@ -797,9 +784,9 @@ void CBlobResult::ClearBlobs() - FUNCTION: RaiseError - FUNCTIONALITY: Error handling function - PARAMETERS: - - errorCode: reason of the error + - errorCode: reason of the error - RESULT: - - Throws an exception with the error. + - Throws an exception with the error. - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. @@ -807,22 +794,19 @@ void CBlobResult::ClearBlobs() */ void CBlobResult::RaiseError(const int errorCode) const { - throw errorCode; + throw errorCode; } - - /************************************************************************** - Auxiliars / Auxiliary functions + Auxiliars / Auxiliary functions **************************************************************************/ - /** - FUNCI�: PrintBlobs -- FUNCIONALITAT: Escriu els par�metres (�rea, per�metre, exterior, mitjana) - de tots els blobs a un fitxer. +- FUNCIONALITAT: Escriu els par�metres (�rea, per�metre, exterior, mitjana) + de tots els blobs a un fitxer. - PAR�METRES: - - nom_fitxer: path complet del fitxer amb el resultat + - nom_fitxer: path complet del fitxer amb el resultat - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borr�s @@ -833,35 +817,35 @@ void CBlobResult::RaiseError(const int errorCode) const - FUNCTION: PrintBlobs - FUNCTIONALITY: Prints some blob features in an ASCII file - PARAMETERS: - - nom_fitxer: full path + filename to generate + - nom_fitxer: full path + filename to generate - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlobResult::PrintBlobs( char *nom_fitxer ) const +void CBlobResult::PrintBlobs(char* nom_fitxer) const { - double_stl_vector area, /*perimetre,*/ exterior, compacitat, longitud, - externPerimeter, perimetreConvex, perimetre; - int i; - FILE *fitxer_sortida; - - area = GetSTLResult( CBlobGetArea()); - perimetre = GetSTLResult( CBlobGetPerimeter()); - exterior = GetSTLResult( CBlobGetExterior()); - compacitat = GetSTLResult(CBlobGetCompactness()); - longitud = GetSTLResult( CBlobGetLength()); - externPerimeter = GetSTLResult( CBlobGetExternPerimeter()); - perimetreConvex = GetSTLResult( CBlobGetHullPerimeter()); - - fitxer_sortida = fopen( nom_fitxer, "w" ); - - for(i=0; i\t a=%7.0f\t p=%8.2f (%8.2f extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n", -// i, area[i], perimetre[i], externPerimeter[i], perimetreConvex[i], exterior[i], compacitat[i], longitud[i] ); - } - fclose( fitxer_sortida ); - + double_stl_vector area, /*perimetre,*/ exterior, compacitat, longitud, + externPerimeter, perimetreConvex, perimetre; + int i; + FILE* fitxer_sortida; + + area = GetSTLResult(CBlobGetArea()); + perimetre = GetSTLResult(CBlobGetPerimeter()); + exterior = GetSTLResult(CBlobGetExterior()); + compacitat = GetSTLResult(CBlobGetCompactness()); + longitud = GetSTLResult(CBlobGetLength()); + externPerimeter = GetSTLResult(CBlobGetExternPerimeter()); + perimetreConvex = GetSTLResult(CBlobGetHullPerimeter()); + + fitxer_sortida = fopen(nom_fitxer, "w"); + + for (i = 0; i < GetNumBlobs(); i++) { + // fprintf( fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f + //extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n", + // i, area[i], perimetre[i], externPerimeter[i], + //perimetreConvex[i], exterior[i], compacitat[i], longitud[i] ); + } + fclose(fitxer_sortida); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h index cf5c182..f9f9ec8 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.h @@ -1,6 +1,6 @@ /************************************************************************ - BlobResult.h - + BlobResult.h + FUNCIONALITAT: Definici� de la classe CBlobResult AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): @@ -11,151 +11,155 @@ MODIFICATIONS (Modification, Author, Date): **************************************************************************/ - #if !defined(_CLASSE_BLOBRESULT_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED + #define _CLASSE_BLOBRESULT_INCLUDED -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 + #if _MSC_VER > 1000 + #pragma once + #endif // _MSC_VER > 1000 -#include "BlobLibraryConfiguration.h" -#include -#include + #include "BlobLibraryConfiguration.h" + #include + #include -#include // vectors de la STL -#include -#include "blob.h" -#include "BlobOperators.h" -#include "ComponentLabeling.h" + #include // vectors de la STL + #include + #include "blob.h" + #include "BlobOperators.h" + #include "ComponentLabeling.h" //! Vector de doubles typedef std::vector double_stl_vector; -/************************************************************************** - Filtres / Filters -**************************************************************************/ - -//! accions que es poden fer amb els filtres -//! Actions performed by a filter (include or exclude blobs) -#define B_INCLUDE 1L -#define B_EXCLUDE 2L - -//! condicions sobre els filtres -//! Conditions to apply the filters -#define B_EQUAL 3L -#define B_NOT_EQUAL 4L -#define B_GREATER 5L -#define B_LESS 6L -#define B_GREATER_OR_EQUAL 7L -#define B_LESS_OR_EQUAL 8L -#define B_INSIDE 9L -#define B_OUTSIDE 10L - - -/************************************************************************** - Excepcions / Exceptions -**************************************************************************/ - -//! Excepcions llen�ades per les funcions: -#define EXCEPTION_BLOB_OUT_OF_BOUNDS 1000 -#define EXCEPCIO_CALCUL_BLOBS 1001 - -/** - Classe que cont� un conjunt de blobs i permet extreure'n propietats - o filtrar-los segons determinats criteris. - Class to calculate the blobs of an image and calculate some properties - on them. Also, the class provides functions to filter the blobs using - some criteria. + /************************************************************************** + Filtres / Filters + **************************************************************************/ + + //! accions que es poden fer amb els filtres + //! Actions performed by a filter (include or exclude blobs) + #define B_INCLUDE 1L + #define B_EXCLUDE 2L + + //! condicions sobre els filtres + //! Conditions to apply the filters + #define B_EQUAL 3L + #define B_NOT_EQUAL 4L + #define B_GREATER 5L + #define B_LESS 6L + #define B_GREATER_OR_EQUAL 7L + #define B_LESS_OR_EQUAL 8L + #define B_INSIDE 9L + #define B_OUTSIDE 10L + + /************************************************************************** + Excepcions / Exceptions + **************************************************************************/ + + //! Excepcions llen�ades per les funcions: + #define EXCEPTION_BLOB_OUT_OF_BOUNDS 1000 + #define EXCEPCIO_CALCUL_BLOBS 1001 + +/** + Classe que cont� un conjunt de blobs i permet extreure'n propietats + o filtrar-los segons determinats criteris. + Class to calculate the blobs of an image and calculate some properties + on them. Also, the class provides functions to filter the blobs using + some criteria. */ -class CBlobResult +class CBlobResult { public: - - //! constructor estandard, crea un conjunt buit de blobs - //! Standard constructor, it creates an empty set of blobs - CBlobResult(); - //! constructor a partir d'una imatge - //! Image constructor, it creates an object with the blobs of the image - CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor); - //! constructor de c�pia - //! Copy constructor - CBlobResult( const CBlobResult &source ); - //! Destructor - virtual ~CBlobResult(); - - //! operador = per a fer assignacions entre CBlobResult - //! Assigment operator - CBlobResult& operator=(const CBlobResult& source); - //! operador + per concatenar dos CBlobResult - //! Addition operator to concatenate two sets of blobs - CBlobResult operator+( const CBlobResult& source ) const; - - //! Afegeix un blob al conjunt - //! Adds a blob to the set of blobs - void AddBlob( CBlob *blob ); - - //! Calcula un valor sobre tots els blobs de la classe retornant un std::vector - //! Computes some property on all the blobs of the class - double_stl_vector GetSTLResult( funcio_calculBlob *evaluador ) const; - - //! Calcula un valor sobre un blob de la classe - //! Computes some property on one blob of the class - double GetNumber( int indexblob, funcio_calculBlob *evaluador ) const; - - //! Retorna aquells blobs que compleixen les condicions del filtre en el destination - //! Filters the blobs of the class using some property - void Filter(CBlobResult &dst, - int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit = 0 ); - void Filter(CBlobResult &dst, - int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit = 0 ) const; - - //! Retorna l'en�ssim blob segons un determinat criteri - //! Sorts the blobs of the class acording to some criteria and returns the n-th blob - void GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst ) const; - - //! Retorna el blob en�ssim - //! Gets the n-th blob of the class ( without sorting ) - CBlob GetBlob(int indexblob) const; - CBlob *GetBlob(int indexblob); - - //! Elimina tots els blobs de l'objecte - //! Clears all the blobs of the class - void ClearBlobs(); - - //! Escriu els blobs a un fitxer - //! Prints some features of all the blobs in a file - void PrintBlobs( char *nom_fitxer ) const; - - -//Metodes GET/SET - - //! Retorna el total de blobs - //! Gets the total number of blobs - int GetNumBlobs() const - { - return(m_blobs.size()); - } - + //! constructor estandard, crea un conjunt buit de blobs + //! Standard constructor, it creates an empty set of blobs + CBlobResult(); + //! constructor a partir d'una imatge + //! Image constructor, it creates an object with the blobs of the image + CBlobResult(cv::Mat source, cv::Mat* mask, uchar backgroundColor); + //! constructor de c�pia + //! Copy constructor + CBlobResult(const CBlobResult& source); + //! Destructor + virtual ~CBlobResult(); + + //! operador = per a fer assignacions entre CBlobResult + //! Assigment operator + CBlobResult& operator=(const CBlobResult& source); + //! operador + per concatenar dos CBlobResult + //! Addition operator to concatenate two sets of blobs + CBlobResult operator+(const CBlobResult& source) const; + + //! Afegeix un blob al conjunt + //! Adds a blob to the set of blobs + void AddBlob(CBlob* blob); + + //! Calcula un valor sobre tots els blobs de la classe retornant un + //! std::vector Computes some property on all the blobs of the + //! class + double_stl_vector GetSTLResult(funcio_calculBlob* evaluador) const; + + //! Calcula un valor sobre un blob de la classe + //! Computes some property on one blob of the class + double GetNumber(int indexblob, funcio_calculBlob* evaluador) const; + + //! Retorna aquells blobs que compleixen les condicions del filtre en el + //! destination Filters the blobs of the class using some property + void Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit = 0); + void Filter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit = 0) const; + + //! Retorna l'en�ssim blob segons un determinat criteri + //! Sorts the blobs of the class acording to some criteria and returns the + //! n-th blob + void GetNthBlob(funcio_calculBlob* criteri, int nBlob, CBlob& dst) const; + + //! Retorna el blob en�ssim + //! Gets the n-th blob of the class ( without sorting ) + CBlob GetBlob(int indexblob) const; + CBlob* GetBlob(int indexblob); + + //! Elimina tots els blobs de l'objecte + //! Clears all the blobs of the class + void ClearBlobs(); + + //! Escriu els blobs a un fitxer + //! Prints some features of all the blobs in a file + void PrintBlobs(char* nom_fitxer) const; + + // Metodes GET/SET + + //! Retorna el total de blobs + //! Gets the total number of blobs + int GetNumBlobs() const + { + return (m_blobs.size()); + } private: - - //! Funci� per gestionar els errors - //! Function to manage the errors - void RaiseError(const int errorCode) const; - - //! Does the Filter method job - void DoFilter(CBlobResult &dst, - int filterAction, funcio_calculBlob *evaluador, - int condition, double lowLimit, double highLimit = 0) const; + //! Funci� per gestionar els errors + //! Function to manage the errors + void RaiseError(const int errorCode) const; + + //! Does the Filter method job + void DoFilter(CBlobResult& dst, + int filterAction, + funcio_calculBlob* evaluador, + int condition, + double lowLimit, + double highLimit = 0) const; protected: - - //! Vector amb els blobs - //! Vector with all the blobs - Blob_vector m_blobs; + //! Vector amb els blobs + //! Vector with all the blobs + Blob_vector m_blobs; }; #endif // !defined(_CLASSE_BLOBRESULT_INCLUDED) diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp index 6bfaa09..a046cb5 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.cpp @@ -7,416 +7,429 @@ //! Conversion from freeman code to coordinate increments (counterclockwise) static const cv::Point freemanCodeIncrement[8] = - { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} }; + {{1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}}; - -inline unsigned char GET_IMAGE_PIXEL( cv::Mat image, cv::Point p ) +inline unsigned char GET_IMAGE_PIXEL(cv::Mat image, cv::Point p) { - return image.at(p); + return image.at(p); } -inline bool GET_IMAGEMASK_PIXEL( cv::Mat* mask, cv::Point p ) +inline bool GET_IMAGEMASK_PIXEL(cv::Mat* mask, cv::Point p) { - if(mask) - return mask->at(p) > 0; - else - return true; + if (mask) + return mask->at(p) > 0; + else + return true; } -inline bool GET_BELOW_VISITEDPIXEL( bool *currentPixel, int imageWidth ) +inline bool GET_BELOW_VISITEDPIXEL(bool* currentPixel, int imageWidth) { - return *( currentPixel + imageWidth ); + return *(currentPixel + imageWidth); } /** - FUNCI�: ASSIGN_LABEL - FUNCIONALITAT: Assigns label value to label image - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/29 - MODIFICACI�: Data. Autor. Descripci�. */ -inline void ASSIGN_LABEL( cv::Point p, t_labelType *labels, int imageWidth, int newLabel ) +inline void ASSIGN_LABEL(cv::Point p, + t_labelType* labels, + int imageWidth, + int newLabel) { - *(labels + p.y * imageWidth + p.x) = newLabel; + *(labels + p.y * imageWidth + p.x) = newLabel; } - -inline void ASSIGN_VISITED( cv::Point p, bool *visitedPoints, int imageWidth ) +inline void ASSIGN_VISITED(cv::Point p, bool* visitedPoints, int imageWidth) { - *(visitedPoints + p.y * imageWidth + p.x) = true; + *(visitedPoints + p.y * imageWidth + p.x) = true; } /** - FUNCI�: ComponentLabeling -- FUNCIONALITAT: Calcula els components binaris (blobs) d'una imatge amb connectivitat a 8 +- FUNCIONALITAT: Calcula els components binaris (blobs) d'una imatge amb +connectivitat a 8 - PAR�METRES: - - inputImage: image to segment (pixel values different than blobColor are treated as background) - - maskImage: if not NULL, all the pixels equal to 0 in mask are skipped in input image - - backgroundColor: color of background (ignored pixels) - - blobs: blob vector destination + - inputImage: image to segment (pixel values different than blobColor are +treated as background) + - maskImage: if not NULL, all the pixels equal to 0 in mask are skipped in +input image + - backgroundColor: color of background (ignored pixels) + - blobs: blob vector destination - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/21 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: Algorithm based on "A linear-time component labeling algorithm using contour tracing technique", - F.Chang et al +- NOTA: Algorithm based on "A linear-time component labeling algorithm using +contour tracing technique", F.Chang et al */ -bool ComponentLabeling(cv::Mat inputImage, - cv::Mat* maskImage, - unsigned char backgroundColor, - Blob_vector &blobs ) +bool ComponentLabeling(cv::Mat inputImage, + cv::Mat* maskImage, + unsigned char backgroundColor, + Blob_vector& blobs) { - // row major vector with visited points - bool internalContour, externalContour; - int imageWidth, imageHeight, currentLabel, contourLabel; - //! current blob pointer - CBlob *currentBlob; - cv::Size imageSizes; - cv::Point currentPoint; - - // verify input image - if (!inputImage.empty()) - return false; - - // verify that input image and mask image has same size - if (maskImage) - { - if (inputImage.size() != maskImage->size()) - return false; - } - - imageSizes = inputImage.size(); - - imageWidth = imageSizes.width; - imageHeight = imageSizes.height; - - // create auxiliary buffers that are initialized to 0 - t_labelType *labelledImage = (t_labelType*) calloc(imageWidth * imageHeight, sizeof(t_labelType)); - bool *visitedPoints = (bool*) calloc(imageWidth * imageHeight, sizeof(bool)); - - // Execute the POI detection parallel. - // This basically just filters out the background (which is the majority of points). - // The result will be an ordered list of non-background points for the blob-detector to work on. - std::vector foregroundPoints; - - const int totalRegionsX = 4; - const int totalRegionsY = 4; - const int totalRegions = totalRegionsX * totalRegionsY; - const int regionWidth = imageWidth / totalRegionsX; - const int regionHeight = imageHeight / totalRegionsY; - - // get the pixel data from an image at a certain position - auto getImageData = [](cv::Mat image, const int row, const int column) - { - return image.data + row * image.step + column; - }; - - // to allow each thread to acces the main list directly (saves us some merging later) - std::mutex foregroundPointAccessMutex; - - auto workOnRegion = [&](int x, int y) { - const int startingX = x * regionWidth; - const int startingY = y * regionHeight; - - for (int j = 0; j < regionHeight; ++j) - for (int i = 0; i < regionWidth; ++i) - { - const int pointX = startingX + i; - const int pointY = startingY + j; - // ignore background pixels or 0 pixels in mask - const unsigned char * pInputImage = getImageData(inputImage, pointY, pointX); - if ((*pInputImage == backgroundColor) || (maskImage && *getImageData(*maskImage, pointY, pointX) == 0)) - { - continue; - } - else // remember all non-background pixels - { - std::lock_guard 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.step + column; - }; - - auto getImageDataLabelled = [&](const int &row, const int &column) - { - return labelledImage + row * inputImage.step + column; - }; - - for (const cv::Point2d & point : foregroundPoints) - { - const int i = point.x; - const int j = point.y; - - t_labelType * pLabels = getImageDataLabelled(j, i); - bool * pVisitedPoints = getImageDataVisited(j, i); - - // new external contour: current label == 0 and above pixel is background - if( j > 0 ) - { - const unsigned char * pAboveInputImage = getImageData(inputImage, j - 1, i); - - externalContour = ((*pAboveInputImage == backgroundColor) || - (maskImage && *getImageData(*maskImage, j - 1, i) == 0)) && - (*pLabels == 0); - } - else - externalContour = (*pLabels == 0); - - // new internal contour: below pixel is background and not visited - if( !externalContour && j < imageHeight - 1 ) - { - const unsigned char * pBelowInputImage = getImageData(inputImage, j + 1, i); - internalContour = *pBelowInputImage == backgroundColor && - !GET_BELOW_VISITEDPIXEL( pVisitedPoints, imageWidth); - } - else - { - internalContour = false; - } - - - if( externalContour ) - { - currentPoint = cv::Point(i,j); - // assign label to labelled image - *pLabels = currentLabel; - - // create new blob - currentBlob = new CBlob(currentLabel, currentPoint, imageSizes ); - - // contour tracing with currentLabel - contourTracing( inputImage, maskImage, currentPoint, - labelledImage, visitedPoints, - currentLabel, false, backgroundColor, currentBlob->GetExternalContour() ); - - // add new created blob - blobs.push_back(currentBlob); - - currentLabel++; - } - else - { - if( internalContour ) - { - currentPoint = cv::Point(i,j); - - if( *pLabels == 0 ) - { - // take left neightbour value as current - if( i > 0 ) - contourLabel = *(pLabels - 1); - } - else - { - contourLabel = *pLabels; - } - - if(contourLabel>0) - { - currentBlob = blobs[contourLabel-1]; - CBlobContour newContour(currentPoint, currentBlob->GetStorage()); - - - // contour tracing with contourLabel - contourTracing( inputImage, maskImage, currentPoint, labelledImage, visitedPoints, - contourLabel, true, backgroundColor, &newContour ); - - currentBlob->AddInternalContour( newContour ); - } - } - // neither internal nor external contour - else - { - // take left neightbour value as current if it is not labelled - if( i > 0 && *pLabels == 0 ) - *pLabels = *(pLabels - 1); - } - - } - } - - - // free auxiliary buffers - free( labelledImage ); - free( visitedPoints ); - - return true; + // row major vector with visited points + bool internalContour, externalContour; + int imageWidth, imageHeight, currentLabel, contourLabel; + //! current blob pointer + CBlob* currentBlob; + cv::Size imageSizes; + cv::Point currentPoint; + + // verify input image + if (!inputImage.empty()) + return false; + + // verify that input image and mask image has same size + if (maskImage) { + if (inputImage.size() != maskImage->size()) + return false; + } + + imageSizes = inputImage.size(); + + imageWidth = imageSizes.width; + imageHeight = imageSizes.height; + + // create auxiliary buffers that are initialized to 0 + t_labelType* labelledImage = (t_labelType*) calloc(imageWidth * + imageHeight, + sizeof(t_labelType)); + bool* visitedPoints = (bool*) calloc(imageWidth * imageHeight, + sizeof(bool)); + + // Execute the POI detection parallel. + // This basically just filters out the background (which is the majority of + // points). The result will be an ordered list of non-background points for + // the blob-detector to work on. + std::vector foregroundPoints; + + const int totalRegionsX = 4; + const int totalRegionsY = 4; + const int totalRegions = totalRegionsX * totalRegionsY; + const int regionWidth = imageWidth / totalRegionsX; + const int regionHeight = imageHeight / totalRegionsY; + + // get the pixel data from an image at a certain position + auto getImageData = [](cv::Mat image, const int row, const int column) { + return image.data + row * image.step + column; + }; + + // to allow each thread to acces the main list directly (saves us some + // merging later) + std::mutex foregroundPointAccessMutex; + + auto workOnRegion = [&](int x, int y) { + const int startingX = x * regionWidth; + const int startingY = y * regionHeight; + + for (int j = 0; j < regionHeight; ++j) + for (int i = 0; i < regionWidth; ++i) { + const int pointX = startingX + i; + const int pointY = startingY + j; + // ignore background pixels or 0 pixels in mask + const unsigned char* pInputImage = getImageData(inputImage, + pointY, + pointX); + if ((*pInputImage == backgroundColor) || + (maskImage && + *getImageData(*maskImage, pointY, pointX) == 0)) { + continue; + } else // remember all non-background pixels + { + std::lock_guard 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.step + column; + }; + + auto getImageDataLabelled = [&](const int& row, const int& column) { + return labelledImage + row * inputImage.step + column; + }; + + for (const cv::Point2d& point : foregroundPoints) { + const int i = point.x; + const int j = point.y; + + t_labelType* pLabels = getImageDataLabelled(j, i); + bool* pVisitedPoints = getImageDataVisited(j, i); + + // new external contour: current label == 0 and above pixel is + // background + if (j > 0) { + const unsigned char* pAboveInputImage = getImageData(inputImage, + j - 1, + i); + + externalContour = ((*pAboveInputImage == backgroundColor) || + (maskImage && + *getImageData(*maskImage, j - 1, i) == 0)) && + (*pLabels == 0); + } else + externalContour = (*pLabels == 0); + + // new internal contour: below pixel is background and not visited + if (!externalContour && j < imageHeight - 1) { + const unsigned char* pBelowInputImage = getImageData(inputImage, + j + 1, + i); + internalContour = *pBelowInputImage == backgroundColor && + !GET_BELOW_VISITEDPIXEL(pVisitedPoints, + imageWidth); + } else { + internalContour = false; + } + + if (externalContour) { + currentPoint = cv::Point(i, j); + // assign label to labelled image + *pLabels = currentLabel; + + // create new blob + currentBlob = new CBlob(currentLabel, currentPoint, imageSizes); + + // contour tracing with currentLabel + contourTracing(inputImage, + maskImage, + currentPoint, + labelledImage, + visitedPoints, + currentLabel, + false, + backgroundColor, + currentBlob->GetExternalContour()); + + // add new created blob + blobs.push_back(currentBlob); + + currentLabel++; + } else { + if (internalContour) { + currentPoint = cv::Point(i, j); + + if (*pLabels == 0) { + // take left neightbour value as current + if (i > 0) + contourLabel = *(pLabels - 1); + } else { + contourLabel = *pLabels; + } + + if (contourLabel > 0) { + currentBlob = blobs[contourLabel - 1]; + CBlobContour newContour(currentPoint, + currentBlob->GetStorage()); + + // contour tracing with contourLabel + contourTracing(inputImage, + maskImage, + currentPoint, + labelledImage, + visitedPoints, + contourLabel, + true, + backgroundColor, + &newContour); + + currentBlob->AddInternalContour(newContour); + } + } + // neither internal nor external contour + else { + // take left neightbour value as current if it is not labelled + if (i > 0 && *pLabels == 0) + *pLabels = *(pLabels - 1); + } + } + } + + // free auxiliary buffers + free(labelledImage); + free(visitedPoints); + + return true; } /** -- FUNCI�: -- FUNCIONALITAT: +- FUNCI�: +- FUNCIONALITAT: - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/29 - MODIFICACI�: Data. Autor. Descripci�. */ -void contourTracing( cv::Mat image, - cv::Mat* maskImage, - cv::Point contourStart, t_labelType *labels, bool *visitedPoints, t_labelType label, - bool internalContour, unsigned char backgroundColor, CBlobContour *currentBlobcontour ) +void contourTracing(cv::Mat image, + cv::Mat* maskImage, + cv::Point contourStart, + t_labelType* labels, + bool* visitedPoints, + t_labelType label, + bool internalContour, + unsigned char backgroundColor, + CBlobContour* currentBlobcontour) { - cv::Point t, tnext, tsecond; - short initialMovement, movement; - - if( internalContour ) - { - initialMovement = 7;//3; - } - else - { - initialMovement = 3;//7; - } - - tsecond = tracer( image, maskImage, contourStart, visitedPoints, initialMovement, - backgroundColor, movement ); - - // assign current label to tnext - ASSIGN_LABEL( contourStart, labels, image.size().width, label ); - - - // contour corresponds to isolated pixel? - if( tsecond.x == contourStart.x && tsecond.y == contourStart.y ) - { - // we are finished with the contour - return; - } - - // add chain code to current contour - currentBlobcontour->AddChainCode(movement); - - // assign label to next point - ASSIGN_LABEL( tsecond, labels, image.size().width, label ); - - tnext.x = tsecond.x; - tnext.y = tsecond.y; - t.x = tnext.x; - t.y = tnext.y; - - // while T is different than contourStart and Tnext is different than T - // follow contour until start point is reached again - while (!(t.x == contourStart.x && t.y == contourStart.y) - || !(tsecond.x == tnext.x && tsecond.y == tnext.y)) - { - - t.x = tnext.x; - t.y = tnext.y; - initialMovement = (movement + 5) % 8; - - // search for next contour point - tnext = tracer( image, maskImage, t, visitedPoints, initialMovement, - backgroundColor, movement ); - - // assign label to contour point - ASSIGN_LABEL( tnext, labels, image.size().width, label ); - - // add chain code to current contour - currentBlobcontour->AddChainCode(movement); - } - + cv::Point t, tnext, tsecond; + short initialMovement, movement; + + if (internalContour) { + initialMovement = 7; // 3; + } else { + initialMovement = 3; // 7; + } + + tsecond = tracer(image, + maskImage, + contourStart, + visitedPoints, + initialMovement, + backgroundColor, + movement); + + // assign current label to tnext + ASSIGN_LABEL(contourStart, labels, image.size().width, label); + + // contour corresponds to isolated pixel? + if (tsecond.x == contourStart.x && tsecond.y == contourStart.y) { + // we are finished with the contour + return; + } + + // add chain code to current contour + currentBlobcontour->AddChainCode(movement); + + // assign label to next point + ASSIGN_LABEL(tsecond, labels, image.size().width, label); + + tnext.x = tsecond.x; + tnext.y = tsecond.y; + t.x = tnext.x; + t.y = tnext.y; + + // while T is different than contourStart and Tnext is different than T + // follow contour until start point is reached again + while (!(t.x == contourStart.x && t.y == contourStart.y) || + !(tsecond.x == tnext.x && tsecond.y == tnext.y)) { + + t.x = tnext.x; + t.y = tnext.y; + initialMovement = (movement + 5) % 8; + + // search for next contour point + tnext = tracer(image, + maskImage, + t, + visitedPoints, + initialMovement, + backgroundColor, + movement); + + // assign label to contour point + ASSIGN_LABEL(tnext, labels, image.size().width, label); + + // add chain code to current contour + currentBlobcontour->AddChainCode(movement); + } } /** - FUNCI�: tracer - FUNCIONALITAT: Searches for next point of a contour - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ -cv::Point tracer( cv::Mat image, cv::Mat* maskImage, cv::Point P, bool *visitedPoints, - short initialMovement, - unsigned char backgroundColor, short &movement ) +cv::Point tracer(cv::Mat image, + cv::Mat* maskImage, + cv::Point P, + bool* visitedPoints, + short initialMovement, + unsigned char backgroundColor, + short& movement) { - int d; - cv::Point pNext; - - for (d = 0; d <= 7; d++ ) - { - movement = (initialMovement + d) % 8; - - pNext.x = P.x + freemanCodeIncrement[movement].x; - pNext.y = P.y + freemanCodeIncrement[movement].y; - - // the point is inside image ? - if( pNext.x < 0 || pNext.x >= image.size().width || - pNext.y < 0 || pNext.y >= image.size().height ) - { - // try other movement - continue; - } - - // image has blobColor value in the new point? - if( (GET_IMAGE_PIXEL( image, pNext ) != backgroundColor ) && GET_IMAGEMASK_PIXEL(maskImage, pNext ) ) - { - return pNext; - } - else - { - // mark point as visited - ASSIGN_VISITED( pNext, visitedPoints, image.size().width ); - } - } - - // no possible movement was found - movement = -1; - pNext.x = P.x; - pNext.y = P.y; - - return pNext; + int d; + cv::Point pNext; + + for (d = 0; d <= 7; d++) { + movement = (initialMovement + d) % 8; + + pNext.x = P.x + freemanCodeIncrement[movement].x; + pNext.y = P.y + freemanCodeIncrement[movement].y; + + // the point is inside image ? + if (pNext.x < 0 || pNext.x >= image.size().width || pNext.y < 0 || + pNext.y >= image.size().height) { + // try other movement + continue; + } + + // image has blobColor value in the new point? + if ((GET_IMAGE_PIXEL(image, pNext) != backgroundColor) && + GET_IMAGEMASK_PIXEL(maskImage, pNext)) { + return pNext; + } else { + // mark point as visited + ASSIGN_VISITED(pNext, visitedPoints, image.size().width); + } + } + + // no possible movement was found + movement = -1; + pNext.x = P.x; + pNext.y = P.y; + + return pNext; } - - diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h index 5aa8ee5..a51c032 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/ComponentLabeling.h @@ -1,30 +1,34 @@ #if !defined(_COMPONENT_LABELING_H_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED - -#include "vector" -#include "BlobContour.h" -#include "blob.h" + #define _CLASSE_BLOBRESULT_INCLUDED + #include "vector" + #include "BlobContour.h" + #include "blob.h" //! definici� de que es un vector de blobs -typedef std::vector Blob_vector; - - - -bool ComponentLabeling(cv::Mat inputImage, - cv::Mat* maskImage, - unsigned char backgroundColor, - Blob_vector &blobs ); - - -void contourTracing( cv::Mat image, cv::Mat* mask, cv::Point contourStart, t_labelType *labels, - bool *visitedPoints, t_labelType label, - bool internalContour, unsigned char backgroundColor, - CBlobContour *currentBlobContour ); - -cv::Point tracer( cv::Mat image, cv::Mat* mask, cv::Point P, bool *visitedPoints, - short initialMovement, - unsigned char backgroundColor, short &movement ); - - -#endif //!_CLASSE_BLOBRESULT_INCLUDED +typedef std::vector Blob_vector; + +bool ComponentLabeling(cv::Mat inputImage, + cv::Mat* maskImage, + unsigned char backgroundColor, + Blob_vector& blobs); + +void contourTracing(cv::Mat image, + cv::Mat* mask, + cv::Point contourStart, + t_labelType* labels, + bool* visitedPoints, + t_labelType label, + bool internalContour, + unsigned char backgroundColor, + CBlobContour* currentBlobContour); + +cv::Point tracer(cv::Mat image, + cv::Mat* mask, + cv::Point P, + bool* visitedPoints, + short initialMovement, + unsigned char backgroundColor, + short& movement); + +#endif //!_CLASSE_BLOBRESULT_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp index 8842c5f..059ab8b 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.cpp @@ -1,555 +1,554 @@ /************************************************************************ - Blob.cpp - + Blob.cpp + - FUNCIONALITAT: Implementaci� de la classe CBlob - AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): - -FUNCTIONALITY: Implementation of the CBlob class and some helper classes to perform - some calculations on it -AUTHOR: Inspecta S.L. -MODIFICATIONS (Modification, Author, Date): -**************************************************************************/ +FUNCTIONALITY: Implementation of the CBlob class and some helper classes to +perform some calculations on it AUTHOR: Inspecta S.L. MODIFICATIONS +(Modification, Author, Date): +**************************************************************************/ #include "blob.h" #include #include - CBlob::CBlob() { - m_area = m_perimeter = -1; - m_externPerimeter = m_meanGray = m_stdDevGray = -1; - m_boundingBox.width = -1; - m_ellipse.size.width = -1; - m_storage = NULL; - m_id = -1; + m_area = m_perimeter = -1; + m_externPerimeter = m_meanGray = m_stdDevGray = -1; + m_boundingBox.width = -1; + m_ellipse.size.width = -1; + m_storage = NULL; + m_id = -1; } -CBlob::CBlob( t_labelType id, cv::Point startPoint, cv::Size originalImageSize ) +CBlob::CBlob(t_labelType id, cv::Point startPoint, cv::Size originalImageSize) { - m_id = id; - m_area = m_perimeter = -1; - m_externPerimeter = m_meanGray = m_stdDevGray = -1; - m_boundingBox.width = -1; - m_ellipse.size.width = -1; - m_storage = cvCreateMemStorage(); - m_externalContour = CBlobContour(startPoint, m_storage); - m_originalImageSize = originalImageSize; + m_id = id; + m_area = m_perimeter = -1; + m_externPerimeter = m_meanGray = m_stdDevGray = -1; + m_boundingBox.width = -1; + m_ellipse.size.width = -1; + m_storage = cvCreateMemStorage(); + m_externalContour = CBlobContour(startPoint, m_storage); + m_originalImageSize = originalImageSize; } //! Copy constructor -CBlob::CBlob( const CBlob &src ) +CBlob::CBlob(const CBlob& src) { - m_storage = NULL; - *this = src; + m_storage = NULL; + *this = src; } -CBlob::CBlob( const CBlob *src ) +CBlob::CBlob(const CBlob* src) { - if (src != NULL ) - { - m_storage = NULL; - *this = *src; - } + if (src != NULL) { + m_storage = NULL; + *this = *src; + } } -CBlob& CBlob::operator=(const CBlob &src ) +CBlob& CBlob::operator=(const CBlob& src) { - if( this != &src ) - { - m_id = src.m_id; - m_area = src.m_area; - m_perimeter = src.m_perimeter; - m_externPerimeter = src.m_externPerimeter; - m_meanGray = src.m_meanGray; - m_stdDevGray = src.m_stdDevGray; - m_boundingBox = src.m_boundingBox; - m_ellipse = src.m_ellipse; - m_originalImageSize = src.m_originalImageSize; - - // clear all current blob contours - ClearContours(); - - if( m_storage ) - cvReleaseMemStorage( &m_storage ); - - m_storage = cvCreateMemStorage(); - - m_externalContour = CBlobContour(src.m_externalContour.GetStartPoint(), m_storage ); - if( src.m_externalContour.m_contour ) - m_externalContour.m_contour = cvCloneSeq( src.m_externalContour.m_contour, m_storage); - m_internalContours.clear(); - - // copy all internal contours - if( src.m_internalContours.size() ) - { - m_internalContours = t_contourList( src.m_internalContours.size() ); - t_contourList::const_iterator itSrc; - t_contourList::iterator it; - - itSrc = src.m_internalContours.begin(); - it = m_internalContours.begin(); - - while (itSrc != src.m_internalContours.end()) - { - *it = CBlobContour((*itSrc).GetStartPoint(), m_storage); - if( (*itSrc).m_contour ) - (*it).m_contour = cvCloneSeq( (*itSrc).m_contour, m_storage); - - it++; - itSrc++; - } - } - } - - return *this; + if (this != &src) { + m_id = src.m_id; + m_area = src.m_area; + m_perimeter = src.m_perimeter; + m_externPerimeter = src.m_externPerimeter; + m_meanGray = src.m_meanGray; + m_stdDevGray = src.m_stdDevGray; + m_boundingBox = src.m_boundingBox; + m_ellipse = src.m_ellipse; + m_originalImageSize = src.m_originalImageSize; + + // clear all current blob contours + ClearContours(); + + if (m_storage) + cvReleaseMemStorage(&m_storage); + + m_storage = cvCreateMemStorage(); + + m_externalContour = CBlobContour(src.m_externalContour.GetStartPoint(), + m_storage); + if (src.m_externalContour.m_contour) + m_externalContour.m_contour = cvCloneSeq( + src.m_externalContour.m_contour, + m_storage); + m_internalContours.clear(); + + // copy all internal contours + if (src.m_internalContours.size()) { + m_internalContours = t_contourList(src.m_internalContours.size()); + t_contourList::const_iterator itSrc; + t_contourList::iterator it; + + itSrc = src.m_internalContours.begin(); + it = m_internalContours.begin(); + + while (itSrc != src.m_internalContours.end()) { + *it = CBlobContour((*itSrc).GetStartPoint(), m_storage); + if ((*itSrc).m_contour) + (*it).m_contour = cvCloneSeq((*itSrc).m_contour, + m_storage); + + it++; + itSrc++; + } + } + } + + return *this; } CBlob::~CBlob() { - ClearContours(); - - if( m_storage ) - cvReleaseMemStorage( &m_storage ); + ClearContours(); + + if (m_storage) + cvReleaseMemStorage(&m_storage); } void CBlob::ClearContours() { - t_contourList::iterator it; + t_contourList::iterator it; - it = m_internalContours.begin(); + it = m_internalContours.begin(); - while (it != m_internalContours.end()) - { - (*it).ResetChainCode(); - it++; - } - m_internalContours.clear(); + while (it != m_internalContours.end()) { + (*it).ResetChainCode(); + it++; + } + m_internalContours.clear(); - m_externalContour.ResetChainCode(); - + m_externalContour.ResetChainCode(); } -void CBlob::AddInternalContour( const CBlobContour &newContour ) +void CBlob::AddInternalContour(const CBlobContour& newContour) { - m_internalContours.push_back(newContour); + m_internalContours.push_back(newContour); } //! Indica si el blob est� buit ( no t� cap info associada ) //! Shows if the blob has associated information bool CBlob::IsEmpty() { - return GetExternalContour()->m_contour == NULL; + return GetExternalContour()->m_contour == NULL; } /** - FUNCI�: Area -- FUNCIONALITAT: Get blob area, ie. external contour area minus internal contours area +- FUNCIONALITAT: Get blob area, ie. external contour area minus internal +contours area - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ double CBlob::Area() { - double area; - t_contourList::iterator itContour; - - area = m_externalContour.GetArea(); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - area -= (*itContour).GetArea(); - itContour++; - } - return area; + double area; + t_contourList::iterator itContour; + + area = m_externalContour.GetArea(); + + itContour = m_internalContours.begin(); + + while (itContour != m_internalContours.end()) { + area -= (*itContour).GetArea(); + itContour++; + } + return area; } /** - FUNCI�: Perimeter - FUNCIONALITAT: Get blob perimeter, ie. sum of the lenght of all the contours - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/04/30 - MODIFICACI�: Data. Autor. Descripci�. */ double CBlob::Perimeter() { - double perimeter; - t_contourList::iterator itContour; + double perimeter; + t_contourList::iterator itContour; - perimeter = m_externalContour.GetPerimeter(); + perimeter = m_externalContour.GetPerimeter(); - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - perimeter += (*itContour).GetPerimeter(); - itContour++; - } - return perimeter; + itContour = m_internalContours.begin(); + while (itContour != m_internalContours.end()) { + perimeter += (*itContour).GetPerimeter(); + itContour++; + } + return perimeter; } /** - FUNCI�: Exterior - FUNCIONALITAT: Return true for extern blobs - PAR�METRES: - - xBorder: true to consider blobs touching horizontal borders as extern - - yBorder: true to consider blobs touching vertical borders as extern + - xBorder: true to consider blobs touching horizontal borders as extern + - yBorder: true to consider blobs touching vertical borders as extern - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ -int CBlob::Exterior(IplImage *mask, bool xBorder /* = true */, bool yBorder /* = true */) +int CBlob::Exterior(IplImage* mask, + bool xBorder /* = true */, + bool yBorder /* = true */) { - if (ExternPerimeter(mask, xBorder, yBorder ) > 0 ) - { - return 1; - } - - return 0; + if (ExternPerimeter(mask, xBorder, yBorder) > 0) { + return 1; + } + + return 0; } /** - FUNCI�: ExternPerimeter - FUNCIONALITAT: Get extern perimeter (perimeter touching image borders) - PAR�METRES: - - maskImage: if != NULL, counts maskImage black pixels as external pixels and contour points touching - them are counted as external contour points. - - xBorder: true to consider blobs touching horizontal borders as extern - - yBorder: true to consider blobs touching vertical borders as extern + - maskImage: if != NULL, counts maskImage black pixels as external pixels +and contour points touching them are counted as external contour points. + - xBorder: true to consider blobs touching horizontal borders as extern + - yBorder: true to consider blobs touching vertical borders as extern - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/05 - MODIFICACI�: Data. Autor. Descripci�. -- NOTA: If CBlobContour::GetContourPoints aproximates contours with a method different that NONE, - this function will not give correct results +- NOTA: If CBlobContour::GetContourPoints aproximates contours with a method +different that NONE, this function will not give correct results */ -double CBlob::ExternPerimeter( IplImage *maskImage, bool xBorder /* = true */, bool yBorder /* = true */) +double CBlob::ExternPerimeter(IplImage* maskImage, + bool xBorder /* = true */, + bool yBorder /* = true */) { - t_PointList externContour, externalPoints; - CvSeqReader reader; - CvSeqWriter writer; - cv::Point actualPoint, previousPoint; - bool find = false; - int i,j; - int delta = 0; - - // it is calculated? - if( m_externPerimeter != -1 ) - { - return m_externPerimeter; - } - - // get contour pixels - externContour = m_externalContour.GetContourPoints(); - - m_externPerimeter = 0; - - // there are contour pixels? - if( externContour == NULL ) - { - return m_externPerimeter; - } - - cvStartReadSeq( externContour, &reader); - - // create a sequence with the external points of the blob - externalPoints = cvCreateSeq( externContour->flags, externContour->header_size, externContour->elem_size, - m_storage ); - cvStartAppendToSeq( externalPoints, &writer ); - previousPoint.x = -1; - - // which contour pixels touch border? - for( j=0; j< externContour->total; j++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - find = false; - - // pixel is touching border? - if ( xBorder & ((actualPoint.x == 0) || (actualPoint.x == m_originalImageSize.width - 1 )) || - yBorder & ((actualPoint.y == 0) || (actualPoint.y == m_originalImageSize.height - 1 ))) - { - find = true; - } - else - { - if( maskImage != NULL ) - { - // verify if some of 8-connected neighbors is black in mask - char *pMask; - - pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y - 1) * maskImage->widthStep); - - for ( i = 0; i < 3; i++, pMask++ ) - { - if(*pMask == 0 && !find ) - { - find = true; - break; - } - } - - if(!find) - { - pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y ) * maskImage->widthStep); - - for ( i = 0; i < 3; i++, pMask++ ) - { - if(*pMask == 0 && !find ) - { - find = true; - break; - } - } - } - - if(!find) - { - pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y + 1) * maskImage->widthStep); - - for ( i = 0; i < 3; i++, pMask++ ) - { - if(*pMask == 0 && !find ) - { - find = true; - break; - } - } - } - } - } - - if( find ) - { - if( previousPoint.x > 0 ) - delta = abs(previousPoint.x - actualPoint.x) + abs(previousPoint.y - actualPoint.y); - - // calculate separately each external contour segment - if( delta > 2 ) - { - cvEndWriteSeq( &writer ); - m_externPerimeter += cvArcLength( externalPoints, CV_WHOLE_SEQ, 0 ); - - cvClearSeq( externalPoints ); - cvStartAppendToSeq( externalPoints, &writer ); - delta = 0; - previousPoint.x = -1; - } - - CV_WRITE_SEQ_ELEM( actualPoint, writer ); - previousPoint = actualPoint; - } - - } - - cvEndWriteSeq( &writer ); - - m_externPerimeter += cvArcLength( externalPoints, CV_WHOLE_SEQ, 0 ); - - cvClearSeq( externalPoints ); - - // divide by two because external points have one side inside the blob and the other outside - // Perimeter of external points counts both sides, so it must be divided - m_externPerimeter /= 2.0; - - return m_externPerimeter; + t_PointList externContour, externalPoints; + CvSeqReader reader; + CvSeqWriter writer; + cv::Point actualPoint, previousPoint; + bool find = false; + int i, j; + int delta = 0; + + // it is calculated? + if (m_externPerimeter != -1) { + return m_externPerimeter; + } + + // get contour pixels + externContour = m_externalContour.GetContourPoints(); + + m_externPerimeter = 0; + + // there are contour pixels? + if (externContour == NULL) { + return m_externPerimeter; + } + + cvStartReadSeq(externContour, &reader); + + // create a sequence with the external points of the blob + externalPoints = cvCreateSeq(externContour->flags, + externContour->header_size, + externContour->elem_size, + m_storage); + cvStartAppendToSeq(externalPoints, &writer); + previousPoint.x = -1; + + // which contour pixels touch border? + for (j = 0; j < externContour->total; j++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + find = false; + + // pixel is touching border? + if (xBorder & ((actualPoint.x == 0) || + (actualPoint.x == m_originalImageSize.width - 1)) || + yBorder & ((actualPoint.y == 0) || + (actualPoint.y == m_originalImageSize.height - 1))) { + find = true; + } else { + if (maskImage != NULL) { + // verify if some of 8-connected neighbors is black in mask + char* pMask; + + pMask = (maskImage->imageData + actualPoint.x - 1 + + (actualPoint.y - 1) * maskImage->widthStep); + + for (i = 0; i < 3; i++, pMask++) { + if (*pMask == 0 && !find) { + find = true; + break; + } + } + + if (!find) { + pMask = (maskImage->imageData + actualPoint.x - 1 + + (actualPoint.y) * maskImage->widthStep); + + for (i = 0; i < 3; i++, pMask++) { + if (*pMask == 0 && !find) { + find = true; + break; + } + } + } + + if (!find) { + pMask = (maskImage->imageData + actualPoint.x - 1 + + (actualPoint.y + 1) * maskImage->widthStep); + + for (i = 0; i < 3; i++, pMask++) { + if (*pMask == 0 && !find) { + find = true; + break; + } + } + } + } + } + + if (find) { + if (previousPoint.x > 0) + delta = abs(previousPoint.x - actualPoint.x) + + abs(previousPoint.y - actualPoint.y); + + // calculate separately each external contour segment + if (delta > 2) { + cvEndWriteSeq(&writer); + m_externPerimeter += cvArcLength(externalPoints, + CV_WHOLE_SEQ, + 0); + + cvClearSeq(externalPoints); + cvStartAppendToSeq(externalPoints, &writer); + delta = 0; + previousPoint.x = -1; + } + + CV_WRITE_SEQ_ELEM(actualPoint, writer); + previousPoint = actualPoint; + } + } + + cvEndWriteSeq(&writer); + + m_externPerimeter += cvArcLength(externalPoints, CV_WHOLE_SEQ, 0); + + cvClearSeq(externalPoints); + + // divide by two because external points have one side inside the blob and + // the other outside Perimeter of external points counts both sides, so it + // must be divided + m_externPerimeter /= 2.0; + + return m_externPerimeter; } //! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS) double CBlob::Moment(int p, int q) { - double moment; - t_contourList::iterator itContour; - - moment = m_externalContour.GetMoment(p,q); - - itContour = m_internalContours.begin(); - - while (itContour != m_internalContours.end() ) - { - moment -= (*itContour).GetMoment(p,q); - itContour++; - } - return moment; + double moment; + t_contourList::iterator itContour; + + moment = m_externalContour.GetMoment(p, q); + + itContour = m_internalContours.begin(); + + while (itContour != m_internalContours.end()) { + moment -= (*itContour).GetMoment(p, q); + itContour++; + } + return moment; } /** - FUNCI�: Mean - FUNCIONALITAT: Get blob mean color in input image - PAR�METRES: - - image: image from gray color are extracted + - image: image from gray color are extracted - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ -double CBlob::Mean( IplImage *image ) +double CBlob::Mean(IplImage* image) { - // it is calculated? -/* if( m_meanGray != -1 ) - { - return m_meanGray; - } -*/ - // Create a mask with same size as blob bounding box - IplImage *mask; - CvScalar mean, std; - cv::Point offset; - - GetBoundingBox(); - - if (m_boundingBox.height == 0 ||m_boundingBox.width == 0 || !CV_IS_IMAGE( image )) - { - m_meanGray = 0; - return m_meanGray; - } - - // apply ROI and mask to input image to compute mean gray and standard deviation - mask = cvCreateImage( cvSize(m_boundingBox.width, m_boundingBox.height), IPL_DEPTH_8U, 1); - cvSetZero(mask); - - offset.x = -m_boundingBox.x; - offset.y = -m_boundingBox.y; - - // draw contours on mask - cvDrawContours( mask, m_externalContour.GetContourPoints(), cvScalar(CV_RGB(255,255,255)), cvScalar(CV_RGB(255,255,255)),0, CV_FILLED, 8, - cvPoint(offset) ); - - // draw internal contours - t_contourList::iterator it = m_internalContours.begin(); - while(it != m_internalContours.end() ) - { - cvDrawContours( mask, (*it).GetContourPoints(), cvScalar(CV_RGB(0,0,0)), cvScalar(CV_RGB(0,0,0)),0, CV_FILLED, 8, - cvPoint(offset) ); - it++; - } - - cvSetImageROI( image, m_boundingBox ); - cvAvgSdv( image, &mean, &std, mask ); - - m_meanGray = mean.val[0]; - m_stdDevGray = std.val[0]; - - cvReleaseImage( &mask ); - cvResetImageROI( image ); - - return m_meanGray; + // it is calculated? + /* if( m_meanGray != -1 ) + { + return m_meanGray; + } + */ + // Create a mask with same size as blob bounding box + IplImage* mask; + CvScalar mean, std; + cv::Point offset; + + GetBoundingBox(); + + if (m_boundingBox.height == 0 || m_boundingBox.width == 0 || + !CV_IS_IMAGE(image)) { + m_meanGray = 0; + return m_meanGray; + } + + // apply ROI and mask to input image to compute mean gray and standard + // deviation + mask = cvCreateImage(cvSize(m_boundingBox.width, m_boundingBox.height), + IPL_DEPTH_8U, + 1); + cvSetZero(mask); + + offset.x = -m_boundingBox.x; + offset.y = -m_boundingBox.y; + + // draw contours on mask + cvDrawContours(mask, + m_externalContour.GetContourPoints(), + cvScalar(CV_RGB(255, 255, 255)), + cvScalar(CV_RGB(255, 255, 255)), + 0, + CV_FILLED, + 8, + cvPoint(offset)); + + // draw internal contours + t_contourList::iterator it = m_internalContours.begin(); + while (it != m_internalContours.end()) { + cvDrawContours(mask, + (*it).GetContourPoints(), + cvScalar(CV_RGB(0, 0, 0)), + cvScalar(CV_RGB(0, 0, 0)), + 0, + CV_FILLED, + 8, + cvPoint(offset)); + it++; + } + + cvSetImageROI(image, m_boundingBox); + cvAvgSdv(image, &mean, &std, mask); + + m_meanGray = mean.val[0]; + m_stdDevGray = std.val[0]; + + cvReleaseImage(&mask); + cvResetImageROI(image); + + return m_meanGray; } -double CBlob::StdDev( IplImage *image ) +double CBlob::StdDev(IplImage* image) { - // it is calculated? -/* if( m_stdDevGray != -1 ) - { - return m_stdDevGray; - } -*/ - // call mean calculation (where also standard deviation is calculated) - Mean( image ); - - return m_stdDevGray; + // it is calculated? + /* if( m_stdDevGray != -1 ) + { + return m_stdDevGray; + } + */ + // call mean calculation (where also standard deviation is calculated) + Mean(image); + + return m_stdDevGray; } /** - FUNCI�: GetBoundingBox - FUNCIONALITAT: Get bounding box (without rotation) of a blob - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. */ CvRect CBlob::GetBoundingBox() { - // it is calculated? - if( m_boundingBox.width != -1 ) - { - return m_boundingBox; - } - - t_PointList externContour; - CvSeqReader reader; - cv::Point actualPoint; - - // get contour pixels - externContour = m_externalContour.GetContourPoints(); - - // it is an empty blob? - if( !externContour ) - { - m_boundingBox.x = 0; - m_boundingBox.y = 0; - m_boundingBox.width = 0; - m_boundingBox.height = 0; - - return m_boundingBox; - } - - cvStartReadSeq( externContour, &reader); - - m_boundingBox.x = m_originalImageSize.width; - m_boundingBox.y = m_originalImageSize.height; - m_boundingBox.width = 0; - m_boundingBox.height = 0; - - for( int i=0; i< externContour->total; i++) - { - CV_READ_SEQ_ELEM( actualPoint, reader); - - m_boundingBox.x = MIN( actualPoint.x, m_boundingBox.x ); - m_boundingBox.y = MIN( actualPoint.y, m_boundingBox.y ); - - m_boundingBox.width = MAX( actualPoint.x, m_boundingBox.width ); - m_boundingBox.height = MAX( actualPoint.y, m_boundingBox.height ); - } - - //m_boundingBox.x = max( m_boundingBox.x , 0 ); - //m_boundingBox.y = max( m_boundingBox.y , 0 ); - - m_boundingBox.width -= m_boundingBox.x; - m_boundingBox.height -= m_boundingBox.y; - - return m_boundingBox; + // it is calculated? + if (m_boundingBox.width != -1) { + return m_boundingBox; + } + + t_PointList externContour; + CvSeqReader reader; + cv::Point actualPoint; + + // get contour pixels + externContour = m_externalContour.GetContourPoints(); + + // it is an empty blob? + if (!externContour) { + m_boundingBox.x = 0; + m_boundingBox.y = 0; + m_boundingBox.width = 0; + m_boundingBox.height = 0; + + return m_boundingBox; + } + + cvStartReadSeq(externContour, &reader); + + m_boundingBox.x = m_originalImageSize.width; + m_boundingBox.y = m_originalImageSize.height; + m_boundingBox.width = 0; + m_boundingBox.height = 0; + + for (int i = 0; i < externContour->total; i++) { + CV_READ_SEQ_ELEM(actualPoint, reader); + + m_boundingBox.x = MIN(actualPoint.x, m_boundingBox.x); + m_boundingBox.y = MIN(actualPoint.y, m_boundingBox.y); + + m_boundingBox.width = MAX(actualPoint.x, m_boundingBox.width); + m_boundingBox.height = MAX(actualPoint.y, m_boundingBox.height); + } + + // m_boundingBox.x = max( m_boundingBox.x , 0 ); + // m_boundingBox.y = max( m_boundingBox.y , 0 ); + + m_boundingBox.width -= m_boundingBox.x; + m_boundingBox.height -= m_boundingBox.y; + + return m_boundingBox; } /** - FUNCI�: GetEllipse - FUNCIONALITAT: Calculates bounding ellipse of external contour points - PAR�METRES: - - + - - RESULTAT: - - + - - RESTRICCIONS: - - + - - AUTOR: rborras - DATA DE CREACI�: 2008/05/06 - MODIFICACI�: Data. Autor. Descripci�. @@ -557,111 +556,104 @@ CvRect CBlob::GetBoundingBox() */ CvBox2D CBlob::GetEllipse() { - // it is calculated? - if( m_ellipse.size.width != -1 ) - return m_ellipse; - - double u00,u11,u01,u10,u20,u02, delta, num, den, temp; - - // central moments calculation - u00 = Moment(0,0); - - // empty blob? - if ( u00 <= 0 ) - { - m_ellipse.size.width = 0; - m_ellipse.size.height = 0; - m_ellipse.center.x = 0; - m_ellipse.center.y = 0; - m_ellipse.angle = 0; - return m_ellipse; - } - u10 = Moment(1,0) / u00; - u01 = Moment(0,1) / u00; - - u11 = -(Moment(1,1) - Moment(1,0) * Moment(0,1) / u00 ) / u00; - u20 = (Moment(2,0) - Moment(1,0) * Moment(1,0) / u00 ) / u00; - u02 = (Moment(0,2) - Moment(0,1) * Moment(0,1) / u00 ) / u00; - - - // elipse calculation - delta = sqrt( 4*u11*u11 + (u20-u02)*(u20-u02) ); - m_ellipse.center.x = float(u10); - m_ellipse.center.y = float(u01); - - temp = u20 + u02 + delta; - if( temp > 0 ) - { - m_ellipse.size.width = sqrt(float( 2*(u20 + u02 + delta ))); - } - else - { - m_ellipse.size.width = 0; - return m_ellipse; - } - - temp = u20 + u02 - delta; - if( temp > 0 ) - { - m_ellipse.size.height = sqrt(float( 2*(u20 + u02 - delta ) )); - } - else - { - m_ellipse.size.height = 0; - return m_ellipse; - } - - // elipse orientation - if (u20 > u02) - { - num = u02 - u20 + sqrt((u02 - u20)*(u02 - u20) + 4*u11*u11); - den = 2*u11; - } - else - { - num = 2*u11; - den = u20 - u02 + sqrt((u20 - u02)*(u20 - u02) + 4*u11*u11); + // it is calculated? + if (m_ellipse.size.width != -1) + return m_ellipse; + + double u00, u11, u01, u10, u20, u02, delta, num, den, temp; + + // central moments calculation + u00 = Moment(0, 0); + + // empty blob? + if (u00 <= 0) { + m_ellipse.size.width = 0; + m_ellipse.size.height = 0; + m_ellipse.center.x = 0; + m_ellipse.center.y = 0; + m_ellipse.angle = 0; + return m_ellipse; + } + u10 = Moment(1, 0) / u00; + u01 = Moment(0, 1) / u00; + + u11 = -(Moment(1, 1) - Moment(1, 0) * Moment(0, 1) / u00) / u00; + u20 = (Moment(2, 0) - Moment(1, 0) * Moment(1, 0) / u00) / u00; + u02 = (Moment(0, 2) - Moment(0, 1) * Moment(0, 1) / u00) / u00; + + // elipse calculation + delta = sqrt(4 * u11 * u11 + (u20 - u02) * (u20 - u02)); + m_ellipse.center.x = float(u10); + m_ellipse.center.y = float(u01); + + temp = u20 + u02 + delta; + if (temp > 0) { + m_ellipse.size.width = sqrt(float(2 * (u20 + u02 + delta))); + } else { + m_ellipse.size.width = 0; + return m_ellipse; } - if( num != 0 && den != 00 ) - { - m_ellipse.angle = float( 180.0 + (180.0 / CV_PI) * atan( num / den ) ); - } - else - { - m_ellipse.angle = 0; - } - - return m_ellipse; + temp = u20 + u02 - delta; + if (temp > 0) { + m_ellipse.size.height = sqrt(float(2 * (u20 + u02 - delta))); + } else { + m_ellipse.size.height = 0; + return m_ellipse; + } + + // elipse orientation + if (u20 > u02) { + num = u02 - u20 + sqrt((u02 - u20) * (u02 - u20) + 4 * u11 * u11); + den = 2 * u11; + } else { + num = 2 * u11; + den = u20 - u02 + sqrt((u20 - u02) * (u20 - u02) + 4 * u11 * u11); + } + if (num != 0 && den != 00) { + m_ellipse.angle = float(180.0 + (180.0 / CV_PI) * atan(num / den)); + } else { + m_ellipse.angle = 0; + } + + return m_ellipse; } /** - FUNCTION: FillBlob -- FUNCTIONALITY: - - Fills the blob with a specified colour +- FUNCTIONALITY: + - Fills the blob with a specified colour - PARAMETERS: - - imatge: where to paint - - color: colour to paint the blob + - imatge: where to paint + - color: colour to paint the blob - RESULT: - - modifies input image and returns the seed point used to fill the blob + - modifies input image and returns the seed point used to fill the blob - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlob::FillBlob( IplImage *imatge, CvScalar color, int offsetX /*=0*/, int offsetY /*=0*/) +void CBlob::FillBlob(IplImage* imatge, + CvScalar color, + int offsetX /*=0*/, + int offsetY /*=0*/) { - cvDrawContours( imatge, m_externalContour.GetContourPoints(), color, color,0, CV_FILLED, 8 ); + cvDrawContours(imatge, + m_externalContour.GetContourPoints(), + color, + color, + 0, + CV_FILLED, + 8); } - /** - FUNCTION: GetConvexHull - FUNCTIONALITY: Calculates the convex hull polygon of the blob - PARAMETERS: - - dst: where to store the result + - dst: where to store the result - RESULT: - - true if no error ocurred + - true if no error ocurred - RESTRICTIONS: - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. @@ -669,41 +661,42 @@ void CBlob::FillBlob( IplImage *imatge, CvScalar color, int offsetX /*=0*/, int */ t_PointList CBlob::GetConvexHull() { - CvSeq *convexHull = NULL; + CvSeq* convexHull = NULL; - if( m_externalContour.GetContourPoints() ) - convexHull = cvConvexHull2( m_externalContour.GetContourPoints(), m_storage, - CV_COUNTER_CLOCKWISE, 1 ); + if (m_externalContour.GetContourPoints()) + convexHull = cvConvexHull2(m_externalContour.GetContourPoints(), + m_storage, + CV_COUNTER_CLOCKWISE, + 1); - return convexHull; + return convexHull; } /** - FUNCTION: JoinBlob - FUNCTIONALITY: Add's external contour to current external contour - PARAMETERS: - - blob: blob from which extract the added external contour + - blob: blob from which extract the added external contour - RESULT: - - true if no error ocurred + - true if no error ocurred - RESTRICTIONS: Only external contours are added - AUTHOR: Ricard Borr�s - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ -void CBlob::JoinBlob( CBlob *blob ) +void CBlob::JoinBlob(CBlob* blob) { - CvSeqWriter writer; - CvSeqReader reader; - t_chainCode chainCode; + CvSeqWriter writer; + CvSeqReader reader; + t_chainCode chainCode; - cvStartAppendToSeq( m_externalContour.GetChainCode(), &writer ); - cvStartReadSeq( blob->GetExternalContour()->GetChainCode(), &reader ); - - for (int i = 0; i < blob->GetExternalContour()->GetChainCode()->total; i++ ) - { - CV_READ_SEQ_ELEM( chainCode, reader ); - CV_WRITE_SEQ_ELEM( chainCode, writer ); - } - cvEndWriteSeq( &writer ); + cvStartAppendToSeq(m_externalContour.GetChainCode(), &writer); + cvStartReadSeq(blob->GetExternalContour()->GetChainCode(), &reader); + for (int i = 0; i < blob->GetExternalContour()->GetChainCode()->total; + i++) { + CV_READ_SEQ_ELEM(chainCode, reader); + CV_WRITE_SEQ_ELEM(chainCode, writer); + } + cvEndWriteSeq(&writer); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h index 2d30a4d..16b7e09 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/blob.h @@ -1,169 +1,171 @@ /************************************************************************ - Blob.h - + Blob.h + FUNCIONALITAT: Definici� de la classe CBlob AUTOR: Inspecta S.L. MODIFICACIONS (Modificaci�, Autor, Data): FUNCTIONALITY: Definition of the CBlob class and some helper classes to perform - some calculations on it + some calculations on it AUTHOR: Inspecta S.L. MODIFICATIONS (Modification, Author, Date): **************************************************************************/ //! Disable warnings referred to 255 character truncation for the std:map -#pragma warning( disable : 4786 ) +#pragma warning(disable : 4786) #ifndef CBLOB_INSPECTA_INCLUDED -#define CBLOB_INSPECTA_INCLUDED - -#include + #define CBLOB_INSPECTA_INCLUDED -#include + #include -#include "BlobLibraryConfiguration.h" -#include "BlobContour.h" + #include + #include "BlobLibraryConfiguration.h" + #include "BlobContour.h" //! Type of labelled images typedef unsigned int t_labelType; - //! Blob class class CBlob { - typedef std::list t_contourList; + typedef std::list t_contourList; public: - CBlob(); - CBlob( t_labelType id, cv::Point startPoint, cv::Size originalImageSize ); - ~CBlob(); - - //! Copy constructor - CBlob( const CBlob &src ); - CBlob( const CBlob *src ); - - //! Operador d'assignaci� - //! Assigment operator - CBlob& operator=(const CBlob &src ); - - //! Adds a new internal contour to the blob - void AddInternalContour( const CBlobContour &newContour ); - - //! Retrieves contour in Freeman's chain code - CBlobContour *GetExternalContour() - { - return &m_externalContour; - } - - //! Retrieves blob storage - CvMemStorage *GetStorage() - { - return m_storage; - } - - //! Get label ID - t_labelType GetID() - { - return m_id; - } - //! > 0 for extern blobs, 0 if not - int Exterior( IplImage *mask, bool xBorder = true, bool yBorder = true ); - //! Compute blob's area - double Area(); - //! Compute blob's perimeter - double Perimeter(); - //! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS) - double Moment(int p, int q); - - //! Compute extern perimeter - double ExternPerimeter( IplImage *mask, bool xBorder = true, bool yBorder = true ); - - //! Get mean grey color - double Mean( IplImage *image ); - - //! Get standard deviation grey color - double StdDev( IplImage *image ); - - //! Indica si el blob est� buit ( no t� cap info associada ) - //! Shows if the blob has associated information - bool IsEmpty(); - - //! Retorna el poligon convex del blob - //! Calculates the convex hull of the blob - t_PointList GetConvexHull(); - - //! Pinta l'interior d'un blob d'un color determinat - //! Paints the blob in an image - void FillBlob( IplImage *imatge, CvScalar color, int offsetX = 0, int offsetY = 0 ); - - //! Join a blob to current one (add's contour - void JoinBlob( CBlob *blob ); - - //! Get bounding box - CvRect GetBoundingBox(); - //! Get bounding ellipse - CvBox2D GetEllipse(); - - //! Minimun X - double MinX() - { - return GetBoundingBox().x; - } - //! Minimun Y - double MinY() - { - return GetBoundingBox().y; - } - //! Maximun X - double MaxX() - { - return GetBoundingBox().x + GetBoundingBox().width; - } - //! Maximun Y - double MaxY() - { - return GetBoundingBox().y + GetBoundingBox().height; - } + CBlob(); + CBlob(t_labelType id, cv::Point startPoint, cv::Size originalImageSize); + ~CBlob(); + + //! Copy constructor + CBlob(const CBlob& src); + CBlob(const CBlob* src); + + //! Operador d'assignaci� + //! Assigment operator + CBlob& operator=(const CBlob& src); + + //! Adds a new internal contour to the blob + void AddInternalContour(const CBlobContour& newContour); + + //! Retrieves contour in Freeman's chain code + CBlobContour* GetExternalContour() + { + return &m_externalContour; + } + + //! Retrieves blob storage + CvMemStorage* GetStorage() + { + return m_storage; + } + + //! Get label ID + t_labelType GetID() + { + return m_id; + } + //! > 0 for extern blobs, 0 if not + int Exterior(IplImage* mask, bool xBorder = true, bool yBorder = true); + //! Compute blob's area + double Area(); + //! Compute blob's perimeter + double Perimeter(); + //! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS) + double Moment(int p, int q); + + //! Compute extern perimeter + double ExternPerimeter(IplImage* mask, + bool xBorder = true, + bool yBorder = true); + + //! Get mean grey color + double Mean(IplImage* image); + + //! Get standard deviation grey color + double StdDev(IplImage* image); + + //! Indica si el blob est� buit ( no t� cap info associada ) + //! Shows if the blob has associated information + bool IsEmpty(); + + //! Retorna el poligon convex del blob + //! Calculates the convex hull of the blob + t_PointList GetConvexHull(); + + //! Pinta l'interior d'un blob d'un color determinat + //! Paints the blob in an image + void FillBlob(IplImage* imatge, + CvScalar color, + int offsetX = 0, + int offsetY = 0); + + //! Join a blob to current one (add's contour + void JoinBlob(CBlob* blob); + + //! Get bounding box + CvRect GetBoundingBox(); + //! Get bounding ellipse + CvBox2D GetEllipse(); + + //! Minimun X + double MinX() + { + return GetBoundingBox().x; + } + //! Minimun Y + double MinY() + { + return GetBoundingBox().y; + } + //! Maximun X + double MaxX() + { + return GetBoundingBox().x + GetBoundingBox().width; + } + //! Maximun Y + double MaxY() + { + return GetBoundingBox().y + GetBoundingBox().height; + } + private: - - //! Deallocates all contours - void ClearContours(); - ////////////////////////////////////////////////////////////////////////// - // Blob contours - ////////////////////////////////////////////////////////////////////////// - - - //! Contour storage memory - CvMemStorage *m_storage; - //! External contour of the blob (crack codes) - CBlobContour m_externalContour; - //! Internal contours (crack codes) - t_contourList m_internalContours; - - ////////////////////////////////////////////////////////////////////////// - // Blob features - ////////////////////////////////////////////////////////////////////////// - - //! Label number - t_labelType m_id; - //! Area - double m_area; - //! Perimeter - double m_perimeter; - //! Extern perimeter from blob - double m_externPerimeter; - //! Mean gray color - double m_meanGray; - //! Standard deviation from gray color blob distribution - double m_stdDevGray; - //! Bounding box - CvRect m_boundingBox; - //! Bounding ellipse - CvBox2D m_ellipse; - //! Sizes from image where blob is extracted - cv::Size m_originalImageSize; + //! Deallocates all contours + void ClearContours(); + ////////////////////////////////////////////////////////////////////////// + // Blob contours + ////////////////////////////////////////////////////////////////////////// + + //! Contour storage memory + CvMemStorage* m_storage; + //! External contour of the blob (crack codes) + CBlobContour m_externalContour; + //! Internal contours (crack codes) + t_contourList m_internalContours; + + ////////////////////////////////////////////////////////////////////////// + // Blob features + ////////////////////////////////////////////////////////////////////////// + + //! Label number + t_labelType m_id; + //! Area + double m_area; + //! Perimeter + double m_perimeter; + //! Extern perimeter from blob + double m_externPerimeter; + //! Mean gray color + double m_meanGray; + //! Standard deviation from gray color blob distribution + double m_stdDevGray; + //! Bounding box + CvRect m_boundingBox; + //! Bounding ellipse + CvBox2D m_ellipse; + //! Sizes from image where blob is extracted + cv::Size m_originalImageSize; }; -#endif //CBLOB_INSPECTA_INCLUDED +#endif // CBLOB_INSPECTA_INCLUDED diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp index 15fc6f1..7cc18cb 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.cpp @@ -1,26 +1,23 @@ #include "IDetector.h" #include "../../../../helper/CvHelper.h" -template +template -std::vector IDetector::convertBlobPosesToFishPoses(std::vector blobPoses) +std::vector IDetector::convertBlobPosesToFishPoses( + std::vector blobPoses) { - std::vector fishPoses; - fishPoses.reserve(blobPoses.size()); + 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() - ) - ); - } + for (BlobPose& blobPose : blobPoses) { + fishPoses.push_back( + FishPose(blobPose.posCm(), + blobPose.posPx(), + CvHelper::degToRad(blobPose.angleDegree()), + blobPose.angleDegree(), + blobPose.width(), + blobPose.height())); + } - return fishPoses; + return fishPoses; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h index 8aa5db6..1e2b70d 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/IDetector.h @@ -4,63 +4,69 @@ #include "Interfaces/IModel/IModelAreaDescriptor.h" #include "blob/BlobPose.h" -template +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 contructor with parameters. - * @param: rectification, the rectification object for calculation the real world coordinate. - * @param: systemProperty, the set of parameters for tracking property. - */ - IDetector(void) {} + /** + * The standard abtract destructor. + */ + ~IDetector(void) + { + } - /** - * The standard abtract destructor. - */ - ~IDetector(void) {} + /** + * Interface function to get the fish poses from a binarzied image. + * @param: binarized_image_mat, binarized image. + * @return: a list of fish poses. + */ + virtual std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage) = 0; - /** - * Interface function to get the fish poses from a binarzied image. - * @param: binarized_image_mat, binarized image. - * @return: a list of fish poses. - */ - virtual std::vector 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; - /** - * 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); + /** + * Gets the specified parameter. + * @param: spec_param, the specified parameter to set, + * @return: the double value of the specifed paramter. + */ + // virtual void getDouble(std::string spec_param) = 0; - /** - * Sets specified parameter with a double value. - * @param: spec_param, the specified parameter to set, - * @param: value, the value double to set, - * @return: void. - */ - virtual void setDouble(std::string spec_param, double value) = 0; - - /** - * Gets the specified parameter. - * @param: spec_param, the specified parameter to set, - * @return: the double value of the specifed paramter. - */ - //virtual void getDouble(std::string spec_param) = 0; - - /** - * - */ - void setAreaInfo(IModelAreaDescriptor* ai) { - _areaInfo = ai; - } + /** + * + */ + void setAreaInfo(IModelAreaDescriptor* ai) + { + _areaInfo = ai; + } private: - virtual std::vector findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) = 0; + virtual std::vector findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage) = 0; protected: - IModelAreaDescriptor* _areaInfo; + IModelAreaDescriptor* _areaInfo; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp index aa7d449..7e550b9 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.cpp @@ -4,14 +4,20 @@ BlobPose::BlobPose(void) { } -BlobPose::BlobPose(cv::Point2f center_cm, cv::Point center_px, float angle_degree, float width, float height, bool use) : - _center_cm(center_cm), - _center_px(center_px), - _angle_degree(angle_degree), - _width(width), - _height(height), - _used(use) -{} +BlobPose::BlobPose(cv::Point2f center_cm, + cv::Point center_px, + float angle_degree, + float width, + float height, + bool use) +: _center_cm(center_cm) +, _center_px(center_px) +, _angle_degree(angle_degree) +, _width(width) +, _height(height) +, _used(use) +{ +} BlobPose::~BlobPose(void) { diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h index 4ebaf7b..94b710c 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/BlobPose.h @@ -5,82 +5,112 @@ class BlobPose { public: - /** - * The standard contructor. - */ - BlobPose(void); + /** + * The standard contructor. + */ + BlobPose(void); - /** - * The contructor with parameters. - * @param: pos_cm, position in real world coordinate. - * @param: pos_px, position in pixel coordinate. - * @param: angle_degree, orientation angle in degree. - * @param: width, width in px. - * @param: height, height in px. - * @param: used, check if this blob pose is currently in use. - */ - BlobPose(cv::Point2f pos_cm, cv::Point pos_px, float angle_degree, float width, float height, bool use = false); + /** + * The contructor with parameters. + * @param: pos_cm, position in real world coordinate. + * @param: pos_px, position in pixel coordinate. + * @param: angle_degree, orientation angle in degree. + * @param: width, width in px. + * @param: height, height in px. + * @param: used, check if this blob pose is currently in use. + */ + BlobPose(cv::Point2f pos_cm, + cv::Point pos_px, + float angle_degree, + float width, + float height, + bool use = false); - /** - * The standard destructor. - */ - ~BlobPose(void); + /** + * The standard destructor. + */ + ~BlobPose(void); - /** - * Gets the pixel position of the pose. - * @return pixel position. - */ - cv::Point posPx() { return _center_px; } + /** + * Gets the pixel position of the pose. + * @return pixel position. + */ + cv::Point posPx() + { + return _center_px; + } - /** - * Gets the real world position of the pose. - * @return real world position. - */ - cv::Point2f posCm() { return _center_cm; } + /** + * Gets the real world position of the pose. + * @return real world position. + */ + cv::Point2f posCm() + { + return _center_cm; + } - /** - * Gets the orientation angle as degree of the pose. - * @return degree angle. - */ - float angleDegree() { return _angle_degree; } + /** + * Gets the orientation angle as degree of the pose. + * @return degree angle. + */ + float angleDegree() + { + return _angle_degree; + } - /** - * Gets the width of the blob pose. - * @return width in px. - */ - float width() { return _width; } + /** + * Gets the width of the blob pose. + * @return width in px. + */ + float width() + { + return _width; + } - /** - * Gets the height of the blob pose. - * @return height in px. - */ - float height() { return _height; } + /** + * Gets the height of the blob pose. + * @return height in px. + */ + float height() + { + return _height; + } - /** - * Gets the flag whether this pose blob is already in use. - * @return true if is used, false otherwise. - */ - bool isUsed() { return _used; } + /** + * Gets the flag whether this pose blob is already in use. + * @return true if is used, false otherwise. + */ + bool isUsed() + { + return _used; + } - /** - * Sets the pixel position of the pose. - * @param int x, int y - * @return void. - */ - void setposPx(int x, int y) { cv::Point point(x,y); _center_px = point; } + /** + * Sets the pixel position of the pose. + * @param int x, int y + * @return void. + */ + void setposPx(int x, int y) + { + cv::Point point(x, y); + _center_px = point; + } - /** - * Sets the angle in degree. - * @param float angleDegree - * @return void. - */ - void setAngle(float angleDegree) { _angle_degree = angleDegree; } + /** + * Sets the angle in degree. + * @param float angleDegree + * @return void. + */ + void setAngle(float angleDegree) + { + _angle_degree = angleDegree; + } private: - bool _used; - cv::Point2f _center_cm; - cv::Point _center_px; - float _angle_degree; - float _width; - float _height; + bool _used; + cv::Point2f _center_cm; + cv::Point _center_px; + float _angle_degree; + float _width; + float _height; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp index cfd62a6..4d302ce 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.cpp @@ -2,79 +2,95 @@ #include "../../../../../../helper/CvHelper.h" #include -BlobsDetector::BlobsDetector(void) : - _mask(nullptr), - _minBlobSize(1), //TODO Min blob size - _maxBlobSize(99999) //TODO Max blob size -{} - +BlobsDetector::BlobsDetector(void) +: _mask(nullptr) +, _minBlobSize(1) +, // TODO Min blob size +_maxBlobSize(99999) // TODO Max blob size +{ +} void BlobsDetector::filterBlobsBySize(CBlobResult& blobs) { - // blobs smaller than the provided blob size - blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER_OR_EQUAL, minBlobSize()); - - // blobs bigger than the provided blob size - blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_LESS_OR_EQUAL, maxBlobSize()); + // blobs smaller than the provided blob size + blobs.Filter(blobs, + B_INCLUDE, + CBlobGetArea(), + B_GREATER_OR_EQUAL, + minBlobSize()); + + // blobs bigger than the provided blob size + blobs.Filter(blobs, + B_INCLUDE, + CBlobGetArea(), + B_LESS_OR_EQUAL, + maxBlobSize()); } -bool isLeft(cv::Point a, cv::Point b, cv::Point c) { - return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0; +bool isLeft(cv::Point a, cv::Point b, cv::Point c) +{ + return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) > 0; } -std::vector BlobsDetector::findBlobs(const cv::Mat& processedImage, const cv::Mat& oriImage) +std::vector BlobsDetector::findBlobs(const cv::Mat& processedImage, + const cv::Mat& oriImage) { - std::vector blobPoses; + std::vector blobPoses; + + CBlob* currentBlob; + CBlobResult blobs(processedImage, _mask, 0); - CBlob *currentBlob; - CBlobResult blobs(processedImage, _mask, 0); + // filter the blobs by size criteria + filterBlobsBySize(blobs); - // filter the blobs by size criteria - filterBlobsBySize(blobs); + for (int i = 0; i < blobs.GetNumBlobs(); i++) { + currentBlob = blobs.GetBlob(i); - for (int i = 0; i < blobs.GetNumBlobs(); i++) - { - currentBlob = blobs.GetBlob(i); + // gets blob center + int x = currentBlob->GetEllipse().center.x; + int y = currentBlob->GetEllipse().center.y; + cv::Point blobPose_px = cv::Point(x, y); - // gets blob center - int x = currentBlob->GetEllipse().center.x; - int y = currentBlob->GetEllipse().center.y; - cv::Point blobPose_px = cv::Point(x, y); + // apply homography + cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); - // apply homography - cv::Point2f blobPose_cm =_areaInfo->pxToCm(blobPose_px); + // ignore blobs outside the tracking area + if (!_areaInfo->inTrackingArea(blobPose_px)) + continue; - // ignore blobs outside the tracking area - if (!_areaInfo->inTrackingArea(blobPose_px)) - continue; - - float blobPose_angle_deg = currentBlob->GetEllipse().angle; - float blobPose_angle_rad = currentBlob->GetEllipse().angle * CV_PI / float(180.0); - assert(blobPose_angle_deg >= 0.0f && blobPose_angle_deg <= 360.0f); + float blobPose_angle_deg = currentBlob->GetEllipse().angle; + float blobPose_angle_rad = currentBlob->GetEllipse().angle * CV_PI / + float(180.0); + assert(blobPose_angle_deg >= 0.0f && blobPose_angle_deg <= 360.0f); - float blobPose_width = currentBlob->GetEllipse().size.width; - float blobPose_height = currentBlob->GetEllipse().size.height; + float blobPose_width = currentBlob->GetEllipse().size.width; + float blobPose_height = currentBlob->GetEllipse().size.height; - blobPoses.push_back(BlobPose(blobPose_cm, blobPose_px, blobPose_angle_deg, blobPose_angle_rad, blobPose_width, blobPose_height)); - } + blobPoses.push_back(BlobPose(blobPose_cm, + blobPose_px, + blobPose_angle_deg, + blobPose_angle_rad, + blobPose_width, + blobPose_height)); + } - return blobPoses; + return blobPoses; } -std::vector BlobsDetector::getPoses(cv::Mat& processedImage, cv::Mat& oriImage) -{ - return findBlobs(processedImage, oriImage); +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; - } +{ + if (spec_param.compare("1") == 0) { + this->setMinBlobSize(value); + } else if (spec_param.compare("999999") == 0) { + this->setMaxBlobSize(value); + } else { + std::cout << "BlobsDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h index e6e339f..4d8a45d 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h @@ -7,48 +7,65 @@ class BlobsDetector : public IDetector { public: + /** + * The contructor with parameters. + * @param: rectification, the rectification object for calculation the real + * world coordinate. + * @param: systemProperty, the set of parameters for tracking property. + */ + BlobsDetector(void); - /** - * The contructor with parameters. - * @param: rectification, the rectification object for calculation the real world coordinate. - * @param: systemProperty, the set of parameters for tracking property. - */ - BlobsDetector(void); + virtual ~BlobsDetector(void) + { + } - virtual ~BlobsDetector(void) {} + void setMask(cv::Mat* mask) + { + _mask = mask; + } - void setMask(cv::Mat *mask) { _mask = mask; } + std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - + void setDouble(std::string spec_param, double value); - void setDouble(std::string spec_param, double value); - - double minBlobSize() { return _minBlobSize; }; - double maxBlobSize() { return _maxBlobSize; }; - void setMinBlobSize(double x) { _minBlobSize = x; }; - void setMaxBlobSize(double x) { _maxBlobSize = x; }; + double minBlobSize() + { + return _minBlobSize; + }; + double maxBlobSize() + { + return _maxBlobSize; + }; + void setMinBlobSize(double x) + { + _minBlobSize = x; + }; + void setMaxBlobSize(double x) + { + _maxBlobSize = x; + }; private: + /** + * Removes blobs, which are too big for the further hanlding. + * @param: blobs, all possible blobs with all possible size. + * @return: void. + */ + void filterBlobsBySize(CBlobResult& blobs); + + /** + * Find all blobs within an image. + * @param: binarized_image_mat, image contains blobs and is already + * binarized, + * @return: all found blobs within the image. + */ + + // TODO: can we make binImage a reference?? + std::vector findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage); + + double _minBlobSize; + double _maxBlobSize; - /** - * Removes blobs, which are too big for the further hanlding. - * @param: blobs, all possible blobs with all possible size. - * @return: void. - */ - void filterBlobsBySize(CBlobResult& blobs); - - /** - * Find all blobs within an image. - * @param: binarized_image_mat, image contains blobs and is already binarized, - * @return: all found blobs within the image. - */ - - // TODO: can we make binImage a reference?? - std::vector findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - double _minBlobSize; - double _maxBlobSize; - - cv::Mat *_mask; + cv::Mat* _mask; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp index 4c5ae92..feb8be7 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.cpp @@ -2,79 +2,89 @@ #include "../../../../../../helper/CvHelper.h" #include -SimpleBlobsDetector::SimpleBlobsDetector(void) : _mask(nullptr) +SimpleBlobsDetector::SimpleBlobsDetector(void) +: _mask(nullptr) { - initParams(); + initParams(); } void SimpleBlobsDetector::initParams() { - _params.minThreshold = 15; - _params.maxThreshold = 50; - _params.thresholdStep = 5; - _params.filterByArea = true; - _params.minArea = 1; - _params.maxArea = 999999; - _params.filterByInertia = false; - _params.filterByColor = true; - _params.blobColor = 255; - _params.filterByCircularity = false; - _params.minDistBetweenBlobs = 0; + _params.minThreshold = 15; + _params.maxThreshold = 50; + _params.thresholdStep = 5; + _params.filterByArea = true; + _params.minArea = 1; + _params.maxArea = 999999; + _params.filterByInertia = false; + _params.filterByColor = true; + _params.blobColor = 255; + _params.filterByCircularity = false; + _params.minDistBetweenBlobs = 0; } - -std::vector SimpleBlobsDetector::findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) +std::vector SimpleBlobsDetector::findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage) { - std::vector blobPoses; - - std::vector keyPoints; + std::vector blobPoses; - cv::Ptr blobDetector = cv::SimpleBlobDetector::create(_params); + std::vector keyPoints; - blobDetector->detect( binImage, keyPoints); + cv::Ptr blobDetector = + cv::SimpleBlobDetector::create(_params); - for (int i = 0; i < keyPoints.size(); i++) - { - // gets blob center - int x = keyPoints.at(i).pt.x; - int y = keyPoints.at(i).pt.y; - cv::Point blobPose_px = cv::Point(x, y); + blobDetector->detect(binImage, keyPoints); - // apply homography - cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); + for (int i = 0; i < keyPoints.size(); i++) { + // gets blob center + int x = keyPoints.at(i).pt.x; + int y = keyPoints.at(i).pt.y; + cv::Point blobPose_px = cv::Point(x, y); - if (!_areaInfo->inTrackingArea(blobPose_px)) - continue; + // apply homography + cv::Point2f blobPose_cm = _areaInfo->pxToCm(blobPose_px); - float blobPose_angleDegree = keyPoints.at(i).angle; // as degree (0..360) - float blobPose_angleRadian = keyPoints.at(i).angle * float(CV_PI) / float(180.0); - float blobPose_width = keyPoints.at(i).size; - float blobPose_height = keyPoints.at(i).size; + if (!_areaInfo->inTrackingArea(blobPose_px)) + continue; - blobPoses.push_back(BlobPose(blobPose_cm, blobPose_px, blobPose_angleDegree, blobPose_angleRadian, blobPose_width, blobPose_height)); - } + float blobPose_angleDegree = + keyPoints.at(i).angle; // as degree (0..360) + float blobPose_angleRadian = keyPoints.at(i).angle * float(CV_PI) / + float(180.0); + float blobPose_width = keyPoints.at(i).size; + float blobPose_height = keyPoints.at(i).size; + blobPoses.push_back(BlobPose(blobPose_cm, + blobPose_px, + blobPose_angleDegree, + blobPose_angleRadian, + blobPose_width, + blobPose_height)); + } - return blobPoses; + return blobPoses; } - -std::vector SimpleBlobsDetector::getPoses(cv::Mat& binarized_image_mat, cv::Mat& original_image_mat) -{ - return findBlobs(binarized_image_mat,original_image_mat); +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; - } +{ + if (spec_param.compare("1") == 0) { // TRACKERPARAM::MIN_BLOB_SIZE + _params.minArea = value; + } else { + std::cout << "SimpleBlobsDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; + } + + if (spec_param.compare("999999") == 0) { // TRACKERPARAM::MAX_BLOB_SIZE + _params.maxArea = value; + } else { + std::cout << "SimpleBlobsDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h index e5b3be4..8abc0ad 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/blob/simpleBlob/SimpleBlobsDetector.h @@ -11,39 +11,42 @@ class SimpleBlobsDetector : public IDetector { public: + /** + * The contructor with parameters. + */ + SimpleBlobsDetector(void); - /** - * The contructor with parameters. - */ - SimpleBlobsDetector(void); + virtual ~SimpleBlobsDetector(void) + { + } - virtual ~SimpleBlobsDetector(void) {} + void setMask(cv::Mat* mask) + { + _mask = mask; + } - void setMask(cv::Mat *mask) { _mask = mask; } - - std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); + std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - void setDouble(std::string spec_param, double value); + void setDouble(std::string spec_param, double value); private: - - cv::Mat *_mask; - cv::SimpleBlobDetector::Params _params; - - /** - * Initialized the parameter for setting up the blob detector. - * @return: void. - */ - void initParams(); - - /** - * Find all blobs within an image. - * @param: binarized_image_mat, image contains blobs and is already binarized, - * @return: all found blobs within the image. - */ - - // TODO: can we make binImage a reference?? - std::vector findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - + cv::Mat* _mask; + cv::SimpleBlobDetector::Params _params; + + /** + * Initialized the parameter for setting up the blob detector. + * @return: void. + */ + void initParams(); + + /** + * Find all blobs within an image. + * @param: binarized_image_mat, image contains blobs and is already + * binarized, + * @return: all found blobs within the image. + */ + + // TODO: can we make binImage a reference?? + std::vector findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage); }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp index cd65b94..2bc733f 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.cpp @@ -4,14 +4,20 @@ ContourPose::ContourPose(void) { } -ContourPose::ContourPose(cv::Point2f center_cm, cv::Point center_px, float angle_degree, float width, float height, bool use) : - _center_cm(center_cm), - _center_px(center_px), - _angle_degree(angle_degree), - _width(width), - _height(height), - _used(use) -{} +ContourPose::ContourPose(cv::Point2f center_cm, + cv::Point center_px, + float angle_degree, + float width, + float height, + bool use) +: _center_cm(center_cm) +, _center_px(center_px) +, _angle_degree(angle_degree) +, _width(width) +, _height(height) +, _used(use) +{ +} ContourPose::~ContourPose(void) { diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h index 4e7e3da..3323b96 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContourPose.h @@ -1,72 +1,94 @@ -#pragma once +#pragma once #include class ContourPose { public: - /** - * The standard contructor. - */ - ContourPose(void); + /** + * The standard contructor. + */ + ContourPose(void); - /** - * The contructor with parameters. - * @param: pos_cm, position in real world coordinate. - * @param: pos_px, position in pixel coordinate. - * @param: angle_degree, orientation angle in degree. - * @param: width, width in px. - * @param: height, height in px. - * @param: used, check if this blob pose is currently in use. - */ - ContourPose(cv::Point2f pos_cm, cv::Point pos_px, float angle_degree, float width, float height, bool use = false); + /** + * The contructor with parameters. + * @param: pos_cm, position in real world coordinate. + * @param: pos_px, position in pixel coordinate. + * @param: angle_degree, orientation angle in degree. + * @param: width, width in px. + * @param: height, height in px. + * @param: used, check if this blob pose is currently in use. + */ + ContourPose(cv::Point2f pos_cm, + cv::Point pos_px, + float angle_degree, + float width, + float height, + bool use = false); - /** - * The standard destructor. - */ - ~ContourPose(void); + /** + * The standard destructor. + */ + ~ContourPose(void); - /** - * Gets the pixel position of the pose. - * @return pixel position. - */ - cv::Point posPx() { return _center_px; } + /** + * Gets the pixel position of the pose. + * @return pixel position. + */ + cv::Point posPx() + { + return _center_px; + } - /** - * Gets the real world position of the pose. - * @return real world position. - */ - cv::Point2f posCm() { return _center_cm; } + /** + * Gets the real world position of the pose. + * @return real world position. + */ + cv::Point2f posCm() + { + return _center_cm; + } - /** - * Gets the orientation angle as degree of the pose. - * @return degree angle. - */ - float angleDegree() { return _angle_degree; } + /** + * Gets the orientation angle as degree of the pose. + * @return degree angle. + */ + float angleDegree() + { + return _angle_degree; + } - /** - * Gets the width of the blob pose. - * @return width in px. - */ - float width() { return _width; } + /** + * Gets the width of the blob pose. + * @return width in px. + */ + float width() + { + return _width; + } - /** - * Gets the height of the blob pose. - * @return height in px. - */ - float height() { return _height; } - - /** - * Gets the flag whether this pose blob is already in use. - * @return true if is used, false otherwise. - */ - bool isUsed() { return _used; } + /** + * Gets the height of the blob pose. + * @return height in px. + */ + float height() + { + return _height; + } + /** + * Gets the flag whether this pose blob is already in use. + * @return true if is used, false otherwise. + */ + bool isUsed() + { + return _used; + } private: - bool _used; - cv::Point2f _center_cm; - cv::Point _center_px; - float _angle_degree; - float _width; - float _height; + bool _used; + cv::Point2f _center_cm; + cv::Point _center_px; + float _angle_degree; + float _width; + float _height; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp index 59e7a93..6a76e59 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp @@ -1,33 +1,38 @@ #include "ContoursDetector.h" #include "../../../../../helper/CvHelper.h" -std::vector ContoursDetector::findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage) +std::vector ContoursDetector::findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage) { - std::vector contourPoses; + std::vector contourPoses; - return contourPoses; + return contourPoses; } -std::vector ContoursDetector::findContours(const cv::Mat& binImage, const cv::Mat& oriImage) +std::vector ContoursDetector::findContours( + const cv::Mat& binImage, + const cv::Mat& oriImage) { - return findBlobs(binImage,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 +// 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; +// for( int y=0; yheight; y++ ) { +// uchar* ptr = (uchar*) ( mask->imageData + y * mask->widthStep ); +// for( int x=0; xwidth; x++ ) { +// ptr[x+2] = 0; // } // } -// +// // cv::Point maskPoints[4]; // // for(int z=0;z<4;z++) @@ -56,13 +61,14 @@ void ContoursDetector::createMask(std::vector points) // //cvDestroyWindow("MyWindow"); //} - -std::vector ContoursDetector::getPoses(cv::Mat& image_mat, cv::Mat& image_ori) -{ - return findContours(image_mat,image_ori); +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; +{ + std::cout << "ContoursDetector::Warning - Parameter: " << spec_param + << " not found!" << std::endl; } \ No newline at end of file diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h index 71fd301..d24a454 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.h @@ -7,30 +7,35 @@ class ContoursDetector : public IDetector { public: + /** + * The contructor with parameters. + */ + ContoursDetector(void) + { + } - /** - * The contructor with parameters. - */ - ContoursDetector(void) {} + ~ContoursDetector(void) + { + } - ~ContoursDetector(void) {} + std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - std::vector getPoses(cv::Mat& binImage, cv::Mat& oriImage); - - void setDouble(std::string spec_param, double value); + void setDouble(std::string spec_param, double value); private: + /** + * Find all cntours within an image. + * @param: binarized_image_mat, image contains blobs and is already + * binarized, + * @return: all found blobs within the image. + */ + std::vector findBlobs(const cv::Mat& binImage, + const cv::Mat& oriImage); - /** - * Find all cntours within an image. - * @param: binarized_image_mat, image contains blobs and is already binarized, - * @return: all found blobs within the image. - */ - std::vector findBlobs(const cv::Mat& binImage, const cv::Mat& oriImage); - - std::vector findContours(const cv::Mat& binImage, const cv::Mat& oriImage); + std::vector findContours(const cv::Mat& binImage, + const cv::Mat& oriImage); - void createMask(std::vector points); + void createMask(std::vector points); - cv::Mat _mask; + cv::Mat _mask; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp index cf8f62a..fab8580 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -9,77 +9,83 @@ CustomBackgroundSubtractor::CustomBackgroundSubtractor() : m_useAbsoluteDifference{true} , m_binarizationThreshold{8} { - } void CustomBackgroundSubtractor::setUseAbsoluteDifference(bool value) { - m_useAbsoluteDifference = value; + m_useAbsoluteDifference = value; } void CustomBackgroundSubtractor::setBinarizationThreshold(int value) { - m_binarizationThreshold = value; + m_binarizationThreshold = value; } -void CustomBackgroundSubtractor::getBackgroundImage(cv::OutputArray backgroundImage) const +void CustomBackgroundSubtractor::getBackgroundImage( + cv::OutputArray backgroundImage) const { - m_background.copyTo(backgroundImage); + m_background.copyTo(backgroundImage); } -void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate) +void CustomBackgroundSubtractor::apply(cv::InputArray image, + cv::OutputArray fgmask, + double learningRate) { - if (!m_background.data) { - image.copyTo(m_background); - } - - const int imageWidth = m_background.cols; - const int imageHeight = m_background.rows; - const int totalRegionsX = 4; - const int totalRegionsY = 4; - const int totalRegions = totalRegionsX * totalRegionsY; - const int regionWidth = imageWidth / totalRegionsX; - const int regionHeight = imageHeight / totalRegionsY; - - fgmask.create(imageHeight, imageWidth, image.type()); - - auto fgmaskmat = fgmask.getMat(); - - const auto useAbsoluteDifference = m_useAbsoluteDifference; - - auto workOnRegion = [&, useAbsoluteDifference](int x, int y) { - const int startingX = x * regionWidth; - const int startingY = y * regionHeight; - const cv::Rect subArea = cv::Rect(startingX, startingY, regionWidth, regionHeight); - cv::Mat subBackground = m_background(subArea); - cv::Mat subImage = image.getMat()(subArea); - cv::Mat subResults = fgmaskmat(subArea); - - if (useAbsoluteDifference) { - cv::absdiff(subBackground, subImage, subResults); - } else { - cv::subtract(subBackground, subImage, subResults); - } - - subBackground = (1.0 - learningRate) * subBackground + learningRate * subImage; - }; - - std::vector> merger; - merger.reserve(totalRegions); - - for (int x = 0; x < totalRegionsX; ++x) - { - for (int y = 0; y < totalRegionsY; ++y) - { - merger.push_back(std::async([&, x, y] { workOnRegion(x, y); })); - } - } - - for (const auto & asyncResult : merger) { - asyncResult.wait(); - } - - if (fgmaskmat.data) { - cv::threshold(fgmaskmat, fgmaskmat, m_binarizationThreshold, 255, cv::THRESH_BINARY); - } + if (!m_background.data) { + image.copyTo(m_background); + } + + const int imageWidth = m_background.cols; + const int imageHeight = m_background.rows; + const int totalRegionsX = 4; + const int totalRegionsY = 4; + const int totalRegions = totalRegionsX * totalRegionsY; + const int regionWidth = imageWidth / totalRegionsX; + const int regionHeight = imageHeight / totalRegionsY; + + fgmask.create(imageHeight, imageWidth, image.type()); + + auto fgmaskmat = fgmask.getMat(); + + const auto useAbsoluteDifference = m_useAbsoluteDifference; + + auto workOnRegion = [&, useAbsoluteDifference](int x, int y) { + const int startingX = x * regionWidth; + const int startingY = y * regionHeight; + const cv::Rect subArea = + cv::Rect(startingX, startingY, regionWidth, regionHeight); + cv::Mat subBackground = m_background(subArea); + cv::Mat subImage = image.getMat()(subArea); + cv::Mat subResults = fgmaskmat(subArea); + + if (useAbsoluteDifference) { + cv::absdiff(subBackground, subImage, subResults); + } else { + cv::subtract(subBackground, subImage, subResults); + } + + subBackground = (1.0 - learningRate) * subBackground + + learningRate * subImage; + }; + + std::vector> merger; + merger.reserve(totalRegions); + + for (int x = 0; x < totalRegionsX; ++x) { + for (int y = 0; y < totalRegionsY; ++y) { + merger.push_back(std::async([&, x, y] { workOnRegion(x, y); })); + } + } + + for (const auto& asyncResult : merger) { + asyncResult.wait(); + } + + if (fgmaskmat.data) { + cv::threshold(fgmaskmat, + fgmaskmat, + m_binarizationThreshold, + 255, + cv::THRESH_BINARY); + } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h index 94c79b0..9d611ca 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h @@ -5,19 +5,21 @@ class CustomBackgroundSubtractor : public cv::BackgroundSubtractor { public: - CustomBackgroundSubtractor(); + CustomBackgroundSubtractor(); - void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = -1) override; + void apply(cv::InputArray image, + cv::OutputArray fgmask, + double learningRate = -1) override; - void getBackgroundImage(cv::OutputArray backgroundImage) const override; + void getBackgroundImage(cv::OutputArray backgroundImage) const override; - void setUseAbsoluteDifference(bool value); - void setBinarizationThreshold(int value); + void setUseAbsoluteDifference(bool value); + void setBinarizationThreshold(int value); private: - cv::Mat m_background; + cv::Mat m_background; - bool m_useAbsoluteDifference; + bool m_useAbsoluteDifference; - int m_binarizationThreshold; + int m_binarizationThreshold; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 9f241aa..ab6d428 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -10,122 +10,136 @@ QMutex bgsMutex; -ImagePreProcessor::ImagePreProcessor(TrackerParameter* TrackingParameter) : - m_subtractor(nullptr), - m_TrackingParameter{TrackingParameter} +ImagePreProcessor::ImagePreProcessor(TrackerParameter* TrackingParameter) +: m_subtractor(nullptr) +, m_TrackingParameter{TrackingParameter} { - init(); + init(); } ImagePreProcessor::~ImagePreProcessor(void) { } - void ImagePreProcessor::init() { - QMutexLocker locker(&bgsMutex); - - auto algorithm = m_TrackingParameter->getAlgorithm(); - if (algorithm == QString("Custom")) { - m_subtractor = new CustomBackgroundSubtractor(); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - m_backgroundImage = std::make_shared(); - m_foregroundMask = std::make_shared(); - - _backgroundSubtractionEnabled = true; - _backgroundEnabled = true; - _erodeEnabled = true; - _dilateEnabled = true; - _gaussianBlurEnabled = false; - _binarizeEnabled = true; - _resetBackgroundImageEnabled = false; + QMutexLocker locker(&bgsMutex); + + auto algorithm = m_TrackingParameter->getAlgorithm(); + if (algorithm == QString("Custom")) { + m_subtractor = new CustomBackgroundSubtractor(); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + m_backgroundImage = std::make_shared(); + m_foregroundMask = std::make_shared(); + + _backgroundSubtractionEnabled = true; + _backgroundEnabled = true; + _erodeEnabled = true; + _dilateEnabled = true; + _gaussianBlurEnabled = false; + _binarizeEnabled = true; + _resetBackgroundImageEnabled = false; } cv::Mat ImagePreProcessor::erode(cv::Mat& image) { - cv::Mat erodedImage; - cv::Mat erodeKernel; - int sizeErode = m_TrackingParameter->getSizeErode(); - if (sizeErode > 0) - { - erodeKernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(sizeErode, sizeErode)); - } - else { - return image; - } - if (image.data) - cv::erode(image, erodedImage, erodeKernel); - return erodedImage; + cv::Mat erodedImage; + cv::Mat erodeKernel; + int sizeErode = m_TrackingParameter->getSizeErode(); + if (sizeErode > 0) { + erodeKernel = cv::getStructuringElement( + cv::MORPH_CROSS, + cv::Size(sizeErode, sizeErode)); + } else { + return image; + } + if (image.data) + cv::erode(image, erodedImage, erodeKernel); + return erodedImage; } cv::Mat ImagePreProcessor::dilate(cv::Mat& image) { - cv::Mat dilatedImage; - cv::Mat dilateKernel; - int sizeDilate = m_TrackingParameter->getSizeDilate(); - if (sizeDilate > 0) - { - dilateKernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(sizeDilate, sizeDilate)); - } - else { - return image; - } - if (image.data) - cv::dilate(image, dilatedImage, dilateKernel); - return dilatedImage; + cv::Mat dilatedImage; + cv::Mat dilateKernel; + int sizeDilate = m_TrackingParameter->getSizeDilate(); + if (sizeDilate > 0) { + dilateKernel = cv::getStructuringElement( + cv::MORPH_RECT, + cv::Size(sizeDilate, sizeDilate)); + } else { + return image; + } + if (image.data) + cv::dilate(image, dilatedImage, dilateKernel); + return dilatedImage; } cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) { - if (auto subtractor = m_subtractor.dynamicCast(); subtractor) { - if (m_TrackingParameter->getAlgorithm() != QString("Custom")) { - init(); - } - subtractor->setUseAbsoluteDifference(m_TrackingParameter->getUseAbsoluteDifference()); - subtractor->setBinarizationThreshold(m_TrackingParameter->getBinarizationThreshold()); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - cv::Mat fgmask; - m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate()); - m_subtractor->getBackgroundImage(*m_backgroundImage); - return fgmask; + if (auto subtractor = + m_subtractor.dynamicCast(); + subtractor) { + if (m_TrackingParameter->getAlgorithm() != QString("Custom")) { + init(); + } + subtractor->setUseAbsoluteDifference( + m_TrackingParameter->getUseAbsoluteDifference()); + subtractor->setBinarizationThreshold( + m_TrackingParameter->getBinarizationThreshold()); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + cv::Mat fgmask; + m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate()); + m_subtractor->getBackgroundImage(*m_backgroundImage); + return fgmask; } -std::map> ImagePreProcessor::preProcess(std::shared_ptr p_image) +std::map> ImagePreProcessor::preProcess( + std::shared_ptr p_image) { - std::shared_ptr greyMat = std::make_shared(); - std::shared_ptr erodedImage = std::make_shared(); - std::shared_ptr dilatedImage = std::make_shared(); - - cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); - - // 1. step: do the background subtraction - *m_foregroundMask = backgroundSubtraction(*greyMat); - - // 2. step: erode the image - *erodedImage = erode(*m_foregroundMask); - - // 3. step: dilate the image - *dilatedImage = dilate(*erodedImage); - - std::map> all; - all.insert(std::pair>(std::string("Greyscale"), greyMat)); - all.insert(std::pair>(std::string("Background"), m_backgroundImage)); - all.insert(std::pair>(std::string("Foreground Mask"), m_foregroundMask)); - all.insert(std::pair>(std::string("Eroded"), erodedImage)); - all.insert(std::pair>(std::string("Dilated"), dilatedImage)); - - return all; + std::shared_ptr greyMat = std::make_shared(); + std::shared_ptr erodedImage = std::make_shared(); + std::shared_ptr dilatedImage = std::make_shared(); + + cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); + + // 1. step: do the background subtraction + *m_foregroundMask = backgroundSubtraction(*greyMat); + + // 2. step: erode the image + *erodedImage = erode(*m_foregroundMask); + + // 3. step: dilate the image + *dilatedImage = dilate(*erodedImage); + + std::map> all; + all.insert(std::pair>( + std::string("Greyscale"), + greyMat)); + all.insert(std::pair>( + std::string("Background"), + m_backgroundImage)); + all.insert(std::pair>( + std::string("Foreground Mask"), + m_foregroundMask)); + 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(); + // this will reset the background at the next opportunity + init(); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index bb03f38..b190f39 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -4,87 +4,83 @@ #include -#include "../../../../helper/StringHelper.h" #include "../../../TrackerParameter.h" - class ImagePreProcessor { public: + /** + * The standard constructor. + */ + ImagePreProcessor(TrackerParameter* TrackingParameter); + + /** + * The standard destructor. + */ + ~ImagePreProcessor(); + + /** + * Init function. Sets the property for the imge pre-processing. + * @return void. + */ + void init(); + + /** + * A mathematical morphology operation using in computer vision to erode an + * image. Erode image with 3x3 4-connectivity. + * @param: image, image to erode, + * @return: an eroded image. + */ + cv::Mat erode(cv::Mat& image); + + /** + * A mathematical morphology operation using in computer vision to dilate + * an image. Dilate image with 6x6 8-connectivity. + * @param: image, image to dilate, + * @return: a dilated image. + */ + cv::Mat dilate(cv::Mat& image); + + /** + * A computer vision methode to calculate the image difference. + * Background image subtracts the foreground image. + * @param: image, image to background subtract, + * @return: the background subtracted image. + */ + cv::Mat backgroundSubtraction(cv::Mat& image); + + /** + * Pre-process an image, if all methods enabled, this function: + * - does the background subtraction + * - erodes the image + * - dilates the image + * @param: image, image to process, + * @return: a pre-process image. + */ + std::map> preProcess( + std::shared_ptr p_image); + + /** + * The method updates the image background. + * @return: void. + */ + void resetBackgroundImage(); + TrackerParameter* m_TrackingParameter; - /** - * The standard constructor. - */ - ImagePreProcessor(TrackerParameter* TrackingParameter); - - /** - * The standard destructor. - */ - ~ImagePreProcessor(); - - /** - * Init function. Sets the property for the imge pre-processing. - * @return void. - */ - void init(); - - /** - * A mathematical morphology operation using in computer vision to erode an image. - * Erode image with 3x3 4-connectivity. - * @param: image, image to erode, - * @return: an eroded image. - */ - cv::Mat erode(cv::Mat& image); - - /** - * A mathematical morphology operation using in computer vision to dilate an image. - * Dilate image with 6x6 8-connectivity. - * @param: image, image to dilate, - * @return: a dilated image. - */ - cv::Mat dilate(cv::Mat& image); - - /** - * A computer vision methode to calculate the image difference. - * Background image subtracts the foreground image. - * @param: image, image to background subtract, - * @return: the background subtracted image. - */ - cv::Mat backgroundSubtraction(cv::Mat& image); - - /** - * Pre-process an image, if all methods enabled, this function: - * - does the background subtraction - * - erodes the image - * - dilates the image - * @param: image, image to process, - * @return: a pre-process image. - */ - std::map> preProcess(std::shared_ptr p_image); - - /** - * The method updates the image background. - * @return: void. - */ - void resetBackgroundImage(); - TrackerParameter* m_TrackingParameter; - private: + cv::Mat _outputImage; + std::shared_ptr m_backgroundImage; + std::shared_ptr m_foregroundMask; - cv::Mat _outputImage; - - std::shared_ptr m_backgroundImage; - std::shared_ptr m_foregroundMask; - - //parameters for image pre-processing - bool _backgroundSubtractionEnabled; - bool _backgroundEnabled; - bool _binarizeEnabled; - bool _erodeEnabled; - bool _dilateEnabled; - bool _gaussianBlurEnabled; - bool _resetBackgroundImageEnabled; + // parameters for image pre-processing + bool _backgroundSubtractionEnabled; + bool _backgroundEnabled; + bool _binarizeEnabled; + bool _erodeEnabled; + bool _dilateEnabled; + bool _gaussianBlurEnabled; + bool _resetBackgroundImageEnabled; - cv::Ptr m_subtractor; + cv::Ptr m_subtractor; }; diff --git a/Src/Model/null_Model.cpp b/Src/Model/null_Model.cpp index db2793d..4328117 100644 --- a/Src/Model/null_Model.cpp +++ b/Src/Model/null_Model.cpp @@ -2,5 +2,4 @@ null_Model::null_Model() { - } diff --git a/Src/PluginContext.cpp b/Src/PluginContext.cpp index 3501bae..7ce0a5c 100644 --- a/Src/PluginContext.cpp +++ b/Src/PluginContext.cpp @@ -3,35 +3,39 @@ #include "Controller/ControllerTrackingAlgorithm.h" #include "Controller/ControllerTrackedComponent.h" -PluginContext::PluginContext(QObject *parent, Config *cfg) : - IBioTrackerContext(parent) +PluginContext::PluginContext(QObject* parent, Config* cfg) +: IBioTrackerContext(parent) { - _cfg = cfg; - ControllerTrackedComponent* ComponentController = new ControllerTrackedComponent(this, this, ENUMS::CONTROLLERTYPE::COMPONENT); - ControllerTrackingAlgorithm* TrackingController = new ControllerTrackingAlgorithm(this, this, ENUMS::CONTROLLERTYPE::TRACKING); - ComponentController->setConfig(_cfg); - TrackingController->setConfig(_cfg); + _cfg = cfg; + ControllerTrackedComponent* ComponentController = + new ControllerTrackedComponent(this, + this, + ENUMS::CONTROLLERTYPE::COMPONENT); + ControllerTrackingAlgorithm* TrackingController = + new ControllerTrackingAlgorithm(this, + this, + ENUMS::CONTROLLERTYPE::TRACKING); + ComponentController->setConfig(_cfg); + TrackingController->setConfig(_cfg); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMPONENT, ComponentController); - m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKING, TrackingController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::COMPONENT, + ComponentController); + m_ControllersMap.insert(ENUMS::CONTROLLERTYPE::TRACKING, + TrackingController); } void PluginContext::createAppController() { - QMap::iterator i; - for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) - { - i.value()->createComponents(); - } + 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(); - } + QMap::iterator i; + for (i = m_ControllersMap.begin(); i != m_ControllersMap.end(); ++i) { + i.value()->connectComponents(); + } } - - diff --git a/Src/PluginContext.h b/Src/PluginContext.h index 403ff4d..395728e 100644 --- a/Src/PluginContext.h +++ b/Src/PluginContext.h @@ -5,17 +5,16 @@ class PluginContext : public IBioTrackerContext { - Q_OBJECT + Q_OBJECT public: - PluginContext(QObject *parent, Config *cfg); + PluginContext(QObject* parent, Config* cfg); - // IBioTrackerContext interface + // IBioTrackerContext interface protected: - void createAppController() override; - void connectController() override; + void createAppController() override; + void connectController() override; private: - Config *_cfg; + Config* _cfg; }; - diff --git a/Src/View/TrackedElementView.cpp b/Src/View/TrackedElementView.cpp index 8b29f6a..c203911 100644 --- a/Src/View/TrackedElementView.cpp +++ b/Src/View/TrackedElementView.cpp @@ -10,14 +10,17 @@ class QGraphicsSceneHoverEvent; -TrackedElementView::TrackedElementView(QGraphicsItem *parent, IController *controller, IModel *model) : - IViewTrackedComponent(parent, controller, model) +TrackedElementView::TrackedElementView(QGraphicsItem* parent, + IController* controller, + IModel* model) +: IViewTrackedComponent(parent, controller, model) { - BST::TrackedElement *elem = dynamic_cast(getModel()); - _boundingRect = QRectF(0,0, 100, 100); + BST::TrackedElement* elem = dynamic_cast(getModel()); + _boundingRect = QRectF(0, 0, 100, 100); } -void TrackedElementView::rcvDimensionUpdate(int x, int y) { +void TrackedElementView::rcvDimensionUpdate(int x, int y) +{ _boundingRect = QRectF(0, 0, x, y); update(); } @@ -28,17 +31,17 @@ QRectF TrackedElementView::boundingRect() const return _boundingRect; } - -void TrackedElementView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +void TrackedElementView::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) { - QGraphicsScene *scene = this->scene(); + QGraphicsScene* scene = this->scene(); - //Dev note: You could do some meaningful drawing here. - //So far, the core does everything we need. + // Dev note: You could do some meaningful drawing here. + // So far, the core does everything we need. } void TrackedElementView::getNotified() { update(); } - diff --git a/Src/View/TrackedElementView.h b/Src/View/TrackedElementView.h index 420fd76..1eddf32 100644 --- a/Src/View/TrackedElementView.h +++ b/Src/View/TrackedElementView.h @@ -5,30 +5,34 @@ /** * This class is an example of how a TrackedElementView could be visualized. - * This class inherits from the IViewTrackedComponent class and is therefor part of the Composite Pattern. + * This class inherits from the IViewTrackedComponent class and is therefor + * part of the Composite Pattern. */ class TrackedElementView : public IViewTrackedComponent { Q_OBJECT public: - TrackedElementView(QGraphicsItem *parent = 0, IController *controller = 0, IModel *model = 0); + TrackedElementView(QGraphicsItem* parent = 0, + IController* controller = 0, + IModel* model = 0); // QGraphicsItem interface public: QRectF boundingRect() const override; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; // IViewTrackedComponent interface public Q_SLOTS: - void getNotified() override; - void rcvDimensionUpdate(int x, int y); + void getNotified() override; + void rcvDimensionUpdate(int x, int y); -public Q_SIGNAL: - void emitUpdateCornersChanged(int id, int relX, int relY); +public + Q_SIGNAL : void emitUpdateCornersChanged(int id, int relX, int relY); private: QRectF _boundingRect; - }; #endif // TRACKEDELEMENTVIEW_H diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 5f21a2f..8099a85 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -3,111 +3,167 @@ #include -TrackerParameterView::TrackerParameterView(QWidget *parent, IController *controller, IModel *model) : IViewWidget(parent, controller, model), - _ui(new Ui::TrackerParameterView), - _useAbsDiff(nullptr), - _binThres(nullptr) +TrackerParameterView::TrackerParameterView(QWidget* parent, + IController* controller, + IModel* model) +: IViewWidget(parent, controller, model) +, _ui(new Ui::TrackerParameterView) +, _useAbsDiff(nullptr) +, _binThres(nullptr) { - _ui->setupUi(this); - getNotified(); - - auto parameter = qobject_cast(getModel()); - - connect(_ui->algorithmCB, &QComboBox::currentTextChanged, parameter, &TrackerParameter::setAlgorithm); - connect(_ui->algorithmCB, &QComboBox::currentTextChanged, this, &TrackerParameterView::initSubtractorSpecificUI); - - connect(_ui->lineEdit_3_SizeErode, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeErode); - connect(_ui->lineEdit_3_SizeErode, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_4_SizeDilate, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setSizeDilate); - connect(_ui->lineEdit_4_SizeDilate, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_8_MinBlob, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMinBlobSize); - connect(_ui->lineEdit_8_MinBlob, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setMaxBlobSize); - connect(_ui->lineEdit_9MaxBlob, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), parameter, &TrackerParameter::setLearningRate); - connect(_ui->lineEdit_7_learningRate, qOverload(&QDoubleSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - - initSubtractorSpecificUI(_ui->algorithmCB->currentText()); - - _ui->algorithmCB->setEnabled(false); + _ui->setupUi(this); + getNotified(); + + auto parameter = qobject_cast(getModel()); + + connect(_ui->algorithmCB, + &QComboBox::currentTextChanged, + parameter, + &TrackerParameter::setAlgorithm); + connect(_ui->algorithmCB, + &QComboBox::currentTextChanged, + this, + &TrackerParameterView::initSubtractorSpecificUI); + + connect(_ui->lineEdit_3_SizeErode, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setSizeErode); + connect(_ui->lineEdit_3_SizeErode, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_4_SizeDilate, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setSizeDilate); + connect(_ui->lineEdit_4_SizeDilate, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_8_MinBlob, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMinBlobSize); + connect(_ui->lineEdit_8_MinBlob, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_9MaxBlob, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMaxBlobSize); + connect(_ui->lineEdit_9MaxBlob, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_7_learningRate, + qOverload(&QDoubleSpinBox::valueChanged), + parameter, + &TrackerParameter::setLearningRate); + connect(_ui->lineEdit_7_learningRate, + qOverload(&QDoubleSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + initSubtractorSpecificUI(_ui->algorithmCB->currentText()); + + _ui->algorithmCB->setEnabled(false); } TrackerParameterView::~TrackerParameterView() { - delete _ui; + delete _ui; } void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) { - auto parameter = qobject_cast(getModel()); - - while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { - _ui->algorithmSpecificParameterLayout->removeRow(0); - } - - _useAbsDiff = nullptr; - _binThres = nullptr; - - if (algorithm == QString("Custom")) { - _useAbsDiff = new QCheckBox(); - _useAbsDiff->setText(" "); - _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); - _ui->algorithmSpecificParameterLayout->addRow(tr("Use Absolute Difference:"), _useAbsDiff); - - connect(_useAbsDiff, &QCheckBox::toggled, parameter, &TrackerParameter::setUseAbsoluteDifference); - connect(_useAbsDiff, &QCheckBox::toggled, this, &TrackerParameterView::parametersChanged); - - _binThres = new QSpinBox(); - _binThres->setMinimum(1); - _binThres->setMaximum(255); - _binThres->setValue(parameter->getBinarizationThreshold()); - _ui->algorithmSpecificParameterLayout->addRow(tr("Binarization Threshold:"), _binThres); - - connect(_binThres, qOverload(&QSpinBox::valueChanged), parameter, &TrackerParameter::setBinarizationThreshold); - connect(_binThres, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - emit parametersChanged(); + auto parameter = qobject_cast(getModel()); + + while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { + _ui->algorithmSpecificParameterLayout->removeRow(0); + } + + _useAbsDiff = nullptr; + _binThres = nullptr; + + if (algorithm == QString("Custom")) { + _useAbsDiff = new QCheckBox(); + _useAbsDiff->setText(" "); + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Use Absolute Difference:"), + _useAbsDiff); + + connect(_useAbsDiff, + &QCheckBox::toggled, + parameter, + &TrackerParameter::setUseAbsoluteDifference); + connect(_useAbsDiff, + &QCheckBox::toggled, + this, + &TrackerParameterView::parametersChanged); + + _binThres = new QSpinBox(); + _binThres->setMinimum(1); + _binThres->setMaximum(255); + _binThres->setValue(parameter->getBinarizationThreshold()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Binarization Threshold:"), + _binThres); + + connect(_binThres, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setBinarizationThreshold); + connect(_binThres, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + emit parametersChanged(); } void TrackerParameterView::on_pushButtonResetBackground_clicked() { - TrackerParameter *parameter = qobject_cast(getModel()); - parameter->setResetBackground(true); + 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()); + TrackerParameter* parameter = qobject_cast(getModel()); + parameter->setSendImage(v); + parameter->setNewSelection( + _ui->comboBoxSendImage->currentText().toStdString()); } void TrackerParameterView::getNotified() { - TrackerParameter *parameter = qobject_cast(getModel()); + TrackerParameter* parameter = qobject_cast(getModel()); - _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); + _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); - if (_useAbsDiff) { - _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); - } + if (_useAbsDiff) { + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + } - if (_binThres) { - _binThres->setValue(parameter->getBinarizationThreshold()); - } + if (_binThres) { + _binThres->setValue(parameter->getBinarizationThreshold()); + } - _ui->lineEdit_3_SizeErode->setValue(parameter->getSizeErode()); + _ui->lineEdit_3_SizeErode->setValue(parameter->getSizeErode()); - _ui->lineEdit_4_SizeDilate->setValue(parameter->getSizeDilate()); + _ui->lineEdit_4_SizeDilate->setValue(parameter->getSizeDilate()); - _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); + _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); - _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); + _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); } diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index 172a0e9..ad1c99f 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -7,8 +7,9 @@ #include #include -namespace Ui { - class TrackerParameterView; +namespace Ui +{ + class TrackerParameterView; } class TrackerParameterView : public IViewWidget @@ -16,21 +17,22 @@ class TrackerParameterView : public IViewWidget Q_OBJECT public: - explicit TrackerParameterView(QWidget *parent = 0, IController *controller = 0, IModel *model = 0); + explicit TrackerParameterView(QWidget* parent = 0, + IController* controller = 0, + IModel* model = 0); ~TrackerParameterView(); private slots: - void on_pushButtonResetBackground_clicked(); - void on_comboBoxSendImage_currentIndexChanged(int v); + void on_pushButtonResetBackground_clicked(); + void on_comboBoxSendImage_currentIndexChanged(int v); - public: - signals: +signals: void trackingAreaType(int v); void parametersChanged(); private: - Ui::TrackerParameterView *_ui; + Ui::TrackerParameterView* _ui; QCheckBox* _useAbsDiff; diff --git a/Src/helper/CvHelper.cpp b/Src/helper/CvHelper.cpp index 5cf0a91..38a255b 100644 --- a/Src/helper/CvHelper.cpp +++ b/Src/helper/CvHelper.cpp @@ -4,150 +4,177 @@ cv::Point CvHelper::subtractTwoCvPoints(cv::Point a, cv::Point b) { - return cv::Point(a.x - b.x, a.y - b.y); + return cv::Point(a.x - b.x, a.y - b.y); } cv::Point CvHelper::addTwoCvPoints(cv::Point a, cv::Point b) { - return cv::Point(a.x + b.x, a.y + b.y); + return cv::Point(a.x + b.x, a.y + b.y); } cv::Point CvHelper::multCvPoint(double scalar, cv::Point p) { - return cv::Point(scalar * p.x, scalar * p.y); + return cv::Point(scalar * p.x, scalar * p.y); } QPointF CvHelper::norm(double x, double y) { - double distance = qSqrt(x * x + y * y); + double distance = qSqrt(x * x + y * y); - if (distance == 0) { - return QPointF(0, 0); - } - return QPointF(x / distance, y / distance); + if (distance == 0) { + return QPointF(0, 0); + } + return QPointF(x / distance, y / distance); } QPointF CvHelper::norm(QPoint p) { - return CvHelper::norm((double) p.x(), (double) p.y()); + return CvHelper::norm((double) p.x(), (double) p.y()); } QPointF CvHelper::norm(QPointF p) { - return CvHelper::norm(p.x(), p.y()); + return CvHelper::norm(p.x(), p.y()); } double CvHelper::getDistance(double x1, double y1, double x2, double y2) { - return qSqrt( ( (x1 - x2) * (x1 - x2) ) + ( (y1 - y2) * (y1 - y2) ) ); + return qSqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2))); } -double CvHelper::getDistance(double x1, double y1, double z1, double x2, double y2, double z2 ) +double CvHelper::getDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2) { - return qSqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + ((z1 - z2) * (z1 - z2))); + return qSqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + + ((z1 - z2) * (z1 - z2))); } double CvHelper::getSqDistance(double x1, double y1, double x2, double y2) { - return ( (x1 - x2) * (x1 - x2) ) + ( (y1 - y2) * (y1 - y2) ); + return ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)); } -double CvHelper::getSqDistance(double x1, double y1, double z1, double x2, double y2, double z2) +double CvHelper::getSqDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2) { - return ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + ((z1 - z2) * (z1 - z2)); + return ((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)) + + ((z1 - z2) * (z1 - z2)); } double CvHelper::getDistance(QPoint p1, QPoint p2) { - return getDistance((double) p1.x(), (double) p1.y(), (double) p2.x(), (double) p2.y()); + return getDistance((double) p1.x(), + (double) p1.y(), + (double) p2.x(), + (double) p2.y()); } double CvHelper::getDistance(QPointF p1, QPointF p2) { - return getDistance(p1.x(), p1.y(), p2.x(), p2.y()); + return getDistance(p1.x(), p1.y(), p2.x(), p2.y()); } double CvHelper::getDistance(cv::Point2f p1, cv::Point2f p2) { - return getDistance(p1.x, p1.y, p2.x, p2.y); + return getDistance(p1.x, p1.y, p2.x, p2.y); } double CvHelper::getDistance(cv::Point3f p1, cv::Point3f p2) { - return getDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); + return getDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); } double CvHelper::getDistance(cv::Point p1, cv::Point p2) { - return sqrt(double((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))); + return sqrt( + double((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))); } double CvHelper::getSqDistance(cv::Point2f p1, cv::Point2f p2) { - return getSqDistance(p1.x, p1.y, p2.x, p2.y); + return getSqDistance(p1.x, p1.y, p2.x, p2.y); } double CvHelper::getSqDistance(cv::Point3f p1, cv::Point3f p2) { - return getSqDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); + return getSqDistance(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z); } double CvHelper::orientation(cv::Point2f front, cv::Point2f back) { - cv::Point2f diff = front - back; - //return qAtan2(diff.x, diff.y); + cv::Point2f diff = front - back; + // return qAtan2(diff.x, diff.y); - // need to check the origin of coorindiates - return qAtan2(diff.x, diff.y) + CV_PI / 2.0; + // need to check the origin of coorindiates + return qAtan2(diff.x, diff.y) + CV_PI / 2.0; } double CvHelper::orientation(QPointF front, QPointF back) { - //QPointF diff = front - back; - //return qAtan2(diff.x(), diff.y()); - return orientation(cv::Point2f(front.x(),front.y()),cv::Point2f(back.x(),back.y())); + // QPointF diff = front - back; + // return qAtan2(diff.x(), diff.y()); + return orientation(cv::Point2f(front.x(), front.y()), + cv::Point2f(back.x(), back.y())); } float CvHelper::angleDifference(float alpha, float beta) { - float difference = alpha - beta; - while (difference < -CV_PI) difference += 2.0f * CV_PI; - while (difference > +CV_PI) difference -= 2.0f * CV_PI; - return difference; + float difference = alpha - beta; + while (difference < -CV_PI) + difference += 2.0f * CV_PI; + while (difference > +CV_PI) + difference -= 2.0f * CV_PI; + return difference; } -float CvHelper::findMin(float n1, float n2, float n3) { - return (n1 < n2 && n1 < n3) ? n1 : (n2 < n3 ? n2 : n3); +float CvHelper::findMin(float n1, float n2, float n3) +{ + return (n1 < n2 && n1 < n3) ? n1 : (n2 < n3 ? n2 : n3); } -float CvHelper::findMax(float n1, float n2, float n3) { - return (n1 > n2 && n1 > n3) ? n1 : (n2 > n3 ? n2 : n3); +float CvHelper::findMax(float n1, float n2, float n3) +{ + return (n1 > n2 && n1 > n3) ? n1 : (n2 > n3 ? n2 : n3); } -float CvHelper::normalDist(float x, float mean, float variance) { - return 1.0 / (variance *qSqrt(2*CV_PI)) * qExp(- ((x - mean) * (x - mean)) / (2 * variance * variance)); +float CvHelper::normalDist(float x, float mean, float variance) +{ + return 1.0 / (variance * qSqrt(2 * CV_PI)) * + qExp(-((x - mean) * (x - mean)) / (2 * variance * variance)); } -float CvHelper::sigmoid(float x, float shrink) { - return (2.0 / (1.0 + qExp(-x * shrink)) - 1.0); +float CvHelper::sigmoid(float x, float shrink) +{ + return (2.0 / (1.0 + qExp(-x * shrink)) - 1.0); } -float CvHelper::sigmoidAbsInv(float x, float shrink) { - return 1.0 - qAbs((2.0 / (1.0 + qExp(-x * shrink)) - 1.0)); +float CvHelper::sigmoidAbsInv(float x, float shrink) +{ + return 1.0 - qAbs((2.0 / (1.0 + qExp(-x * shrink)) - 1.0)); } -double CvHelper::getAngleDifference(double dirToTargetAsRad, double currOrientationAsRad) { - /*double angleDiff = dirToTargetAsRad - currOrientationAsRad + CV_PI / 2.0; - while (angleDiff < -CV_PI) angleDiff += 2 * CV_PI; - while (angleDiff > CV_PI) angleDiff -= 2 * CV_PI; - return angleDiff;*/ +double CvHelper::getAngleDifference(double dirToTargetAsRad, + double currOrientationAsRad) +{ + /*double angleDiff = dirToTargetAsRad - currOrientationAsRad + CV_PI / 2.0; + while (angleDiff < -CV_PI) angleDiff += 2 * CV_PI; + while (angleDiff > CV_PI) angleDiff -= 2 * CV_PI; + return angleDiff;*/ - double a = dirToTargetAsRad - currOrientationAsRad; - a += (a > CV_PI) ? -(2*CV_PI) : (a < -CV_PI) ? (2*CV_PI) : 0; - return a; + double a = dirToTargetAsRad - currOrientationAsRad; + a += (a > CV_PI) ? -(2 * CV_PI) : (a < -CV_PI) ? (2 * CV_PI) : 0; + return a; } -//double CvHelper::getAngleToTarget(cv::Point2f A, cv::Point2f B) { +// double CvHelper::getAngleToTarget(cv::Point2f A, cv::Point2f B) { // double ab = A.x*B.x + A.y*B.y; // double a = qSqrt(A.x*A.x + A.y*A.y); // double b = qSqrt(B.x*B.x + B.y*B.y); @@ -155,251 +182,275 @@ double CvHelper::getAngleDifference(double dirToTargetAsRad, double currOrientat // return qAcos(cosT); //} -double CvHelper::getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos) { - return qAtan2(targetPos.x - currentPos.x, targetPos.y - currentPos.y); +double CvHelper::getAngleToTarget(cv::Point2f currentPos, + cv::Point2f targetPos) +{ + return qAtan2(targetPos.x - currentPos.x, targetPos.y - currentPos.y); } std::deque CvHelper::convertMat2Point2fDeque(cv::Mat mat) { - std::deque point2fS; + std::deque point2fS; - if(mat.cols != 2) - return point2fS; + if (mat.cols != 2) + return point2fS; - for (int row = 0; row < mat.rows; row++) - { - float x = mat.at(row,0); - float y = mat.at(row,1); - point2fS.push_back(cv::Point2f(x,y)); - } + 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; + return point2fS; } cv::Mat CvHelper::convertPoint2fDeque2Mat(std::deque points) { - cv::Mat mat; + cv::Mat mat; - if(points.empty()) - return mat; + if (points.empty()) + return mat; - mat = cv::Mat(points.size(), 2, CV_32F); + mat = cv::Mat(points.size(), 2, CV_32F); - for (int i = 0; i < points.size(); i++) - { - cv::Point2f p = points.at(i); - mat.at(i,0)= p.x; - mat.at(i,1)= p.y; - } - - return mat; + 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> CvHelper::convertMatList2Point2fDequeList( + QList mats) { - QList> pointList; - cv::Mat mat; - foreach (mat , mats) - { - pointList << CvHelper::convertMat2Point2fDeque(mat); - } - return pointList; + 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::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 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 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 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 point2MirrorFromOrigin = point2MirrorMat - pointOfOriginMat; - cv::Mat point2MirrorMatT; + cv::Mat point2MirrorMatT; cv::transpose(point2MirrorFromOrigin, point2MirrorMatT); - cv::Mat mirrowedPointMat = (G * point2MirrorMatT); + cv::Mat mirrowedPointMat = (G * point2MirrorMatT); - cv::Mat mirrowedPointMatT; - cv::transpose(mirrowedPointMat, mirrowedPointMatT); + cv::Mat mirrowedPointMatT; + cv::transpose(mirrowedPointMat, mirrowedPointMatT); - cv::Mat finalMat = mirrowedPointMatT + pointOfOriginMat; + cv::Mat finalMat = mirrowedPointMatT + pointOfOriginMat; - return cv::Point2f(finalMat.at(0,0),finalMat.at(0,1)); + 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 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 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; +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 r = CvHelper::getDistance(pointOfOrigin, cv::Point2f(width, height)); - float xOff1 = pointOfOrigin.x + r * cos(angle); - float yOff1 = pointOfOrigin.y + r * sin(angle); + float xOff1 = pointOfOrigin.x + r * cos(angle); + float yOff1 = pointOfOrigin.y + r * sin(angle); - float xOff2 = pointOfOrigin.x - r * cos(angle); - float yOff2 = pointOfOrigin.y - r * sin(angle); + float xOff2 = pointOfOrigin.x - r * cos(angle); + float yOff2 = pointOfOrigin.y - r * sin(angle); - cv::Point2f front(xOff2,yOff2); - cv::Point2f back(xOff1,yOff1); + cv::Point2f front(xOff2, yOff2); + cv::Point2f back(xOff1, yOff1); - std::deque points; + std::deque points; - points.push_back(front); - points.push_back(back); - return 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; + 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; + 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; + return deg * CV_PI / 180.0; } float CvHelper::radToDeg(float rad) { - return rad * 180.0 / CV_PI; + return rad * 180.0 / CV_PI; } int CvHelper::stdStringToInt(std::string string) { - int numb; - std::istringstream iss(string); - if (!(iss >> numb)) - { - throw "String cannot convert to float number!"; - } - return numb; + int numb; + std::istringstream iss(string); + if (!(iss >> numb)) { + throw "String cannot convert to float number!"; + } + return numb; } float CvHelper::stdStringToFloat(std::string string) { - float numb; - std::istringstream iss(string); - if (!(iss >> numb)) - { - throw "String cannot convert to float number!"; - } - - return numb; + float numb; + std::istringstream iss(string); + if (!(iss >> numb)) { + throw "String cannot convert to float number!"; + } + + return numb; } -std::string CvHelper::convertStdVectorCvPointToStdString(std::vector points) +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 pointListString; + for (int i = 0; i < points.size(); i++) { + int x = points.at(i).x; + int y = points.at(i).y; + if (i < points.size() - 1) + pointListString.append(StringHelper::iToSS(x)) + .append(":") + .append(StringHelper::iToSS(y)) + .append(" "); + else + pointListString.append(StringHelper::iToSS(x)) + .append(":") + .append(StringHelper::iToSS(y)); + } + return pointListString; } std::string CvHelper::convertCvScalarToStdString(cv::Scalar scalar) { - std::string scalarString; - - int r = scalar.val[0,0]; - int g = scalar.val[0,1]; - int b = scalar.val[0,2]; + std::string scalarString; - scalarString.append(StringHelper::iToSS(r)).append(" ").append(StringHelper::iToSS(g)).append(" ").append(StringHelper::iToSS(b)).append(" "); + int r = scalar.val[0, 0]; + int g = scalar.val[0, 1]; + int b = scalar.val[0, 2]; - return scalarString; + scalarString.append(StringHelper::iToSS(r)) + .append(" ") + .append(StringHelper::iToSS(g)) + .append(" ") + .append(StringHelper::iToSS(b)) + .append(" "); + return scalarString; } std::string CvHelper::cvSizeToSS(cv::Size cvSize_value) { - std::string cvSizeString; + std::string cvSizeString; - int width = cvSize_value.width; - int height = cvSize_value.height; + int width = cvSize_value.width; + int height = cvSize_value.height; - cvSizeString.append(StringHelper::iToSS(height)).append("x").append(StringHelper::iToSS(width)); + cvSizeString.append(StringHelper::iToSS(height)) + .append("x") + .append(StringHelper::iToSS(width)); - return cvSizeString; + return cvSizeString; } std::string CvHelper::cvSize2fToSS(cv::Size2f cvSize2f_value) { - std::string cvSize2fString; + std::string cvSize2fString; - float width = cvSize2f_value.width; - float height = cvSize2f_value.height; + float width = cvSize2f_value.width; + float height = cvSize2f_value.height; - cvSize2fString.append(StringHelper::fToSS(height)).append("x").append(StringHelper::fToSS(width)); + cvSize2fString.append(StringHelper::fToSS(height)) + .append("x") + .append(StringHelper::fToSS(width)); - return cvSize2fString; + return cvSize2fString; } std::string CvHelper::cvSize2fToSS(QString width, QString height) { - std::string cvSize2fString; + std::string cvSize2fString; - cvSize2fString.append(height.toStdString()).append("x").append(width.toStdString()); + cvSize2fString.append(height.toStdString()) + .append("x") + .append(width.toStdString()); - return cvSize2fString; + return cvSize2fString; } std::string CvHelper::getCurrentDatetimeAsStd() { - return QDateTime::currentDateTime().toString("_yyMMddThhmmss").toUtf8().constData(); + return QDateTime::currentDateTime() + .toString("_yyMMddThhmmss") + .toUtf8() + .constData(); } bool CvHelper::isFrameSizeEqual(cv::Size o1, cv::Size o2) { - bool equal = false; + bool equal = false; - if (o1.width == o2.width && o1.height == o2.height) - equal = true; + if (o1.width == o2.width && o1.height == o2.height) + equal = true; - return equal; + return equal; } \ No newline at end of file diff --git a/Src/helper/CvHelper.h b/Src/helper/CvHelper.h index 2c842df..b64dff9 100644 --- a/Src/helper/CvHelper.h +++ b/Src/helper/CvHelper.h @@ -9,189 +9,211 @@ #include - /** * Computer vision helper class, contains only static methods */ namespace CvHelper { - /** - * Subtract operation for two CvPoints. - * @return: the difference of the CvPoints. - */ - cv::Point subtractTwoCvPoints(cv::Point a, cv::Point b); - - /** - * Add operation for two CvPoints. - * @return: the sum of the CvPoints. - */ - cv::Point addTwoCvPoints(cv::Point a, cv::Point b); - - cv::Point multCvPoint(double scalar, cv::Point p); - - /** - * Normalizes a coordinate point. - * @param x, the x coordinate. - * @param y, the y coordinate. - * @return the normlized point as floating number. - */ - QPointF norm(double x, double y); - - /** - * Normalizes a point. - * @param p, point to normalize. - * @return the normalized point as floating number. - */ - QPointF norm(QPoint p); - - /** - * Normalizes a floating number point. - * @param p, point to normalize. - * @return the normalized point as floating number. - */ - QPointF norm(QPointF p); - - /** - * Calculates the distance between two coordinates. - * @param x1, x-coordinate of the source point. - * @param y1, y-coordinate of the source point. - * @param x2, x-coordinate of the destination point. - * @param y2, y-coordinate of the destination point. - * @return the distance between the provided coordinates as floating number. - */ - double getDistance(double x1, double y1, double x2, double y2); - double getSqDistance(double x1, double y1, double x2, double y2); - - /** - * Calculates the distance between two coordinates. - * @param x1, x-coordinate of the source point. - * @param y1, y-coordinate of the source point. - * @param z1, z-coordinate of the source point. - * @param x2, x-coordinate of the destination point. - * @param y2, y-coordinate of the destination point. - * @param z2, y-coordinate of the destination point. - * @return the distance between the provided coordinates as floating number. - */ - double getDistance(double x1, double y1, double z1, double x2, double y2, double z2); - double getSqDistance(double x1, double y1, double z1, double x2, double y2, double z2); - - /** - * Calculates the distance between two points. - * @param p1, source point. - * @param p2, destination point. - * @return the distance between p1 and p2 as floating number. - */ - double getDistance(QPoint p1, QPoint p2); - - /** - * Calculates the distance between two floating number points. - * @param p1, source point. - * @param p2, destination point. - * @return the distance between p1 and p2 as floating number. - */ - double getDistance(QPointF p1, QPointF p2); - - double getDistance(cv::Point2f p1, cv::Point2f p2); - double getDistance(cv::Point p1, cv::Point p2); - double getSqDistance(cv::Point2f p1, cv::Point2f p2); - - double getDistance(cv::Point3f p1, cv::Point3f p2); - double getSqDistance(cv::Point3f p1, cv::Point3f p2); - - double orientation(cv::Point2f front, cv::Point2f back); - double orientation(QPointF front, QPointF back); - - float angleDifference(float alpha, float beta); - - /** - * Convert degree to radian. - * @param: deg, degree value, - * @return: rad value. - */ - float degToRad(float deg); - - /** - * Convert radian to degree. - * @param: rad, radian value, - * @return: degree value. - */ - float radToDeg(float rad); - - /** - * This function finds the minimal number of three numbers. - */ - float findMin(float n1, float n2, float n3); - - /** - * This function finds the maximal number of three numbers. - */ - float findMax(float n1, float n2, float n3); - - float normalDist(float x, float mean, float variance); - - float sigmoid(float x, float shrink); - - float sigmoidAbsInv(float x, float shrink); - - double getAngleDifference(double dirToTargetAsRad, double currOrientationAsRad); - double getAngleToTarget(cv::Point2f A, cv::Point2f B); - //double getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos); - - cv::Point2f getMirrowPoint(cv::Point2f point2Mirror, cv::Point2f pointOfOrigin, float angelAsGrad); - std::deque 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); + /** + * Subtract operation for two CvPoints. + * @return: the difference of the CvPoints. + */ + cv::Point subtractTwoCvPoints(cv::Point a, cv::Point b); + + /** + * Add operation for two CvPoints. + * @return: the sum of the CvPoints. + */ + cv::Point addTwoCvPoints(cv::Point a, cv::Point b); + + cv::Point multCvPoint(double scalar, cv::Point p); + + /** + * Normalizes a coordinate point. + * @param x, the x coordinate. + * @param y, the y coordinate. + * @return the normlized point as floating number. + */ + QPointF norm(double x, double y); + + /** + * Normalizes a point. + * @param p, point to normalize. + * @return the normalized point as floating number. + */ + QPointF norm(QPoint p); + + /** + * Normalizes a floating number point. + * @param p, point to normalize. + * @return the normalized point as floating number. + */ + QPointF norm(QPointF p); + + /** + * Calculates the distance between two coordinates. + * @param x1, x-coordinate of the source point. + * @param y1, y-coordinate of the source point. + * @param x2, x-coordinate of the destination point. + * @param y2, y-coordinate of the destination point. + * @return the distance between the provided coordinates as floating + * number. + */ + double getDistance(double x1, double y1, double x2, double y2); + double getSqDistance(double x1, double y1, double x2, double y2); + + /** + * Calculates the distance between two coordinates. + * @param x1, x-coordinate of the source point. + * @param y1, y-coordinate of the source point. + * @param z1, z-coordinate of the source point. + * @param x2, x-coordinate of the destination point. + * @param y2, y-coordinate of the destination point. + * @param z2, y-coordinate of the destination point. + * @return the distance between the provided coordinates as floating + * number. + */ + double getDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2); + double getSqDistance(double x1, + double y1, + double z1, + double x2, + double y2, + double z2); + + /** + * Calculates the distance between two points. + * @param p1, source point. + * @param p2, destination point. + * @return the distance between p1 and p2 as floating number. + */ + double getDistance(QPoint p1, QPoint p2); + + /** + * Calculates the distance between two floating number points. + * @param p1, source point. + * @param p2, destination point. + * @return the distance between p1 and p2 as floating number. + */ + double getDistance(QPointF p1, QPointF p2); + + double getDistance(cv::Point2f p1, cv::Point2f p2); + double getDistance(cv::Point p1, cv::Point p2); + double getSqDistance(cv::Point2f p1, cv::Point2f p2); + + double getDistance(cv::Point3f p1, cv::Point3f p2); + double getSqDistance(cv::Point3f p1, cv::Point3f p2); + + double orientation(cv::Point2f front, cv::Point2f back); + double orientation(QPointF front, QPointF back); + + float angleDifference(float alpha, float beta); + + /** + * Convert degree to radian. + * @param: deg, degree value, + * @return: rad value. + */ + float degToRad(float deg); + + /** + * Convert radian to degree. + * @param: rad, radian value, + * @return: degree value. + */ + float radToDeg(float rad); + + /** + * This function finds the minimal number of three numbers. + */ + float findMin(float n1, float n2, float n3); + + /** + * This function finds the maximal number of three numbers. + */ + float findMax(float n1, float n2, float n3); + + float normalDist(float x, float mean, float variance); + + float sigmoid(float x, float shrink); + + float sigmoidAbsInv(float x, float shrink); + + double getAngleDifference(double dirToTargetAsRad, + double currOrientationAsRad); + double getAngleToTarget(cv::Point2f A, cv::Point2f B); + // double getAngleToTarget(cv::Point2f currentPos, cv::Point2f targetPos); + + cv::Point2f getMirrowPoint(cv::Point2f point2Mirror, + cv::Point2f pointOfOrigin, + float angelAsGrad); + std::deque 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/Src/helper/StringHelper.cpp b/Src/helper/StringHelper.cpp index 4f4b3f8..e3543b6 100644 --- a/Src/helper/StringHelper.cpp +++ b/Src/helper/StringHelper.cpp @@ -3,103 +3,103 @@ #include #include - -bool StringHelper::hasEnding(std::string const &fullString, std::string const &ending) +bool StringHelper::hasEnding(std::string const& fullString, + std::string const& ending) { - if (fullString.length() >= ending.length()) - return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); - else - return false; + if (fullString.length() >= ending.length()) + return (0 == fullString.compare(fullString.length() - ending.length(), + ending.length(), + ending)); + else + return false; } - -bool StringHelper::startsWithDigit(std::string const &fullString) +bool StringHelper::startsWithDigit(std::string const& fullString) { - if(fullString.empty()) - return false; - + if (fullString.empty()) + return false; - if(isdigit(fullString.at(0))) - { - return true; - } - - return false; + if (isdigit(fullString.at(0))) { + return true; + } + return false; } bool StringHelper::startsWithDigitQ(QString fullString) { - return StringHelper::startsWithDigit(fullString.toLocal8Bit().data()); + return StringHelper::startsWithDigit(fullString.toLocal8Bit().data()); } bool StringHelper::isNumber(QString fullStringQ) -{ - std::string fullString = fullStringQ.toLocal8Bit().data(); - - for(int i = 0; i < fullString.length(); i++) - { - if(isdigit(fullString.at(i))) - { - return true; - } +{ + std::string fullString = fullStringQ.toLocal8Bit().data(); - } + for (int i = 0; i < fullString.length(); i++) { + if (isdigit(fullString.at(i))) { + return true; + } + } - return false; + return false; } std::string StringHelper::iToSS(int int_num) { - return QString::number(int_num).toUtf8().constData(); + return QString::number(int_num).toUtf8().constData(); } std::string StringHelper::boolToSS(bool bool_value) { - if(bool_value) - return std::string("true"); - return std::string("false"); + if (bool_value) + return std::string("true"); + return std::string("false"); } std::string StringHelper::fToSS(float float_num) { - return QString::number(float_num).toUtf8().constData(); + return QString::number(float_num).toUtf8().constData(); } - std::string StringHelper::toStdString(QString qString) { - return qString.toUtf8().constData(); + return qString.toUtf8().constData(); } QString StringHelper::toQString(std::string stdString) { - return QString::fromUtf8(stdString.c_str()); + return QString::fromUtf8(stdString.c_str()); } std::string StringHelper::toLowerCase(std::string stringValue) { - std::string lowCaseString(stringValue); - std::transform(lowCaseString.begin(), lowCaseString.end(), lowCaseString.begin(), tolower); - return lowCaseString; + std::string lowCaseString(stringValue); + std::transform(lowCaseString.begin(), + lowCaseString.end(), + lowCaseString.begin(), + tolower); + return lowCaseString; } -int StringHelper::split(std::string &txt, std::vector &strs, char ch) +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; + std::string::size_type pos = txt.find(ch); + std::string::size_type initialPos = 0; strs.clear(); // Decompose statement - while( pos != std::string::npos ) { - strs.push_back( txt.substr( initialPos, pos - initialPos ) ); + while (pos != std::string::npos) { + strs.push_back(txt.substr(initialPos, pos - initialPos)); initialPos = pos + 1; - pos = txt.find( ch, initialPos ); + pos = txt.find(ch, initialPos); } // Add the last one - strs.push_back(txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1)); + strs.push_back( + txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1)); return strs.size(); } \ No newline at end of file diff --git a/Src/helper/StringHelper.h b/Src/helper/StringHelper.h index 10f05d6..1d820d3 100644 --- a/Src/helper/StringHelper.h +++ b/Src/helper/StringHelper.h @@ -10,71 +10,80 @@ class StringHelper { public: - StringHelper(void) {} - ~StringHelper(void) {} + StringHelper(void) + { + } + ~StringHelper(void) + { + } - /** - * This method is used to check whether the full string contains the provided ending. - * @param: fullString, the specifies the string which needs to be checked. - * @param: ending, string specifes the ending string. - * @return: true if ending string is at the end of fullString, otherwise false - */ - static bool hasEnding(std::string const &fullString, std::string const &ending); + /** + * This method is used to check whether the full string contains the + * provided ending. + * @param: fullString, the specifies the string which needs to be checked. + * @param: ending, string specifes the ending string. + * @return: true if ending string is at the end of fullString, otherwise + * false + */ + static bool hasEnding(std::string const& fullString, + std::string const& ending); - - static bool startsWithDigitQ(QString fullString); - static bool startsWithDigit(std::string const &fullString); + static bool startsWithDigitQ(QString fullString); + static bool startsWithDigit(std::string const& fullString); - static bool isNumber(QString fullString); + static bool isNumber(QString fullString); - /** - * Convert QString to standard string. - * @param: qString, the string to convert, - * @return: a standard string. - */ - static std::string toStdString(QString qString); + /** + * Convert QString to standard string. + * @param: qString, the string to convert, + * @return: a standard string. + */ + static std::string toStdString(QString qString); - /** - * Convert standard string to QString - * @param: stdString, the string to convert, - * @return: a qt string. - */ - static QString toQString(std::string stdString); + /** + * Convert standard string to QString + * @param: stdString, the string to convert, + * @return: a qt string. + */ + static QString toQString(std::string stdString); - /** - * Convert integer to standard string. - * @param: int_num, integer number to convert, - * @return: a standard string. - */ - static std::string iToSS(int int_num); + /** + * Convert integer to standard string. + * @param: int_num, integer number to convert, + * @return: a standard string. + */ + static std::string iToSS(int int_num); - /** - * Convert a bool to standard string. - * @param: bool_value, bool valueto convert, - * @return: a standard string. - */ - static std::string boolToSS(bool bool_value); + /** + * Convert a bool to standard string. + * @param: bool_value, bool valueto convert, + * @return: a standard string. + */ + static std::string boolToSS(bool bool_value); - /** - * Convert float to standard string. - * @param: float_num, float number to convert, - * @return: a standard string. - */ - static std::string fToSS(float float_num); + /** + * Convert float to standard string. + * @param: float_num, float number to convert, + * @return: a standard string. + */ + static std::string fToSS(float float_num); - /** - * Convert a given string to lower case string. - * @param: stringValue, string to convert, - * @return: a standard string. - */ - static std::string toLowerCase(std::string stringValue); + /** + * Convert a given string to lower case string. + * @param: stringValue, string to convert, + * @return: a standard string. + */ + static std::string toLowerCase(std::string stringValue); - /** - * Use from here: http://stackoverflow.com/questions/5888022/split-string-by-single-spaces - * Method to split a string by a given character. - * @param: txt, a reference to the string, which will be split, - * @param: strs, a reference to a vector containing the splitted result, - * @param: ch, the split character. - **/ - static int split(std::string &txt, std::vector &strs, char ch); + /** + * Use from here: + *http://stackoverflow.com/questions/5888022/split-string-by-single-spaces + * Method to split a string by a given character. + * @param: txt, a reference to the string, which will be split, + * @param: strs, a reference to a vector containing the splitted result, + * @param: ch, the split character. + **/ + static int split(std::string& txt, + std::vector& strs, + char ch); }; From dbb395b7d4f384765d86f83edc2f8f6098e3a9a2 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 29 Jul 2022 17:35:21 +0200 Subject: [PATCH 13/22] Clarify erosion/dilation parameters --- Src/Config.cpp | 12 +++++----- Src/Config.h | 4 ++-- Src/Model/TrackerParameter.cpp | 4 ++-- Src/Model/TrackerParameter.h | 24 +++++++++---------- .../preprocessor/ImagePreProcessor.cpp | 4 ++-- Src/View/TrackerParameterView.cpp | 16 ++++++------- Src/View/TrackerParameterView.ui | 12 +++++----- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Src/Config.cpp b/Src/Config.cpp index 1f06a68..1bcb863 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -62,10 +62,10 @@ void Config::load(QString dir, QString file) config->BinarizationThreshold = tree.get( globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); - config->SizeErode = tree.get(globalPrefix + "SizeErode", - config->SizeErode); - config->SizeDilate = tree.get(globalPrefix + "SizeDilate", - config->SizeDilate); + config->OpeningErosionSize = tree.get(globalPrefix + "OpeningErosionSize", + config->OpeningErosionSize); + config->OpeningDilationSize = tree.get(globalPrefix + "OpeningDilationSize", + config->OpeningDilationSize); config->MinBlobSize = tree.get(globalPrefix + "MinBlobSize", config->MinBlobSize); config->MaxBlobSize = tree.get(globalPrefix + "MaxBlobSize", @@ -100,8 +100,8 @@ void Config::save(QString dir, QString file) config->UseAbsoluteDifference); tree.put(globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); - tree.put(globalPrefix + "SizeErode", config->SizeErode); - tree.put(globalPrefix + "SizeDilate", config->SizeDilate); + tree.put(globalPrefix + "OpeningErosionSize", config->OpeningErosionSize); + tree.put(globalPrefix + "OpeningDilationSize", config->OpeningDilationSize); tree.put(globalPrefix + "MinBlobSize", config->MinBlobSize); tree.put(globalPrefix + "MaxBlobSize", config->MaxBlobSize); tree.put(globalPrefix + "LearningRate", config->LearningRate); diff --git a/Src/Config.h b/Src/Config.h index 01bb358..c1648c4 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -10,8 +10,8 @@ class Config : public IConfig bool UseAbsoluteDifference = true; int BinarizationThreshold = 40; - int SizeErode = 8; - int SizeDilate = 8; + int OpeningErosionSize = 8; + int OpeningDilationSize = 8; int MinBlobSize = 40; int MaxBlobSize = 999999; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 365bc9e..3a47fd5 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -9,8 +9,8 @@ TrackerParameter::TrackerParameter(QObject* parent) _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; _BinarizationThreshold = _cfg->BinarizationThreshold; - _SizeErode = _cfg->SizeErode; - _SizeDilate = _cfg->SizeDilate; + _OpeningErosionSize = _cfg->OpeningErosionSize; + _OpeningDilationSize = _cfg->OpeningDilationSize; _MinBlobSize = _cfg->MinBlobSize; _MaxBlobSize = _cfg->MaxBlobSize; diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 4ee2f4b..64a268e 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -27,25 +27,25 @@ public slots: void setBinarizationThreshold(int x); int getBinarizationThreshold(); - int getSizeErode() + int getOpeningErosionSize() { - return _SizeErode; + return _OpeningErosionSize; }; - void setSizeErode(int x) + void setOpeningErosionSize(int x) { - _SizeErode = x; - _cfg->SizeErode = x; + _OpeningErosionSize = x; + _cfg->OpeningErosionSize = x; Q_EMIT notifyView(); }; - int getSizeDilate() + int getOpeningDilationSize() { - return _SizeDilate; + return _OpeningDilationSize; }; - void setSizeDilate(int x) + void setOpeningDilationSize(int x) { - _SizeDilate = x; - _cfg->SizeDilate = x; + _OpeningDilationSize = x; + _cfg->OpeningDilationSize = x; Q_EMIT notifyView(); }; @@ -150,8 +150,8 @@ public slots: bool _UseAbsoluteDifference; int _BinarizationThreshold; - int _SizeErode; - int _SizeDilate; + int _OpeningErosionSize; + int _OpeningDilationSize; double _LearningRate; int _MinBlobSize; int _MaxBlobSize; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index ab6d428..f9ff90d 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -48,7 +48,7 @@ cv::Mat ImagePreProcessor::erode(cv::Mat& image) { cv::Mat erodedImage; cv::Mat erodeKernel; - int sizeErode = m_TrackingParameter->getSizeErode(); + int sizeErode = m_TrackingParameter->getOpeningErosionSize(); if (sizeErode > 0) { erodeKernel = cv::getStructuringElement( cv::MORPH_CROSS, @@ -65,7 +65,7 @@ cv::Mat ImagePreProcessor::dilate(cv::Mat& image) { cv::Mat dilatedImage; cv::Mat dilateKernel; - int sizeDilate = m_TrackingParameter->getSizeDilate(); + int sizeDilate = m_TrackingParameter->getOpeningDilationSize(); if (sizeDilate > 0) { dilateKernel = cv::getStructuringElement( cv::MORPH_RECT, diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 8099a85..6d910e8 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -25,20 +25,20 @@ TrackerParameterView::TrackerParameterView(QWidget* parent, this, &TrackerParameterView::initSubtractorSpecificUI); - connect(_ui->lineEdit_3_SizeErode, + connect(_ui->lineEdit_3_OpeningErosionSize, qOverload(&QSpinBox::valueChanged), parameter, - &TrackerParameter::setSizeErode); - connect(_ui->lineEdit_3_SizeErode, + &TrackerParameter::setOpeningErosionSize); + connect(_ui->lineEdit_3_OpeningErosionSize, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - connect(_ui->lineEdit_4_SizeDilate, + connect(_ui->lineEdit_4_OpeningDilationSize, qOverload(&QSpinBox::valueChanged), parameter, - &TrackerParameter::setSizeDilate); - connect(_ui->lineEdit_4_SizeDilate, + &TrackerParameter::setOpeningDilationSize); + connect(_ui->lineEdit_4_OpeningDilationSize, qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); @@ -159,9 +159,9 @@ void TrackerParameterView::getNotified() _binThres->setValue(parameter->getBinarizationThreshold()); } - _ui->lineEdit_3_SizeErode->setValue(parameter->getSizeErode()); + _ui->lineEdit_3_OpeningErosionSize->setValue(parameter->getOpeningErosionSize()); - _ui->lineEdit_4_SizeDilate->setValue(parameter->getSizeDilate()); + _ui->lineEdit_4_OpeningDilationSize->setValue(parameter->getOpeningDilationSize()); _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index 59e548d..f1d3dfd 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -231,12 +231,12 @@ - Size Erosion: + Opening erosion size: - + 132 @@ -244,19 +244,19 @@ - Set the erosion size + Set the opening erosion size - Size Dilation: + Opening dilation size: - + 132 @@ -264,7 +264,7 @@ - Set the dilation size + Set the opening dilation size From 483067481c1768c0075f179b4bb8b8a3bbcf8ac3 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 29 Jul 2022 17:36:05 +0200 Subject: [PATCH 14/22] Enable networking by default --- Src/Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/Config.h b/Src/Config.h index c1648c4..e3ecd5f 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -17,7 +17,7 @@ class Config : public IConfig double LearningRate = 0.05; - int DoNetwork = false; + int DoNetwork = true; int NetworkPort = 54444; int DoBackground = true; From 62d4bdc0bb4be8199400c7318d4154608f941bce Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 29 Jul 2022 18:27:08 +0200 Subject: [PATCH 15/22] Merged erosion->dilation into single opening moprh, add closing morph --- Src/Config.cpp | 25 ++- Src/Config.h | 8 +- Src/Model/BioTrackerTrackingAlgorithm.cpp | 20 +-- Src/Model/TrackerParameter.cpp | 6 +- Src/Model/TrackerParameter.h | 29 +++- .../imageProcessor/cvblobs/BlobResult.cpp | 4 +- .../detector/contour/ContoursDetector.cpp | 2 +- .../preprocessor/ImagePreProcessor.cpp | 66 +++---- .../preprocessor/ImagePreProcessor.h | 6 +- Src/View/TrackerParameterView.cpp | 30 +++- Src/View/TrackerParameterView.ui | 164 +++++++++++++----- 11 files changed, 252 insertions(+), 108 deletions(-) diff --git a/Src/Config.cpp b/Src/Config.cpp index 1bcb863..1d10278 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -62,10 +62,21 @@ void Config::load(QString dir, QString file) config->BinarizationThreshold = tree.get( globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); - config->OpeningErosionSize = tree.get(globalPrefix + "OpeningErosionSize", - config->OpeningErosionSize); - config->OpeningDilationSize = tree.get(globalPrefix + "OpeningDilationSize", - config->OpeningDilationSize); + + config->OpeningErosionSize = tree.get(globalPrefix + + "OpeningErosionSize", + config->OpeningErosionSize); + config->OpeningDilationSize = tree.get(globalPrefix + + "OpeningDilationSize", + config->OpeningDilationSize); + + config->ClosingDilationSize = tree.get(globalPrefix + + "ClosingDilationSize", + config->ClosingDilationSize); + config->ClosingErosionSize = tree.get(globalPrefix + + "ClosingErosionSize", + config->ClosingErosionSize); + config->MinBlobSize = tree.get(globalPrefix + "MinBlobSize", config->MinBlobSize); config->MaxBlobSize = tree.get(globalPrefix + "MaxBlobSize", @@ -101,7 +112,11 @@ void Config::save(QString dir, QString file) tree.put(globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); tree.put(globalPrefix + "OpeningErosionSize", config->OpeningErosionSize); - tree.put(globalPrefix + "OpeningDilationSize", config->OpeningDilationSize); + tree.put(globalPrefix + "OpeningDilationSize", + config->OpeningDilationSize); + tree.put(globalPrefix + "ClosingDilationSize", + config->ClosingDilationSize); + tree.put(globalPrefix + "ClosingErosionSize", config->ClosingErosionSize); tree.put(globalPrefix + "MinBlobSize", config->MinBlobSize); tree.put(globalPrefix + "MaxBlobSize", config->MaxBlobSize); tree.put(globalPrefix + "LearningRate", config->LearningRate); diff --git a/Src/Config.h b/Src/Config.h index e3ecd5f..690b9b2 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -10,8 +10,12 @@ class Config : public IConfig bool UseAbsoluteDifference = true; int BinarizationThreshold = 40; - int OpeningErosionSize = 8; - int OpeningDilationSize = 8; + int OpeningErosionSize = 8; + int OpeningDilationSize = 8; + + int ClosingDilationSize = 8; + int ClosingErosionSize = 8; + int MinBlobSize = 40; int MaxBlobSize = 999999; diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index e0efb86..f615e6e 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -95,14 +95,14 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage( Q_EMIT emitChangeDisplayImage(QString("Foreground Mask")); break; case 3: - sendImage = images->find(std::string("Eroded"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Eroded")); - Q_EMIT emitChangeDisplayImage(QString("Eroded")); + sendImage = images->find(std::string("Opened Mask"))->second; + Q_EMIT emitCvMatA(sendImage, QString("Opened Mask")); + Q_EMIT emitChangeDisplayImage(QString("Opened Mask")); break; case 4: - sendImage = images->find(std::string("Dilated"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Dilated")); - Q_EMIT emitChangeDisplayImage(QString("Dilated")); + sendImage = images->find(std::string("Closed Mask"))->second; + Q_EMIT emitCvMatA(sendImage, QString("Closed Mask")); + Q_EMIT emitChangeDisplayImage(QString("Closed Mask")); break; } } @@ -195,16 +195,16 @@ void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr p_image, // Do the preprocessing std::map> images = _ipp.preProcess( p_image); - std::shared_ptr dilated = - images.find(std::string("Dilated"))->second; + std::shared_ptr mask = + images.find(std::string("Closed Mask"))->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); - std::vector blobs = getContourCentroids(*dilated, 111); + // std::vector blobs = _bd.getPoses(*mask, *greyMat); + std::vector blobs = getContourCentroids(*mask, 111); // Never switch the position of the trajectories. The NN2d mapper relies on // this! If you mess up the order, add or remove some t, then create a new diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 3a47fd5..1bdbab5 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -9,8 +9,10 @@ TrackerParameter::TrackerParameter(QObject* parent) _UseAbsoluteDifference = _cfg->UseAbsoluteDifference; _BinarizationThreshold = _cfg->BinarizationThreshold; - _OpeningErosionSize = _cfg->OpeningErosionSize; - _OpeningDilationSize = _cfg->OpeningDilationSize; + _OpeningErosionSize = _cfg->OpeningErosionSize; + _OpeningDilationSize = _cfg->OpeningDilationSize; + _ClosingDilationSize = _cfg->ClosingDilationSize; + _ClosingErosionSize = _cfg->ClosingErosionSize; _MinBlobSize = _cfg->MinBlobSize; _MaxBlobSize = _cfg->MaxBlobSize; diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 64a268e..2df14f0 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -49,6 +49,28 @@ public slots: Q_EMIT notifyView(); }; + int getClosingDilationSize() + { + return _ClosingDilationSize; + }; + void setClosingDilationSize(int x) + { + _ClosingDilationSize = x; + _cfg->ClosingDilationSize = x; + Q_EMIT notifyView(); + }; + + int getClosingErosionSize() + { + return _ClosingErosionSize; + }; + void setClosingErosionSize(int x) + { + _ClosingErosionSize = x; + _cfg->ClosingErosionSize = x; + Q_EMIT notifyView(); + }; + double getLearningRate() { return _LearningRate; @@ -150,8 +172,11 @@ public slots: bool _UseAbsoluteDifference; int _BinarizationThreshold; - int _OpeningErosionSize; - int _OpeningDilationSize; + int _OpeningErosionSize; + int _OpeningDilationSize; + int _ClosingDilationSize; + int _ClosingErosionSize; + double _LearningRate; int _MinBlobSize; int _MaxBlobSize; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp index 02b23e9..ea01bd5 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/cvblobs/BlobResult.cpp @@ -843,9 +843,9 @@ void CBlobResult::PrintBlobs(char* nom_fitxer) const for (i = 0; i < GetNumBlobs(); i++) { // fprintf( fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f - //extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n", + // 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] ); + // perimetreConvex[i], exterior[i], compacitat[i], longitud[i] ); } fclose(fitxer_sortida); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp index 6a76e59..0f86ae8 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/detector/contour/ContoursDetector.cpp @@ -23,7 +23,7 @@ void ContoursDetector::createMask(std::vector points) // return; // // mask = cvCreateImage(cvSize(_xRes, _yRes), IPL_DEPTH_8U,1);//erstellt -//schwarzwei� bild +// schwarzwei� bild // // //folgender Block setzt die Pixel schwarz // for( int y=0; yheight; y++ ) { diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index f9ff90d..872a624 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -44,38 +44,36 @@ void ImagePreProcessor::init() _resetBackgroundImageEnabled = false; } -cv::Mat ImagePreProcessor::erode(cv::Mat& image) +cv::Mat ImagePreProcessor::erode(cv::Mat image, int kernelSize) { - cv::Mat erodedImage; - cv::Mat erodeKernel; - int sizeErode = m_TrackingParameter->getOpeningErosionSize(); - if (sizeErode > 0) { - erodeKernel = cv::getStructuringElement( + if (kernelSize > 0 && image.data) { + auto kernel = cv::getStructuringElement( cv::MORPH_CROSS, - cv::Size(sizeErode, sizeErode)); + cv::Size(kernelSize, kernelSize)); + + cv::Mat morphed; + cv::erode(image, morphed, kernel); + + return morphed; } else { return image; } - if (image.data) - cv::erode(image, erodedImage, erodeKernel); - return erodedImage; } -cv::Mat ImagePreProcessor::dilate(cv::Mat& image) +cv::Mat ImagePreProcessor::dilate(cv::Mat image, int kernelSize) { - cv::Mat dilatedImage; - cv::Mat dilateKernel; - int sizeDilate = m_TrackingParameter->getOpeningDilationSize(); - if (sizeDilate > 0) { - dilateKernel = cv::getStructuringElement( + if (kernelSize > 0 && image.data) { + auto kernel = cv::getStructuringElement( cv::MORPH_RECT, - cv::Size(sizeDilate, sizeDilate)); + cv::Size(kernelSize, kernelSize)); + + cv::Mat morphed; + cv::dilate(image, morphed, kernel); + + return morphed; } else { return image; } - if (image.data) - cv::dilate(image, dilatedImage, dilateKernel); - return dilatedImage; } cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) @@ -103,20 +101,24 @@ cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) std::map> ImagePreProcessor::preProcess( std::shared_ptr p_image) { - std::shared_ptr greyMat = std::make_shared(); - std::shared_ptr erodedImage = std::make_shared(); - std::shared_ptr dilatedImage = std::make_shared(); + std::shared_ptr greyMat = std::make_shared(); + std::shared_ptr openedMask = std::make_shared(); + std::shared_ptr closedMask = std::make_shared(); cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); // 1. step: do the background subtraction *m_foregroundMask = backgroundSubtraction(*greyMat); - // 2. step: erode the image - *erodedImage = erode(*m_foregroundMask); + // 2. step: open the mask + *openedMask = dilate( + erode(*m_foregroundMask, m_TrackingParameter->getOpeningErosionSize()), + m_TrackingParameter->getOpeningDilationSize()); - // 3. step: dilate the image - *dilatedImage = dilate(*erodedImage); + // 3. step: close the image + *closedMask = erode( + dilate(*openedMask, m_TrackingParameter->getClosingDilationSize()), + m_TrackingParameter->getClosingErosionSize()); std::map> all; all.insert(std::pair>( @@ -128,12 +130,12 @@ std::map> ImagePreProcessor::preProcess( all.insert(std::pair>( std::string("Foreground Mask"), m_foregroundMask)); - all.insert( - std::pair>(std::string("Eroded"), - erodedImage)); all.insert(std::pair>( - std::string("Dilated"), - dilatedImage)); + std::string("Opened Mask"), + openedMask)); + all.insert(std::pair>( + std::string("Closed Mask"), + closedMask)); return all; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index b190f39..0acbcc4 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -29,17 +29,19 @@ class ImagePreProcessor * A mathematical morphology operation using in computer vision to erode an * image. Erode image with 3x3 4-connectivity. * @param: image, image to erode, + * @param: kernelSize, size of erosion kernel, * @return: an eroded image. */ - cv::Mat erode(cv::Mat& image); + cv::Mat erode(cv::Mat image, int kernelSize); /** * A mathematical morphology operation using in computer vision to dilate * an image. Dilate image with 6x6 8-connectivity. * @param: image, image to dilate, + * @param: kernelSize, size of dilation kernel, * @return: a dilated image. */ - cv::Mat dilate(cv::Mat& image); + cv::Mat dilate(cv::Mat image, int kernelSize); /** * A computer vision methode to calculate the image difference. diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 6d910e8..2cdb497 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -43,6 +43,24 @@ TrackerParameterView::TrackerParameterView(QWidget* parent, this, &TrackerParameterView::parametersChanged); + connect(_ui->lineEdit_4_ClosingDilationSize, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setClosingDilationSize); + connect(_ui->lineEdit_4_ClosingDilationSize, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_3_ClosingErosionSize, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setClosingErosionSize); + connect(_ui->lineEdit_3_ClosingErosionSize, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + connect(_ui->lineEdit_8_MinBlob, qOverload(&QSpinBox::valueChanged), parameter, @@ -159,9 +177,17 @@ void TrackerParameterView::getNotified() _binThres->setValue(parameter->getBinarizationThreshold()); } - _ui->lineEdit_3_OpeningErosionSize->setValue(parameter->getOpeningErosionSize()); + _ui->lineEdit_3_OpeningErosionSize->setValue( + parameter->getOpeningErosionSize()); + + _ui->lineEdit_4_OpeningDilationSize->setValue( + parameter->getOpeningDilationSize()); + + _ui->lineEdit_4_ClosingDilationSize->setValue( + parameter->getClosingDilationSize()); - _ui->lineEdit_4_OpeningDilationSize->setValue(parameter->getOpeningDilationSize()); + _ui->lineEdit_3_ClosingErosionSize->setValue( + parameter->getClosingErosionSize()); _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index f1d3dfd..d3aaeff 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -221,54 +221,122 @@ - - - QFormLayout::ExpandingFieldsGrow + + + Opening - - 74 + + + + + QFormLayout::ExpandingFieldsGrow + + + 74 + + + + + Erosion kernel size: + + + + + + + + 132 + 60 + + + + Set the opening erosion size + + + + + + + Dilation kernel size: + + + + + + + + 132 + 60 + + + + Set the opening dilation size + + + + + + + + + + + + Closing - - - - Opening erosion size: - - - - - - - - 132 - 60 - - - - Set the opening erosion size - - - - - - - Opening dilation size: - - - - - - - - 132 - 60 - - - - Set the opening dilation size - - - - + + + + + QFormLayout::ExpandingFieldsGrow + + + 74 + + + + + Erosion kernel size: + + + + + + + + 132 + 60 + + + + Set the opening erosion size + + + + + + + + 132 + 60 + + + + Set the opening dilation size + + + + + + + Dilation kernel size: + + + + + + + @@ -399,12 +467,12 @@ - Eroded + Opened Mask - Dilated + Closed Mask From bdd371ef26cd7ea2397e5434fb61734e9dc0084d Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 29 Jul 2022 18:49:53 +0200 Subject: [PATCH 16/22] Calculate and show masked grayscale image --- Src/Model/BioTrackerTrackingAlgorithm.cpp | 5 +++++ .../imageProcessor/preprocessor/ImagePreProcessor.cpp | 8 ++++++++ Src/View/TrackerParameterView.ui | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index f615e6e..f48cef5 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -104,6 +104,11 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage( Q_EMIT emitCvMatA(sendImage, QString("Closed Mask")); Q_EMIT emitChangeDisplayImage(QString("Closed Mask")); break; + case 5: + sendImage = images->find(std::string("Masked Greyscale"))->second; + Q_EMIT emitCvMatA(sendImage, QString("Masked Greyscale")); + Q_EMIT emitChangeDisplayImage(QString("Masked Greyscale")); + break; } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 872a624..92c2ab0 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -105,6 +105,8 @@ std::map> ImagePreProcessor::preProcess( std::shared_ptr openedMask = std::make_shared(); std::shared_ptr closedMask = std::make_shared(); + std::shared_ptr maskedGrey = std::make_shared(); + cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); // 1. step: do the background subtraction @@ -119,6 +121,9 @@ std::map> ImagePreProcessor::preProcess( *closedMask = erode( dilate(*openedMask, m_TrackingParameter->getClosingDilationSize()), m_TrackingParameter->getClosingErosionSize()); + + // 4. step: masked greyscale image + greyMat->copyTo(*maskedGrey, *closedMask); std::map> all; all.insert(std::pair>( @@ -136,6 +141,9 @@ std::map> ImagePreProcessor::preProcess( all.insert(std::pair>( std::string("Closed Mask"), closedMask)); + all.insert(std::pair>( + std::string("Masked Greyscale"), + maskedGrey)); return all; } diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index d3aaeff..26d1e8f 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -475,6 +475,11 @@ Closed Mask + + + Masked Greyscale + + From f1b319203bc583b3a4d3bd6dc4cbf491333d652b Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Fri, 29 Jul 2022 19:34:15 +0200 Subject: [PATCH 17/22] Add maximum image value filter --- Src/Config.cpp | 5 ++++ Src/Config.h | 1 + Src/Model/TrackerParameter.cpp | 12 +++++++++ Src/Model/TrackerParameter.h | 4 +++ .../CustomBackgroundSubtractor.cpp | 26 ++++++++++++++----- .../preprocessor/CustomBackgroundSubtractor.h | 2 ++ .../preprocessor/ImagePreProcessor.cpp | 2 ++ Src/View/TrackerParameterView.cpp | 23 ++++++++++++++++ Src/View/TrackerParameterView.h | 1 + 9 files changed, 69 insertions(+), 7 deletions(-) diff --git a/Src/Config.cpp b/Src/Config.cpp index 1d10278..aaed4dd 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -62,6 +62,9 @@ void Config::load(QString dir, QString file) config->BinarizationThreshold = tree.get( globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); + config->MaximumImageValue = tree.get( + globalPrefix + "MaximumImageValue", + config->MaximumImageValue); config->OpeningErosionSize = tree.get(globalPrefix + "OpeningErosionSize", @@ -111,6 +114,8 @@ void Config::save(QString dir, QString file) config->UseAbsoluteDifference); tree.put(globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); + tree.put(globalPrefix + "MaximumImageValue", + config->MaximumImageValue); tree.put(globalPrefix + "OpeningErosionSize", config->OpeningErosionSize); tree.put(globalPrefix + "OpeningDilationSize", config->OpeningDilationSize); diff --git a/Src/Config.h b/Src/Config.h index 690b9b2..185581c 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -9,6 +9,7 @@ class Config : public IConfig public: bool UseAbsoluteDifference = true; int BinarizationThreshold = 40; + int MaximumImageValue = 255; int OpeningErosionSize = 8; int OpeningDilationSize = 8; diff --git a/Src/Model/TrackerParameter.cpp b/Src/Model/TrackerParameter.cpp index 1bdbab5..3641989 100644 --- a/Src/Model/TrackerParameter.cpp +++ b/Src/Model/TrackerParameter.cpp @@ -42,6 +42,18 @@ int TrackerParameter::getBinarizationThreshold() return _BinarizationThreshold; } +void TrackerParameter::setMaximumImageValue(int x) +{ + _MaximumImageValue = x; + _cfg->MaximumImageValue = x; + Q_EMIT notifyView(); +} + +int TrackerParameter::getMaximumImageValue() +{ + return _MaximumImageValue; +} + void TrackerParameter::setUseAbsoluteDifference(bool value) { _UseAbsoluteDifference = value; diff --git a/Src/Model/TrackerParameter.h b/Src/Model/TrackerParameter.h index 2df14f0..15dd7db 100644 --- a/Src/Model/TrackerParameter.h +++ b/Src/Model/TrackerParameter.h @@ -27,6 +27,9 @@ public slots: void setBinarizationThreshold(int x); int getBinarizationThreshold(); + void setMaximumImageValue(int x); + int getMaximumImageValue(); + int getOpeningErosionSize() { return _OpeningErosionSize; @@ -171,6 +174,7 @@ public slots: bool _UseAbsoluteDifference; int _BinarizationThreshold; + int _MaximumImageValue; int _OpeningErosionSize; int _OpeningDilationSize; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp index fab8580..35398a5 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -8,6 +8,7 @@ CustomBackgroundSubtractor::CustomBackgroundSubtractor() : m_useAbsoluteDifference{true} , m_binarizationThreshold{8} +, m_maximumImageValue{255} { } @@ -21,6 +22,11 @@ void CustomBackgroundSubtractor::setBinarizationThreshold(int value) m_binarizationThreshold = value; } +void CustomBackgroundSubtractor::setMaximumImageValue(int value) +{ + m_maximumImageValue = value; +} + void CustomBackgroundSubtractor::getBackgroundImage( cv::OutputArray backgroundImage) const { @@ -43,9 +49,7 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, const int regionWidth = imageWidth / totalRegionsX; const int regionHeight = imageHeight / totalRegionsY; - fgmask.create(imageHeight, imageWidth, image.type()); - - auto fgmaskmat = fgmask.getMat(); + auto diffimg = cv::Mat(imageHeight, imageWidth, image.type()); const auto useAbsoluteDifference = m_useAbsoluteDifference; @@ -56,7 +60,7 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, cv::Rect(startingX, startingY, regionWidth, regionHeight); cv::Mat subBackground = m_background(subArea); cv::Mat subImage = image.getMat()(subArea); - cv::Mat subResults = fgmaskmat(subArea); + cv::Mat subResults = diffimg(subArea); if (useAbsoluteDifference) { cv::absdiff(subBackground, subImage, subResults); @@ -81,11 +85,19 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, asyncResult.wait(); } - if (fgmaskmat.data) { - cv::threshold(fgmaskmat, - fgmaskmat, + if (diffimg.data) { + cv::Mat diffmask; + + cv::Mat maxabsmask; + + cv::threshold(diffimg, + diffmask, m_binarizationThreshold, 255, cv::THRESH_BINARY); + + cv::threshold(image, maxabsmask, m_maximumImageValue, 255, cv::THRESH_BINARY_INV); + + cv::bitwise_and(diffmask, maxabsmask, fgmask); } } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h index 9d611ca..e979826 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.h @@ -15,6 +15,7 @@ class CustomBackgroundSubtractor : public cv::BackgroundSubtractor void setUseAbsoluteDifference(bool value); void setBinarizationThreshold(int value); + void setMaximumImageValue(int value); private: cv::Mat m_background; @@ -22,4 +23,5 @@ class CustomBackgroundSubtractor : public cv::BackgroundSubtractor bool m_useAbsoluteDifference; int m_binarizationThreshold; + int m_maximumImageValue; }; diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 92c2ab0..5b1f9ba 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -88,6 +88,8 @@ cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) m_TrackingParameter->getUseAbsoluteDifference()); subtractor->setBinarizationThreshold( m_TrackingParameter->getBinarizationThreshold()); + subtractor->setMaximumImageValue( + m_TrackingParameter->getMaximumImageValue()); } else { qFatal("Unsupported background subtraction algorithm"); } diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 2cdb497..254400a 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -10,6 +10,7 @@ TrackerParameterView::TrackerParameterView(QWidget* parent, , _ui(new Ui::TrackerParameterView) , _useAbsDiff(nullptr) , _binThres(nullptr) +, _maxImg(nullptr) { _ui->setupUi(this); getNotified(); @@ -108,6 +109,7 @@ void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) _useAbsDiff = nullptr; _binThres = nullptr; + _maxImg = nullptr; if (algorithm == QString("Custom")) { _useAbsDiff = new QCheckBox(); @@ -142,6 +144,23 @@ void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); + + _maxImg = new QSpinBox(); + _maxImg->setMinimum(1); + _maxImg->setMaximum(255); + _maxImg->setValue(parameter->getMaximumImageValue()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Maximum Image Value:"), + _maxImg); + + connect(_maxImg, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMaximumImageValue); + connect(_maxImg, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); } else { qFatal("Unsupported background subtraction algorithm"); } @@ -177,6 +196,10 @@ void TrackerParameterView::getNotified() _binThres->setValue(parameter->getBinarizationThreshold()); } + if (_maxImg) { + _maxImg->setValue(parameter->getMaximumImageValue()); + } + _ui->lineEdit_3_OpeningErosionSize->setValue( parameter->getOpeningErosionSize()); diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index ad1c99f..da49ce8 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -37,6 +37,7 @@ private slots: QCheckBox* _useAbsDiff; QSpinBox* _binThres; + QSpinBox* _maxImg; private slots: void initSubtractorSpecificUI(QString algorithm); From 193c7aa4de5d1908c1dd570f54aec60ed251412e Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Wed, 3 Aug 2022 09:48:20 +0200 Subject: [PATCH 18/22] Misc --- Src/BioTrackerPlugin.h | 6 ++-- Src/Config.cpp | 9 +++-- Src/Config.h | 2 +- Src/Model/BioTrackerTrackingAlgorithm.cpp | 35 +++++++++++++------ Src/Model/BioTrackerTrackingAlgorithm.h | 2 +- .../CustomBackgroundSubtractor.cpp | 6 +++- .../preprocessor/ImagePreProcessor.cpp | 2 +- Src/View/TrackerParameterView.cpp | 4 +-- 8 files changed, 42 insertions(+), 24 deletions(-) diff --git a/Src/BioTrackerPlugin.h b/Src/BioTrackerPlugin.h index cbf2cf2..e194e8d 100644 --- a/Src/BioTrackerPlugin.h +++ b/Src/BioTrackerPlugin.h @@ -29,8 +29,6 @@ class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin public: void createPlugin(); - void receiveCurrentFrameFromMainApp(std::shared_ptr mat, - uint frameNumber); void sendCorePermissions(); private: @@ -70,7 +68,9 @@ public slots: IModelTrackedTrajectory* trajectory1); void receiveCurrentFrameNumberFromMainApp(uint frameNumber); -private slots: +public slots: + void receiveCurrentFrameFromMainApp(std::shared_ptr mat, + uint frameNumber); void receiveAreaDescriptor(IModelAreaDescriptor* areaDescr); private: diff --git a/Src/Config.cpp b/Src/Config.cpp index aaed4dd..e23dc0f 100644 --- a/Src/Config.cpp +++ b/Src/Config.cpp @@ -62,9 +62,9 @@ void Config::load(QString dir, QString file) config->BinarizationThreshold = tree.get( globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); - config->MaximumImageValue = tree.get( - globalPrefix + "MaximumImageValue", - config->MaximumImageValue); + config->MaximumImageValue = tree.get(globalPrefix + + "MaximumImageValue", + config->MaximumImageValue); config->OpeningErosionSize = tree.get(globalPrefix + "OpeningErosionSize", @@ -114,8 +114,7 @@ void Config::save(QString dir, QString file) config->UseAbsoluteDifference); tree.put(globalPrefix + "BinarizationThreshold", config->BinarizationThreshold); - tree.put(globalPrefix + "MaximumImageValue", - config->MaximumImageValue); + tree.put(globalPrefix + "MaximumImageValue", config->MaximumImageValue); tree.put(globalPrefix + "OpeningErosionSize", config->OpeningErosionSize); tree.put(globalPrefix + "OpeningDilationSize", config->OpeningDilationSize); diff --git a/Src/Config.h b/Src/Config.h index 185581c..f63f0aa 100644 --- a/Src/Config.h +++ b/Src/Config.h @@ -9,7 +9,7 @@ class Config : public IConfig public: bool UseAbsoluteDifference = true; int BinarizationThreshold = 40; - int MaximumImageValue = 255; + int MaximumImageValue = 255; int OpeningErosionSize = 8; int OpeningDilationSize = 8; diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index f48cef5..094b2c2 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -113,20 +113,20 @@ void BioTrackerTrackingAlgorithm::sendSelectedImage( } std::vector BioTrackerTrackingAlgorithm::getContourCentroids( - cv::Mat& image, - int minSize) + cv::Mat image) { std::vector> contours; std::vector hierarchy; std::vector centroids; - findContours(image, - contours, - hierarchy, - cv::RETR_TREE, - cv::CHAIN_APPROX_SIMPLE, - cv::Point(0, 0)); + cv::findContours(image, + contours, + hierarchy, + cv::RETR_TREE, + cv::CHAIN_APPROX_SIMPLE, + cv::Point(0, 0)); + for (auto x : contours) { cv::Point2f c(0, 0); float i = 0; @@ -208,8 +208,23 @@ void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr p_image, // Find blobs via ellipsefitting _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); - // std::vector blobs = _bd.getPoses(*mask, *greyMat); - std::vector blobs = getContourCentroids(*mask, 111); + + auto foo = *images.find(std::string("Masked Greyscale"))->second; + + std::vector> contours; + std::vector hierarchy; + cv::findContours(foo, + contours, + hierarchy, + cv::RETR_TREE, + cv::CHAIN_APPROX_SIMPLE, + cv::Point(0, 0)); + + for (size_t i = 0; i < contours.size(); i++) { + drawContours(foo, contours, (int) i, cv::Scalar(255)); + } + + std::vector blobs = getContourCentroids(*mask); // 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 diff --git a/Src/Model/BioTrackerTrackingAlgorithm.h b/Src/Model/BioTrackerTrackingAlgorithm.h index ca456fe..4fb1042 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.h +++ b/Src/Model/BioTrackerTrackingAlgorithm.h @@ -41,7 +41,7 @@ public Q_SLOTS: void receiveParametersChanged(); private: - std::vector getContourCentroids(cv::Mat& image, int minSize); + std::vector getContourCentroids(cv::Mat image); void refreshPolygon(); void sendSelectedImage( std::map>* images); diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp index 35398a5..05f2a3a 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/CustomBackgroundSubtractor.cpp @@ -96,7 +96,11 @@ void CustomBackgroundSubtractor::apply(cv::InputArray image, 255, cv::THRESH_BINARY); - cv::threshold(image, maxabsmask, m_maximumImageValue, 255, cv::THRESH_BINARY_INV); + cv::threshold(image, + maxabsmask, + m_maximumImageValue, + 255, + cv::THRESH_BINARY_INV); cv::bitwise_and(diffmask, maxabsmask, fgmask); } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 5b1f9ba..2a61ac8 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -123,7 +123,7 @@ std::map> ImagePreProcessor::preProcess( *closedMask = erode( dilate(*openedMask, m_TrackingParameter->getClosingDilationSize()), m_TrackingParameter->getClosingErosionSize()); - + // 4. step: masked greyscale image greyMat->copyTo(*maskedGrey, *closedMask); diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 254400a..3707fdf 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -109,7 +109,7 @@ void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) _useAbsDiff = nullptr; _binThres = nullptr; - _maxImg = nullptr; + _maxImg = nullptr; if (algorithm == QString("Custom")) { _useAbsDiff = new QCheckBox(); @@ -144,7 +144,7 @@ void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) qOverload(&QSpinBox::valueChanged), this, &TrackerParameterView::parametersChanged); - + _maxImg = new QSpinBox(); _maxImg->setMinimum(1); _maxImg->setMaximum(255); From d9cfb21d6f49f304d987d81d11e564550a47e24e Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Wed, 3 Aug 2022 12:11:04 +0200 Subject: [PATCH 19/22] Update formating style --- .clang-format | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.clang-format b/.clang-format index 2b27bb2..b3b525e 100644 --- a/.clang-format +++ b/.clang-format @@ -32,13 +32,13 @@ BreakBeforeBraces: Custom BraceWrapping: AfterClass: true AfterControlStatement: false - AfterEnum: false + AfterEnum: true AfterFunction: true AfterNamespace: true - AfterObjCDeclaration: false + AfterObjCDeclaration: true AfterStruct: true - AfterUnion: false - AfterExternBlock: false + AfterUnion: true + AfterExternBlock: true BeforeCatch: false BeforeElse: false IndentBraces: false From 6eee57bfc5b7e3655c5655d61d8ea7ee9e81dc09 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Wed, 3 Aug 2022 13:47:13 +0200 Subject: [PATCH 20/22] Replace std::shared_ptr with cv::Mat cv::Mat is already reference counted. Also use QMap for storage of tracking images. --- Src/BioTrackerPlugin.cpp | 5 +- Src/BioTrackerPlugin.h | 5 +- .../ControllerTrackingAlgorithm.cpp | 3 +- Src/Controller/ControllerTrackingAlgorithm.h | 4 +- Src/Model/BioTrackerTrackingAlgorithm.cpp | 543 +++++++++--------- Src/Model/BioTrackerTrackingAlgorithm.h | 149 ++--- .../preprocessor/ImagePreProcessor.cpp | 59 +- .../preprocessor/ImagePreProcessor.h | 8 +- 8 files changed, 379 insertions(+), 397 deletions(-) diff --git a/Src/BioTrackerPlugin.cpp b/Src/BioTrackerPlugin.cpp index d683f94..12a7cc2 100644 --- a/Src/BioTrackerPlugin.cpp +++ b/Src/BioTrackerPlugin.cpp @@ -163,9 +163,8 @@ void BioTrackerPlugin::receiveAreaDescriptor(IModelAreaDescriptor* areaDescr) Q_EMIT emitAreaDescriptorUpdate(areaDescr); } -void BioTrackerPlugin::receiveCurrentFrameFromMainApp( - std::shared_ptr mat, - uint frameNumber) +void BioTrackerPlugin::receiveCurrentFrameFromMainApp(cv::Mat mat, + uint frameNumber) { qobject_cast(m_TrackerController) ->doTracking(mat, frameNumber); diff --git a/Src/BioTrackerPlugin.h b/Src/BioTrackerPlugin.h index e194e8d..847b047 100644 --- a/Src/BioTrackerPlugin.h +++ b/Src/BioTrackerPlugin.h @@ -34,7 +34,7 @@ class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin private: void connectInterfaces(); signals: - void emitCvMat(std::shared_ptr mat, QString name); + void emitCvMat(cv::Mat mat, QString name); void emitTrackingDone(uint framenumber); void emitChangeDisplayImage(QString str); void emitAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); @@ -69,8 +69,7 @@ public slots: void receiveCurrentFrameNumberFromMainApp(uint frameNumber); public slots: - void receiveCurrentFrameFromMainApp(std::shared_ptr mat, - uint frameNumber); + void receiveCurrentFrameFromMainApp(cv::Mat mat, uint frameNumber); void receiveAreaDescriptor(IModelAreaDescriptor* areaDescr); private: diff --git a/Src/Controller/ControllerTrackingAlgorithm.cpp b/Src/Controller/ControllerTrackingAlgorithm.cpp index 555a7f6..a368101 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.cpp +++ b/Src/Controller/ControllerTrackingAlgorithm.cpp @@ -24,8 +24,7 @@ void ControllerTrackingAlgorithm::connectControllerToController() m_TrackedTrajectoryMajor = ctrComponent->getModel(); } -void ControllerTrackingAlgorithm::doTracking(std::shared_ptr mat, - uint number) +void ControllerTrackingAlgorithm::doTracking(cv::Mat mat, uint number) { qobject_cast(m_Model)->doTracking(mat, number); diff --git a/Src/Controller/ControllerTrackingAlgorithm.h b/Src/Controller/ControllerTrackingAlgorithm.h index 9f8af37..eeb75a4 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.h +++ b/Src/Controller/ControllerTrackingAlgorithm.h @@ -28,7 +28,7 @@ class ControllerTrackingAlgorithm : public IController public: void connectControllerToController() override; - void doTracking(std::shared_ptr mat, uint number); + void doTracking(cv::Mat mat, uint number); IView* getTrackingParameterWidget(); @@ -41,7 +41,7 @@ public Q_SLOTS: void connectModelToController() override; Q_SIGNALS: - void emitCvMat(std::shared_ptr mat, QString name); + void emitCvMat(cv::Mat mat, QString name); void emitTrackingDone(uint framenumber); void emitChangeDisplayImage(QString str); void emitAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 094b2c2..8b771a8 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -1,274 +1,269 @@ -#include "BioTrackerTrackingAlgorithm.h" -#include -#include "TrackedComponents/TrackedComponentFactory.h" -#include - -BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController* parent, - IModel* parameter, - IModel* trajectory) -: IModelTrackingAlgorithm(parent) -, _ipp((TrackerParameter*) parameter) -{ - _cfg = static_cast(parent)->getConfig(); - _TrackingParameter = (TrackerParameter*) parameter; - _TrackedTrajectoryMajor = (BST::TrackedTrajectory*) trajectory; - _nn2d = std::make_shared(_TrackedTrajectoryMajor); - - _bd = BlobsDetector(); - - _noFish = -1; - - if (_cfg->DoNetwork) { - _listener = new TcpListener(this); - _listener->listen(QHostAddress::Any, _cfg->NetworkPort); - QObject::connect(_listener, - SIGNAL(newConnection()), - _listener, - SLOT(acceptConnection())); - } - - _lastImage = nullptr; - _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++) { - BST::TrackedTrajectory* t = dynamic_cast( - _TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - BST::TrackedElement* e = (BST::TrackedElement*) t->getLastChild(); - last.push_back(e->getFishPose()); - } - } - return last; -} - -void BioTrackerTrackingAlgorithm::refreshPolygon() -{ -} - -void BioTrackerTrackingAlgorithm::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 - Q_EMIT emitChangeDisplayImage("Original"); - break; - case 1: - sendImage = images->find(std::string("Background"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Background")); - Q_EMIT emitChangeDisplayImage(QString("Background")); - break; - case 2: - sendImage = images->find(std::string("Foreground Mask"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Foreground Mask")); - Q_EMIT emitChangeDisplayImage(QString("Foreground Mask")); - break; - case 3: - sendImage = images->find(std::string("Opened Mask"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Opened Mask")); - Q_EMIT emitChangeDisplayImage(QString("Opened Mask")); - break; - case 4: - sendImage = images->find(std::string("Closed Mask"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Closed Mask")); - Q_EMIT emitChangeDisplayImage(QString("Closed Mask")); - break; - case 5: - sendImage = images->find(std::string("Masked Greyscale"))->second; - Q_EMIT emitCvMatA(sendImage, QString("Masked Greyscale")); - Q_EMIT emitChangeDisplayImage(QString("Masked Greyscale")); - break; - } -} - -std::vector BioTrackerTrackingAlgorithm::getContourCentroids( - cv::Mat image) -{ - - std::vector> contours; - std::vector hierarchy; - std::vector centroids; - - cv::findContours(image, - contours, - hierarchy, - cv::RETR_TREE, - cv::CHAIN_APPROX_SIMPLE, - cv::Point(0, 0)); - - for (auto x : contours) { - cv::Point2f c(0, 0); - float i = 0; - for (auto y : x) { - c += cv::Point2f(y); - i++; - } - c.x = c.x / i; - c.y = c.y / i; - - // cv::RotatedRect minEllipse; - cv::RotatedRect bb = minAreaRect(x); - - // check if blob is in tracking area --> this can be optimized by - // checking earlier (only search blobs in tracking area) - if (!_AreaInfo->inTrackingArea(c)) { - continue; - } - - BlobPose bc(_AreaInfo->pxToCm(c), - c, - bb.angle, - bb.size.width, - bb.size.height); - - centroids.push_back(bc); - } - - return centroids; -} - -void BioTrackerTrackingAlgorithm::doTracking(std::shared_ptr 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(); - _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 mask = - images.find(std::string("Closed Mask"))->second; - std::shared_ptr greyMat = - images.find(std::string("Greyscale"))->second; - - // Find blobs via ellipsefitting - _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); - _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); - - auto foo = *images.find(std::string("Masked Greyscale"))->second; - - std::vector> contours; - std::vector hierarchy; - cv::findContours(foo, - contours, - hierarchy, - cv::RETR_TREE, - cv::CHAIN_APPROX_SIMPLE, - cv::Point(0, 0)); - - for (size_t i = 0; i < contours.size(); i++) { - drawContours(foo, contours, (int) i, cv::Scalar(255)); - } - - std::vector blobs = getContourCentroids(*mask); - - // 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 neighbor - 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++) { - BST::TrackedTrajectory* t = dynamic_cast( - _TrackedTrajectoryMajor->getChild(i)); - if (t && t->getValid() && !t->getFixed()) { - BST::TrackedElement* e = new BST::TrackedElement(t, - "n.a.", - t->getId()); - - e->setFishPose(std::get<0>(poses)[trajNumber]); - e->setTime(start); - t->add(e, framenumber); - trajNumber++; - } - } - - // Send forth new positions to the robotracker, if networking is enabled - if (_TrackingParameter->getDoNetwork()) { - std::vector 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); -} +#include "BioTrackerTrackingAlgorithm.h" +#include +#include "TrackedComponents/TrackedComponentFactory.h" +#include + +#include +#include + +BioTrackerTrackingAlgorithm::BioTrackerTrackingAlgorithm(IController* parent, + IModel* parameter, + IModel* trajectory) +: IModelTrackingAlgorithm(parent) +, _ipp((TrackerParameter*) parameter) +, _lastImage(std::nullopt) +{ + _cfg = static_cast(parent)->getConfig(); + _TrackingParameter = (TrackerParameter*) parameter; + _TrackedTrajectoryMajor = (BST::TrackedTrajectory*) trajectory; + _nn2d = std::make_shared(_TrackedTrajectoryMajor); + + _bd = BlobsDetector(); + + _noFish = -1; + + if (_cfg->DoNetwork) { + _listener = new TcpListener(this); + _listener->listen(QHostAddress::Any, _cfg->NetworkPort); + QObject::connect(_listener, + SIGNAL(newConnection()), + _listener, + SLOT(acceptConnection())); + } + + _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++) { + BST::TrackedTrajectory* t = dynamic_cast( + _TrackedTrajectoryMajor->getChild(i)); + if (t && t->getValid() && !t->getFixed()) { + BST::TrackedElement* e = (BST::TrackedElement*) t->getLastChild(); + last.push_back(e->getFishPose()); + } + } + return last; +} + +void BioTrackerTrackingAlgorithm::refreshPolygon() +{ +} + +void BioTrackerTrackingAlgorithm::receiveParametersChanged() +{ + if (_lastFramenumber >= 0 && _lastImage && !_lastImage->empty()) { + doTracking(*_lastImage, _lastFramenumber); + } +} + +void BioTrackerTrackingAlgorithm::sendSelectedImage( + QMap images) +{ + auto index = _TrackingParameter->getSendImage(); + auto name = [&]() -> QString { + switch (index) { + case 0: + return "Original"; + case 1: + return "Background"; + case 2: + return "Foreground Mask"; + case 3: + return "Opened Mask"; + case 4: + return "Closed Mask"; + case 5: + return "Masked Greyscale"; + default: + return ""; + } + }(); + + if (name.isEmpty()) { + qCritical() << "Invalid tracking image"; + return; + } + + if (index != 0) { + emit emitCvMatA(*images.find(name), name); + } + + emit emitChangeDisplayImage(name); +} + +std::vector BioTrackerTrackingAlgorithm::getContourCentroids( + cv::Mat image) +{ + + std::vector> contours; + std::vector hierarchy; + std::vector centroids; + + cv::findContours(image, + contours, + hierarchy, + cv::RETR_TREE, + cv::CHAIN_APPROX_SIMPLE, + cv::Point(0, 0)); + + for (auto x : contours) { + cv::Point2f c(0, 0); + float i = 0; + for (auto y : x) { + c += cv::Point2f(y); + i++; + } + c.x = c.x / i; + c.y = c.y / i; + + // cv::RotatedRect minEllipse; + cv::RotatedRect bb = minAreaRect(x); + + // check if blob is in tracking area --> this can be optimized by + // checking earlier (only search blobs in tracking area) + if (!_AreaInfo->inTrackingArea(c)) { + continue; + } + + BlobPose bc(_AreaInfo->pxToCm(c), + c, + bb.angle, + bb.size.width, + bb.size.height); + + centroids.push_back(bc); + } + + return centroids; +} + +void BioTrackerTrackingAlgorithm::doTracking(cv::Mat image, uint framenumber) +{ + _ipp.m_TrackingParameter = _TrackingParameter; + _lastImage = image; + _lastFramenumber = framenumber; + + // dont do nothing if we ain't got an image + if (image.empty()) { + return; + } + + if (_imageX != image.size().width || _imageY != image.size().height) { + _imageX = image.size().width; + _imageY = 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(); + _nn2d = std::make_shared(_TrackedTrajectoryMajor); + } + + if (_TrackingParameter->getResetBackground()) { + _TrackingParameter->setResetBackground(false); + _ipp.resetBackgroundImage(); + } + + // Do the preprocessing + auto images = _ipp.preProcess(image); + cv::Mat mask = *images.find("Closed Mask"); + cv::Mat greyMat = *images.find("Greyscale"); + + // Find blobs via ellipsefitting + _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); + _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); + + auto foo = *images.find("Masked Greyscale"); + + std::vector> contours; + std::vector hierarchy; + cv::findContours(foo, + contours, + hierarchy, + cv::RETR_TREE, + cv::CHAIN_APPROX_SIMPLE, + cv::Point(0, 0)); + + for (size_t i = 0; i < contours.size(); i++) { + drawContours(foo, contours, (int) i, cv::Scalar(255)); + } + + std::vector blobs = getContourCentroids(mask); + + // 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 neighbor + 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++) { + BST::TrackedTrajectory* t = dynamic_cast( + _TrackedTrajectoryMajor->getChild(i)); + if (t && t->getValid() && !t->getFixed()) { + BST::TrackedElement* e = new BST::TrackedElement(t, + "n.a.", + t->getId()); + + e->setFishPose(std::get<0>(poses)[trajNumber]); + e->setTime(start); + t->add(e, framenumber); + trajNumber++; + } + } + + // Send forth new positions to the robotracker, if networking is enabled + if (_TrackingParameter->getDoNetwork()) { + std::vector 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/Src/Model/BioTrackerTrackingAlgorithm.h b/Src/Model/BioTrackerTrackingAlgorithm.h index 4fb1042..4b916ca 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.h +++ b/Src/Model/BioTrackerTrackingAlgorithm.h @@ -1,73 +1,76 @@ -#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 "TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h" -#include "TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h" -#include "../Controller/ControllerTrackingAlgorithm.h" -#include "TrackingAlgorithm/NN2dMapper.h" -#include "Interfaces/IModel/IModelAreaDescriptor.h" -#include - -#include "Network/TcpListener.h" -#include "../Config.h" - -class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm -{ - Q_OBJECT -public: - BioTrackerTrackingAlgorithm(IController* parent, - 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: - std::vector getContourCentroids(cv::Mat image); - void refreshPolygon(); - void sendSelectedImage( - std::map>* images); - - std::vector getLastPositionsAsPose(); - - BST::TrackedTrajectory* _TrackedTrajectoryMajor; - TrackerParameter* _TrackingParameter; - IModelAreaDescriptor* _AreaInfo; - - TcpListener* _listener; - - ImagePreProcessor _ipp; - BlobsDetector _bd; - std::shared_ptr _nn2d; - - int _noFish; - - // std::ofstream _ofs; - - int _imageX; - int _imageY; - - std::shared_ptr _lastImage; - uint _lastFramenumber; - Config* _cfg; -}; - -#endif // BIOTRACKERTRACKINGALGORITHM_H +#ifndef BIOTRACKERTRACKINGALGORITHM_H +#define BIOTRACKERTRACKINGALGORITHM_H + +#include "Interfaces/IModel/IModel.h" + +#include "TrackerParameter.h" + +#include + +#include + +#include +#include "Interfaces/IModel/IModelTrackingAlgorithm.h" +#include "Interfaces/IModel/IModelDataExporter.h" +#include "TrackedComponents/TrackedElement.h" +#include "TrackedComponents/TrackedTrajectory.h" +#include "TrackingAlgorithm/imageProcessor/detector/blob/cvBlob/BlobsDetector.h" +#include "TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h" +#include "../Controller/ControllerTrackingAlgorithm.h" +#include "TrackingAlgorithm/NN2dMapper.h" +#include "Interfaces/IModel/IModelAreaDescriptor.h" +#include + +#include "Network/TcpListener.h" +#include "../Config.h" + +class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm +{ + Q_OBJECT +public: + BioTrackerTrackingAlgorithm(IController* parent, + IModel* parameter, + IModel* trajectory); + ~BioTrackerTrackingAlgorithm(); + +Q_SIGNALS: + void emitCvMatA(cv::Mat image, QString name); + void emitDimensionUpdate(int x, int y); + void emitTrackingDone(uint framenumber); + + // ITrackingAlgorithm interface +public Q_SLOTS: + void doTracking(cv::Mat image, uint framenumber) override; + void receiveAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); + void receiveParametersChanged(); + +private: + std::vector getContourCentroids(cv::Mat image); + void refreshPolygon(); + void sendSelectedImage(QMap images); + + std::vector getLastPositionsAsPose(); + + BST::TrackedTrajectory* _TrackedTrajectoryMajor; + TrackerParameter* _TrackingParameter; + IModelAreaDescriptor* _AreaInfo; + + TcpListener* _listener; + + ImagePreProcessor _ipp; + BlobsDetector _bd; + std::shared_ptr _nn2d; + + int _noFish; + + // std::ofstream _ofs; + + int _imageX; + int _imageY; + + std::optional _lastImage; + uint _lastFramenumber; + Config* _cfg; +}; + +#endif // BIOTRACKERTRACKINGALGORITHM_H diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 2a61ac8..598f404 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -32,8 +32,8 @@ void ImagePreProcessor::init() qFatal("Unsupported background subtraction algorithm"); } - m_backgroundImage = std::make_shared(); - m_foregroundMask = std::make_shared(); + m_backgroundImage = cv::Mat(); + m_foregroundMask = cv::Mat(); _backgroundSubtractionEnabled = true; _backgroundEnabled = true; @@ -96,56 +96,43 @@ cv::Mat ImagePreProcessor::backgroundSubtraction(cv::Mat& image) cv::Mat fgmask; m_subtractor->apply(image, fgmask, m_TrackingParameter->getLearningRate()); - m_subtractor->getBackgroundImage(*m_backgroundImage); + m_subtractor->getBackgroundImage(m_backgroundImage); return fgmask; } -std::map> ImagePreProcessor::preProcess( - std::shared_ptr p_image) +QMap ImagePreProcessor::preProcess(cv::Mat image) { - std::shared_ptr greyMat = std::make_shared(); - std::shared_ptr openedMask = std::make_shared(); - std::shared_ptr closedMask = std::make_shared(); + cv::Mat greyMat; + cv::Mat openedMask; + cv::Mat closedMask; - std::shared_ptr maskedGrey = std::make_shared(); + cv::Mat maskedGrey; - cv::cvtColor(*p_image, *greyMat, cv::COLOR_BGR2GRAY); + cv::cvtColor(image, greyMat, cv::COLOR_BGR2GRAY); // 1. step: do the background subtraction - *m_foregroundMask = backgroundSubtraction(*greyMat); + m_foregroundMask = backgroundSubtraction(greyMat); // 2. step: open the mask - *openedMask = dilate( - erode(*m_foregroundMask, m_TrackingParameter->getOpeningErosionSize()), + openedMask = dilate( + erode(m_foregroundMask, m_TrackingParameter->getOpeningErosionSize()), m_TrackingParameter->getOpeningDilationSize()); // 3. step: close the image - *closedMask = erode( - dilate(*openedMask, m_TrackingParameter->getClosingDilationSize()), + closedMask = erode( + dilate(openedMask, m_TrackingParameter->getClosingDilationSize()), m_TrackingParameter->getClosingErosionSize()); // 4. step: masked greyscale image - greyMat->copyTo(*maskedGrey, *closedMask); - - 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("Foreground Mask"), - m_foregroundMask)); - all.insert(std::pair>( - std::string("Opened Mask"), - openedMask)); - all.insert(std::pair>( - std::string("Closed Mask"), - closedMask)); - all.insert(std::pair>( - std::string("Masked Greyscale"), - maskedGrey)); + greyMat.copyTo(maskedGrey, closedMask); + + QMap all; + all.insert("Greyscale", greyMat); + all.insert("Background", m_backgroundImage); + all.insert("Foreground Mask", m_foregroundMask); + all.insert("Opened Mask", openedMask); + all.insert("Closed Mask", closedMask); + all.insert("Masked Greyscale", maskedGrey); return all; } diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h index 0acbcc4..7773edd 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -59,8 +60,7 @@ class ImagePreProcessor * @param: image, image to process, * @return: a pre-process image. */ - std::map> preProcess( - std::shared_ptr p_image); + QMap preProcess(cv::Mat p_image); /** * The method updates the image background. @@ -72,8 +72,8 @@ class ImagePreProcessor private: cv::Mat _outputImage; - std::shared_ptr m_backgroundImage; - std::shared_ptr m_foregroundMask; + cv::Mat m_backgroundImage; + cv::Mat m_foregroundMask; // parameters for image pre-processing bool _backgroundSubtractionEnabled; From aa0d4cc0c5b4099ee13c4121177cd655b34fcb0e Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Thu, 11 Aug 2022 14:35:03 +0200 Subject: [PATCH 21/22] Follow interface changes --- Src/BioTrackerPlugin.cpp | 20 +- Src/BioTrackerPlugin.h | 7 +- .../ControllerTrackingAlgorithm.cpp | 8 +- Src/Controller/ControllerTrackingAlgorithm.h | 3 +- Src/Model/BioTrackerTrackingAlgorithm.cpp | 57 +-- Src/Model/BioTrackerTrackingAlgorithm.h | 3 +- Src/View/TrackerParameterView.cpp | 428 +++++++++--------- Src/View/TrackerParameterView.h | 1 - Src/View/TrackerParameterView.ui | 84 ---- 9 files changed, 228 insertions(+), 383 deletions(-) diff --git a/Src/BioTrackerPlugin.cpp b/Src/BioTrackerPlugin.cpp index 12a7cc2..ececc60 100644 --- a/Src/BioTrackerPlugin.cpp +++ b/Src/BioTrackerPlugin.cpp @@ -42,7 +42,7 @@ IModelTrackedComponentFactory* BioTrackerPlugin::getComponentFactory() return new TrackedComponentFactory(); } -void BioTrackerPlugin::createPlugin() +void BioTrackerPlugin::init() { _cfg = new Config(); _cfg->load(Config::configLocation, "BackgroundSubtractionConfig.ini"); @@ -59,7 +59,15 @@ void BioTrackerPlugin::createPlugin() connectInterfaces(); - qDebug() << "BST-Tracker loaded!"; + emit trackingImageNamesChanged({ + "Greyscale", + "Background", + "Foreground Mask", + "Opened Mask", + "Closed Mask", + }); + + qDebug() << "BST-Tracker initialized"; } void BioTrackerPlugin::connectInterfaces() @@ -71,17 +79,13 @@ void BioTrackerPlugin::connectInterfaces() // controllertrackingalgorithm QObject::connect(ctrAlg, - &ControllerTrackingAlgorithm::emitCvMat, + &ControllerTrackingAlgorithm::trackingImagesChanged, this, - &BioTrackerPlugin::emitCvMat); + &BioTrackerPlugin::trackingImagesChanged); QObject::connect(ctrAlg, &ControllerTrackingAlgorithm::emitTrackingDone, this, &BioTrackerPlugin::emitTrackingDone); - QObject::connect(ctrAlg, - &ControllerTrackingAlgorithm::emitChangeDisplayImage, - this, - &BioTrackerPlugin::emitChangeDisplayImage); QObject::connect( this, &BioTrackerPlugin::emitAreaDescriptorUpdate, diff --git a/Src/BioTrackerPlugin.h b/Src/BioTrackerPlugin.h index 847b047..f9490a0 100644 --- a/Src/BioTrackerPlugin.h +++ b/Src/BioTrackerPlugin.h @@ -28,18 +28,13 @@ class Q_DECL_EXPORT BioTrackerPlugin : public IBioTrackerPlugin IModelTrackedComponentFactory* getComponentFactory(); public: - void createPlugin(); + void init(); void sendCorePermissions(); private: void connectInterfaces(); signals: - void emitCvMat(cv::Mat 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); diff --git a/Src/Controller/ControllerTrackingAlgorithm.cpp b/Src/Controller/ControllerTrackingAlgorithm.cpp index a368101..5195f0a 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.cpp +++ b/Src/Controller/ControllerTrackingAlgorithm.cpp @@ -56,17 +56,13 @@ void ControllerTrackingAlgorithm::connectModelToController() BioTrackerTrackingAlgorithm* trackingAlg = qobject_cast(m_Model); QObject::connect(trackingAlg, - &BioTrackerTrackingAlgorithm::emitCvMatA, + &BioTrackerTrackingAlgorithm::trackingImagesChanged, this, - &ControllerTrackingAlgorithm::emitCvMat); + &ControllerTrackingAlgorithm::trackingImagesChanged); QObject::connect(trackingAlg, &BioTrackerTrackingAlgorithm::emitTrackingDone, this, &ControllerTrackingAlgorithm::emitTrackingDone); - QObject::connect(trackingAlg, - &BioTrackerTrackingAlgorithm::emitChangeDisplayImage, - this, - &ControllerTrackingAlgorithm::emitChangeDisplayImage); QObject::connect( this, &ControllerTrackingAlgorithm::emitAreaDescriptorUpdate, diff --git a/Src/Controller/ControllerTrackingAlgorithm.h b/Src/Controller/ControllerTrackingAlgorithm.h index eeb75a4..9a599f7 100644 --- a/Src/Controller/ControllerTrackingAlgorithm.h +++ b/Src/Controller/ControllerTrackingAlgorithm.h @@ -41,9 +41,8 @@ public Q_SLOTS: void connectModelToController() override; Q_SIGNALS: - void emitCvMat(cv::Mat mat, QString name); void emitTrackingDone(uint framenumber); - void emitChangeDisplayImage(QString str); + void trackingImagesChanged(QMap images); void emitAreaDescriptorUpdate(IModelAreaDescriptor* areaDescr); private: diff --git a/Src/Model/BioTrackerTrackingAlgorithm.cpp b/Src/Model/BioTrackerTrackingAlgorithm.cpp index 8b771a8..78514cf 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.cpp +++ b/Src/Model/BioTrackerTrackingAlgorithm.cpp @@ -77,41 +77,6 @@ void BioTrackerTrackingAlgorithm::receiveParametersChanged() } } -void BioTrackerTrackingAlgorithm::sendSelectedImage( - QMap images) -{ - auto index = _TrackingParameter->getSendImage(); - auto name = [&]() -> QString { - switch (index) { - case 0: - return "Original"; - case 1: - return "Background"; - case 2: - return "Foreground Mask"; - case 3: - return "Opened Mask"; - case 4: - return "Closed Mask"; - case 5: - return "Masked Greyscale"; - default: - return ""; - } - }(); - - if (name.isEmpty()) { - qCritical() << "Invalid tracking image"; - return; - } - - if (index != 0) { - emit emitCvMatA(*images.find(name), name); - } - - emit emitChangeDisplayImage(name); -} - std::vector BioTrackerTrackingAlgorithm::getContourCentroids( cv::Mat image) { @@ -204,21 +169,6 @@ void BioTrackerTrackingAlgorithm::doTracking(cv::Mat image, uint framenumber) _bd.setMaxBlobSize(_TrackingParameter->getMaxBlobSize()); _bd.setMinBlobSize(_TrackingParameter->getMinBlobSize()); - auto foo = *images.find("Masked Greyscale"); - - std::vector> contours; - std::vector hierarchy; - cv::findContours(foo, - contours, - hierarchy, - cv::RETR_TREE, - cv::CHAIN_APPROX_SIMPLE, - cv::Point(0, 0)); - - for (size_t i = 0; i < contours.size(); i++) { - drawContours(foo, contours, (int) i, cv::Scalar(255)); - } - std::vector blobs = getContourCentroids(mask); // Never switch the position of the trajectories. The NN2d mapper relies on @@ -256,12 +206,7 @@ void BioTrackerTrackingAlgorithm::doTracking(cv::Mat image, uint framenumber) start); } - sendSelectedImage(images); - - // First the user still wants to see the original image, right? - if (framenumber == 1) { - Q_EMIT emitChangeDisplayImage("Original"); - } + emit trackingImagesChanged(images); std::string newSel = _TrackingParameter->getNewSelection(); diff --git a/Src/Model/BioTrackerTrackingAlgorithm.h b/Src/Model/BioTrackerTrackingAlgorithm.h index 4b916ca..393479f 100644 --- a/Src/Model/BioTrackerTrackingAlgorithm.h +++ b/Src/Model/BioTrackerTrackingAlgorithm.h @@ -34,7 +34,7 @@ class BioTrackerTrackingAlgorithm : public IModelTrackingAlgorithm ~BioTrackerTrackingAlgorithm(); Q_SIGNALS: - void emitCvMatA(cv::Mat image, QString name); + void trackingImagesChanged(QMap images); void emitDimensionUpdate(int x, int y); void emitTrackingDone(uint framenumber); @@ -47,7 +47,6 @@ public Q_SLOTS: private: std::vector getContourCentroids(cv::Mat image); void refreshPolygon(); - void sendSelectedImage(QMap images); std::vector getLastPositionsAsPose(); diff --git a/Src/View/TrackerParameterView.cpp b/Src/View/TrackerParameterView.cpp index 3707fdf..9666664 100644 --- a/Src/View/TrackerParameterView.cpp +++ b/Src/View/TrackerParameterView.cpp @@ -1,218 +1,210 @@ -#include "TrackerParameterView.h" -#include "ui_TrackerParameterView.h" - -#include - -TrackerParameterView::TrackerParameterView(QWidget* parent, - IController* controller, - IModel* model) -: IViewWidget(parent, controller, model) -, _ui(new Ui::TrackerParameterView) -, _useAbsDiff(nullptr) -, _binThres(nullptr) -, _maxImg(nullptr) -{ - _ui->setupUi(this); - getNotified(); - - auto parameter = qobject_cast(getModel()); - - connect(_ui->algorithmCB, - &QComboBox::currentTextChanged, - parameter, - &TrackerParameter::setAlgorithm); - connect(_ui->algorithmCB, - &QComboBox::currentTextChanged, - this, - &TrackerParameterView::initSubtractorSpecificUI); - - connect(_ui->lineEdit_3_OpeningErosionSize, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setOpeningErosionSize); - connect(_ui->lineEdit_3_OpeningErosionSize, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_4_OpeningDilationSize, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setOpeningDilationSize); - connect(_ui->lineEdit_4_OpeningDilationSize, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_4_ClosingDilationSize, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setClosingDilationSize); - connect(_ui->lineEdit_4_ClosingDilationSize, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_3_ClosingErosionSize, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setClosingErosionSize); - connect(_ui->lineEdit_3_ClosingErosionSize, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_8_MinBlob, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setMinBlobSize); - connect(_ui->lineEdit_8_MinBlob, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_9MaxBlob, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setMaxBlobSize); - connect(_ui->lineEdit_9MaxBlob, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - connect(_ui->lineEdit_7_learningRate, - qOverload(&QDoubleSpinBox::valueChanged), - parameter, - &TrackerParameter::setLearningRate); - connect(_ui->lineEdit_7_learningRate, - qOverload(&QDoubleSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - initSubtractorSpecificUI(_ui->algorithmCB->currentText()); - - _ui->algorithmCB->setEnabled(false); -} - -TrackerParameterView::~TrackerParameterView() -{ - delete _ui; -} - -void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) -{ - auto parameter = qobject_cast(getModel()); - - while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { - _ui->algorithmSpecificParameterLayout->removeRow(0); - } - - _useAbsDiff = nullptr; - _binThres = nullptr; - _maxImg = nullptr; - - if (algorithm == QString("Custom")) { - _useAbsDiff = new QCheckBox(); - _useAbsDiff->setText(" "); - _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); - _ui->algorithmSpecificParameterLayout->addRow( - tr("Use Absolute Difference:"), - _useAbsDiff); - - connect(_useAbsDiff, - &QCheckBox::toggled, - parameter, - &TrackerParameter::setUseAbsoluteDifference); - connect(_useAbsDiff, - &QCheckBox::toggled, - this, - &TrackerParameterView::parametersChanged); - - _binThres = new QSpinBox(); - _binThres->setMinimum(1); - _binThres->setMaximum(255); - _binThres->setValue(parameter->getBinarizationThreshold()); - _ui->algorithmSpecificParameterLayout->addRow( - tr("Binarization Threshold:"), - _binThres); - - connect(_binThres, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setBinarizationThreshold); - connect(_binThres, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - - _maxImg = new QSpinBox(); - _maxImg->setMinimum(1); - _maxImg->setMaximum(255); - _maxImg->setValue(parameter->getMaximumImageValue()); - _ui->algorithmSpecificParameterLayout->addRow( - tr("Maximum Image Value:"), - _maxImg); - - connect(_maxImg, - qOverload(&QSpinBox::valueChanged), - parameter, - &TrackerParameter::setMaximumImageValue); - connect(_maxImg, - qOverload(&QSpinBox::valueChanged), - this, - &TrackerParameterView::parametersChanged); - } else { - qFatal("Unsupported background subtraction algorithm"); - } - - emit parametersChanged(); -} - -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::getNotified() -{ - TrackerParameter* parameter = qobject_cast(getModel()); - - _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); - - if (_useAbsDiff) { - _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); - } - - if (_binThres) { - _binThres->setValue(parameter->getBinarizationThreshold()); - } - - if (_maxImg) { - _maxImg->setValue(parameter->getMaximumImageValue()); - } - - _ui->lineEdit_3_OpeningErosionSize->setValue( - parameter->getOpeningErosionSize()); - - _ui->lineEdit_4_OpeningDilationSize->setValue( - parameter->getOpeningDilationSize()); - - _ui->lineEdit_4_ClosingDilationSize->setValue( - parameter->getClosingDilationSize()); - - _ui->lineEdit_3_ClosingErosionSize->setValue( - parameter->getClosingErosionSize()); - - _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); - - _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); -} +#include "TrackerParameterView.h" +#include "ui_TrackerParameterView.h" + +#include + +TrackerParameterView::TrackerParameterView(QWidget* parent, + IController* controller, + IModel* model) +: IViewWidget(parent, controller, model) +, _ui(new Ui::TrackerParameterView) +, _useAbsDiff(nullptr) +, _binThres(nullptr) +, _maxImg(nullptr) +{ + _ui->setupUi(this); + getNotified(); + + auto parameter = qobject_cast(getModel()); + + connect(_ui->algorithmCB, + &QComboBox::currentTextChanged, + parameter, + &TrackerParameter::setAlgorithm); + connect(_ui->algorithmCB, + &QComboBox::currentTextChanged, + this, + &TrackerParameterView::initSubtractorSpecificUI); + + connect(_ui->lineEdit_3_OpeningErosionSize, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setOpeningErosionSize); + connect(_ui->lineEdit_3_OpeningErosionSize, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_4_OpeningDilationSize, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setOpeningDilationSize); + connect(_ui->lineEdit_4_OpeningDilationSize, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_4_ClosingDilationSize, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setClosingDilationSize); + connect(_ui->lineEdit_4_ClosingDilationSize, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_3_ClosingErosionSize, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setClosingErosionSize); + connect(_ui->lineEdit_3_ClosingErosionSize, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_8_MinBlob, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMinBlobSize); + connect(_ui->lineEdit_8_MinBlob, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_9MaxBlob, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMaxBlobSize); + connect(_ui->lineEdit_9MaxBlob, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + connect(_ui->lineEdit_7_learningRate, + qOverload(&QDoubleSpinBox::valueChanged), + parameter, + &TrackerParameter::setLearningRate); + connect(_ui->lineEdit_7_learningRate, + qOverload(&QDoubleSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + initSubtractorSpecificUI(_ui->algorithmCB->currentText()); + + _ui->algorithmCB->setEnabled(false); +} + +TrackerParameterView::~TrackerParameterView() +{ + delete _ui; +} + +void TrackerParameterView::initSubtractorSpecificUI(QString algorithm) +{ + auto parameter = qobject_cast(getModel()); + + while (_ui->algorithmSpecificParameterLayout->rowCount() > 0) { + _ui->algorithmSpecificParameterLayout->removeRow(0); + } + + _useAbsDiff = nullptr; + _binThres = nullptr; + _maxImg = nullptr; + + if (algorithm == QString("Custom")) { + _useAbsDiff = new QCheckBox(); + _useAbsDiff->setText(" "); + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Use Absolute Difference:"), + _useAbsDiff); + + connect(_useAbsDiff, + &QCheckBox::toggled, + parameter, + &TrackerParameter::setUseAbsoluteDifference); + connect(_useAbsDiff, + &QCheckBox::toggled, + this, + &TrackerParameterView::parametersChanged); + + _binThres = new QSpinBox(); + _binThres->setMinimum(1); + _binThres->setMaximum(255); + _binThres->setValue(parameter->getBinarizationThreshold()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Binarization Threshold:"), + _binThres); + + connect(_binThres, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setBinarizationThreshold); + connect(_binThres, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + + _maxImg = new QSpinBox(); + _maxImg->setMinimum(1); + _maxImg->setMaximum(255); + _maxImg->setValue(parameter->getMaximumImageValue()); + _ui->algorithmSpecificParameterLayout->addRow( + tr("Maximum Image Value:"), + _maxImg); + + connect(_maxImg, + qOverload(&QSpinBox::valueChanged), + parameter, + &TrackerParameter::setMaximumImageValue); + connect(_maxImg, + qOverload(&QSpinBox::valueChanged), + this, + &TrackerParameterView::parametersChanged); + } else { + qFatal("Unsupported background subtraction algorithm"); + } + + emit parametersChanged(); +} + +void TrackerParameterView::on_pushButtonResetBackground_clicked() +{ + TrackerParameter* parameter = qobject_cast(getModel()); + parameter->setResetBackground(true); +} + +void TrackerParameterView::getNotified() +{ + TrackerParameter* parameter = qobject_cast(getModel()); + + _ui->lineEdit_7_learningRate->setValue(parameter->getLearningRate()); + + if (_useAbsDiff) { + _useAbsDiff->setChecked(parameter->getUseAbsoluteDifference()); + } + + if (_binThres) { + _binThres->setValue(parameter->getBinarizationThreshold()); + } + + if (_maxImg) { + _maxImg->setValue(parameter->getMaximumImageValue()); + } + + _ui->lineEdit_3_OpeningErosionSize->setValue( + parameter->getOpeningErosionSize()); + + _ui->lineEdit_4_OpeningDilationSize->setValue( + parameter->getOpeningDilationSize()); + + _ui->lineEdit_4_ClosingDilationSize->setValue( + parameter->getClosingDilationSize()); + + _ui->lineEdit_3_ClosingErosionSize->setValue( + parameter->getClosingErosionSize()); + + _ui->lineEdit_8_MinBlob->setValue(parameter->getMinBlobSize()); + + _ui->lineEdit_9MaxBlob->setValue(parameter->getMaxBlobSize()); +} diff --git a/Src/View/TrackerParameterView.h b/Src/View/TrackerParameterView.h index da49ce8..678d653 100644 --- a/Src/View/TrackerParameterView.h +++ b/Src/View/TrackerParameterView.h @@ -24,7 +24,6 @@ class TrackerParameterView : public IViewWidget private slots: void on_pushButtonResetBackground_clicked(); - void on_comboBoxSendImage_currentIndexChanged(int v); public: signals: diff --git a/Src/View/TrackerParameterView.ui b/Src/View/TrackerParameterView.ui index 26d1e8f..a6eb0ee 100644 --- a/Src/View/TrackerParameterView.ui +++ b/Src/View/TrackerParameterView.ui @@ -403,90 +403,6 @@ - - - - Display - - - - - - QFormLayout::ExpandingFieldsGrow - - - 108 - - - - - Image: - - - - - - - - 0 - 0 - - - - - 132 - 0 - - - - - 132 - 16777215 - - - - Choose which image to display for the next frames. Tracking must be actived. - - - Original - - - - Original - - - - - Background - - - - - Foreground Mask - - - - - Opened Mask - - - - - Closed Mask - - - - - Masked Greyscale - - - - - - - - - From b8ce83c5600454201a629a745adb8c2ae18a2712 Mon Sep 17 00:00:00 2001 From: Moritz Maxeiner Date: Thu, 11 Aug 2022 16:38:28 +0200 Subject: [PATCH 22/22] Fix masked greyscale image being emitted --- .../imageProcessor/preprocessor/ImagePreProcessor.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp index 598f404..eca112f 100644 --- a/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp +++ b/Src/Model/TrackingAlgorithm/imageProcessor/preprocessor/ImagePreProcessor.cpp @@ -123,16 +123,12 @@ QMap ImagePreProcessor::preProcess(cv::Mat image) dilate(openedMask, m_TrackingParameter->getClosingDilationSize()), m_TrackingParameter->getClosingErosionSize()); - // 4. step: masked greyscale image - greyMat.copyTo(maskedGrey, closedMask); - QMap all; all.insert("Greyscale", greyMat); all.insert("Background", m_backgroundImage); all.insert("Foreground Mask", m_foregroundMask); all.insert("Opened Mask", openedMask); all.insert("Closed Mask", closedMask); - all.insert("Masked Greyscale", maskedGrey); return all; }