From d32d359e9e14a24c35063c035cbfa1f9b683df23 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Thu, 21 Oct 2021 09:37:00 +0200
Subject: [PATCH 01/45] Move plausiblility to be a free function

Signed-off-by: schroedtert <t.schroedter@fz-juelich.de>
---
 CMakeLists.txt         |   5 +-
 include/plausibility.h |  48 ++++++++++
 include/tracker.h      |   9 ++
 src/petrack.cpp        |  27 +++---
 src/plausibility.cpp   | 195 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 273 insertions(+), 11 deletions(-)
 create mode 100644 include/plausibility.h
 create mode 100644 src/plausibility.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b4fe811d5..085465345 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -398,6 +398,7 @@ target_sources(petrack_core PRIVATE
     include/autosaveSettings.h
     include/editMoCapDialog.h
     include/moCapEditingWidget.h
+    include/plausibility.h
     include/coordinateStructs.h
 )
 
@@ -474,6 +475,7 @@ target_sources(petrack_core PRIVATE
     ui/coordinateSystemBox.ui
     ui/moCapEditingWidget.ui
     ui/editMoCapDialog.ui
+    src/plausibility.cpp
     ui/about.ui
     ui/codeMarker.ui
     ui/colorMarker.ui
@@ -492,7 +494,8 @@ target_sources(petrack_core PRIVATE
 
 target_sources(petrack PRIVATE
   petrack.rc
-  icons/icons.qrc)
+  icons/icons.qrc
+)
 
 #*****************************************************************************
 # CODE AUS DER ALTEN .PRO DATEI, DER NOCH NICHT IN DIE CMAKE EINGEBAUT WURDE *
diff --git a/include/plausibility.h b/include/plausibility.h
new file mode 100644
index 000000000..cdbb10150
--- /dev/null
+++ b/include/plausibility.h
@@ -0,0 +1,48 @@
+/*
+ * PeTrack - Software for tracking pedestrians movement in videos
+ * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
+ * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
+ * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef PLAUSIBILITY_H
+#define PLAUSIBILITY_H
+
+#include "tracker.h"
+
+#include <string>
+#include <vector>
+
+namespace plausibility
+{
+struct FailedCheck
+{
+    int         pers{};
+    int         frame{};
+    std::string message{};
+};
+
+std::vector<FailedCheck> checkPlausibility(
+    Tracker &      tracker,
+    Petrack &      petrack,
+    const cv::Mat &mat,
+    bool           testEqual    = true,
+    bool           testVelocity = true,
+    bool           testInside   = true,
+    bool           testLength   = true);
+
+} // namespace plausibility
+#endif // PLAUSIBILITY_H
diff --git a/include/tracker.h b/include/tracker.h
index 7a45e29fe..ffc5a0af6 100644
--- a/include/tracker.h
+++ b/include/tracker.h
@@ -21,6 +21,7 @@
 
 #include "recognition.h"
 #include "vector.h"
+//#include "plausibility.h"
 
 #include <QColor>
 #include <QList>
@@ -300,6 +301,14 @@ public:
         QSet<size_t>            onlyVisible        = QSet<size_t>(),
         int                     errorScaleExponent = 0);
 
+    void checkPlausibility(
+        QList<int> &pers,
+        QList<int> &frame,
+        bool        testEqual    = true,
+        bool        testVelocity = true,
+        bool        testInside   = true,
+        bool        testLength   = true);
+
 private:
     bool tryMergeTrajectories(const TrackPoint &v, size_t i, int frame);
 
diff --git a/src/petrack.cpp b/src/petrack.cpp
index 98d9c1b58..c22b3f9a4 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -69,6 +69,7 @@
 #include <deque>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
+#include <plausibility.h>
 
 int Petrack::trcVersion = 0;
 
@@ -2786,25 +2787,31 @@ void Petrack::importTracker(QString dest) // default = ""
 
 void Petrack::testTracker()
 {
-    static int idx = 0; // index in Fehlerliste, die als letztes angesprungen wurde
-    QList<int> pers, frame;
-
-    mPersonStorage.checkPlausibility(
-        pers,
-        frame,
+    static size_t                          idx = 0; // index in Fehlerliste, die als letztes angesprungen wurde
+    QList<int>                             pers, frame;
+    std::vector<plausibility::FailedCheck> failedChecks = plausibility::checkPlausibility(
+        *mTracker,
+        *this,
+        mImg,
         mControlWidget->isTestEqualChecked(),
         mControlWidget->isTestVelocityChecked(),
         mControlWidget->isTestInsideChecked(),
         mControlWidget->isTestLengthChecked());
-    if(pers.length() <= idx)
+
+    for(auto failedCheck : failedChecks)
+    {
+        debout << failedCheck.message << std::endl;
+    }
+
+    if(failedChecks.size() <= idx)
     {
         idx = 0;
     }
-    if(pers.length() > idx)
+    if(failedChecks.size() > idx)
     {
         mControlWidget->setTrackShowOnly(Qt::Checked);
-        mControlWidget->setTrackShowOnlyNr(pers[idx]);
-        mPlayerWidget->skipToFrame(frame[idx]);
+        mControlWidget->setTrackShowOnlyNr(failedChecks[idx].pers);
+        mPlayerWidget->skipToFrame(failedChecks[idx].frame);
         ++idx;
     }
 }
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
new file mode 100644
index 000000000..6cdb91952
--- /dev/null
+++ b/src/plausibility.cpp
@@ -0,0 +1,195 @@
+/*
+ * PeTrack - Software for tracking pedestrians movement in videos
+ * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
+ * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
+ * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "plausibility.h"
+
+#include "animation.h"
+#include "recognitionRoiItem.h"
+
+namespace plausibility
+{
+/**
+* @brief Performs different tests to check the plausibility of trajectories.
+ *
+* This method can check for
+* <ul><li>shortness (less than 10 points)</li>
+* <li>start and endpoint (both should be outside the reco ROI
+* with exceptions for the beginning and end of the video)</li>
+* <li>Fast variations of speed (4 frame interval)</li>
+* <li>TrackPoints are too close together</li></ul>
+*
+* @param tracker containing the trajectory data
+* @param petrack main window (some data is only accessbile that way currently)
+* @param mat current image (only used to get size of the image)
+* @param testEqual true if warning for very close points are wished
+* @param testVelocity true if warning for fast speed variations is whished
+* @param testInside true if warning for start and endpoint in reco ROI is wished
+* @param testLength if warning for very short trajectories is wished
+* @return all failed checks, for enabled tests
+*/
+std::vector<FailedCheck> checkPlausibility(
+    Tracker &      tracker,
+    Petrack &      petrack,
+    const cv::Mat &mat,
+    bool           testEqual,
+    bool           testVelocity,
+    bool           testInside,
+    bool           testLength)
+{
+    std::vector<plausibility::FailedCheck> failedChecks;
+
+    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, petrack.window());
+    progress.setWindowTitle("Check plausibility");
+    progress.setWindowModality(Qt::WindowModal);
+    progress.setVisible(true);
+    progress.setValue(0);
+    progress.setLabelText("Check Plausibility...");
+    static int margin    = 30; // rand am bild, ab dem trajectorie verloren sein darf
+    int        bS        = petrack.getImageBorderSize();
+    QRectF     rect      = petrack.getRecoRoiItem()->rect();
+    int        lastFrame = petrack.getAnimation()->getNumFrames() - 1;
+
+    // test, if the trajectory is very short (less than 10 Trackpoints)
+    if(testLength)
+    {
+        progress.setValue(0);
+        progress.setLabelText("Check trajectories lengths...");
+        qApp->processEvents();
+
+        for(int i = 0; i < tracker.size(); ++i) // ueber TrackPerson
+        {
+            progress.setValue(i * 100. / tracker.size());
+            qApp->processEvents();
+            if(tracker.at(i).size() < 10)
+            {
+                std::stringstream stream;
+                stream << "Trajectory of person " << i + 1 << " has less than 10 trackpoints!";
+                failedChecks.push_back({i + 1, tracker[i].firstFrame(), stream.str()});
+            }
+        }
+    }
+
+    // check, if trajectory starts and ends outside the recognition area
+    if(testInside)
+    {
+        progress.setValue(100);
+        progress.setLabelText("Check if trajectories are inside image...");
+        qApp->processEvents();
+
+        for(int i = 0; i < tracker.size(); ++i) // ueber TrackPerson
+        {
+            qApp->processEvents();
+            progress.setValue(100 + i * 100. / tracker.size());
+            double x = tracker[i].first().x();
+            double y = tracker[i].first().y();
+            // mGrey hat gleiche groesse wie zuletzt getracktes bild
+            if((tracker[i].firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
+                x <= MIN(mat.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
+                y <= MIN(mat.rows - 1 - 2 * bS - margin, rect.y() + rect.height())))
+            {
+                std::stringstream stream;
+                stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
+                failedChecks.push_back({i + 1, tracker[i].firstFrame(), stream.str()});
+            }
+
+            x = tracker[i].last().x();
+            y = tracker[i].last().y();
+
+            // mGrey hat gleiche groesse wie zuletzt getracktes bild
+            if(tracker[i].lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
+               x <= MIN(mat.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
+               y <= MIN(mat.rows - 1 - 2 * bS - margin, rect.y() + rect.height()))
+            {
+                std::stringstream stream;
+                stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
+                failedChecks.push_back({i + 1, tracker[i].lastFrame(), stream.str()});
+            }
+        }
+    }
+
+    // testen, ob grosse Geschwindigkeitsaenderungen
+    // statt distanz koennte man auch noch vektoren vergleichen, was genauere analyse waer!!!!
+    if(testVelocity)
+    {
+        qApp->processEvents();
+        progress.setValue(200);
+        progress.setLabelText("Check velocity...");
+
+        for(int i = 0; i < tracker.size(); ++i) // ueber TrackPerson
+        {
+            qApp->processEvents();
+            progress.setValue(200 + i * 100. / tracker.size());
+            for(int j = 1; j < tracker.at(i).size() - 2; ++j) // ueber TrackPoint (ohne ersten und letzten beiden)
+            {
+                double d01 = tracker.at(i).at(j).distanceToPoint(tracker.at(i).at(j - 1));
+                double d12 = tracker.at(i).at(j + 1).distanceToPoint(tracker.at(i).at(j));
+                double d23 = tracker.at(i).at(j + 2).distanceToPoint(tracker.at(i).at(j + 1));
+                if(((1.8 * (d01 + d23) / 2.) < d12) &&
+                   ((d12 > 6.) ||
+                    ((d01 + d23) / 2. > 3.))) // geschwindigkeit 1,8-fach && mindestpixelbewegung im schnitt von 3
+                {
+                    std::stringstream stream;
+                    stream << "Fast variation of velocity of person " << i + 1 << " between frame "
+                           << j + tracker.at(i).firstFrame() << " and " << j + 1 + tracker.at(i).firstFrame() << "!";
+                    failedChecks.push_back({i + 1, j + tracker.at(i).firstFrame(), stream.str()});
+                }
+            }
+        }
+    }
+
+    // testen, ob zwei trackpoint sehr nah beieinanderliegen (es gibt trajektorien, die uebereinander liegen, wenn nicht
+    // genmergt wird)
+    if(testEqual)
+    {
+        progress.setValue(300);
+        progress.setLabelText("Check if trajectories are equal...");
+        qApp->processEvents();
+
+        int lLF = tracker.largestLastFrame();
+        int f;
+        for(f = tracker.smallestFirstFrame(); f <= lLF; ++f)
+        {
+            progress.setValue(300 + f * 100. / lLF);
+            qApp->processEvents();
+
+            for(int i = 0; i < tracker.size(); ++i)
+            {
+                // if (!pers.contains(i+1)) man koennte nur einmal eine Person aufnehmen, da aufeinanderfolgende frames
+                // oft betroffen
+                for(int j = i + 1; j < tracker.size(); ++j)
+                {
+                    if(tracker.at(i).trackPointExist(f) && tracker.at(j).trackPointExist(f))
+                    {
+                        if(tracker.at(i).trackPointAt(f).distanceToPoint(tracker.at(j).trackPointAt(f)) <
+                           petrack.getHeadSize(nullptr, i, f) / 2.)
+                        {
+                            std::stringstream stream;
+                            stream << "Person " << i + 1 << " and " << j + 1
+                                   << " are very close to each other at frame " << f << "!";
+                            failedChecks.push_back({i + 1, f, stream.str()});
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return failedChecks;
+}
+} // namespace plausibility
\ No newline at end of file
-- 
GitLab


From 29a86428af70dc0f9e9743655420122baec98dbc Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Thu, 21 Oct 2021 14:10:19 +0200
Subject: [PATCH 02/45] Add corrrection tab

- Table shows the results of the failed test (formerly output was posted to the commandline)
- Clicking on test jumps to frame and shows only the person with the issue

Signed-off-by: schroedtert <t.schroedter@fz-juelich.de>
---
 CMakeLists.txt         |   3 +
 include/control.h      |   5 +-
 include/correction.h   |  90 +++++++++++++++++++++++++
 include/petrack.h      |  11 ++-
 include/plausibility.h |   1 +
 include/tracker.h      |   1 -
 src/control.cpp        |  10 +--
 src/correction.cpp     | 148 +++++++++++++++++++++++++++++++++++++++++
 src/petrack.cpp        |  33 +--------
 src/plausibility.cpp   |  34 +++++-----
 ui/control.ui          | 110 ++----------------------------
 ui/correction.ui       | 131 ++++++++++++++++++++++++++++++++++++
 12 files changed, 410 insertions(+), 167 deletions(-)
 create mode 100644 include/correction.h
 create mode 100644 src/correction.cpp
 create mode 100644 ui/correction.ui

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 085465345..4321b9e80 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -400,6 +400,7 @@ target_sources(petrack_core PRIVATE
     include/moCapEditingWidget.h
     include/plausibility.h
     include/coordinateStructs.h
+    include/correction.h
 )
 
 target_sources(petrack_core PRIVATE
@@ -476,6 +477,7 @@ target_sources(petrack_core PRIVATE
     ui/moCapEditingWidget.ui
     ui/editMoCapDialog.ui
     src/plausibility.cpp
+    src/correction.cpp
     ui/about.ui
     ui/codeMarker.ui
     ui/colorMarker.ui
@@ -485,6 +487,7 @@ target_sources(petrack_core PRIVATE
     ui/control.ui
     ui/openMoCapDialog.ui
     ui/moCapSelectionWidget.ui
+    ui/correction.ui
     ui/filterBeforeBox.ui
     ui/intrinsicBox.ui
     ui/extrinsicBox.ui
diff --git a/include/control.h b/include/control.h
index bcec87127..e50038bab 100644
--- a/include/control.h
+++ b/include/control.h
@@ -26,6 +26,8 @@
 #include <Qt>
 #include <QtWidgets>
 
+class Petrack;
+class Correction;
 class QGraphicsScene;
 class QDomElement;
 class IntrinsicBox;
@@ -320,7 +322,6 @@ private slots:
     void on_trackReset_clicked();
     void on_trackExport_clicked();
     void on_trackImport_clicked();
-    void on_trackTest_clicked();
 
     void on_trackRegionScale_valueChanged(int i);
     void on_trackRegionLevels_valueChanged(int i);
@@ -575,6 +576,8 @@ private:
     ExtrinsicBox        *mExtr;
     CoordinateSystemBox *mCoordSys;
     QGraphicsScene      *mScene;
+    Correction          *CorrectionWidget;
+
     bool                 mColorChanging;
     bool mIndexChanging; // shows, if the index of the color model is really changing; nor while constructor (initialer
     // durchlauf) and may be while loading xml file
diff --git a/include/correction.h b/include/correction.h
new file mode 100644
index 000000000..544dfcd48
--- /dev/null
+++ b/include/correction.h
@@ -0,0 +1,90 @@
+/*
+ * PeTrack - Software for tracking pedestrians movement in videos
+ * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
+ * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
+ * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CORRECTION_H
+#define CORRECTION_H
+
+#include "plausibility.h"
+
+#include <QAbstractTableModel>
+#include <QFrame>
+#include <ui_correction.h>
+
+Q_DECLARE_METATYPE(plausibility::FailedCheck)
+
+class FailedChecksTableModel : public QAbstractTableModel
+{
+    Q_OBJECT
+private:
+    QVector<plausibility::FailedCheck> mFailedChecks;
+
+public:
+    explicit FailedChecksTableModel(QObject *parent) : QAbstractTableModel(parent) {}
+
+    ~FailedChecksTableModel() override = default;
+
+    void setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks);
+
+    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+};
+
+namespace Ui
+{
+class Correction;
+}
+
+class Correction : public QWidget
+{
+    Q_OBJECT
+
+public:
+    Correction(Petrack *petrack, QWidget *parent = nullptr);
+    void setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks);
+
+    bool getTestEqualChecked() { return mUi->chbEqual->isChecked(); }
+    void setTestEqualCheckState(Qt::CheckState testEqual) { mUi->chbEqual->setCheckState(testEqual); }
+
+    bool getTestVelocityChecked() { return mUi->chbVelocit->isChecked(); }
+    void setTestVelocityCheckState(Qt::CheckState testVelocity) { mUi->chbVelocit->setCheckState(testVelocity); }
+
+    bool getTestLengthChecked() { return mUi->chbLength->isChecked(); }
+    void setTestLengthCheckState(Qt::CheckState testLength) { mUi->chbLength->setCheckState(testLength); }
+
+    bool getTestInsideChecked() { return mUi->chbInside->isChecked(); }
+    void setTestInsideCheckState(Qt::CheckState testInside) { mUi->chbInside->setCheckState(testInside); }
+
+    ~Correction();
+
+private:
+    Petrack *               mPeTrack;
+    Ui::Correction *        mUi;
+    FailedChecksTableModel *mTableModel;
+
+private slots:
+    void on_tblFailedChecks_selectedRowChanged();
+    void on_btnCheck_clicked();
+};
+
+#endif // CORRECTION_H
diff --git a/include/petrack.h b/include/petrack.h
index d265ac272..7c0f9dd64 100644
--- a/include/petrack.h
+++ b/include/petrack.h
@@ -190,13 +190,12 @@ public:
     int          calculateRealTracker();
     void         exportTracker(QString dest = "");
     void         importTracker(QString dest = "");
-    void         testTracker();
     void         trackAll();
-    void         playAll();
-    int          winSize(QPointF *pos = nullptr, int pers = -1, int frame = -1, int level = -1);
-    void         updateImage(bool imageChanged = false);
-    void         updateImage(const cv::Mat &img);
-    void         updateSequence();
+    void      playAll();
+    int       winSize(QPointF *pos = nullptr, int pers = -1, int frame = -1, int level = -1);
+    void      updateImage(bool imageChanged = false);
+    void      updateImage(const cv::Mat &img);
+    void      updateSequence();
     QSet<size_t> getPedestrianUserSelection();
     QSet<size_t> getPedestriansToTrack();
     double       getCmPerPixel() const;
diff --git a/include/plausibility.h b/include/plausibility.h
index cdbb10150..5512facf0 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -45,4 +45,5 @@ std::vector<FailedCheck> checkPlausibility(
     bool           testLength   = true);
 
 } // namespace plausibility
+
 #endif // PLAUSIBILITY_H
diff --git a/include/tracker.h b/include/tracker.h
index ffc5a0af6..8f5b1c778 100644
--- a/include/tracker.h
+++ b/include/tracker.h
@@ -21,7 +21,6 @@
 
 #include "recognition.h"
 #include "vector.h"
-//#include "plausibility.h"
 
 #include <QColor>
 #include <QList>
diff --git a/src/control.cpp b/src/control.cpp
index f401d47af..8e0898fc3 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -27,6 +27,7 @@
 #include "colorRangeWidget.h"
 #include "coordinateSystemBox.h"
 #include "extrinsicBox.h"
+#include "correction.h"
 #include "extrinsicParameters.h"
 #include "filterBeforeBox.h"
 #include "intrinsicBox.h"
@@ -246,6 +247,10 @@ Control::Control(
 
     // "Hide" analysis tab until it is fixed
     mUi->tabs->removeTab(3);
+
+    mCorrectionWidget = new Correction(mMainWindow, correction);
+    mCorrectionWidget->setObjectName(QString::fromUtf8("frame"));
+    mCorrectionWidget->setGeometry(QRect(0, 0, 541, 561));
 }
 
 void Control::setScene(QGraphicsScene *sc)
@@ -1019,11 +1024,6 @@ void Control::on_trackImport_clicked()
     mMainWindow->importTracker();
 }
 
-void Control::on_trackTest_clicked()
-{
-    mMainWindow->testTracker();
-}
-
 void Control::on_trackPathColorButton_clicked()
 {
     QColor col = QColorDialog::getColor(getTrackPathColor(), this);
diff --git a/src/correction.cpp b/src/correction.cpp
new file mode 100644
index 000000000..28cda9fcb
--- /dev/null
+++ b/src/correction.cpp
@@ -0,0 +1,148 @@
+/*
+ * PeTrack - Software for tracking pedestrians movement in videos
+ * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
+ * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
+ * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "include/correction.h"
+
+#include "control.h"
+#include "player.h"
+#include "ui_correction.h"
+
+#include <QByteArray>
+#include <QFile>
+#include <QVector>
+#include <string>
+
+
+QVariant FailedChecksTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if(role == Qt::DisplayRole && orientation == Qt::Horizontal)
+    {
+        switch(section)
+        {
+            case 0:
+                return QString("Person");
+            case 1:
+                return QString("Frame");
+            case 2:
+                return QString("Failed check");
+        }
+    }
+    return QVariant();
+}
+
+int FailedChecksTableModel::rowCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent)
+    return mFailedChecks.size();
+}
+
+int FailedChecksTableModel::columnCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent)
+    return 3;
+}
+
+QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
+{
+    if(!index.isValid())
+    {
+        return QVariant();
+    }
+
+    if(role != Qt::DisplayRole)
+    {
+        return QVariant();
+    }
+
+    switch(index.column())
+    {
+        case 0:
+            return mFailedChecks[index.row()].pers;
+        case 1:
+            return mFailedChecks[index.row()].frame;
+        case 2:
+            return QString::fromStdString(mFailedChecks[index.row()].message);
+    }
+
+    return QVariant();
+}
+
+void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks)
+{
+    mFailedChecks = QVector<plausibility::FailedCheck>(failedChecks.begin(), failedChecks.end());
+
+    QModelIndex topLeft     = index(0, 0);
+    QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);
+
+    emit dataChanged(topLeft, bottomRight);
+    emit layoutChanged();
+}
+
+
+Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPeTrack(petrack), mUi(new Ui::Correction)
+{
+    mUi->setupUi(this);
+    mTableModel = new FailedChecksTableModel(this); // NOLINTLINE
+
+    mUi->tblFailedChecks->setModel(mTableModel);
+
+    connect(
+        mUi->tblFailedChecks->selectionModel(),
+        SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+        this,
+        SLOT(on_tblFailedChecks_selectedRowChanged()));
+}
+
+void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks)
+{
+    mTableModel->setFailedChecks(failedChecks);
+}
+
+void Correction::on_tblFailedChecks_selectedRowChanged()
+{
+    if(mUi->tblFailedChecks->selectionModel()->hasSelection())
+    {
+        auto selectedIndex = mUi->tblFailedChecks->selectionModel()->selectedIndexes();
+
+        int pers  = mUi->tblFailedChecks->model()->data(selectedIndex[0]).toInt();
+        int frame = mUi->tblFailedChecks->model()->data(selectedIndex[1]).toInt();
+        mPeTrack->getControlWidget()->trackShowOnly->setCheckState(Qt::Checked);
+        mPeTrack->getControlWidget()->trackShowOnlyNr->setValue(pers);
+        mPeTrack->getPlayer()->skipToFrame(frame);
+    }
+}
+
+Correction::~Correction()
+{
+    delete mUi;
+}
+
+void Correction::on_btnCheck_clicked()
+{
+    std::vector<plausibility::FailedCheck> failedChecks = plausibility::checkPlausibility(
+        *mPeTrack->getTracker(),
+        *mPeTrack,
+        mPeTrack->getImg(),
+        mUi->chbEqual->isChecked(),
+        mUi->chbVelocit->isChecked(),
+        mUi->chbInside->isChecked(),
+        mUi->chbLength->isChecked());
+    mTableModel->setFailedChecks(failedChecks);
+}
diff --git a/src/petrack.cpp b/src/petrack.cpp
index c22b3f9a4..656eab636 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -69,7 +69,7 @@
 #include <deque>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
-#include <plausibility.h>
+
 
 int Petrack::trcVersion = 0;
 
@@ -2785,37 +2785,6 @@ void Petrack::importTracker(QString dest) // default = ""
     }
 }
 
-void Petrack::testTracker()
-{
-    static size_t                          idx = 0; // index in Fehlerliste, die als letztes angesprungen wurde
-    QList<int>                             pers, frame;
-    std::vector<plausibility::FailedCheck> failedChecks = plausibility::checkPlausibility(
-        *mTracker,
-        *this,
-        mImg,
-        mControlWidget->isTestEqualChecked(),
-        mControlWidget->isTestVelocityChecked(),
-        mControlWidget->isTestInsideChecked(),
-        mControlWidget->isTestLengthChecked());
-
-    for(auto failedCheck : failedChecks)
-    {
-        debout << failedCheck.message << std::endl;
-    }
-
-    if(failedChecks.size() <= idx)
-    {
-        idx = 0;
-    }
-    if(failedChecks.size() > idx)
-    {
-        mControlWidget->setTrackShowOnly(Qt::Checked);
-        mControlWidget->setTrackShowOnlyNr(failedChecks[idx].pers);
-        mPlayerWidget->skipToFrame(failedChecks[idx].frame);
-        ++idx;
-    }
-}
-
 int Petrack::calculateRealTracker()
 {
     bool autoCorrectOnlyExport = (mReco.getRecoMethod() == reco::RecognitionMethod::MultiColor) && // multicolor
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 6cdb91952..912312b4b 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -26,24 +26,24 @@
 namespace plausibility
 {
 /**
-* @brief Performs different tests to check the plausibility of trajectories.
+ * @brief Performs different tests to check the plausibility of trajectories.
  *
-* This method can check for
-* <ul><li>shortness (less than 10 points)</li>
-* <li>start and endpoint (both should be outside the reco ROI
-* with exceptions for the beginning and end of the video)</li>
-* <li>Fast variations of speed (4 frame interval)</li>
-* <li>TrackPoints are too close together</li></ul>
-*
-* @param tracker containing the trajectory data
-* @param petrack main window (some data is only accessbile that way currently)
-* @param mat current image (only used to get size of the image)
-* @param testEqual true if warning for very close points are wished
-* @param testVelocity true if warning for fast speed variations is whished
-* @param testInside true if warning for start and endpoint in reco ROI is wished
-* @param testLength if warning for very short trajectories is wished
-* @return all failed checks, for enabled tests
-*/
+ * This method can check for
+ * <ul><li>shortness (less than 10 points)</li>
+ * <li>start and endpoint (both should be outside the reco ROI
+ * with exceptions for the beginning and end of the video)</li>
+ * <li>Fast variations of speed (4 frame interval)</li>
+ * <li>TrackPoints are too close together</li></ul>
+ *
+ * @param tracker containing the trajectory data
+ * @param petrack main window (some data is only accessbile that way currently)
+ * @param mat current image (only used to get size of the image)
+ * @param testEqual true if warning for very close points are wished
+ * @param testVelocity true if warning for fast speed variations is whished
+ * @param testInside true if warning for start and endpoint in reco ROI is wished
+ * @param testLength if warning for very short trajectories is wished
+ * @return all failed checks, for enabled tests
+ */
 std::vector<FailedCheck> checkPlausibility(
     Tracker &      tracker,
     Petrack &      petrack,
diff --git a/ui/control.ui b/ui/control.ui
index af8d50174..3dedf8834 100644
--- a/ui/control.ui
+++ b/ui/control.ui
@@ -3004,111 +3004,6 @@
              </layout>
             </widget>
            </item>
-           <item>
-            <layout class="QHBoxLayout" name="horizontalLayout_9" stretch="1,0,0,0,0">
-             <item>
-              <widget class="QPushButton" name="trackTest">
-               <property name="maximumSize">
-                <size>
-                 <width>999</width>
-                 <height>16777215</height>
-                </size>
-               </property>
-               <property name="text">
-                <string>test</string>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QCheckBox" name="testEqual">
-               <property name="maximumSize">
-                <size>
-                 <width>999</width>
-                 <height>16777215</height>
-                </size>
-               </property>
-               <property name="toolTip">
-                <string>search for trajectories with similar trackpoints</string>
-               </property>
-               <property name="whatsThis">
-                <string/>
-               </property>
-               <property name="text">
-                <string>equal</string>
-               </property>
-               <property name="checked">
-                <bool>true</bool>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QCheckBox" name="testVelocity">
-               <property name="maximumSize">
-                <size>
-                 <width>999</width>
-                 <height>16777215</height>
-                </size>
-               </property>
-               <property name="toolTip">
-                <string>search for hight velocity variations</string>
-               </property>
-               <property name="whatsThis">
-                <string/>
-               </property>
-               <property name="text">
-                <string>velocity</string>
-               </property>
-               <property name="checked">
-                <bool>true</bool>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QCheckBox" name="testInside">
-               <property name="maximumSize">
-                <size>
-                 <width>999</width>
-                 <height>16777215</height>
-                </size>
-               </property>
-               <property name="toolTip">
-                <string>search for trajectories which start or end outside recognition area</string>
-               </property>
-               <property name="whatsThis">
-                <string/>
-               </property>
-               <property name="text">
-                <string>inside</string>
-               </property>
-               <property name="checked">
-                <bool>true</bool>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QCheckBox" name="testLength">
-               <property name="maximumSize">
-                <size>
-                 <width>999</width>
-                 <height>16777215</height>
-                </size>
-               </property>
-               <property name="toolTip">
-                <string>search for short trajectories</string>
-               </property>
-               <property name="whatsThis">
-                <string/>
-               </property>
-               <property name="text">
-                <string>length</string>
-               </property>
-               <property name="checked">
-                <bool>true</bool>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
            <item>
             <widget class="QGroupBox" name="groupBox_6">
              <property name="sizePolicy">
@@ -4793,6 +4688,11 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="correction">
+      <attribute name="title">
+       <string>correction</string>
+      </attribute>
+     </widget>
      <widget class="QWidget" name="ana">
       <property name="sizePolicy">
        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
diff --git a/ui/correction.ui b/ui/correction.ui
new file mode 100644
index 000000000..021e7aeac
--- /dev/null
+++ b/ui/correction.ui
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Correction</class>
+ <widget class="QWidget" name="Correction">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>651</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Frame</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="1">
+    <widget class="QCheckBox" name="chbVelocit">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>velocity</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="2">
+    <widget class="QCheckBox" name="chbLength">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>length</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="0" colspan="4">
+    <widget class="QTableView" name="tblFailedChecks">
+     <property name="verticalScrollBarPolicy">
+      <enum>Qt::ScrollBarAlwaysOn</enum>
+     </property>
+     <property name="horizontalScrollBarPolicy">
+      <enum>Qt::ScrollBarAsNeeded</enum>
+     </property>
+     <property name="selectionBehavior">
+      <enum>QAbstractItemView::SelectRows</enum>
+     </property>
+     <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="horizontalHeaderStretchLastSection">
+      <bool>true</bool>
+     </attribute>
+     <attribute name="verticalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="verticalHeaderHighlightSections">
+      <bool>false</bool>
+     </attribute>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QCheckBox" name="chbEqual">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if two trajectories are close to each other&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>equality</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="3">
+    <widget class="QCheckBox" name="chbInside">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;&quot;&gt;&lt;span style=&quot; background-color:#2b2b2b;&quot;&gt;check, if the trajectory starts and ends outside of the recognition area&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>inside</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0" colspan="4">
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="2" colspan="2">
+    <spacer name="spacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="7" column="0" colspan="2">
+    <widget class="QPushButton" name="btnCheck">
+     <property name="text">
+      <string>Check trajectories</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
-- 
GitLab


From de476783a19e2918fff1bcc83356e3a456b17b21 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 27 Oct 2021 13:51:10 +0200
Subject: [PATCH 03/45] Add warning about deleting trajectories

Signed-off-by: schroedtert <t.schroedter@fz-juelich.de>
---
 ui/correction.ui | 96 +++++++++++++++++++++++++++++-------------------
 1 file changed, 59 insertions(+), 37 deletions(-)

diff --git a/ui/correction.ui b/ui/correction.ui
index 021e7aeac..14b474d86 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>400</width>
-    <height>651</height>
+    <height>1451</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -20,29 +20,10 @@
    <string>Frame</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="1">
-    <widget class="QCheckBox" name="chbVelocit">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
-     <property name="text">
-      <string>velocity</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
-     </property>
-    </widget>
-   </item>
-   <item row="0" column="2">
-    <widget class="QCheckBox" name="chbLength">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
+   <item row="7" column="0" colspan="2">
+    <widget class="QPushButton" name="btnCheck">
      <property name="text">
-      <string>length</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
+      <string>Check trajectories</string>
      </property>
     </widget>
    </item>
@@ -71,6 +52,32 @@
      </attribute>
     </widget>
    </item>
+   <item row="0" column="1">
+    <widget class="QCheckBox" name="chbVelocit">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>velocity</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="2">
+    <widget class="QCheckBox" name="chbLength">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>length</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
    <item row="0" column="0">
     <widget class="QCheckBox" name="chbEqual">
      <property name="toolTip">
@@ -84,6 +91,19 @@
      </property>
     </widget>
    </item>
+   <item row="7" column="2" colspan="2">
+    <spacer name="spacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
    <item row="0" column="3">
     <widget class="QCheckBox" name="chbInside">
      <property name="toolTip">
@@ -104,23 +124,25 @@
      </property>
     </widget>
    </item>
-   <item row="7" column="2" colspan="2">
-    <spacer name="spacer">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
+   <item row="9" column="0" colspan="4">
+    <widget class="QLabel" name="label">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
      </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>40</width>
-       <height>20</height>
-      </size>
+     <property name="frameShape">
+      <enum>QFrame::Box</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
      </property>
-    </spacer>
-   </item>
-   <item row="7" column="0" colspan="2">
-    <widget class="QPushButton" name="btnCheck">
      <property name="text">
-      <string>Check trajectories</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Warning: &lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-- 
GitLab


From bf67f3ea795ddf28f15b1154ebdc0fa8146fcb3c Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 27 Oct 2021 14:56:52 +0200
Subject: [PATCH 04/45] Fix layout issues

Signed-off-by: schroedtert <t.schroedter@fz-juelich.de>
---
 src/control.cpp  |  4 ++--
 ui/control.ui    |  5 -----
 ui/correction.ui | 12 +++++++++---
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/control.cpp b/src/control.cpp
index 8e0898fc3..d9a11cd6a 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -248,9 +248,9 @@ Control::Control(
     // "Hide" analysis tab until it is fixed
     mUi->tabs->removeTab(3);
 
-    mCorrectionWidget = new Correction(mMainWindow, correction);
+    mCorrectionWidget = new Correction(mMainWindow, this);
     mCorrectionWidget->setObjectName(QString::fromUtf8("frame"));
-    mCorrectionWidget->setGeometry(QRect(0, 0, 541, 561));
+    tabs->insertTab(3, mCorrectionWidget, "correction");
 }
 
 void Control::setScene(QGraphicsScene *sc)
diff --git a/ui/control.ui b/ui/control.ui
index 3dedf8834..43e3e8680 100644
--- a/ui/control.ui
+++ b/ui/control.ui
@@ -4688,11 +4688,6 @@
        </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="correction">
-      <attribute name="title">
-       <string>correction</string>
-      </attribute>
-     </widget>
      <widget class="QWidget" name="ana">
       <property name="sizePolicy">
        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
diff --git a/ui/correction.ui b/ui/correction.ui
index 14b474d86..f3a4ba706 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -7,11 +7,11 @@
     <x>0</x>
     <y>0</y>
     <width>400</width>
-    <height>1451</height>
+    <height>579</height>
    </rect>
   </property>
   <property name="sizePolicy">
-   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
@@ -119,6 +119,12 @@
    </item>
    <item row="6" column="0" colspan="4">
     <widget class="Line" name="line">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
@@ -127,7 +133,7 @@
    <item row="9" column="0" colspan="4">
     <widget class="QLabel" name="label">
      <property name="sizePolicy">
-      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
-- 
GitLab


From 20311cac616c772b28e9eca3c6ddf32652deca91 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Fri, 28 Oct 2022 14:43:29 +0200
Subject: [PATCH 05/45] Make work again

Signed-off-by: schroedtert <t.schroedter@fz-juelich.de>
---
 include/control.h      |  2 +-
 include/correction.h   |  4 ++--
 include/petrack.h      | 10 +++++-----
 include/plausibility.h |  6 +++---
 src/control.cpp        | 28 ++++++++++++++--------------
 src/correction.cpp     |  6 +++---
 src/plausibility.cpp   | 41 +++++++++++++++++++++--------------------
 7 files changed, 49 insertions(+), 48 deletions(-)

diff --git a/include/control.h b/include/control.h
index e50038bab..529aadf7c 100644
--- a/include/control.h
+++ b/include/control.h
@@ -578,7 +578,7 @@ private:
     QGraphicsScene      *mScene;
     Correction          *CorrectionWidget;
 
-    bool                 mColorChanging;
+    bool mColorChanging;
     bool mIndexChanging; // shows, if the index of the color model is really changing; nor while constructor (initialer
     // durchlauf) and may be while loading xml file
     bool mLoading; // shows, if new project is just loading
diff --git a/include/correction.h b/include/correction.h
index 544dfcd48..75f4085bb 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -78,8 +78,8 @@ public:
     ~Correction();
 
 private:
-    Petrack *               mPeTrack;
-    Ui::Correction *        mUi;
+    Petrack                *mPeTrack;
+    Ui::Correction         *mUi;
     FailedChecksTableModel *mTableModel;
 
 private slots:
diff --git a/include/petrack.h b/include/petrack.h
index 7c0f9dd64..56f6601f5 100644
--- a/include/petrack.h
+++ b/include/petrack.h
@@ -191,11 +191,11 @@ public:
     void         exportTracker(QString dest = "");
     void         importTracker(QString dest = "");
     void         trackAll();
-    void      playAll();
-    int       winSize(QPointF *pos = nullptr, int pers = -1, int frame = -1, int level = -1);
-    void      updateImage(bool imageChanged = false);
-    void      updateImage(const cv::Mat &img);
-    void      updateSequence();
+    void         playAll();
+    int          winSize(QPointF *pos = nullptr, int pers = -1, int frame = -1, int level = -1);
+    void         updateImage(bool imageChanged = false);
+    void         updateImage(const cv::Mat &img);
+    void         updateSequence();
     QSet<size_t> getPedestrianUserSelection();
     QSet<size_t> getPedestriansToTrack();
     double       getCmPerPixel() const;
diff --git a/include/plausibility.h b/include/plausibility.h
index 5512facf0..c9d12621d 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -21,7 +21,7 @@
 #ifndef PLAUSIBILITY_H
 #define PLAUSIBILITY_H
 
-#include "tracker.h"
+#include "personStorage.h"
 
 #include <string>
 #include <vector>
@@ -36,8 +36,8 @@ struct FailedCheck
 };
 
 std::vector<FailedCheck> checkPlausibility(
-    Tracker &      tracker,
-    Petrack &      petrack,
+    PersonStorage &tracker,
+    Petrack       &petrack,
     const cv::Mat &mat,
     bool           testEqual    = true,
     bool           testVelocity = true,
diff --git a/src/control.cpp b/src/control.cpp
index d9a11cd6a..4e686b4c1 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -250,7 +250,7 @@ Control::Control(
 
     mCorrectionWidget = new Correction(mMainWindow, this);
     mCorrectionWidget->setObjectName(QString::fromUtf8("frame"));
-    tabs->insertTab(3, mCorrectionWidget, "correction");
+    mUi->tabs->insertTab(3, mCorrectionWidget, "correction");
 }
 
 void Control::setScene(QGraphicsScene *sc)
@@ -2025,21 +2025,21 @@ void Control::setXml(QDomElement &elem)
     subSubElem.setAttribute("ENABLED", mUi->exportMarkerID->isChecked());
     subElem.appendChild(subSubElem);
 
-
+    // TODO from other tab
     subSubElem = (elem.ownerDocument()).createElement("TEST_EQUAL");
-    subSubElem.setAttribute("ENABLED", mUi->testEqual->isChecked());
+    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestEqualChecked());
     subElem.appendChild(subSubElem);
 
     subSubElem = (elem.ownerDocument()).createElement("TEST_VELOCITY");
-    subSubElem.setAttribute("ENABLED", mUi->testVelocity->isChecked());
+    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestVelocityChecked());
     subElem.appendChild(subSubElem);
 
     subSubElem = (elem.ownerDocument()).createElement("TEST_INSIDE");
-    subSubElem.setAttribute("ENABLED", mUi->testInside->isChecked());
+    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestInsideChecked());
     subElem.appendChild(subSubElem);
 
     subSubElem = (elem.ownerDocument()).createElement("TEST_LENGTH");
-    subSubElem.setAttribute("ENABLED", mUi->testLength->isChecked());
+    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestLengthChecked());
     subElem.appendChild(subSubElem);
 
 
@@ -2672,7 +2672,7 @@ void Control::getXml(const QDomElement &elem)
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
-                        mUi->testEqual->setCheckState(
+                        mCorrectionWidget->setTestEqualCheckState(
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
@@ -2680,7 +2680,7 @@ void Control::getXml(const QDomElement &elem)
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
-                        mUi->testVelocity->setCheckState(
+                        mCorrectionWidget->setTestVelocityCheckState(
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
@@ -2688,7 +2688,7 @@ void Control::getXml(const QDomElement &elem)
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
-                        mUi->testInside->setCheckState(
+                        mCorrectionWidget->setTestInsideCheckState(
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
@@ -2696,7 +2696,7 @@ void Control::getXml(const QDomElement &elem)
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
-                        mUi->testLength->setCheckState(
+                        mCorrectionWidget->setTestLengthCheckState(
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
@@ -3081,22 +3081,22 @@ void Control::replotColorplot()
 
 bool Control::isTestEqualChecked() const
 {
-    return mUi->testEqual->isChecked();
+    return mCorrectionWidget->getTestEqualChecked();
 }
 
 bool Control::isTestVelocityChecked() const
 {
-    return mUi->testVelocity->isChecked();
+    return mCorrectionWidget->getTestVelocityChecked();
 }
 
 bool Control::isTestInsideChecked() const
 {
-    return mUi->testInside->isChecked();
+    return mCorrectionWidget->getTestInsideChecked();
 }
 
 bool Control::isTestLengthChecked() const
 {
-    return mUi->testLength->isChecked();
+    return mCorrectionWidget->getTestLengthChecked();
 }
 
 void Control::setMapX(int val)
diff --git a/src/correction.cpp b/src/correction.cpp
index 28cda9fcb..702da51fc 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -123,8 +123,8 @@ void Correction::on_tblFailedChecks_selectedRowChanged()
 
         int pers  = mUi->tblFailedChecks->model()->data(selectedIndex[0]).toInt();
         int frame = mUi->tblFailedChecks->model()->data(selectedIndex[1]).toInt();
-        mPeTrack->getControlWidget()->trackShowOnly->setCheckState(Qt::Checked);
-        mPeTrack->getControlWidget()->trackShowOnlyNr->setValue(pers);
+        mPeTrack->getControlWidget()->setTrackShowOnly(Qt::Checked);
+        mPeTrack->getControlWidget()->setTrackShowOnlyNr(pers);
         mPeTrack->getPlayer()->skipToFrame(frame);
     }
 }
@@ -137,7 +137,7 @@ Correction::~Correction()
 void Correction::on_btnCheck_clicked()
 {
     std::vector<plausibility::FailedCheck> failedChecks = plausibility::checkPlausibility(
-        *mPeTrack->getTracker(),
+        mPeTrack->getPersonStorage(),
         *mPeTrack,
         mPeTrack->getImg(),
         mUi->chbEqual->isChecked(),
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 912312b4b..a592d3658 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -21,7 +21,8 @@
 #include "plausibility.h"
 
 #include "animation.h"
-#include "recognitionRoiItem.h"
+#include "personStorage.h"
+#include "roiItem.h"
 
 namespace plausibility
 {
@@ -45,8 +46,8 @@ namespace plausibility
  * @return all failed checks, for enabled tests
  */
 std::vector<FailedCheck> checkPlausibility(
-    Tracker &      tracker,
-    Petrack &      petrack,
+    PersonStorage &tracker,
+    Petrack       &petrack,
     const cv::Mat &mat,
     bool           testEqual,
     bool           testVelocity,
@@ -73,15 +74,15 @@ std::vector<FailedCheck> checkPlausibility(
         progress.setLabelText("Check trajectories lengths...");
         qApp->processEvents();
 
-        for(int i = 0; i < tracker.size(); ++i) // ueber TrackPerson
+        for(int i = 0; i < tracker.nbPersons(); ++i) // ueber TrackPerson
         {
-            progress.setValue(i * 100. / tracker.size());
+            progress.setValue(i * 100. / tracker.nbPersons());
             qApp->processEvents();
             if(tracker.at(i).size() < 10)
             {
                 std::stringstream stream;
                 stream << "Trajectory of person " << i + 1 << " has less than 10 trackpoints!";
-                failedChecks.push_back({i + 1, tracker[i].firstFrame(), stream.str()});
+                failedChecks.push_back({i + 1, tracker.at(i).firstFrame(), stream.str()});
             }
         }
     }
@@ -93,33 +94,33 @@ std::vector<FailedCheck> checkPlausibility(
         progress.setLabelText("Check if trajectories are inside image...");
         qApp->processEvents();
 
-        for(int i = 0; i < tracker.size(); ++i) // ueber TrackPerson
+        for(int i = 0; i < tracker.nbPersons(); ++i) // ueber TrackPerson
         {
             qApp->processEvents();
-            progress.setValue(100 + i * 100. / tracker.size());
-            double x = tracker[i].first().x();
-            double y = tracker[i].first().y();
+            progress.setValue(100 + i * 100. / tracker.nbPersons());
+            double x = tracker.at(i).first().x();
+            double y = tracker.at(i).first().y();
             // mGrey hat gleiche groesse wie zuletzt getracktes bild
-            if((tracker[i].firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
+            if((tracker.at(i).firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
                 x <= MIN(mat.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
                 y <= MIN(mat.rows - 1 - 2 * bS - margin, rect.y() + rect.height())))
             {
                 std::stringstream stream;
                 stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
-                failedChecks.push_back({i + 1, tracker[i].firstFrame(), stream.str()});
+                failedChecks.push_back({i + 1, tracker.at(i).firstFrame(), stream.str()});
             }
 
-            x = tracker[i].last().x();
-            y = tracker[i].last().y();
+            x = tracker.at(i).last().x();
+            y = tracker.at(i).last().y();
 
             // mGrey hat gleiche groesse wie zuletzt getracktes bild
-            if(tracker[i].lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
+            if(tracker.at(i).lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
                x <= MIN(mat.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
                y <= MIN(mat.rows - 1 - 2 * bS - margin, rect.y() + rect.height()))
             {
                 std::stringstream stream;
                 stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
-                failedChecks.push_back({i + 1, tracker[i].lastFrame(), stream.str()});
+                failedChecks.push_back({i + 1, tracker.at(i).lastFrame(), stream.str()});
             }
         }
     }
@@ -132,10 +133,10 @@ std::vector<FailedCheck> checkPlausibility(
         progress.setValue(200);
         progress.setLabelText("Check velocity...");
 
-        for(int i = 0; i < tracker.size(); ++i) // ueber TrackPerson
+        for(int i = 0; i < tracker.nbPersons(); ++i) // ueber TrackPerson
         {
             qApp->processEvents();
-            progress.setValue(200 + i * 100. / tracker.size());
+            progress.setValue(200 + i * 100. / tracker.nbPersons());
             for(int j = 1; j < tracker.at(i).size() - 2; ++j) // ueber TrackPoint (ohne ersten und letzten beiden)
             {
                 double d01 = tracker.at(i).at(j).distanceToPoint(tracker.at(i).at(j - 1));
@@ -169,11 +170,11 @@ std::vector<FailedCheck> checkPlausibility(
             progress.setValue(300 + f * 100. / lLF);
             qApp->processEvents();
 
-            for(int i = 0; i < tracker.size(); ++i)
+            for(int i = 0; i < tracker.nbPersons(); ++i)
             {
                 // if (!pers.contains(i+1)) man koennte nur einmal eine Person aufnehmen, da aufeinanderfolgende frames
                 // oft betroffen
-                for(int j = i + 1; j < tracker.size(); ++j)
+                for(int j = i + 1; j < tracker.nbPersons(); ++j)
                 {
                     if(tracker.at(i).trackPointExist(f) && tracker.at(j).trackPointExist(f))
                     {
-- 
GitLab


From c91d2b165d0e724b21ea13dc2a9d96a928f507b7 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 10:16:01 +0100
Subject: [PATCH 06/45] Add context menu for marking rows (problems) as
 resolved

---
 include/correction.h |  9 ++++++---
 src/correction.cpp   | 48 ++++++++++++++++++++++++++++++++++++++++++++
 ui/correction.ui     |  6 ++++++
 3 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 75f4085bb..2a1665a10 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -43,11 +43,12 @@ public:
     void setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks);
 
     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
-
-    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+    int      rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    int      columnCount(const QModelIndex &parent = QModelIndex()) const override;
 
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
 };
 
 namespace Ui
@@ -85,6 +86,8 @@ private:
 private slots:
     void on_tblFailedChecks_selectedRowChanged();
     void on_btnCheck_clicked();
+    void on_tblFailedChecks_contextMenuRequested();
+    void on_tblFailedChecks_markResolved(QList<QModelIndex> pos);
 };
 
 #endif // CORRECTION_H
diff --git a/src/correction.cpp b/src/correction.cpp
index 702da51fc..c5a61e1a5 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -21,6 +21,7 @@
 #include "include/correction.h"
 
 #include "control.h"
+#include "pMessageBox.h"
 #include "player.h"
 #include "ui_correction.h"
 
@@ -95,6 +96,18 @@ void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedChe
     emit layoutChanged();
 }
 
+bool FailedChecksTableModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+    beginRemoveRows(parent, row, row + count - 1);
+
+    for(int i = 0; i < count; ++i)
+    {
+        mFailedChecks.removeAt(row);
+    }
+
+    endRemoveRows();
+    return true;
+}
 
 Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPeTrack(petrack), mUi(new Ui::Correction)
 {
@@ -108,6 +121,12 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
         SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
         this,
         SLOT(on_tblFailedChecks_selectedRowChanged()));
+
+    connect(
+        mUi->tblFailedChecks,
+        &QTableWidget::customContextMenuRequested,
+        this,
+        &Correction::on_tblFailedChecks_contextMenuRequested);
 }
 
 void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks)
@@ -129,6 +148,35 @@ void Correction::on_tblFailedChecks_selectedRowChanged()
     }
 }
 
+void Correction::on_tblFailedChecks_contextMenuRequested()
+{
+    auto selectedIndex = mUi->tblFailedChecks->selectionModel()->selectedIndexes();
+
+    if(selectedIndex.empty())
+    {
+        return;
+    }
+
+    QMenu   contextMenu(tr("&Correction"), this);
+    QAction markResolvedAction("Mark as resolved", this);
+    connect(
+        &markResolvedAction,
+        &QAction::triggered,
+        this,
+        [this, &selectedIndex]() { this->on_tblFailedChecks_markResolved(selectedIndex); });
+    contextMenu.addAction(&markResolvedAction);
+    contextMenu.exec(QCursor::pos());
+}
+
+void Correction::on_tblFailedChecks_markResolved(QList<QModelIndex> pos)
+{
+    auto success = mUi->tblFailedChecks->model()->removeRows(pos[0].row(), 1);
+    if(!success)
+    {
+        PWarning(this, "Correction", "Could not mark check as resolved.");
+    }
+}
+
 Correction::~Correction()
 {
     delete mUi;
diff --git a/ui/correction.ui b/ui/correction.ui
index f3a4ba706..b4176f657 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -29,12 +29,18 @@
    </item>
    <item row="8" column="0" colspan="4">
     <widget class="QTableView" name="tblFailedChecks">
+     <property name="contextMenuPolicy">
+      <enum>Qt::CustomContextMenu</enum>
+     </property>
      <property name="verticalScrollBarPolicy">
       <enum>Qt::ScrollBarAlwaysOn</enum>
      </property>
      <property name="horizontalScrollBarPolicy">
       <enum>Qt::ScrollBarAsNeeded</enum>
      </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::SingleSelection</enum>
+     </property>
      <property name="selectionBehavior">
       <enum>QAbstractItemView::SelectRows</enum>
      </property>
-- 
GitLab


From 3d9884855b5ae664735e58ef67cb2633eee5cba7 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 10:22:34 +0100
Subject: [PATCH 07/45] Slight reordering in UI to allow test specific
 parameters

---
 ui/correction.ui | 104 +++++++++++++++++++++++------------------------
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/ui/correction.ui b/ui/correction.ui
index b4176f657..c1b3f7d0a 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -20,14 +20,20 @@
    <string>Frame</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="7" column="0" colspan="2">
-    <widget class="QPushButton" name="btnCheck">
+   <item row="1" column="0">
+    <widget class="QCheckBox" name="chbVelocit">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
      <property name="text">
-      <string>Check trajectories</string>
+      <string>velocity</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="8" column="0" colspan="4">
+   <item row="11" column="0" colspan="4">
     <widget class="QTableView" name="tblFailedChecks">
      <property name="contextMenuPolicy">
       <enum>Qt::CustomContextMenu</enum>
@@ -58,20 +64,29 @@
      </attribute>
     </widget>
    </item>
-   <item row="0" column="1">
-    <widget class="QCheckBox" name="chbVelocit">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   <item row="12" column="0" colspan="4">
+    <widget class="QLabel" name="label">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="frameShape">
+      <enum>QFrame::Box</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
      </property>
      <property name="text">
-      <string>velocity</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Warning: &lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
-     <property name="checked">
+     <property name="wordWrap">
       <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="0" column="2">
+   <item row="2" column="0">
     <widget class="QCheckBox" name="chbLength">
      <property name="toolTip">
       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -84,20 +99,7 @@
      </property>
     </widget>
    </item>
-   <item row="0" column="0">
-    <widget class="QCheckBox" name="chbEqual">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if two trajectories are close to each other&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
-     <property name="text">
-      <string>equality</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
-     </property>
-    </widget>
-   </item>
-   <item row="7" column="2" colspan="2">
+   <item row="10" column="2" colspan="2">
     <spacer name="spacer">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
@@ -110,20 +112,7 @@
      </property>
     </spacer>
    </item>
-   <item row="0" column="3">
-    <widget class="QCheckBox" name="chbInside">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;&quot;&gt;&lt;span style=&quot; background-color:#2b2b2b;&quot;&gt;check, if the trajectory starts and ends outside of the recognition area&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
-     <property name="text">
-      <string>inside</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
-     </property>
-    </widget>
-   </item>
-   <item row="6" column="0" colspan="4">
+   <item row="9" column="0" colspan="4">
     <widget class="Line" name="line">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -136,24 +125,35 @@
      </property>
     </widget>
    </item>
-   <item row="9" column="0" colspan="4">
-    <widget class="QLabel" name="label">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
+   <item row="0" column="0">
+    <widget class="QCheckBox" name="chbEqual">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if two trajectories are close to each other&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
-     <property name="frameShape">
-      <enum>QFrame::Box</enum>
+     <property name="text">
+      <string>equality</string>
      </property>
-     <property name="frameShadow">
-      <enum>QFrame::Raised</enum>
+     <property name="checked">
+      <bool>true</bool>
      </property>
+    </widget>
+   </item>
+   <item row="10" column="0" colspan="2">
+    <widget class="QPushButton" name="btnCheck">
      <property name="text">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Warning: &lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>Check trajectories</string>
      </property>
-     <property name="wordWrap">
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QCheckBox" name="chbInside">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;&quot;&gt;&lt;span style=&quot; background-color:#2b2b2b;&quot;&gt;check, if the trajectory starts and ends outside of the recognition area&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="text">
+      <string>inside</string>
+     </property>
+     <property name="checked">
       <bool>true</bool>
      </property>
     </widget>
-- 
GitLab


From 341c5bbca28f7effaa599f2b506e5e1eb71d84d5 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 10:39:40 +0100
Subject: [PATCH 08/45] Make length check a separate function

---
 include/plausibility.h | 18 +++++++++------
 src/plausibility.cpp   | 51 ++++++++++++++++++++++++------------------
 2 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index c9d12621d..0bce7b546 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -26,6 +26,8 @@
 #include <string>
 #include <vector>
 
+class QProgressDialog;
+
 namespace plausibility
 {
 struct FailedCheck
@@ -36,13 +38,15 @@ struct FailedCheck
 };
 
 std::vector<FailedCheck> checkPlausibility(
-    PersonStorage &tracker,
-    Petrack       &petrack,
-    const cv::Mat &mat,
-    bool           testEqual    = true,
-    bool           testVelocity = true,
-    bool           testInside   = true,
-    bool           testLength   = true);
+    const PersonStorage &tracker,
+    Petrack             &petrack,
+    const cv::Mat       &mat,
+    bool                 testEqual    = true,
+    bool                 testVelocity = true,
+    bool                 testInside   = true,
+    bool                 testLength   = true);
+
+std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog);
 
 } // namespace plausibility
 
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index a592d3658..566ced399 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -46,13 +46,13 @@ namespace plausibility
  * @return all failed checks, for enabled tests
  */
 std::vector<FailedCheck> checkPlausibility(
-    PersonStorage &tracker,
-    Petrack       &petrack,
-    const cv::Mat &mat,
-    bool           testEqual,
-    bool           testVelocity,
-    bool           testInside,
-    bool           testLength)
+    const PersonStorage &tracker,
+    Petrack             &petrack,
+    const cv::Mat       &mat,
+    bool                 testEqual,
+    bool                 testVelocity,
+    bool                 testInside,
+    bool                 testLength)
 {
     std::vector<plausibility::FailedCheck> failedChecks;
 
@@ -70,21 +70,8 @@ std::vector<FailedCheck> checkPlausibility(
     // test, if the trajectory is very short (less than 10 Trackpoints)
     if(testLength)
     {
-        progress.setValue(0);
-        progress.setLabelText("Check trajectories lengths...");
-        qApp->processEvents();
-
-        for(int i = 0; i < tracker.nbPersons(); ++i) // ueber TrackPerson
-        {
-            progress.setValue(i * 100. / tracker.nbPersons());
-            qApp->processEvents();
-            if(tracker.at(i).size() < 10)
-            {
-                std::stringstream stream;
-                stream << "Trajectory of person " << i + 1 << " has less than 10 trackpoints!";
-                failedChecks.push_back({i + 1, tracker.at(i).firstFrame(), stream.str()});
-            }
-        }
+        auto failedLengthChecks{checkLength(tracker, &progress)};
+        failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
     }
 
     // check, if trajectory starts and ends outside the recognition area
@@ -193,4 +180,24 @@ std::vector<FailedCheck> checkPlausibility(
     }
     return failedChecks;
 }
+
+std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog)
+{
+    std::vector<FailedCheck> failedChecks;
+    progressDialog->setValue(0);
+    progressDialog->setLabelText("Check trajectories lengths...");
+    qApp->processEvents();
+
+    for(int i = 0; i < personStorage.nbPersons(); ++i)
+    {
+        if(personStorage.at(i).size() < 10)
+        {
+            std::stringstream stream;
+            stream << "Trajectory of person " << i + 1 << " has less than 10 trackpoints!";
+            failedChecks.push_back({i + 1, personStorage.at(i).firstFrame(), stream.str()});
+        }
+    }
+    return failedChecks;
+}
+
 } // namespace plausibility
\ No newline at end of file
-- 
GitLab


From ea94eda8aa6f6454a47edef4850c0791f853d5ec Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 11:06:32 +0100
Subject: [PATCH 09/45] Make inside check a separate function

---
 include/plausibility.h |  8 +++-
 src/correction.cpp     |  2 +-
 src/plausibility.cpp   | 96 ++++++++++++++++++++++++------------------
 3 files changed, 62 insertions(+), 44 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 0bce7b546..302efb440 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -40,14 +40,18 @@ struct FailedCheck
 std::vector<FailedCheck> checkPlausibility(
     const PersonStorage &tracker,
     Petrack             &petrack,
-    const cv::Mat       &mat,
+    const cv::Size      &imageSize,
     bool                 testEqual    = true,
     bool                 testVelocity = true,
     bool                 testInside   = true,
     bool                 testLength   = true);
 
 std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog);
-
+std::vector<FailedCheck> checkInside(
+    const PersonStorage &personStorage,
+    QProgressDialog     *progressDialog,
+    const cv::Size      &imageSize,
+    Petrack             &petrack);
 } // namespace plausibility
 
 #endif // PLAUSIBILITY_H
diff --git a/src/correction.cpp b/src/correction.cpp
index c5a61e1a5..d69950c04 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -187,7 +187,7 @@ void Correction::on_btnCheck_clicked()
     std::vector<plausibility::FailedCheck> failedChecks = plausibility::checkPlausibility(
         mPeTrack->getPersonStorage(),
         *mPeTrack,
-        mPeTrack->getImg(),
+        mPeTrack->getImg().size(),
         mUi->chbEqual->isChecked(),
         mUi->chbVelocit->isChecked(),
         mUi->chbInside->isChecked(),
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 566ced399..56b1a7e34 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -37,10 +37,10 @@ namespace plausibility
  * <li>TrackPoints are too close together</li></ul>
  *
  * @param tracker containing the trajectory data
- * @param petrack main window (some data is only accessbile that way currently)
- * @param mat current image (only used to get size of the image)
+ * @param petrack main window (some data is only accessible that way currently)
+ * @param imageSize size of the image
  * @param testEqual true if warning for very close points are wished
- * @param testVelocity true if warning for fast speed variations is whished
+ * @param testVelocity true if warning for fast speed variations is wished
  * @param testInside true if warning for start and endpoint in reco ROI is wished
  * @param testLength if warning for very short trajectories is wished
  * @return all failed checks, for enabled tests
@@ -48,7 +48,7 @@ namespace plausibility
 std::vector<FailedCheck> checkPlausibility(
     const PersonStorage &tracker,
     Petrack             &petrack,
-    const cv::Mat       &mat,
+    const cv::Size      &imageSize,
     bool                 testEqual,
     bool                 testVelocity,
     bool                 testInside,
@@ -62,10 +62,6 @@ std::vector<FailedCheck> checkPlausibility(
     progress.setVisible(true);
     progress.setValue(0);
     progress.setLabelText("Check Plausibility...");
-    static int margin    = 30; // rand am bild, ab dem trajectorie verloren sein darf
-    int        bS        = petrack.getImageBorderSize();
-    QRectF     rect      = petrack.getRecoRoiItem()->rect();
-    int        lastFrame = petrack.getAnimation()->getNumFrames() - 1;
 
     // test, if the trajectory is very short (less than 10 Trackpoints)
     if(testLength)
@@ -77,39 +73,8 @@ std::vector<FailedCheck> checkPlausibility(
     // check, if trajectory starts and ends outside the recognition area
     if(testInside)
     {
-        progress.setValue(100);
-        progress.setLabelText("Check if trajectories are inside image...");
-        qApp->processEvents();
-
-        for(int i = 0; i < tracker.nbPersons(); ++i) // ueber TrackPerson
-        {
-            qApp->processEvents();
-            progress.setValue(100 + i * 100. / tracker.nbPersons());
-            double x = tracker.at(i).first().x();
-            double y = tracker.at(i).first().y();
-            // mGrey hat gleiche groesse wie zuletzt getracktes bild
-            if((tracker.at(i).firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-                x <= MIN(mat.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
-                y <= MIN(mat.rows - 1 - 2 * bS - margin, rect.y() + rect.height())))
-            {
-                std::stringstream stream;
-                stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
-                failedChecks.push_back({i + 1, tracker.at(i).firstFrame(), stream.str()});
-            }
-
-            x = tracker.at(i).last().x();
-            y = tracker.at(i).last().y();
-
-            // mGrey hat gleiche groesse wie zuletzt getracktes bild
-            if(tracker.at(i).lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-               x <= MIN(mat.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
-               y <= MIN(mat.rows - 1 - 2 * bS - margin, rect.y() + rect.height()))
-            {
-                std::stringstream stream;
-                stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
-                failedChecks.push_back({i + 1, tracker.at(i).lastFrame(), stream.str()});
-            }
-        }
+        auto failedInsideChecks{checkInside(tracker, &progress, imageSize, petrack)};
+        failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
 
     // testen, ob grosse Geschwindigkeitsaenderungen
@@ -200,4 +165,53 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
     return failedChecks;
 }
 
+std::vector<FailedCheck> checkInside(
+    const PersonStorage &personStorage,
+    QProgressDialog     *progressDialog,
+    const cv::Size      &imageSize,
+    Petrack             &petrack)
+{
+    std::vector<FailedCheck> failedChecks;
+
+    static int margin    = 30; // distance to image border, in which the trajectory may get lost
+    int        bS        = petrack.getImageBorderSize();
+    QRectF     rect      = petrack.getRecoRoiItem()->rect();
+    int        lastFrame = petrack.getAnimation()->getNumFrames() - 1;
+
+    progressDialog->setValue(100);
+    progressDialog->setLabelText("Check if trajectories are inside image...");
+    qApp->processEvents();
+
+    for(int i = 0; i < personStorage.nbPersons(); ++i)
+    {
+        qApp->processEvents();
+        progressDialog->setValue(100 + i * 100. / personStorage.nbPersons());
+        double x = personStorage.at(i).first().x();
+        double y = personStorage.at(i).first().y();
+
+        if((personStorage.at(i).firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
+            x <= MIN(imageSize.width - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
+            y <= MIN(imageSize.height - 1 - 2 * bS - margin, rect.y() + rect.height())))
+        {
+            std::stringstream stream;
+            stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
+            failedChecks.push_back({i + 1, personStorage.at(i).firstFrame(), stream.str()});
+        }
+
+        x = personStorage.at(i).last().x();
+        y = personStorage.at(i).last().y();
+
+        if(personStorage.at(i).lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
+           x <= MIN(imageSize.width - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
+           y <= MIN(imageSize.height - 1 - 2 * bS - margin, rect.y() + rect.height()))
+        {
+            std::stringstream stream;
+            stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
+            failedChecks.push_back({i + 1, personStorage.at(i).lastFrame(), stream.str()});
+        }
+    }
+
+    return failedChecks;
+}
+
 } // namespace plausibility
\ No newline at end of file
-- 
GitLab


From bedd1a1c9a800a6083ee88506136d64f40342947 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 11:19:32 +0100
Subject: [PATCH 10/45] Make velocity variation check a separate function

---
 include/plausibility.h |  4 +++
 src/plausibility.cpp   | 59 +++++++++++++++++++++++++-----------------
 2 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 302efb440..a68745476 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -47,11 +47,15 @@ std::vector<FailedCheck> checkPlausibility(
     bool                 testLength   = true);
 
 std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog);
+
 std::vector<FailedCheck> checkInside(
     const PersonStorage &personStorage,
     QProgressDialog     *progressDialog,
     const cv::Size      &imageSize,
     Petrack             &petrack);
+
+std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog);
+
 } // namespace plausibility
 
 #endif // PLAUSIBILITY_H
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 56b1a7e34..451c0f7d5 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -81,30 +81,8 @@ std::vector<FailedCheck> checkPlausibility(
     // statt distanz koennte man auch noch vektoren vergleichen, was genauere analyse waer!!!!
     if(testVelocity)
     {
-        qApp->processEvents();
-        progress.setValue(200);
-        progress.setLabelText("Check velocity...");
-
-        for(int i = 0; i < tracker.nbPersons(); ++i) // ueber TrackPerson
-        {
-            qApp->processEvents();
-            progress.setValue(200 + i * 100. / tracker.nbPersons());
-            for(int j = 1; j < tracker.at(i).size() - 2; ++j) // ueber TrackPoint (ohne ersten und letzten beiden)
-            {
-                double d01 = tracker.at(i).at(j).distanceToPoint(tracker.at(i).at(j - 1));
-                double d12 = tracker.at(i).at(j + 1).distanceToPoint(tracker.at(i).at(j));
-                double d23 = tracker.at(i).at(j + 2).distanceToPoint(tracker.at(i).at(j + 1));
-                if(((1.8 * (d01 + d23) / 2.) < d12) &&
-                   ((d12 > 6.) ||
-                    ((d01 + d23) / 2. > 3.))) // geschwindigkeit 1,8-fach && mindestpixelbewegung im schnitt von 3
-                {
-                    std::stringstream stream;
-                    stream << "Fast variation of velocity of person " << i + 1 << " between frame "
-                           << j + tracker.at(i).firstFrame() << " and " << j + 1 + tracker.at(i).firstFrame() << "!";
-                    failedChecks.push_back({i + 1, j + tracker.at(i).firstFrame(), stream.str()});
-                }
-            }
-        }
+        auto failedVelocityChecks{checkVelocityVariation(tracker, &progress)};
+        failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
 
     // testen, ob zwei trackpoint sehr nah beieinanderliegen (es gibt trajektorien, die uebereinander liegen, wenn nicht
@@ -214,4 +192,37 @@ std::vector<FailedCheck> checkInside(
     return failedChecks;
 }
 
+std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog)
+{
+    std::vector<FailedCheck> failedChecks;
+
+    qApp->processEvents();
+    progressDialog->setValue(200);
+    progressDialog->setLabelText("Check velocity...");
+
+    for(int i = 0; i < personStorage.nbPersons(); ++i) // ueber TrackPerson
+    {
+        qApp->processEvents();
+        progressDialog->setValue(200 + i * 100. / personStorage.nbPersons());
+        for(int j = 1; j < personStorage.at(i).size() - 2; ++j) // ueber TrackPoint (ohne ersten und letzten beiden)
+        {
+            double d01 = personStorage.at(i).at(j).distanceToPoint(personStorage.at(i).at(j - 1));
+            double d12 = personStorage.at(i).at(j + 1).distanceToPoint(personStorage.at(i).at(j));
+            double d23 = personStorage.at(i).at(j + 2).distanceToPoint(personStorage.at(i).at(j + 1));
+            if(((1.8 * (d01 + d23) / 2.) < d12) &&
+               ((d12 > 6.) ||
+                ((d01 + d23) / 2. > 3.))) // geschwindigkeit 1,8-fach && mindestpixelbewegung im schnitt von 3
+            {
+                std::stringstream stream;
+                stream << "Fast variation of velocity of person " << i + 1 << " between frame "
+                       << j + personStorage.at(i).firstFrame() << " and " << j + 1 + personStorage.at(i).firstFrame()
+                       << "!";
+                failedChecks.push_back({i + 1, j + personStorage.at(i).firstFrame(), stream.str()});
+            }
+        }
+    }
+
+    return failedChecks;
+}
+
 } // namespace plausibility
\ No newline at end of file
-- 
GitLab


From 3f7628882d7b5efcc84b4e74d5e35be47a6fb873 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 11:31:31 +0100
Subject: [PATCH 11/45] Make equality check a separate function

---
 include/plausibility.h |  3 ++
 src/plausibility.cpp   | 70 +++++++++++++++++++++++-------------------
 2 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index a68745476..0859f33ff 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -56,6 +56,9 @@ std::vector<FailedCheck> checkInside(
 
 std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog);
 
+std::vector<FailedCheck>
+checkEquality(const PersonStorage &personStorage, QProgressDialog *progressDialog, Petrack &petrack);
+
 } // namespace plausibility
 
 #endif // PLAUSIBILITY_H
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 451c0f7d5..9ce5e86b8 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -89,37 +89,8 @@ std::vector<FailedCheck> checkPlausibility(
     // genmergt wird)
     if(testEqual)
     {
-        progress.setValue(300);
-        progress.setLabelText("Check if trajectories are equal...");
-        qApp->processEvents();
-
-        int lLF = tracker.largestLastFrame();
-        int f;
-        for(f = tracker.smallestFirstFrame(); f <= lLF; ++f)
-        {
-            progress.setValue(300 + f * 100. / lLF);
-            qApp->processEvents();
-
-            for(int i = 0; i < tracker.nbPersons(); ++i)
-            {
-                // if (!pers.contains(i+1)) man koennte nur einmal eine Person aufnehmen, da aufeinanderfolgende frames
-                // oft betroffen
-                for(int j = i + 1; j < tracker.nbPersons(); ++j)
-                {
-                    if(tracker.at(i).trackPointExist(f) && tracker.at(j).trackPointExist(f))
-                    {
-                        if(tracker.at(i).trackPointAt(f).distanceToPoint(tracker.at(j).trackPointAt(f)) <
-                           petrack.getHeadSize(nullptr, i, f) / 2.)
-                        {
-                            std::stringstream stream;
-                            stream << "Person " << i + 1 << " and " << j + 1
-                                   << " are very close to each other at frame " << f << "!";
-                            failedChecks.push_back({i + 1, f, stream.str()});
-                        }
-                    }
-                }
-            }
-        }
+        auto failedEqualityChecks{checkEquality(tracker, &progress, petrack)};
+        failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
     }
     return failedChecks;
 }
@@ -225,4 +196,41 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
     return failedChecks;
 }
 
+std::vector<FailedCheck>
+checkEquality(const PersonStorage &personStorage, QProgressDialog *progressDialog, Petrack &petrack)
+{
+    std::vector<FailedCheck> failedChecks;
+    progressDialog->setValue(300);
+    progressDialog->setLabelText("Check if trajectories are equal...");
+    qApp->processEvents();
+
+    int largestLastFrame = personStorage.largestLastFrame();
+    for(int frame = personStorage.smallestFirstFrame(); frame <= largestLastFrame; ++frame)
+    {
+        progressDialog->setValue(300 + frame * 100. / largestLastFrame);
+        qApp->processEvents();
+
+        for(int i = 0; i < personStorage.nbPersons(); ++i)
+        {
+            // if (!pers.contains(i+1)) man koennte nur einmal eine Person aufnehmen, da aufeinanderfolgende frames
+            // oft betroffen
+            for(int j = i + 1; j < personStorage.nbPersons(); ++j)
+            {
+                if(personStorage.at(i).trackPointExist(frame) && personStorage.at(j).trackPointExist(frame))
+                {
+                    if(personStorage.at(i).trackPointAt(frame).distanceToPoint(
+                           personStorage.at(j).trackPointAt(frame)) < petrack.getHeadSize(nullptr, i, frame) / 2.)
+                    {
+                        std::stringstream stream;
+                        stream << "Person " << i + 1 << " and " << j + 1 << " are very close to each other at frame "
+                               << frame << "!";
+                        failedChecks.push_back({i + 1, frame, stream.str()});
+                    }
+                }
+            }
+        }
+    }
+
+    return failedChecks;
+}
 } // namespace plausibility
\ No newline at end of file
-- 
GitLab


From 0f62fbc5eb4cb70beadaa0fd1218ff1e3ea0b3d9 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 11:35:38 +0100
Subject: [PATCH 12/45] Use std::vector instead of QVector as backend for
 FailedChecksTableModel

---
 include/correction.h | 2 +-
 src/correction.cpp   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 2a1665a10..b3db9efb5 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -33,7 +33,7 @@ class FailedChecksTableModel : public QAbstractTableModel
 {
     Q_OBJECT
 private:
-    QVector<plausibility::FailedCheck> mFailedChecks;
+    std::vector<plausibility::FailedCheck> mFailedChecks;
 
 public:
     explicit FailedChecksTableModel(QObject *parent) : QAbstractTableModel(parent) {}
diff --git a/src/correction.cpp b/src/correction.cpp
index d69950c04..22fc81eb8 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -87,7 +87,7 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
 
 void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks)
 {
-    mFailedChecks = QVector<plausibility::FailedCheck>(failedChecks.begin(), failedChecks.end());
+    mFailedChecks = failedChecks;
 
     QModelIndex topLeft     = index(0, 0);
     QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);
@@ -102,7 +102,7 @@ bool FailedChecksTableModel::removeRows(int row, int count, const QModelIndex &p
 
     for(int i = 0; i < count; ++i)
     {
-        mFailedChecks.removeAt(row);
+        mFailedChecks.erase(mFailedChecks.cbegin() + row);
     }
 
     endRemoveRows();
-- 
GitLab


From f9e5291efde9d9c9bcbf07a8c4058ab4c1175103 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 14:08:53 +0100
Subject: [PATCH 13/45] Remove duplicate of plausibility check

---
 src/personStorage.cpp | 167 ------------------------------------------
 1 file changed, 167 deletions(-)

diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index 32558c05d..6b36c9db6 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -750,173 +750,6 @@ void PersonStorage::recalcHeight(float altitude)
     }
 }
 
-/**
- * @brief Performs different tests to check the plausibility of trajectories.
- *
- * This method can check for
- * <ul><li>shortness (less than 10 points)</li>
- * <li>start and endpoint (both should be outside the reco ROI
- * with exceptions for the beginning and end of the video)</li>
- * <li>Fast variations of speed (4 frame interval)</li>
- * <li>TrackPoints are too close together</li></ul>
- *
- * @param pers[in] list of persons (ID) to check
- * @param frame[out] list of frames at which "problems" occured
- * @param testEqual[in] true if warning for very close points are wished
- * @param testVelocity[in] true if warning for fast speed variations is whished
- * @param testInside[in] true if warning for start and endpoint in reco ROI is wished
- * @param testLength[in] true if warning for very short trajectories is wished
- */
-void PersonStorage::checkPlausibility(
-    QList<int> &pers,
-    QList<int> &frame,
-    bool        testEqual,
-    bool        testVelocity,
-    bool        testInside,
-    bool        testLength)
-{
-    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mMainWindow.window());
-    progress.setWindowTitle("Check plausibility");
-    progress.setWindowModality(Qt::WindowModal);
-    progress.setVisible(true);
-    progress.setValue(0);
-    progress.setLabelText("Check Plausibility...");
-    static int margin = 30; // rand am bild, ab dem trajectorie verloren sein darf
-    int        i, j;
-    double     x, y;
-    QRectF     rect      = mMainWindow.getRecoRoiItem()->rect();
-    int        lastFrame = mMainWindow.getAnimation()->getNumFrames() - 1;
-
-    // test, if the trajectory is very short (less than 10 Trackpoints)
-    if(testLength)
-    {
-        progress.setValue(0);
-        progress.setLabelText("Check trajectories lengths...");
-        qApp->processEvents();
-        for(i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson
-        {
-            progress.setValue(static_cast<int>(i * 100. / mPersons.size()));
-            qApp->processEvents();
-            if(mPersons.at(i).size() < 10)
-            {
-                SPDLOG_WARN("Trajectory of person {} has less than 10 TrackPoints!", i + 1);
-                pers.append(i + 1);
-                frame.append(mPersons[i].firstFrame());
-            }
-        }
-    }
-
-    // check, if trajectory starts and ends outside the recognition area
-    if(testInside)
-    {
-        progress.setValue(100);
-        progress.setLabelText("Check if trajectories are inside image...");
-        qApp->processEvents();
-
-        for(i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson
-        {
-            qApp->processEvents();
-            progress.setValue(100 + i * 100. / mPersons.size());
-            x = mPersons[i].first().x();
-            y = mPersons[i].first().y();
-            // mGrey hat gleiche groesse wie zuletzt getracktes bild
-            if(mPersons[i].firstFrame() != 0 && x >= MAX(margin, rect.x()) &&
-               y >= MAX(margin, rect.y())) //&&
-                                           // x <= MIN(mGrey.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
-                                           // y <= MIN(mGrey.rows - 1 - 2 * bS - margin, rect.y() + rect.height()))
-            {
-                SPDLOG_WARN("Start of trajectory inside picture and recognition area of person {}", i + 1);
-                pers.append(i + 1);
-                frame.append(mPersons[i].firstFrame());
-            }
-
-            x = mPersons[i].last().x();
-            y = mPersons[i].last().y();
-            // mGrey hat gleiche groesse wie zuletzt getracktes bild
-            if(mPersons[i].lastFrame() != lastFrame && x >= MAX(margin, rect.x()) &&
-               y >= MAX(margin, rect.y())) //&&
-                                           // x <= MIN(mGrey.cols - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
-                                           // y <= MIN(mGrey.rows - 1 - 2 * bS - margin, rect.y() + rect.height()))
-            {
-                SPDLOG_WARN("End of trajectory inside picture and recognition area of person {}", i + 1);
-
-                pers.append(i + 1);
-                frame.append(mPersons[i].lastFrame());
-            }
-        }
-    }
-
-    // testen, ob grosse Geschwindigkeitsaenderungen
-    // statt distanz koennte man auch noch vektoren vergleichen, was genauere analyse waer!!!!
-    if(testVelocity)
-    {
-        qApp->processEvents();
-        progress.setValue(200);
-        progress.setLabelText("Check velocity...");
-
-        double d01, d12, d23;
-        for(i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson
-        {
-            qApp->processEvents();
-            progress.setValue(200 + i * 100. / mPersons.size());
-            for(j = 1; j < mPersons.at(i).size() - 2; ++j) // ueber TrackPoint (ohne ersten und letzten beiden)
-            {
-                d01 = mPersons.at(i).at(j).distanceToPoint(mPersons.at(i).at(j - 1));
-                d12 = mPersons.at(i).at(j + 1).distanceToPoint(mPersons.at(i).at(j));
-                d23 = mPersons.at(i).at(j + 2).distanceToPoint(mPersons.at(i).at(j + 1));
-                if(((1.8 * (d01 + d23) / 2.) < d12) &&
-                   ((d12 > 6.) ||
-                    ((d01 + d23) / 2. > 3.))) // geschwindigkeit 1,8-fach && mindestpixelbewegung im schnitt von 3
-                {
-                    SPDLOG_WARN(
-                        "Fast variation of velocity of person {} between frame {} and {}!",
-                        i + 1,
-                        j + mPersons.at(i).firstFrame(),
-                        j + 1 + mPersons.at(i).firstFrame());
-                    pers.append(i + 1);
-                    frame.append(j + mPersons.at(i).firstFrame());
-                }
-            }
-        }
-    }
-
-    // testen, ob zwei trackpoint sehr nah beieinanderliegen (es gibt trajektorien, die uebereinander liegen, wenn nicht
-    // genmergt wird)
-    if(testEqual)
-    {
-        progress.setValue(300);
-        progress.setLabelText("Check if trajectories are equal...");
-        qApp->processEvents();
-
-        int lLF = largestLastFrame();
-        int f;
-        for(f = smallestFirstFrame(); f <= lLF; ++f)
-        {
-            progress.setValue(300 + f * 100. / lLF);
-            qApp->processEvents();
-
-            for(i = 0; i < static_cast<int>(mPersons.size()); ++i)
-            {
-                // if (!pers.contains(i+1)) man koennte nur einmal eine Person aufnehmen, da aufeinanderfolgende frames
-                // oft betroffen
-                for(j = i + 1; j < static_cast<int>(mPersons.size()); ++j)
-                {
-                    if(mPersons.at(i).trackPointExist(f) && mPersons.at(j).trackPointExist(f))
-                    {
-                        if(mPersons.at(i).trackPointAt(f).distanceToPoint(mPersons.at(j).trackPointAt(f)) <
-                           mMainWindow.getHeadSize(nullptr, i, f) / 2.)
-                        {
-                            SPDLOG_WARN("Person {} and {} are very close to each other at frame {}!", i + 1, j + 1, f);
-                            pers.append(i + 1);
-                            frame.append(f);
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
 /// optimize color for all persons
 void PersonStorage::optimizeColor()
 {
-- 
GitLab


From c59a06910447efdf8aa2bdfb4bb4cf47329db59a Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 14:09:15 +0100
Subject: [PATCH 14/45] Call functions directly instead of wrapper function

---
 include/plausibility.h | 13 ++-----
 src/correction.cpp     | 56 +++++++++++++++++++++++----
 src/plausibility.cpp   | 86 ++++--------------------------------------
 3 files changed, 59 insertions(+), 96 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 0859f33ff..44026317c 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -37,22 +37,15 @@ struct FailedCheck
     std::string message{};
 };
 
-std::vector<FailedCheck> checkPlausibility(
-    const PersonStorage &tracker,
-    Petrack             &petrack,
-    const cv::Size      &imageSize,
-    bool                 testEqual    = true,
-    bool                 testVelocity = true,
-    bool                 testInside   = true,
-    bool                 testLength   = true);
-
 std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog);
 
 std::vector<FailedCheck> checkInside(
     const PersonStorage &personStorage,
     QProgressDialog     *progressDialog,
     const cv::Size      &imageSize,
-    Petrack             &petrack);
+    int                  imageBorderSize,
+    QRectF               rect,
+    int                  lastFrame);
 
 std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog);
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 22fc81eb8..06a8e5c2c 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -20,9 +20,11 @@
 
 #include "include/correction.h"
 
+#include "animation.h"
 #include "control.h"
 #include "pMessageBox.h"
 #include "player.h"
+#include "roiItem.h"
 #include "ui_correction.h"
 
 #include <QByteArray>
@@ -184,13 +186,51 @@ Correction::~Correction()
 
 void Correction::on_btnCheck_clicked()
 {
-    std::vector<plausibility::FailedCheck> failedChecks = plausibility::checkPlausibility(
-        mPeTrack->getPersonStorage(),
-        *mPeTrack,
-        mPeTrack->getImg().size(),
-        mUi->chbEqual->isChecked(),
-        mUi->chbVelocit->isChecked(),
-        mUi->chbInside->isChecked(),
-        mUi->chbLength->isChecked());
+    std::vector<plausibility::FailedCheck> failedChecks;
+
+    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPeTrack);
+    progress.setWindowTitle("Check plausibility");
+    progress.setWindowModality(Qt::WindowModal);
+    progress.setVisible(true);
+    progress.setValue(0);
+    progress.setLabelText("Check Plausibility...");
+
+    // test, if the trajectory is very short (less than 10 Trackpoints)
+    if(mUi->chbLength->isChecked())
+    {
+        auto failedLengthChecks{plausibility::checkLength(mPeTrack->getPersonStorage(), &progress)};
+        failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
+    }
+
+    // check, if trajectory starts and ends outside the recognition area
+    if(mUi->chbInside->isChecked())
+    {
+        int lastFrame = mPeTrack->getAnimation()->getNumFrames() - 1;
+
+        auto failedInsideChecks{plausibility::checkInside(
+            mPeTrack->getPersonStorage(),
+            &progress,
+            mPeTrack->getImg().size(),
+            mPeTrack->getImageBorderSize(),
+            mPeTrack->getRecoRoiItem()->rect(),
+            lastFrame)};
+        failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
+    }
+
+    // testen, ob grosse Geschwindigkeitsaenderungen
+    // statt distanz koennte man auch noch vektoren vergleichen, was genauere analyse waer!!!!
+    if(mUi->chbVelocit->isChecked())
+    {
+        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
+        failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
+    }
+
+    // testen, ob zwei trackpoint sehr nah beieinanderliegen (es gibt trajektorien, die uebereinander liegen, wenn nicht
+    // genmergt wird)
+    if(mUi->chbEqual->isChecked())
+    {
+        auto failedEqualityChecks{plausibility::checkEquality(mPeTrack->getPersonStorage(), &progress, *mPeTrack)};
+        failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
+    }
     mTableModel->setFailedChecks(failedChecks);
 }
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 9ce5e86b8..ae9468e35 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -26,75 +26,6 @@
 
 namespace plausibility
 {
-/**
- * @brief Performs different tests to check the plausibility of trajectories.
- *
- * This method can check for
- * <ul><li>shortness (less than 10 points)</li>
- * <li>start and endpoint (both should be outside the reco ROI
- * with exceptions for the beginning and end of the video)</li>
- * <li>Fast variations of speed (4 frame interval)</li>
- * <li>TrackPoints are too close together</li></ul>
- *
- * @param tracker containing the trajectory data
- * @param petrack main window (some data is only accessible that way currently)
- * @param imageSize size of the image
- * @param testEqual true if warning for very close points are wished
- * @param testVelocity true if warning for fast speed variations is wished
- * @param testInside true if warning for start and endpoint in reco ROI is wished
- * @param testLength if warning for very short trajectories is wished
- * @return all failed checks, for enabled tests
- */
-std::vector<FailedCheck> checkPlausibility(
-    const PersonStorage &tracker,
-    Petrack             &petrack,
-    const cv::Size      &imageSize,
-    bool                 testEqual,
-    bool                 testVelocity,
-    bool                 testInside,
-    bool                 testLength)
-{
-    std::vector<plausibility::FailedCheck> failedChecks;
-
-    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, petrack.window());
-    progress.setWindowTitle("Check plausibility");
-    progress.setWindowModality(Qt::WindowModal);
-    progress.setVisible(true);
-    progress.setValue(0);
-    progress.setLabelText("Check Plausibility...");
-
-    // test, if the trajectory is very short (less than 10 Trackpoints)
-    if(testLength)
-    {
-        auto failedLengthChecks{checkLength(tracker, &progress)};
-        failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
-    }
-
-    // check, if trajectory starts and ends outside the recognition area
-    if(testInside)
-    {
-        auto failedInsideChecks{checkInside(tracker, &progress, imageSize, petrack)};
-        failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
-    }
-
-    // testen, ob grosse Geschwindigkeitsaenderungen
-    // statt distanz koennte man auch noch vektoren vergleichen, was genauere analyse waer!!!!
-    if(testVelocity)
-    {
-        auto failedVelocityChecks{checkVelocityVariation(tracker, &progress)};
-        failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
-    }
-
-    // testen, ob zwei trackpoint sehr nah beieinanderliegen (es gibt trajektorien, die uebereinander liegen, wenn nicht
-    // genmergt wird)
-    if(testEqual)
-    {
-        auto failedEqualityChecks{checkEquality(tracker, &progress, petrack)};
-        failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
-    }
-    return failedChecks;
-}
-
 std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog)
 {
     std::vector<FailedCheck> failedChecks;
@@ -118,14 +49,13 @@ std::vector<FailedCheck> checkInside(
     const PersonStorage &personStorage,
     QProgressDialog     *progressDialog,
     const cv::Size      &imageSize,
-    Petrack             &petrack)
+    int                  imageBorderSize,
+    QRectF               rect,
+    int                  lastFrame)
 {
     std::vector<FailedCheck> failedChecks;
 
-    static int margin    = 30; // distance to image border, in which the trajectory may get lost
-    int        bS        = petrack.getImageBorderSize();
-    QRectF     rect      = petrack.getRecoRoiItem()->rect();
-    int        lastFrame = petrack.getAnimation()->getNumFrames() - 1;
+    static int margin = 30; // distance to image border, in which the trajectory may get lost
 
     progressDialog->setValue(100);
     progressDialog->setLabelText("Check if trajectories are inside image...");
@@ -139,8 +69,8 @@ std::vector<FailedCheck> checkInside(
         double y = personStorage.at(i).first().y();
 
         if((personStorage.at(i).firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-            x <= MIN(imageSize.width - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
-            y <= MIN(imageSize.height - 1 - 2 * bS - margin, rect.y() + rect.height())))
+            x <= MIN(imageSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
+            y <= MIN(imageSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height())))
         {
             std::stringstream stream;
             stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
@@ -151,8 +81,8 @@ std::vector<FailedCheck> checkInside(
         y = personStorage.at(i).last().y();
 
         if(personStorage.at(i).lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-           x <= MIN(imageSize.width - 1 - 2 * bS - margin, rect.x() + rect.width()) &&
-           y <= MIN(imageSize.height - 1 - 2 * bS - margin, rect.y() + rect.height()))
+           x <= MIN(imageSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
+           y <= MIN(imageSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height()))
         {
             std::stringstream stream;
             stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
-- 
GitLab


From d451c16043d0b6df76fd21259ff38bd8bdc6afb2 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 14:23:13 +0100
Subject: [PATCH 15/45] Add minLength as parameter for length check

---
 include/plausibility.h |  3 ++-
 src/correction.cpp     |  4 ++--
 src/plausibility.cpp   | 15 ++++++++++++---
 ui/correction.ui       | 29 ++++++++++++++++++++++++++++-
 4 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 44026317c..4a8ec5559 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -37,7 +37,8 @@ struct FailedCheck
     std::string message{};
 };
 
-std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog);
+std::vector<FailedCheck>
+checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog, int minLength);
 
 std::vector<FailedCheck> checkInside(
     const PersonStorage &personStorage,
diff --git a/src/correction.cpp b/src/correction.cpp
index 06a8e5c2c..2bc6f891c 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -195,10 +195,10 @@ void Correction::on_btnCheck_clicked()
     progress.setValue(0);
     progress.setLabelText("Check Plausibility...");
 
-    // test, if the trajectory is very short (less than 10 Trackpoints)
     if(mUi->chbLength->isChecked())
     {
-        auto failedLengthChecks{plausibility::checkLength(mPeTrack->getPersonStorage(), &progress)};
+        auto failedLengthChecks{
+            plausibility::checkLength(mPeTrack->getPersonStorage(), &progress, mUi->spbxMinFrameLength->value())};
         failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
     }
 
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index ae9468e35..d44b75e71 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -26,7 +26,16 @@
 
 namespace plausibility
 {
-std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog)
+
+/**
+ * Checks if the length for any trajectory is less than minLength frames.
+ *
+ * @param personStorage data container for trajectories
+ * @param progressDialog dialog for showing progress of all checks
+ * @param minLength minimum length each trajectory needs to have to not be reported as faulty
+ * @return vector of all trajectories which consists of less than minLength frames
+ */
+std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog, int minLength)
 {
     std::vector<FailedCheck> failedChecks;
     progressDialog->setValue(0);
@@ -35,10 +44,10 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
 
     for(int i = 0; i < personStorage.nbPersons(); ++i)
     {
-        if(personStorage.at(i).size() < 10)
+        if(personStorage.at(i).size() < minLength)
         {
             std::stringstream stream;
-            stream << "Trajectory of person " << i + 1 << " has less than 10 trackpoints!";
+            stream << "Trajectory of person " << i + 1 << " has less than " << minLength << " trackpoints!";
             failedChecks.push_back({i + 1, personStorage.at(i).firstFrame(), stream.str()});
         }
     }
diff --git a/ui/correction.ui b/ui/correction.ui
index c1b3f7d0a..d8e18c9a2 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -19,7 +19,7 @@
   <property name="windowTitle">
    <string>Frame</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout">
+  <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0">
    <item row="1" column="0">
     <widget class="QCheckBox" name="chbVelocit">
      <property name="toolTip">
@@ -158,8 +158,35 @@
      </property>
     </widget>
    </item>
+   <item row="2" column="1">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>min. length [frames]:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="2" colspan="2">
+    <widget class="PSpinBox" name="spbxMinFrameLength">
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+     <property name="maximum">
+      <number>999999</number>
+     </property>
+     <property name="value">
+      <number>10</number>
+     </property>
+    </widget>
+   </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>PSpinBox</class>
+   <extends>QSpinBox</extends>
+   <header>pspinbox.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>
-- 
GitLab


From 27c1e3041b83a9f5bf46346ff7112c6cee4d0ab5 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 14:31:43 +0100
Subject: [PATCH 16/45] Add margin as parameter for inside check

---
 include/plausibility.h |  5 +++--
 src/correction.cpp     |  4 ++--
 src/plausibility.cpp   | 27 +++++++++++++++++++--------
 ui/correction.ui       | 20 ++++++++++++++++++++
 4 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 4a8ec5559..80d5bfd4d 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -43,10 +43,11 @@ checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog,
 std::vector<FailedCheck> checkInside(
     const PersonStorage &personStorage,
     QProgressDialog     *progressDialog,
-    const cv::Size      &imageSize,
+    const cv::Size      &sequenceSize,
     int                  imageBorderSize,
     QRectF               rect,
-    int                  lastFrame);
+    int                  lastFrame,
+    int                  margin);
 
 std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog);
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 2bc6f891c..5ad858d4b 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -202,7 +202,6 @@ void Correction::on_btnCheck_clicked()
         failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
     }
 
-    // check, if trajectory starts and ends outside the recognition area
     if(mUi->chbInside->isChecked())
     {
         int lastFrame = mPeTrack->getAnimation()->getNumFrames() - 1;
@@ -213,7 +212,8 @@ void Correction::on_btnCheck_clicked()
             mPeTrack->getImg().size(),
             mPeTrack->getImageBorderSize(),
             mPeTrack->getRecoRoiItem()->rect(),
-            lastFrame)};
+            lastFrame,
+            mUi->spbxInsideMargin->value())};
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
 
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index d44b75e71..fc7c39aac 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -54,18 +54,29 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
     return failedChecks;
 }
 
+/**
+ * Checks if the first or last frame of trajectory are inside rect and the picture.
+ *
+ * @param personStorage data container for trajectories
+ * @param progressDialog dialog for showing progress of all checks
+ * @param sequenceSize size of the sequence
+ * @param imageBorderSize border size
+ * @param rect rectangle used for checking
+ * @param lastFrame last frame of sequence
+ * @param margin distance to image border, in which the trajectory may get lost
+ * @return vector of all trajectories where the first or last frame are inside rect and the picture
+ */
 std::vector<FailedCheck> checkInside(
     const PersonStorage &personStorage,
     QProgressDialog     *progressDialog,
-    const cv::Size      &imageSize,
+    const cv::Size      &sequenceSize,
     int                  imageBorderSize,
     QRectF               rect,
-    int                  lastFrame)
+    int                  lastFrame,
+    int                  margin)
 {
     std::vector<FailedCheck> failedChecks;
 
-    static int margin = 30; // distance to image border, in which the trajectory may get lost
-
     progressDialog->setValue(100);
     progressDialog->setLabelText("Check if trajectories are inside image...");
     qApp->processEvents();
@@ -78,8 +89,8 @@ std::vector<FailedCheck> checkInside(
         double y = personStorage.at(i).first().y();
 
         if((personStorage.at(i).firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-            x <= MIN(imageSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
-            y <= MIN(imageSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height())))
+            x <= MIN(sequenceSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
+            y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height())))
         {
             std::stringstream stream;
             stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
@@ -90,8 +101,8 @@ std::vector<FailedCheck> checkInside(
         y = personStorage.at(i).last().y();
 
         if(personStorage.at(i).lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-           x <= MIN(imageSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
-           y <= MIN(imageSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height()))
+           x <= MIN(sequenceSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
+           y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height()))
         {
             std::stringstream stream;
             stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
diff --git a/ui/correction.ui b/ui/correction.ui
index d8e18c9a2..e1fdfc818 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -178,6 +178,26 @@
      </property>
     </widget>
    </item>
+   <item row="3" column="2" colspan="2">
+    <widget class="PSpinBox" name="spbxInsideMargin">
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+     <property name="maximum">
+      <number>9999999</number>
+     </property>
+     <property name="value">
+      <number>30</number>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>margin [pixel]:</string>
+     </property>
+    </widget>
+   </item>
   </layout>
  </widget>
  <customwidgets>
-- 
GitLab


From a2a8a6e0fb40fbfca17426bd730b07848af0f794 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 14:46:09 +0100
Subject: [PATCH 17/45] Add documentation for velocity variation check

---
 src/correction.cpp   |  2 --
 src/plausibility.cpp | 28 ++++++++++++++++++++++++++--
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/src/correction.cpp b/src/correction.cpp
index 5ad858d4b..b5fb9eb38 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -217,8 +217,6 @@ void Correction::on_btnCheck_clicked()
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
 
-    // testen, ob grosse Geschwindigkeitsaenderungen
-    // statt distanz koennte man auch noch vektoren vergleichen, was genauere analyse waer!!!!
     if(mUi->chbVelocit->isChecked())
     {
         auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index fc7c39aac..a0c37e433 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -113,6 +113,27 @@ std::vector<FailedCheck> checkInside(
     return failedChecks;
 }
 
+/**
+ * Check for large velocity variations in all trajectories
+ *
+ * A faulty velocity variations means:
+ * - speed changed with a factor > 1.8
+ * AND
+ * - more than 6 px movement OR average in 2 frames > 3 px
+ *
+ * For computation, following points are taken into account:
+ *
+ * frame-1      frame       frame+1         frame+2
+ *    o-----------o------------o---------------o
+ *    |           |            |
+ *    |... d01 ...|.... d12 ...|..... d23 .....|
+ *
+ * Note: Instead of the distance, comparing vectors would be accurate.
+ *
+ * @param personStorage data container for trajectories
+ * @param progressDialog dialog for showing progress of all checks
+ * @return vector of all trajectories with large velocity variations
+ */
 std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog)
 {
     std::vector<FailedCheck> failedChecks;
@@ -125,14 +146,17 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
     {
         qApp->processEvents();
         progressDialog->setValue(200 + i * 100. / personStorage.nbPersons());
-        for(int j = 1; j < personStorage.at(i).size() - 2; ++j) // ueber TrackPoint (ohne ersten und letzten beiden)
+
+        // ignore first and two last TrackPoints, as these points are needed as buffer
+        for(int j = 1; j < personStorage.at(i).size() - 2; ++j)
         {
             double d01 = personStorage.at(i).at(j).distanceToPoint(personStorage.at(i).at(j - 1));
             double d12 = personStorage.at(i).at(j + 1).distanceToPoint(personStorage.at(i).at(j));
             double d23 = personStorage.at(i).at(j + 2).distanceToPoint(personStorage.at(i).at(j + 1));
+
             if(((1.8 * (d01 + d23) / 2.) < d12) &&
                ((d12 > 6.) ||
-                ((d01 + d23) / 2. > 3.))) // geschwindigkeit 1,8-fach && mindestpixelbewegung im schnitt von 3
+                ((d01 + d23) / 2. > 3.)))
             {
                 std::stringstream stream;
                 stream << "Fast variation of velocity of person " << i + 1 << " between frame "
-- 
GitLab


From dd9c352d567306e672707d7ff24956895953511e Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:12:16 +0100
Subject: [PATCH 18/45] Add factor as parameter for equality check

---
 include/plausibility.h |  7 +++++--
 src/correction.cpp     |  5 ++---
 src/plausibility.cpp   | 30 +++++++++++++++++++++---------
 ui/correction.ui       | 28 ++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 80d5bfd4d..792816583 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -51,8 +51,11 @@ std::vector<FailedCheck> checkInside(
 
 std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog);
 
-std::vector<FailedCheck>
-checkEquality(const PersonStorage &personStorage, QProgressDialog *progressDialog, Petrack &petrack);
+std::vector<FailedCheck> checkEquality(
+    const PersonStorage &personStorage,
+    QProgressDialog     *progressDialog,
+    Petrack             &petrack,
+    double               headSizeFactor);
 
 } // namespace plausibility
 
diff --git a/src/correction.cpp b/src/correction.cpp
index b5fb9eb38..ba88b997c 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -223,11 +223,10 @@ void Correction::on_btnCheck_clicked()
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
 
-    // testen, ob zwei trackpoint sehr nah beieinanderliegen (es gibt trajektorien, die uebereinander liegen, wenn nicht
-    // genmergt wird)
     if(mUi->chbEqual->isChecked())
     {
-        auto failedEqualityChecks{plausibility::checkEquality(mPeTrack->getPersonStorage(), &progress, *mPeTrack)};
+        auto failedEqualityChecks{plausibility::checkEquality(
+            mPeTrack->getPersonStorage(), &progress, *mPeTrack, mUi->spbxEqualityDistance->value())};
         failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
     }
     mTableModel->setFailedChecks(failedChecks);
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index a0c37e433..62e30c052 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -33,6 +33,7 @@ namespace plausibility
  * @param personStorage data container for trajectories
  * @param progressDialog dialog for showing progress of all checks
  * @param minLength minimum length each trajectory needs to have to not be reported as faulty
+ *
  * @return vector of all trajectories which consists of less than minLength frames
  */
 std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog, int minLength)
@@ -64,6 +65,7 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
  * @param rect rectangle used for checking
  * @param lastFrame last frame of sequence
  * @param margin distance to image border, in which the trajectory may get lost
+ *
  * @return vector of all trajectories where the first or last frame are inside rect and the picture
  */
 std::vector<FailedCheck> checkInside(
@@ -132,6 +134,7 @@ std::vector<FailedCheck> checkInside(
  *
  * @param personStorage data container for trajectories
  * @param progressDialog dialog for showing progress of all checks
+ *
  * @return vector of all trajectories with large velocity variations
  */
 std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStorage, QProgressDialog *progressDialog)
@@ -154,9 +157,7 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
             double d12 = personStorage.at(i).at(j + 1).distanceToPoint(personStorage.at(i).at(j));
             double d23 = personStorage.at(i).at(j + 2).distanceToPoint(personStorage.at(i).at(j + 1));
 
-            if(((1.8 * (d01 + d23) / 2.) < d12) &&
-               ((d12 > 6.) ||
-                ((d01 + d23) / 2. > 3.)))
+            if(((1.8 * (d01 + d23) / 2.) < d12) && ((d12 > 6.) || ((d01 + d23) / 2. > 3.)))
             {
                 std::stringstream stream;
                 stream << "Fast variation of velocity of person " << i + 1 << " between frame "
@@ -170,8 +171,21 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
     return failedChecks;
 }
 
-std::vector<FailedCheck>
-checkEquality(const PersonStorage &personStorage, QProgressDialog *progressDialog, Petrack &petrack)
+/**
+ * Checks if two trajectories are close to each other in a specific frame.
+ *
+ * @param personStorage data container for trajectories
+ * @param progressDialog dialog for showing progress of all checks
+ * @param petrack main window
+ * @param headSizeFactor factor used to determine the distance at which two traj are considered equal
+ *
+ * @return vector of all trajectories which were too close to an other trajectory in one frame
+ */
+std::vector<FailedCheck> checkEquality(
+    const PersonStorage &personStorage,
+    QProgressDialog     *progressDialog,
+    Petrack             &petrack,
+    double               headSizeFactor)
 {
     std::vector<FailedCheck> failedChecks;
     progressDialog->setValue(300);
@@ -186,14 +200,12 @@ checkEquality(const PersonStorage &personStorage, QProgressDialog *progressDialo
 
         for(int i = 0; i < personStorage.nbPersons(); ++i)
         {
-            // if (!pers.contains(i+1)) man koennte nur einmal eine Person aufnehmen, da aufeinanderfolgende frames
-            // oft betroffen
             for(int j = i + 1; j < personStorage.nbPersons(); ++j)
             {
                 if(personStorage.at(i).trackPointExist(frame) && personStorage.at(j).trackPointExist(frame))
                 {
-                    if(personStorage.at(i).trackPointAt(frame).distanceToPoint(
-                           personStorage.at(j).trackPointAt(frame)) < petrack.getHeadSize(nullptr, i, frame) / 2.)
+                    if(personStorage.at(i).trackPointAt(frame).distanceToPoint(personStorage.at(j).trackPointAt(
+                           frame)) < headSizeFactor * petrack.getHeadSize(nullptr, i, frame))
                     {
                         std::stringstream stream;
                         stream << "Person " << i + 1 << " and " << j + 1 << " are very close to each other at frame "
diff --git a/ui/correction.ui b/ui/correction.ui
index e1fdfc818..1464eec36 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -198,6 +198,29 @@
      </property>
     </widget>
    </item>
+   <item row="0" column="1">
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>distance [headsize]:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="2" colspan="2">
+    <widget class="PDoubleSpinBox" name="spbxEqualityDistance">
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+     <property name="maximum">
+      <double>10.000000000000000</double>
+     </property>
+     <property name="singleStep">
+      <double>0.100000000000000</double>
+     </property>
+     <property name="value">
+      <double>0.500000000000000</double>
+     </property>
+    </widget>
+   </item>
   </layout>
  </widget>
  <customwidgets>
@@ -206,6 +229,11 @@
    <extends>QSpinBox</extends>
    <header>pspinbox.h</header>
   </customwidget>
+  <customwidget>
+   <class>PDoubleSpinBox</class>
+   <extends>QDoubleSpinBox</extends>
+   <header>pdoublespinbox.h</header>
+  </customwidget>
  </customwidgets>
  <resources/>
  <connections/>
-- 
GitLab


From 60d89d5d8986af6c260acb638da5bcdf144a48fd Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:15:42 +0100
Subject: [PATCH 19/45] Fix typo in member name

---
 include/correction.h | 4 ++--
 src/correction.cpp   | 2 +-
 ui/correction.ui     | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index b3db9efb5..bbd1232a4 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -67,8 +67,8 @@ public:
     bool getTestEqualChecked() { return mUi->chbEqual->isChecked(); }
     void setTestEqualCheckState(Qt::CheckState testEqual) { mUi->chbEqual->setCheckState(testEqual); }
 
-    bool getTestVelocityChecked() { return mUi->chbVelocit->isChecked(); }
-    void setTestVelocityCheckState(Qt::CheckState testVelocity) { mUi->chbVelocit->setCheckState(testVelocity); }
+    bool getTestVelocityChecked() { return mUi->chbVelocity->isChecked(); }
+    void setTestVelocityCheckState(Qt::CheckState testVelocity) { mUi->chbVelocity->setCheckState(testVelocity); }
 
     bool getTestLengthChecked() { return mUi->chbLength->isChecked(); }
     void setTestLengthCheckState(Qt::CheckState testLength) { mUi->chbLength->setCheckState(testLength); }
diff --git a/src/correction.cpp b/src/correction.cpp
index ba88b997c..c793e086d 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -217,7 +217,7 @@ void Correction::on_btnCheck_clicked()
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
 
-    if(mUi->chbVelocit->isChecked())
+    if(mUi->chbVelocity->isChecked())
     {
         auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
diff --git a/ui/correction.ui b/ui/correction.ui
index 1464eec36..31e157f25 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -21,7 +21,7 @@
   </property>
   <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0">
    <item row="1" column="0">
-    <widget class="QCheckBox" name="chbVelocit">
+    <widget class="QCheckBox" name="chbVelocity">
      <property name="toolTip">
       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
-- 
GitLab


From bb9fddcbc1ce708770ed4c81f07008c34cb45c43 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:24:02 +0100
Subject: [PATCH 20/45] Shorten error strings as frame and person number are
 already in the table

---
 src/plausibility.cpp | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 62e30c052..20da50f3f 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -48,7 +48,7 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
         if(personStorage.at(i).size() < minLength)
         {
             std::stringstream stream;
-            stream << "Trajectory of person " << i + 1 << " has less than " << minLength << " trackpoints!";
+            stream << "Has less than " << minLength << " trackpoints";
             failedChecks.push_back({i + 1, personStorage.at(i).firstFrame(), stream.str()});
         }
     }
@@ -94,9 +94,8 @@ std::vector<FailedCheck> checkInside(
             x <= MIN(sequenceSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
             y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height())))
         {
-            std::stringstream stream;
-            stream << "Start of trajectory inside picture and recognition area of person " << i + 1 << "!";
-            failedChecks.push_back({i + 1, personStorage.at(i).firstFrame(), stream.str()});
+            failedChecks.push_back(
+                {i + 1, personStorage.at(i).firstFrame(), "Start of trajectory is inside picture and reco ROI!"});
         }
 
         x = personStorage.at(i).last().x();
@@ -106,9 +105,8 @@ std::vector<FailedCheck> checkInside(
            x <= MIN(sequenceSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
            y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height()))
         {
-            std::stringstream stream;
-            stream << "End of trajectory inside picture and recognition area of person " << i + 1 << "!";
-            failedChecks.push_back({i + 1, personStorage.at(i).lastFrame(), stream.str()});
+            failedChecks.push_back(
+                {i + 1, personStorage.at(i).lastFrame(), "End of trajectory is inside picture and reco ROI!"});
         }
     }
 
@@ -159,11 +157,8 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
 
             if(((1.8 * (d01 + d23) / 2.) < d12) && ((d12 > 6.) || ((d01 + d23) / 2. > 3.)))
             {
-                std::stringstream stream;
-                stream << "Fast variation of velocity of person " << i + 1 << " between frame "
-                       << j + personStorage.at(i).firstFrame() << " and " << j + 1 + personStorage.at(i).firstFrame()
-                       << "!";
-                failedChecks.push_back({i + 1, j + personStorage.at(i).firstFrame(), stream.str()});
+                failedChecks.push_back(
+                    {i + 1, j + personStorage.at(i).firstFrame(), "Fast variation of velocity to following frame!"});
             }
         }
     }
@@ -208,8 +203,7 @@ std::vector<FailedCheck> checkEquality(
                            frame)) < headSizeFactor * petrack.getHeadSize(nullptr, i, frame))
                     {
                         std::stringstream stream;
-                        stream << "Person " << i + 1 << " and " << j + 1 << " are very close to each other at frame "
-                               << frame << "!";
+                        stream << "Trajectory is every close to Person " << j + 1 << "!";
                         failedChecks.push_back({i + 1, frame, stream.str()});
                     }
                 }
-- 
GitLab


From 480acd370a9b0c4fa17a07942dc4c0f9016eb7d3 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:31:01 +0100
Subject: [PATCH 21/45] Fixing compiler warnings

---
 include/plausibility.h |  2 +-
 src/correction.cpp     | 10 ++++++----
 src/plausibility.cpp   | 10 +++++-----
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 792816583..23dbca826 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -32,7 +32,7 @@ namespace plausibility
 {
 struct FailedCheck
 {
-    int         pers{};
+    size_t      pers{};
     int         frame{};
     std::string message{};
 };
diff --git a/src/correction.cpp b/src/correction.cpp
index c793e086d..cec7d278b 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -77,9 +77,9 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
     switch(index.column())
     {
         case 0:
-            return mFailedChecks[index.row()].pers;
+            return QVariant::fromValue(mFailedChecks[index.row()].pers);
         case 1:
-            return mFailedChecks[index.row()].frame;
+            return QVariant::fromValue(mFailedChecks[index.row()].frame);
         case 2:
             return QString::fromStdString(mFailedChecks[index.row()].message);
     }
@@ -89,6 +89,8 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
 
 void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks)
 {
+    emit layoutAboutToBeChanged();
+
     mFailedChecks = failedChecks;
 
     QModelIndex topLeft     = index(0, 0);
@@ -120,9 +122,9 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
 
     connect(
         mUi->tblFailedChecks->selectionModel(),
-        SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+        &QItemSelectionModel::selectionChanged,
         this,
-        SLOT(on_tblFailedChecks_selectedRowChanged()));
+        &Correction::on_tblFailedChecks_selectedRowChanged);
 
     connect(
         mUi->tblFailedChecks,
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 20da50f3f..ec7276b0b 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -43,7 +43,7 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
     progressDialog->setLabelText("Check trajectories lengths...");
     qApp->processEvents();
 
-    for(int i = 0; i < personStorage.nbPersons(); ++i)
+    for(size_t i = 0; i < personStorage.nbPersons(); ++i)
     {
         if(personStorage.at(i).size() < minLength)
         {
@@ -83,7 +83,7 @@ std::vector<FailedCheck> checkInside(
     progressDialog->setLabelText("Check if trajectories are inside image...");
     qApp->processEvents();
 
-    for(int i = 0; i < personStorage.nbPersons(); ++i)
+    for(size_t i = 0; i < personStorage.nbPersons(); ++i)
     {
         qApp->processEvents();
         progressDialog->setValue(100 + i * 100. / personStorage.nbPersons());
@@ -143,7 +143,7 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
     progressDialog->setValue(200);
     progressDialog->setLabelText("Check velocity...");
 
-    for(int i = 0; i < personStorage.nbPersons(); ++i) // ueber TrackPerson
+    for(size_t i = 0; i < personStorage.nbPersons(); ++i) // ueber TrackPerson
     {
         qApp->processEvents();
         progressDialog->setValue(200 + i * 100. / personStorage.nbPersons());
@@ -193,9 +193,9 @@ std::vector<FailedCheck> checkEquality(
         progressDialog->setValue(300 + frame * 100. / largestLastFrame);
         qApp->processEvents();
 
-        for(int i = 0; i < personStorage.nbPersons(); ++i)
+        for(size_t i = 0; i < personStorage.nbPersons(); ++i)
         {
-            for(int j = i + 1; j < personStorage.nbPersons(); ++j)
+            for(size_t j = i + 1; j < personStorage.nbPersons(); ++j)
             {
                 if(personStorage.at(i).trackPointExist(frame) && personStorage.at(j).trackPointExist(frame))
                 {
-- 
GitLab


From 5d281c1c556b2ecb48b38b066921458241001b62 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:35:34 +0100
Subject: [PATCH 22/45] Fixing tab order

---
 ui/correction.ui | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/ui/correction.ui b/ui/correction.ui
index 31e157f25..d81d70a34 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -235,6 +235,17 @@
    <header>pdoublespinbox.h</header>
   </customwidget>
  </customwidgets>
+ <tabstops>
+  <tabstop>chbEqual</tabstop>
+  <tabstop>spbxEqualityDistance</tabstop>
+  <tabstop>chbVelocity</tabstop>
+  <tabstop>chbLength</tabstop>
+  <tabstop>spbxMinFrameLength</tabstop>
+  <tabstop>chbInside</tabstop>
+  <tabstop>spbxInsideMargin</tabstop>
+  <tabstop>btnCheck</tabstop>
+  <tabstop>tblFailedChecks</tabstop>
+ </tabstops>
  <resources/>
  <connections/>
 </ui>
-- 
GitLab


From d044cfd08e6796ee530b99aaf9b1525646f91ae4 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:49:37 +0100
Subject: [PATCH 23/45] Fixing some minor issues

---
 include/correction.h | 33 ++++++++++++-----------
 src/correction.cpp   | 62 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index bbd1232a4..287e31396 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -38,8 +38,6 @@ private:
 public:
     explicit FailedChecksTableModel(QObject *parent) : QAbstractTableModel(parent) {}
 
-    ~FailedChecksTableModel() override = default;
-
     void setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks);
 
     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
@@ -62,21 +60,26 @@ class Correction : public QWidget
 
 public:
     Correction(Petrack *petrack, QWidget *parent = nullptr);
-    void setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks);
 
-    bool getTestEqualChecked() { return mUi->chbEqual->isChecked(); }
-    void setTestEqualCheckState(Qt::CheckState testEqual) { mUi->chbEqual->setCheckState(testEqual); }
+    Correction(Correction const &other)            = delete;
+    Correction &operator=(Correction const &other) = delete;
+    Correction(Correction &&other)                 = delete;
+    Correction &operator=(Correction &&other)      = delete;
+    ~Correction();
+
+    void setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks);
 
-    bool getTestVelocityChecked() { return mUi->chbVelocity->isChecked(); }
-    void setTestVelocityCheckState(Qt::CheckState testVelocity) { mUi->chbVelocity->setCheckState(testVelocity); }
+    bool getTestEqualChecked() const;
+    void setTestEqualCheckState(Qt::CheckState testEqual);
 
-    bool getTestLengthChecked() { return mUi->chbLength->isChecked(); }
-    void setTestLengthCheckState(Qt::CheckState testLength) { mUi->chbLength->setCheckState(testLength); }
+    bool getTestVelocityChecked() const;
+    void setTestVelocityCheckState(Qt::CheckState testVelocity);
 
-    bool getTestInsideChecked() { return mUi->chbInside->isChecked(); }
-    void setTestInsideCheckState(Qt::CheckState testInside) { mUi->chbInside->setCheckState(testInside); }
+    bool getTestLengthChecked() const;
+    void setTestLengthCheckState(Qt::CheckState testLength);
 
-    ~Correction();
+    bool getTestInsideChecked() const;
+    void setTestInsideCheckState(Qt::CheckState testInside);
 
 private:
     Petrack                *mPeTrack;
@@ -84,10 +87,10 @@ private:
     FailedChecksTableModel *mTableModel;
 
 private slots:
-    void on_tblFailedChecks_selectedRowChanged();
+    void selectedRowChanged();
     void on_btnCheck_clicked();
-    void on_tblFailedChecks_contextMenuRequested();
-    void on_tblFailedChecks_markResolved(QList<QModelIndex> pos);
+    void openContextMenu();
+    void markResolved(QList<QModelIndex> pos);
 };
 
 #endif // CORRECTION_H
diff --git a/src/correction.cpp b/src/correction.cpp
index cec7d278b..511a6e704 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -124,13 +124,9 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
         mUi->tblFailedChecks->selectionModel(),
         &QItemSelectionModel::selectionChanged,
         this,
-        &Correction::on_tblFailedChecks_selectedRowChanged);
+        &Correction::selectedRowChanged);
 
-    connect(
-        mUi->tblFailedChecks,
-        &QTableWidget::customContextMenuRequested,
-        this,
-        &Correction::on_tblFailedChecks_contextMenuRequested);
+    connect(mUi->tblFailedChecks, &QTableWidget::customContextMenuRequested, this, &Correction::openContextMenu);
 }
 
 void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks)
@@ -138,7 +134,43 @@ void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &f
     mTableModel->setFailedChecks(failedChecks);
 }
 
-void Correction::on_tblFailedChecks_selectedRowChanged()
+bool Correction::getTestEqualChecked() const
+{
+    return mUi->chbEqual->isChecked();
+}
+void Correction::setTestEqualCheckState(Qt::CheckState testEqual)
+{
+    mUi->chbEqual->setCheckState(testEqual);
+}
+
+bool Correction::getTestVelocityChecked() const
+{
+    return mUi->chbVelocity->isChecked();
+}
+void Correction::setTestVelocityCheckState(Qt::CheckState testVelocity)
+{
+    mUi->chbVelocity->setCheckState(testVelocity);
+}
+
+bool Correction::getTestLengthChecked() const
+{
+    return mUi->chbLength->isChecked();
+}
+void Correction::setTestLengthCheckState(Qt::CheckState testLength)
+{
+    mUi->chbLength->setCheckState(testLength);
+}
+
+bool Correction::getTestInsideChecked() const
+{
+    return mUi->chbInside->isChecked();
+}
+void Correction::setTestInsideCheckState(Qt::CheckState testInside)
+{
+    mUi->chbInside->setCheckState(testInside);
+}
+
+void Correction::selectedRowChanged()
 {
     if(mUi->tblFailedChecks->selectionModel()->hasSelection())
     {
@@ -152,7 +184,7 @@ void Correction::on_tblFailedChecks_selectedRowChanged()
     }
 }
 
-void Correction::on_tblFailedChecks_contextMenuRequested()
+void Correction::openContextMenu()
 {
     auto selectedIndex = mUi->tblFailedChecks->selectionModel()->selectedIndexes();
 
@@ -167,12 +199,12 @@ void Correction::on_tblFailedChecks_contextMenuRequested()
         &markResolvedAction,
         &QAction::triggered,
         this,
-        [this, &selectedIndex]() { this->on_tblFailedChecks_markResolved(selectedIndex); });
+        [this, &selectedIndex]() { this->markResolved(selectedIndex); });
     contextMenu.addAction(&markResolvedAction);
     contextMenu.exec(QCursor::pos());
 }
 
-void Correction::on_tblFailedChecks_markResolved(QList<QModelIndex> pos)
+void Correction::markResolved(QList<QModelIndex> pos)
 {
     auto success = mUi->tblFailedChecks->model()->removeRows(pos[0].row(), 1);
     if(!success)
@@ -181,11 +213,6 @@ void Correction::on_tblFailedChecks_markResolved(QList<QModelIndex> pos)
     }
 }
 
-Correction::~Correction()
-{
-    delete mUi;
-}
-
 void Correction::on_btnCheck_clicked()
 {
     std::vector<plausibility::FailedCheck> failedChecks;
@@ -233,3 +260,8 @@ void Correction::on_btnCheck_clicked()
     }
     mTableModel->setFailedChecks(failedChecks);
 }
+
+Correction::~Correction()
+{
+    delete mUi;
+}
-- 
GitLab


From cc44700dcd8783ca1a22f3a4581f1cb329508675 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 22 Mar 2023 15:57:03 +0100
Subject: [PATCH 24/45] Using correct copyright notice

---
 include/correction.h   | 4 +---
 include/plausibility.h | 4 +---
 src/correction.cpp     | 4 +---
 src/plausibility.cpp   | 4 +---
 4 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 287e31396..53102061e 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -1,8 +1,6 @@
 /*
  * PeTrack - Software for tracking pedestrians movement in videos
- * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
- * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
- * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ * Copyright (C) 2023 Forschungszentrum Jülich GmbH, IAS-7
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/include/plausibility.h b/include/plausibility.h
index 23dbca826..ec987ba38 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -1,8 +1,6 @@
 /*
  * PeTrack - Software for tracking pedestrians movement in videos
- * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
- * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
- * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ * Copyright (C) 2023 Forschungszentrum Jülich GmbH, IAS-7
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/correction.cpp b/src/correction.cpp
index 511a6e704..3b16a1950 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -1,8 +1,6 @@
 /*
  * PeTrack - Software for tracking pedestrians movement in videos
- * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
- * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
- * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ * Copyright (C) 2023 Forschungszentrum Jülich GmbH, IAS-7
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index ec7276b0b..e9b4fabf5 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -1,8 +1,6 @@
 /*
  * PeTrack - Software for tracking pedestrians movement in videos
- * Copyright (C) 2010-2021 Forschungszentrum Jülich GmbH,
- * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
- * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ * Copyright (C) 2023 Forschungszentrum Jülich GmbH, IAS-7
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
-- 
GitLab


From 86ebdaba7631466876c4711c8b0303cda70151d5 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Thu, 1 Jun 2023 10:10:34 +0200
Subject: [PATCH 25/45] Introduce new function for deleting persons

---
 include/personStorage.h | 11 ++---------
 src/control.cpp         |  1 +
 src/personStorage.cpp   | 21 ++++++++-------------
 3 files changed, 11 insertions(+), 22 deletions(-)

diff --git a/include/personStorage.h b/include/personStorage.h
index e382397ed..1f042a95e 100644
--- a/include/personStorage.h
+++ b/include/personStorage.h
@@ -101,15 +101,6 @@ public:
         float             height);
     int merge(int pers1, int pers2);
 
-
-    void checkPlausibility(
-        QList<int> &pers,
-        QList<int> &frame,
-        bool        testEqual    = true,
-        bool        testVelocity = true,
-        bool        testInside   = true,
-        bool        testLength   = true);
-
     void optimizeColor();
 
     // reset the height of all persons, but not the pos of the trackpoints
@@ -132,6 +123,8 @@ private:
     std::vector<TrackPerson> mPersons;
     Petrack                 &mMainWindow;
     Autosave                &mAutosave;
+
+    auto deletePerson(int index) { return mPersons.erase(mPersons.begin() + index); };
 };
 
 #endif // PERSONSTORAGE_H
diff --git a/src/control.cpp b/src/control.cpp
index 4e686b4c1..49a82644a 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -29,6 +29,7 @@
 #include "extrinsicBox.h"
 #include "correction.h"
 #include "extrinsicParameters.h"
+#include "extrinsicBox.h"
 #include "filterBeforeBox.h"
 #include "intrinsicBox.h"
 #include "logger.h"
diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index 6b36c9db6..2e7b070ee 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -91,7 +91,7 @@ bool PersonStorage::delPointOf(int pers, int direction, int frame)
     }
     else if(direction == 0)
     {
-        mPersons.erase(mPersons.begin() + pers);
+        deletePerson(pers);
     }
     else if(direction == 1)
     {
@@ -142,10 +142,9 @@ void PersonStorage::delPointAll(Direction direction, int frame)
             {
                 case Direction::Previous:
                     mPersons[i].removeFramesBetween(mPersons[i].firstFrame(), frame - 1);
-
                     break;
                 case Direction::Whole:
-                    mPersons.erase(mPersons.begin() + i--); // nach Loeschen wird i um 1 erniedrigt
+                    deletePerson(i--); // after deleting the person decrease i by one
                     break;
                 case Direction::Following:
                     mPersons[i].removeFramesBetween(frame + 1, mPersons[i].lastFrame());
@@ -157,8 +156,7 @@ void PersonStorage::delPointAll(Direction direction, int frame)
             (direction == Direction::Whole) ||
             ((direction == Direction::Following) && (frame < mPersons.at(i).firstFrame())))
         {
-            mPersons.erase(mPersons.begin() + i);
-            i--;
+            deletePerson(i--); // after deleting the person decrease i by one
         }
     }
 }
@@ -185,8 +183,7 @@ void PersonStorage::delPointInsideROI()
                 splitPerson(i, mPersons.at(i).firstFrame() + j);
                 if(inside)
                 {
-                    mPersons.erase(mPersons.begin() + i);
-                    i--;
+                    deletePerson(i--); // after deleting the person decrease i by one
                     inside = !inside;
                 }
                 break;
@@ -195,8 +192,7 @@ void PersonStorage::delPointInsideROI()
         if(inside)
         {
             // rest loeschen
-            mPersons.erase(mPersons.begin() + i);
-            i--;
+            deletePerson(i--); // after deleting the person decrease i by one
         }
     }
 }
@@ -218,8 +214,7 @@ void PersonStorage::delPointROI()
             if(rect.contains(mPersons.at(i).at(j).x(), mPersons.at(i).at(j).y()))
             {
                 anz++;
-                mPersons.erase(mPersons.begin() + i);
-                i--;
+                deletePerson(i--); // after deleting the person decrease i by one
                 break;
             }
         }
@@ -947,7 +942,7 @@ void PersonStorage::purge(int frame)
             }
             if(count / mPersons.at(i).size() > 0.8) // Achtung, wenn roi klein, dann viele tp nur getrackt
             {
-                mPersons.erase(mPersons.begin() + i); // delete trj}
+                deletePerson(i--); // after deleting the person decrease i by one
             }
         }
     }
@@ -1096,7 +1091,7 @@ int PersonStorage::merge(int pers1, int pers2)
         }
         deleteIndex = pers2;
     }
-    mPersons.erase(mPersons.begin() + deleteIndex);
+    deletePerson(deleteIndex);
 
     return deleteIndex;
 }
-- 
GitLab


From 50abbf49cdf3f527c2dc83029429197d49b9474a Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Thu, 1 Jun 2023 13:56:06 +0200
Subject: [PATCH 26/45] Add signal for registering delete person in the
 correction table and adapt the table data accordingly

---
 include/correction.h               |  2 ++
 include/personStorage.h            |  9 +++++--
 src/correction.cpp                 | 38 ++++++++++++++++++++++++++++++
 src/personStorage.cpp              |  7 ++++++
 tests/unit_test/CMakeLists.txt     |  1 +
 tests/unit_test/tst_correction.cpp | 31 ++++++++++++++++++++++++
 6 files changed, 86 insertions(+), 2 deletions(-)
 create mode 100644 tests/unit_test/tst_correction.cpp

diff --git a/include/correction.h b/include/correction.h
index 53102061e..7c76c9e88 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -45,6 +45,7 @@ public:
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
     bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
+    std::vector<plausibility::FailedCheck> getFailedChecks();
 };
 
 namespace Ui
@@ -89,6 +90,7 @@ private slots:
     void on_btnCheck_clicked();
     void openContextMenu();
     void markResolved(QList<QModelIndex> pos);
+    void removePerson(size_t index);
 };
 
 #endif // CORRECTION_H
diff --git a/include/personStorage.h b/include/personStorage.h
index 1f042a95e..c14ba513a 100644
--- a/include/personStorage.h
+++ b/include/personStorage.h
@@ -33,8 +33,10 @@ struct PersonFrame
     int frame;
 };
 
-class PersonStorage
+class PersonStorage : public QObject
 {
+    Q_OBJECT
+
 public:
     enum class Direction
     {
@@ -119,12 +121,15 @@ public:
 
     void setNrInBg(size_t idx, int nr) { mPersons[idx].setNrInBg(nr); }
 
+signals:
+    void deletedPerson(int index);
+
 private:
     std::vector<TrackPerson> mPersons;
     Petrack                 &mMainWindow;
     Autosave                &mAutosave;
 
-    auto deletePerson(int index) { return mPersons.erase(mPersons.begin() + index); };
+    std::vector<TrackPerson>::iterator deletePerson(size_t index);
 };
 
 #endif // PERSONSTORAGE_H
diff --git a/src/correction.cpp b/src/correction.cpp
index 3b16a1950..80061609e 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -21,6 +21,7 @@
 #include "animation.h"
 #include "control.h"
 #include "pMessageBox.h"
+#include "personStorage.h"
 #include "player.h"
 #include "roiItem.h"
 #include "ui_correction.h"
@@ -111,6 +112,12 @@ bool FailedChecksTableModel::removeRows(int row, int count, const QModelIndex &p
     return true;
 }
 
+std::vector<plausibility::FailedCheck> FailedChecksTableModel::getFailedChecks()
+{
+    return mFailedChecks;
+}
+
+
 Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPeTrack(petrack), mUi(new Ui::Correction)
 {
     mUi->setupUi(this);
@@ -125,6 +132,8 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
         &Correction::selectedRowChanged);
 
     connect(mUi->tblFailedChecks, &QTableWidget::customContextMenuRequested, this, &Correction::openContextMenu);
+
+    connect(&petrack->getPersonStorage(), &PersonStorage::deletedPerson, this, &Correction::removePerson);
 }
 
 void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks)
@@ -259,6 +268,35 @@ void Correction::on_btnCheck_clicked()
     mTableModel->setFailedChecks(failedChecks);
 }
 
+void Correction::removePerson(size_t index)
+{
+    SPDLOG_WARN(fmt::format("Delete person {}", index));
+
+    auto failedChecks = mTableModel->getFailedChecks();
+
+    // Delete every row where person == index + 1
+    failedChecks.erase(
+        std::remove_if(
+            failedChecks.begin(),
+            failedChecks.end(),
+            [index](const plausibility::FailedCheck &failedCheck) { return failedCheck.pers == (index + 1); }),
+        failedChecks.end());
+
+    // Update every row where person > index + 1 by decreasing person by one
+    std::for_each(
+        failedChecks.begin(),
+        failedChecks.end(),
+        [index](plausibility::FailedCheck &failedCheck)
+        {
+            if(failedCheck.pers > (index + 1))
+            {
+                failedCheck.pers--;
+            }
+        });
+
+    mTableModel->setFailedChecks(failedChecks);
+}
+
 Correction::~Correction()
 {
     delete mUi;
diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index 2e7b070ee..a29d2b5b7 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -1095,3 +1095,10 @@ int PersonStorage::merge(int pers1, int pers2)
 
     return deleteIndex;
 }
+
+std::vector<TrackPerson>::iterator PersonStorage::deletePerson(size_t index)
+{
+    auto retIt = mPersons.erase(mPersons.begin() + index);
+    emit deletedPerson(index);
+    return retIt;
+}
diff --git a/tests/unit_test/CMakeLists.txt b/tests/unit_test/CMakeLists.txt
index 71f689b79..9811beb18 100644
--- a/tests/unit_test/CMakeLists.txt
+++ b/tests/unit_test/CMakeLists.txt
@@ -18,4 +18,5 @@ target_sources(petrack_tests PRIVATE
     tst_extrinsicBox.cpp
     tst_coordinateSystemBox.cpp
     tst_tracker.cpp
+    tst_correction.cpp
 )
diff --git a/tests/unit_test/tst_correction.cpp b/tests/unit_test/tst_correction.cpp
new file mode 100644
index 000000000..3824e4b34
--- /dev/null
+++ b/tests/unit_test/tst_correction.cpp
@@ -0,0 +1,31 @@
+/*
+ * PeTrack - Software for tracking pedestrians movement in videos
+ * Copyright (C) 2023 Forschungszentrum Jülich GmbH, IAS-7
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "correction.h"
+#include "petrack.h"
+
+#include <QAbstractItemModelTester>
+#include <catch2/catch.hpp>
+
+SCENARIO("Verify FailedChecksTableModel", "[correction]")
+{
+    Petrack pet{"Unknown"};
+
+    FailedChecksTableModel *model = new FailedChecksTableModel(&pet);
+    new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Fatal, &pet);
+}
-- 
GitLab


From 54cada41e13a3158285fe18a668b53b9800a929c Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 6 Jun 2023 13:19:35 +0200
Subject: [PATCH 27/45] Add signal for registering deletion of a person in a
 frame range in the correction table and adapt the table data accordingly

---
 include/correction.h    |  1 +
 include/personStorage.h |  4 +-
 include/plausibility.h  |  8 ++++
 src/correction.cpp      | 92 +++++++++++++++++++++++++++++++++++++++++
 src/personStorage.cpp   | 18 +++++---
 src/plausibility.cpp    | 34 ++++++++++-----
 6 files changed, 140 insertions(+), 17 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 7c76c9e88..acaa8f29e 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -91,6 +91,7 @@ private slots:
     void openContextMenu();
     void markResolved(QList<QModelIndex> pos);
     void removePerson(size_t index);
+    void removePersonInFrameRange(size_t index, int startFrame, int endFrame);
 };
 
 #endif // CORRECTION_H
diff --git a/include/personStorage.h b/include/personStorage.h
index c14ba513a..a7d2a8e93 100644
--- a/include/personStorage.h
+++ b/include/personStorage.h
@@ -122,7 +122,8 @@ public:
     void setNrInBg(size_t idx, int nr) { mPersons[idx].setNrInBg(nr); }
 
 signals:
-    void deletedPerson(int index);
+    void deletedPerson(size_t index);
+    void deletedPersonFrameRange(size_t index, int startFrame, int endFrame);
 
 private:
     std::vector<TrackPerson> mPersons;
@@ -130,6 +131,7 @@ private:
     Autosave                &mAutosave;
 
     std::vector<TrackPerson>::iterator deletePerson(size_t index);
+    void                               deletePersonFrameRange(size_t index, int startFrame, int endFrame);
 };
 
 #endif // PERSONSTORAGE_H
diff --git a/include/plausibility.h b/include/plausibility.h
index ec987ba38..adfd446f3 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -28,11 +28,19 @@ class QProgressDialog;
 
 namespace plausibility
 {
+enum class CheckType
+{
+    Velocity,
+    Length,
+    Inside,
+    Equality
+};
 struct FailedCheck
 {
     size_t      pers{};
     int         frame{};
     std::string message{};
+    CheckType   type{};
 };
 
 std::vector<FailedCheck>
diff --git a/src/correction.cpp b/src/correction.cpp
index 80061609e..ad6129bc2 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -134,6 +134,11 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
     connect(mUi->tblFailedChecks, &QTableWidget::customContextMenuRequested, this, &Correction::openContextMenu);
 
     connect(&petrack->getPersonStorage(), &PersonStorage::deletedPerson, this, &Correction::removePerson);
+    connect(
+        &petrack->getPersonStorage(),
+        &PersonStorage::deletedPersonFrameRange,
+        this,
+        &Correction::removePersonInFrameRange);
 }
 
 void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks)
@@ -294,6 +299,93 @@ void Correction::removePerson(size_t index)
             }
         });
 
+    // Delete all failed equality checks where the deleted person is mentioned
+    failedChecks.erase(
+        std::remove_if(
+            failedChecks.begin(),
+            failedChecks.end(),
+            [index](const plausibility::FailedCheck &failedCheck)
+            {
+                bool personMentioned = failedCheck.message.find(std::to_string(index + 1)) != std::string::npos;
+                bool checks          = failedCheck.type == plausibility::CheckType::Equality;
+                return personMentioned && checks;
+            }),
+        failedChecks.end());
+
+    mTableModel->setFailedChecks(failedChecks);
+}
+
+void Correction::removePersonInFrameRange(size_t index, int startFrame, int endFrame)
+{
+    SPDLOG_WARN(fmt::format("Delete person {} in frame range {}-{}", index, startFrame, endFrame));
+    auto failedChecks = mTableModel->getFailedChecks();
+
+    // Handle equality checks differently as they take too long to be re-run after each removal of a frame range
+    // Delete equality checks of person in frame range
+    failedChecks.erase(
+        std::remove_if(
+            failedChecks.begin(),
+            failedChecks.end(),
+            [index, startFrame, endFrame](const plausibility::FailedCheck &failedCheck)
+            {
+                bool samePerson   = failedCheck.pers == (index + 1);
+                bool inFrameRange = (startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame);
+                bool checks       = failedCheck.type == plausibility::CheckType::Velocity ||
+                              failedCheck.type == plausibility::CheckType::Equality;
+                return samePerson && inFrameRange && checks;
+            }),
+        failedChecks.end());
+
+    // Delete all failed equality checks where the deleted person is mentioned
+    failedChecks.erase(
+        std::remove_if(
+            failedChecks.begin(),
+            failedChecks.end(),
+            [index, startFrame, endFrame](const plausibility::FailedCheck &failedCheck)
+            {
+                bool personMentioned = failedCheck.message.find(std::to_string(index + 1)) != std::string::npos;
+                bool inFrameRange    = (startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame);
+                bool checks          = failedCheck.type == plausibility::CheckType::Equality;
+                return personMentioned && inFrameRange && checks;
+            }),
+        failedChecks.end());
+
+    // Rerun-other test
+    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPeTrack);
+    progress.setWindowTitle("Check plausibility");
+    progress.setWindowModality(Qt::WindowModal);
+    progress.setVisible(true);
+    progress.setValue(0);
+    progress.setLabelText("Check Plausibility...");
+
+    if(mUi->chbLength->isChecked())
+    {
+        auto failedLengthChecks{
+            plausibility::checkLength(mPeTrack->getPersonStorage(), &progress, mUi->spbxMinFrameLength->value())};
+        failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
+    }
+
+    if(mUi->chbInside->isChecked())
+    {
+        int lastFrame = mPeTrack->getAnimation()->getNumFrames() - 1;
+
+        auto failedInsideChecks{plausibility::checkInside(
+            mPeTrack->getPersonStorage(),
+            &progress,
+            mPeTrack->getImg().size(),
+            mPeTrack->getImageBorderSize(),
+            mPeTrack->getRecoRoiItem()->rect(),
+            lastFrame,
+            mUi->spbxInsideMargin->value())};
+        failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
+    }
+
+    if(mUi->chbVelocity->isChecked())
+    {
+        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
+        failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
+    }
+
     mTableModel->setFailedChecks(failedChecks);
 }
 
diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index a29d2b5b7..6a7fb84ef 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -41,10 +41,10 @@ void PersonStorage::splitPerson(size_t pers, int frame)
         mPersons.push_back(mPersons.at(pers));
 
         // alte trj einkuerzen und ab aktuellem frame zukunft loeschen
-        mPersons[pers].removeFramesBetween(frame, mPersons[pers].lastFrame());
+        deletePersonFrameRange(pers, frame, mPersons[pers].lastFrame());
 
         // neu angehaengte/gedoppelte trajektorie
-        mPersons.back().removeFramesBetween(mPersons[pers].firstFrame(), frame - 1);
+        deletePersonFrameRange(mPersons.size() - 1, mPersons[pers].firstFrame(), frame - 1);
     }
 }
 
@@ -87,7 +87,7 @@ bool PersonStorage::delPointOf(int pers, int direction, int frame)
     mAutosave.trackPersonModified();
     if(direction == -1)
     {
-        mPersons[pers].removeFramesBetween(mPersons[pers].firstFrame(), frame - 1);
+        deletePersonFrameRange(pers, mPersons[pers].firstFrame(), frame - 1);
     }
     else if(direction == 0)
     {
@@ -95,7 +95,7 @@ bool PersonStorage::delPointOf(int pers, int direction, int frame)
     }
     else if(direction == 1)
     {
-        mPersons[pers].removeFramesBetween(frame + 1, mPersons[pers].lastFrame());
+        deletePersonFrameRange(pers, frame + 1, mPersons[pers].lastFrame());
     }
     return true;
 }
@@ -141,13 +141,13 @@ void PersonStorage::delPointAll(Direction direction, int frame)
             switch(direction)
             {
                 case Direction::Previous:
-                    mPersons[i].removeFramesBetween(mPersons[i].firstFrame(), frame - 1);
+                    deletePersonFrameRange(i, mPersons[i].firstFrame(), frame - 1);
                     break;
                 case Direction::Whole:
                     deletePerson(i--); // after deleting the person decrease i by one
                     break;
                 case Direction::Following:
-                    mPersons[i].removeFramesBetween(frame + 1, mPersons[i].lastFrame());
+                    deletePersonFrameRange(i, frame + 1, mPersons[i].lastFrame());
                     break;
             }
         }
@@ -1102,3 +1102,9 @@ std::vector<TrackPerson>::iterator PersonStorage::deletePerson(size_t index)
     emit deletedPerson(index);
     return retIt;
 }
+
+void PersonStorage::deletePersonFrameRange(size_t index, int startFrame, int endFrame)
+{
+    mPersons[index].removeFramesBetween(startFrame, endFrame);
+    emit deletedPersonFrameRange(index, startFrame, endFrame);
+}
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index e9b4fabf5..e126b5484 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -45,9 +45,11 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
     {
         if(personStorage.at(i).size() < minLength)
         {
-            std::stringstream stream;
-            stream << "Has less than " << minLength << " trackpoints";
-            failedChecks.push_back({i + 1, personStorage.at(i).firstFrame(), stream.str()});
+            failedChecks.push_back(
+                {i + 1,
+                 personStorage.at(i).firstFrame(),
+                 fmt::format("Has less than {} trackpoints!", minLength),
+                 plausibility::CheckType::Length});
         }
     }
     return failedChecks;
@@ -93,7 +95,10 @@ std::vector<FailedCheck> checkInside(
             y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height())))
         {
             failedChecks.push_back(
-                {i + 1, personStorage.at(i).firstFrame(), "Start of trajectory is inside picture and reco ROI!"});
+                {i + 1,
+                 personStorage.at(i).firstFrame(),
+                 "Start of trajectory is inside picture and reco ROI!",
+                 plausibility::CheckType::Inside});
         }
 
         x = personStorage.at(i).last().x();
@@ -104,7 +109,10 @@ std::vector<FailedCheck> checkInside(
            y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height()))
         {
             failedChecks.push_back(
-                {i + 1, personStorage.at(i).lastFrame(), "End of trajectory is inside picture and reco ROI!"});
+                {i + 1,
+                 personStorage.at(i).lastFrame(),
+                 "End of trajectory is inside picture and reco ROI!",
+                 plausibility::CheckType::Inside});
         }
     }
 
@@ -153,10 +161,14 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
             double d12 = personStorage.at(i).at(j + 1).distanceToPoint(personStorage.at(i).at(j));
             double d23 = personStorage.at(i).at(j + 2).distanceToPoint(personStorage.at(i).at(j + 1));
 
-            if(((1.8 * (d01 + d23) / 2.) < d12) && ((d12 > 6.) || ((d01 + d23) / 2. > 3.)))
+            // TODO!!!
+            if(!((1.8 * (d01 + d23) / 2.) < d12) && ((d12 > 6.) || ((d01 + d23) / 2. > 3.)))
             {
                 failedChecks.push_back(
-                    {i + 1, j + personStorage.at(i).firstFrame(), "Fast variation of velocity to following frame!"});
+                    {i + 1,
+                     j + personStorage.at(i).firstFrame(),
+                     "Fast variation of velocity to following frame!",
+                     plausibility::CheckType::Velocity});
             }
         }
     }
@@ -200,9 +212,11 @@ std::vector<FailedCheck> checkEquality(
                     if(personStorage.at(i).trackPointAt(frame).distanceToPoint(personStorage.at(j).trackPointAt(
                            frame)) < headSizeFactor * petrack.getHeadSize(nullptr, i, frame))
                     {
-                        std::stringstream stream;
-                        stream << "Trajectory is every close to Person " << j + 1 << "!";
-                        failedChecks.push_back({i + 1, frame, stream.str()});
+                        failedChecks.push_back(
+                            {i + 1,
+                             frame,
+                             fmt::format("Trajectory is every close to Person {}!", j + 1),
+                             plausibility::CheckType::Equality});
                     }
                 }
             }
-- 
GitLab


From f0da5d1f24c5e486ea315b9aabb60a96f4d4c065 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Sun, 11 Jun 2023 10:27:27 +0200
Subject: [PATCH 28/45] Update to pet-file version 0.10.0

---
 CMakeLists.txt                                     |  2 +-
 demo/01_calibration/01_intrinsic.pet               | 12 +++++++-----
 demo/01_calibration/02_extrinsic.pet               | 12 +++++++-----
 demo/01_calibration/03_calibrated_with_video.pet   | 12 +++++++-----
 demo/02_recognition/04_recognition.pet             | 14 ++++++++------
 demo/03_tracking/05_tracking.pet                   | 12 +++++++-----
 demo/03_tracking/06_tracking_with_trajectories.pet | 12 +++++++-----
 demo/04_correcting/07_corrected.pet                | 12 +++++++-----
 tests/regression_test/data/00_empty.pet            | 12 +++++++-----
 tests/regression_test/data/01_intrinsic.pet        | 12 +++++++-----
 tests/regression_test/data/blackdotMarker.pet      | 12 +++++++-----
 tests/regression_test/data/codeMarker.pet          | 12 +++++++-----
 tests/regression_test/data/markerCasern.pet        | 12 +++++++-----
 tests/regression_test/data/markerJapan.pet         | 12 +++++++-----
 .../data/multiColorMarkerWithAruco.pet             | 12 +++++++-----
 .../multiColorMarkerWithAruco_dictMip36h12.pet     | 12 +++++++-----
 tests/regression_test/data/multicolor.pet          | 12 +++++++-----
 tests/unit_test/tst_extrCalibration.cpp            | 12 ++++++------
 18 files changed, 120 insertions(+), 88 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4321b9e80..5956703bb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@
 # Project setup
 ################################################################################
 cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
-project(petrack LANGUAGES CXX VERSION 0.9.4)
+project(petrack LANGUAGES CXX VERSION 0.10.0)
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
diff --git a/demo/01_calibration/01_intrinsic.pet b/demo/01_calibration/01_intrinsic.pet
index 8176c5d1d..6745b7702 100644
--- a/demo/01_calibration/01_intrinsic.pet
+++ b/demo/01_calibration/01_intrinsic.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="0" MAX_PH="0" MAX_PX="0" SD_DH="0" SD_PH="0" SD_PX="0" USED_HEIGHT="0"/>
diff --git a/demo/01_calibration/02_extrinsic.pet b/demo/01_calibration/02_extrinsic.pet
index c95df13b9..80267f2a3 100644
--- a/demo/01_calibration/02_extrinsic.pet
+++ b/demo/01_calibration/02_extrinsic.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="../00_files/calibration/extrinsic/00_all.jpg" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="1.5282007521032739" MAX_PH="1.9084653722971126" MAX_PX="2.9165169096333834" SD_DH="0.43009984448603678" SD_PH="0.47246997925264522" SD_PX="0.79801084449283222" USED_HEIGHT="180"/>
diff --git a/demo/01_calibration/03_calibrated_with_video.pet b/demo/01_calibration/03_calibrated_with_video.pet
index e80e0f05b..77e790576 100644
--- a/demo/01_calibration/03_calibrated_with_video.pet
+++ b/demo/01_calibration/03_calibrated_with_video.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="../00_files/video/video.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="1.5282007521032739" MAX_PH="1.9084653722971126" MAX_PX="2.9165169096333834" SD_DH="0.43009984448603678" SD_PH="0.47246997925264522" SD_PX="0.79801084449283222" USED_HEIGHT="180"/>
diff --git a/demo/02_recognition/04_recognition.pet b/demo/02_recognition/04_recognition.pet
index 656593792..f8b12569f 100644
--- a/demo/02_recognition/04_recognition.pet
+++ b/demo/02_recognition/04_recognition.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="../00_files/video/video.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="1">
         <CALIBRATION>
@@ -46,10 +46,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -59,6 +55,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="1.5282007521032739" MAX_PH="1.9084653722971126" MAX_PX="2.9165169096333834" SD_DH="0.43009984448603678" SD_PH="0.47246997925264522" SD_PX="0.79801084449283222" USED_HEIGHT="180"/>
@@ -89,7 +91,7 @@
     </MULTI_COLOR_MARKER>
     <MOCAP COLOR="#ffff37" SHOW="0" SIZE="2"/>
     <PLAYER FPS="25" FRAME="0" PLAYER_SPEED_FIXED="0" SOURCE_FRAME_IN="0" SOURCE_FRAME_OUT="420"/>
-    <VIEW ANTIALIAS="0" CAMERA="2" HIDE_CONTROLS="0" OPENGL="0" SAVE_TRANSFORMED="0" TRANSFORMATION="208 0 0 0"/>
+    <VIEW ANTIALIAS="0" CAMERA="2" HIDE_CONTROLS="0" OPENGL="0" SAVE_TRANSFORMED="0" TRANSFORMATION="194 0 0 0"/>
     <AUTO_TRACK BACK_TRACK="1" OPTIMZE_COLOR="0"/>
     <MISSING_FRAMES executed="0"/>
 </PETRACK>
diff --git a/demo/03_tracking/05_tracking.pet b/demo/03_tracking/05_tracking.pet
index 7e5e52f6f..2804f1090 100644
--- a/demo/03_tracking/05_tracking.pet
+++ b/demo/03_tracking/05_tracking.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="../00_files/video/video.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="2">
         <CALIBRATION>
@@ -46,10 +46,6 @@
             <EXPORT_USE_METER ENABLED="1"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="1" LEVELS="2" MAX_ERROR="0" SCALE="14" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="7" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="0" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -59,6 +55,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="1.5282007521032739" MAX_PH="1.9084653722971126" MAX_PX="2.9165169096333834" SD_DH="0.43009984448603678" SD_PH="0.47246997925264522" SD_PX="0.79801084449283222" USED_HEIGHT="180"/>
diff --git a/demo/03_tracking/06_tracking_with_trajectories.pet b/demo/03_tracking/06_tracking_with_trajectories.pet
index 3c8a16c32..ba83d986c 100644
--- a/demo/03_tracking/06_tracking_with_trajectories.pet
+++ b/demo/03_tracking/06_tracking_with_trajectories.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="../00_files/video/video.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="2">
         <CALIBRATION>
@@ -46,10 +46,6 @@
             <EXPORT_USE_METER ENABLED="1"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME="06_exported_trajectories.trc"/>
             <SEARCH_REGION ADAPTIVE="1" LEVELS="2" MAX_ERROR="0" SCALE="14" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="7" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="0" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -59,6 +55,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="1.5282007521032739" MAX_PH="1.9084653722971126" MAX_PX="2.9165169096333834" SD_DH="0.43009984448603678" SD_PH="0.47246997925264522" SD_PX="0.79801084449283222" USED_HEIGHT="180"/>
diff --git a/demo/04_correcting/07_corrected.pet b/demo/04_correcting/07_corrected.pet
index 4ca9240e6..3a90feee8 100644
--- a/demo/04_correcting/07_corrected.pet
+++ b/demo/04_correcting/07_corrected.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="../00_files/video/video.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="2">
         <CALIBRATION>
@@ -46,10 +46,6 @@
             <EXPORT_USE_METER ENABLED="1"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME="07_corrected_trajectories.trc"/>
             <SEARCH_REGION ADAPTIVE="1" LEVELS="2" MAX_ERROR="0" SCALE="14" SHOW="0"/>
             <PATH AFTER="1000" BEFORE="1000" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="7" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="0" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="1" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="86" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="1" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -59,6 +55,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="1.5282007521032739" MAX_PH="1.9084653722971126" MAX_PX="2.9165169096333834" SD_DH="0.43009984448603678" SD_PH="0.47246997925264522" SD_PX="0.79801084449283222" USED_HEIGHT="180"/>
diff --git a/tests/regression_test/data/00_empty.pet b/tests/regression_test/data/00_empty.pet
index a94248d0d..4f6a8d7de 100644
--- a/tests/regression_test/data/00_empty.pet
+++ b/tests/regression_test/data/00_empty.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="1.1400328837962875e-311" AVG_PH="3.9525251667299724e-322" AVG_PX="6.9525070095192605e-310" MAX_DH="4.6632130749188108e-310" MAX_PH="4.6632130749149077e-310" MAX_PX="4.6632132612882775e-310" SD_DH="4.6632137672154514e-310" SD_PH="6.9526421601088563e-310" SD_PX="6.952642160144429e-310" USED_HEIGHT="4.6632137672154514e-310"/>
diff --git a/tests/regression_test/data/01_intrinsic.pet b/tests/regression_test/data/01_intrinsic.pet
index 0e08dffc7..53be2ad71 100644
--- a/tests/regression_test/data/01_intrinsic.pet
+++ b/tests/regression_test/data/01_intrinsic.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="1.1421466874887316e-311" AVG_PH="3.9525251667299724e-322" AVG_PX="6.9525070095192605e-310" MAX_DH="4.6632130749188108e-310" MAX_PH="4.6632130749149077e-310" MAX_PX="4.6632132612882775e-310" SD_DH="4.6632137672154514e-310" SD_PH="6.9526421601088563e-310" SD_PX="6.952642160144429e-310" USED_HEIGHT="4.6632137672154514e-310"/>
diff --git a/tests/regression_test/data/blackdotMarker.pet b/tests/regression_test/data/blackdotMarker.pet
index 5d5369b9f..9f1aaa22f 100755
--- a/tests/regression_test/data/blackdotMarker.pet
+++ b/tests/regression_test/data/blackdotMarker.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="blackdotMarker.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="2">
         <CALIBRATION>
@@ -46,10 +46,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="0"/>
-            <TEST_VELOCITY ENABLED="0"/>
-            <TEST_INSIDE ENABLED="0"/>
-            <TEST_LENGTH ENABLED="0"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="2" MAX_ERROR="0" SCALE="12" SHOW="1"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="15" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="0" NUMBER_BOLD="1" NUMBER_SIZE="25" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="0" SHOW_COLOR_MARKER="0" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#0000ff"/>
@@ -59,6 +55,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="0"/>
+            <VELOCITY ENABLED="0"/>
+            <LENGTH ENABLED="0" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="0" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="8.3618533772265552e-312" AVG_PH="3.9525251667299724e-322" AVG_PX="6.9525070095192605e-310" MAX_DH="4.646775768903306e-310" MAX_PH="4.6467757711238346e-310" MAX_PX="6.9346406892679761e-310" SD_DH="4.6467747728396915e-310" SD_PH="6.9346406888723283e-310" SD_PX="4.6467757687831492e-310" USED_HEIGHT="6.9346406107594628e-310"/>
diff --git a/tests/regression_test/data/codeMarker.pet b/tests/regression_test/data/codeMarker.pet
index b9e59027a..35b59f584 100644
--- a/tests/regression_test/data/codeMarker.pet
+++ b/tests/regression_test/data/codeMarker.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="codeMarker.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="2">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="1.2302022927518785e-311" AVG_PH="3.9525251667299724e-322" AVG_PX="1.0325971998082053e-321" MAX_DH="4.6560227635167419e-310" MAX_PH="4.6560217882062561e-310" MAX_PX="6.9527326009498098e-310" SD_DH="4.6560217882058609e-310" SD_PH="6.952732600939138e-310" SD_PX="3.8829051134825777e-249" USED_HEIGHT="6.9527326009367665e-310"/>
diff --git a/tests/regression_test/data/markerCasern.pet b/tests/regression_test/data/markerCasern.pet
index 06535af34..8f77897b0 100644
--- a/tests/regression_test/data/markerCasern.pet
+++ b/tests/regression_test/data/markerCasern.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="markerCasern.avi" STATUS_HEIGHT="180"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -50,10 +50,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -63,6 +59,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="1.3264491913277669e-311" AVG_PH="3.9525251667299724e-322" AVG_PX="6.4228533959362051e-323" MAX_DH="4.6462645603376439e-310" MAX_PH="4.646262983180894e-310" MAX_PX="6.9526686235197743e-310" SD_DH="4.6462629831804987e-310" SD_PH="6.9526686235091025e-310" SD_PX="2.1013090475021298e+139" USED_HEIGHT="6.952668623506731e-310"/>
diff --git a/tests/regression_test/data/markerJapan.pet b/tests/regression_test/data/markerJapan.pet
index 3be547531..879f272e6 100644
--- a/tests/regression_test/data/markerJapan.pet
+++ b/tests/regression_test/data/markerJapan.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="markerJapan/000100000.jpg" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="1" MAX_ERROR="0" SCALE="14" SHOW="1"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="1" POINTS_COLORED="1" POINTS_SIZE="4" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="1" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="1.0224146229884167e-311" AVG_PH="3.9525251667299724e-322" AVG_PX="6.9525070095192605e-310" MAX_DH="4.6653580084069812e-310" MAX_PH="4.6653566439403536e-310" MAX_PX="6.9526629706364624e-310" SD_DH="4.6653566439399583e-310" SD_PH="6.9526629706257906e-310" SD_PX="2.033759975024312e-156" USED_HEIGHT="6.9526629706234191e-310"/>
diff --git a/tests/regression_test/data/multiColorMarkerWithAruco.pet b/tests/regression_test/data/multiColorMarkerWithAruco.pet
index aea821b8f..f44a5fab6 100644
--- a/tests/regression_test/data/multiColorMarkerWithAruco.pet
+++ b/tests/regression_test/data/multiColorMarkerWithAruco.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="multiColorMarkerWithAruco.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="1">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="1"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="1500" BEFORE="1500" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.80000000000000004" ENABLED="1"/>
+            <VELOCITY ENABLED="0"/>
+            <LENGTH ENABLED="0" MIN_LENGTH="13"/>
+            <INSIDE ENABLED="0" MARGIN="34"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="8.0655271030870288e-312" AVG_PH="3.9525251667299724e-322" AVG_PX="6.9525070095192605e-310" MAX_DH="4.6482249247897014e-310" MAX_PH="4.6482248811874201e-310" MAX_PX="6.9531746720061243e-310" SD_DH="4.6482248811870248e-310" SD_PH="6.9531746719954525e-310" SD_PX="-9.9104429895508597e+290" USED_HEIGHT="6.953174671993081e-310"/>
diff --git a/tests/regression_test/data/multiColorMarkerWithAruco_dictMip36h12.pet b/tests/regression_test/data/multiColorMarkerWithAruco_dictMip36h12.pet
index 256d96d99..4f76ad2d8 100644
--- a/tests/regression_test/data/multiColorMarkerWithAruco_dictMip36h12.pet
+++ b/tests/regression_test/data/multiColorMarkerWithAruco_dictMip36h12.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="multiColorMarkerWithAruco_dictMip36h12.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="1">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="1"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="1"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="1500" BEFORE="1500" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="5" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="0" SHOW_COLOR_MARKER="0" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="0" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="8.3470056377034328e-312" AVG_PH="3.9525251667299724e-322" AVG_PX="6.9525070095192605e-310" MAX_DH="4.6363028400314047e-310" MAX_PH="4.6363018019864395e-310" MAX_PX="6.9531972930325466e-310" SD_DH="4.6363018019860442e-310" SD_PH="6.9531972930218748e-310" SD_PX="5.8990226972632587e-278" USED_HEIGHT="6.9531972930195033e-310"/>
diff --git a/tests/regression_test/data/multicolor.pet b/tests/regression_test/data/multicolor.pet
index ee2763a0e..ff4aa6e6d 100644
--- a/tests/regression_test/data/multicolor.pet
+++ b/tests/regression_test/data/multicolor.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="multicolor.mp4" STATUS_HEIGHT="0"/>
     <CONTROL TAB="2">
         <CALIBRATION>
@@ -46,10 +46,6 @@
             <EXPORT_USE_METER ENABLED="1"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="1" LEVELS="2" MAX_ERROR="0" SCALE="14" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="7" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="0" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -59,6 +55,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="9.4071814262911059e-312" AVG_PH="0" AVG_PX="6.9526710516562795e-310" MAX_DH="4.6884896848343745e-310" MAX_PH="4.6884881402590801e-310" MAX_PX="6.9528791764073219e-310" SD_DH="4.6884881402586848e-310" SD_PH="6.9528791763966501e-310" SD_PX="1.5962438829080507e+218" USED_HEIGHT="6.9528791763942786e-310"/>
diff --git a/tests/unit_test/tst_extrCalibration.cpp b/tests/unit_test/tst_extrCalibration.cpp
index 44b6c09e0..89de02f67 100644
--- a/tests/unit_test/tst_extrCalibration.cpp
+++ b/tests/unit_test/tst_extrCalibration.cpp
@@ -41,7 +41,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
 
     QDomDocument doc;
     doc.setContent(testConfig.arg("0", "0", "0"));
-    control->getXml(doc.documentElement());
+    control->getXml(doc.documentElement(), QString("0.10.0"));
 
     SECTION("Identity Coordinate System")
     {
@@ -58,7 +58,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
     {
         // rotate 90 degrees
         doc.setContent(testConfig.arg("0", "0", QString::number(PI / 2)));
-        control->getXml(doc.documentElement());
+        control->getXml(doc.documentElement(), QString("0.10.0"));
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 0, 0)) - cv::Vec3d(0, -1, 0)) ==
             Approx(0).margin(VEC_MARGIN));
@@ -77,7 +77,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
 
         // negative rotation
         doc.setContent(testConfig.arg("0", "0", QString::number(-PI)));
-        control->getXml(doc.documentElement());
+        control->getXml(doc.documentElement(), <#initializer #>);
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 0, 0)) - cv::Vec3d(-1, 0, 0)) ==
             Approx(0).margin(VEC_MARGIN));
@@ -91,7 +91,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
     {
         // vector (1, 1, 1) with length pi/2
         doc.setContent(testConfig.arg("0.9067", "0.9067", "0.9067"));
-        control->getXml(doc.documentElement());
+        control->getXml(doc.documentElement(), <#initializer #>);
 
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 1, 1)) - cv::Vec3d(1, 1, 1)) ==
@@ -114,7 +114,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
                         </CALIBRATION>
                     </CONTROL>)"};
             doc.setContent(testConfig.arg("0.9067", "0.9067", "0.9067"));
-            control->getXml(doc.documentElement());
+            control->getXml(doc.documentElement(), <#initializer #>);
             REQUIRE(
                 cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 0, 0)) - cv::Vec3d(0.33, -0.24, 0.91)) ==
                 Approx(0).margin(VEC_MARGIN));
@@ -128,7 +128,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
     SECTION("Another Wild Rotation")
     {
         doc.setContent(testConfig.arg("0.5", "-2", "1.1"));
-        control->getXml(doc.documentElement());
+        control->getXml(doc.documentElement(), <#initializer #>);
 
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 1, 1)) - cv::Vec3d(0.2, -0.63, -1.6)) ==
-- 
GitLab


From 5bb34472da28b72bc08228d7ed8c86f659e279fa Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Sun, 11 Jun 2023 10:32:27 +0200
Subject: [PATCH 29/45] Add writing and parsing of correction tab

---
 include/control.h                       |  2 +-
 include/correction.h                    |  5 ++
 src/control.cpp                         | 37 ++++------
 src/correction.cpp                      | 89 ++++++++++++++++++++++++-
 src/petrack.cpp                         |  4 +-
 tests/unit_test/tst_extrCalibration.cpp |  8 +--
 6 files changed, 113 insertions(+), 32 deletions(-)

diff --git a/include/control.h b/include/control.h
index 529aadf7c..6e9c3e53c 100644
--- a/include/control.h
+++ b/include/control.h
@@ -213,7 +213,7 @@ public:
     double getCameraAltitude() const;
 
     void       setXml(QDomElement &elem);
-    void       getXml(const QDomElement &elem);
+    void       getXml(const QDomElement &elem, const QString &version);
     bool       isLoading() const;
     ColorPlot *getColorPlot() const;
     void       replotColorplot();
diff --git a/include/correction.h b/include/correction.h
index acaa8f29e..bbf4eb0e1 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -22,6 +22,7 @@
 #include "plausibility.h"
 
 #include <QAbstractTableModel>
+#include <QDomElement>
 #include <QFrame>
 #include <ui_correction.h>
 
@@ -80,6 +81,9 @@ public:
     bool getTestInsideChecked() const;
     void setTestInsideCheckState(Qt::CheckState testInside);
 
+    void setXml(QDomElement &elem) const;
+    bool getXml(const QDomElement &elem);
+
 private:
     Petrack                *mPeTrack;
     Ui::Correction         *mUi;
@@ -92,6 +96,7 @@ private slots:
     void markResolved(QList<QModelIndex> pos);
     void removePerson(size_t index);
     void removePersonInFrameRange(size_t index, int startFrame, int endFrame);
+    void clear();
 };
 
 #endif // CORRECTION_H
diff --git a/src/control.cpp b/src/control.cpp
index 49a82644a..6cae1722e 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -2026,24 +2026,6 @@ void Control::setXml(QDomElement &elem)
     subSubElem.setAttribute("ENABLED", mUi->exportMarkerID->isChecked());
     subElem.appendChild(subSubElem);
 
-    // TODO from other tab
-    subSubElem = (elem.ownerDocument()).createElement("TEST_EQUAL");
-    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestEqualChecked());
-    subElem.appendChild(subSubElem);
-
-    subSubElem = (elem.ownerDocument()).createElement("TEST_VELOCITY");
-    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestVelocityChecked());
-    subElem.appendChild(subSubElem);
-
-    subSubElem = (elem.ownerDocument()).createElement("TEST_INSIDE");
-    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestInsideChecked());
-    subElem.appendChild(subSubElem);
-
-    subSubElem = (elem.ownerDocument()).createElement("TEST_LENGTH");
-    subSubElem.setAttribute("ENABLED", mCorrectionWidget->getTestLengthChecked());
-    subElem.appendChild(subSubElem);
-
-
     subSubElem = (elem.ownerDocument()).createElement("TRACK_FILE");
     fn         = mMainWindow->getTrackFileName();
     if(fn != "")
@@ -2123,13 +2105,18 @@ void Control::setXml(QDomElement &elem)
     subSubElem.setAttribute("REVERSE", mUi->anaConsiderRev->isChecked());
     subSubElem.setAttribute("SHOW_VORONOI", mUi->showVoronoiCells->isChecked());
     subElem.appendChild(subSubElem);
+
+    auto correctionElem = (elem.ownerDocument()).createElement("CORRECTION");
+    mCorrectionWidget->setXml(correctionElem);
+    elem.appendChild(correctionElem);
 }
 
 // read data from xml node
-void Control::getXml(const QDomElement &elem)
+void Control::getXml(const QDomElement &elem, const QString &version)
 {
     QDomElement subElem, subSubElem, subSubSubElem;
 
+
     if(elem.hasAttribute("TAB"))
     {
         mUi->tabs->setCurrentIndex(elem.attribute("TAB").toInt());
@@ -2669,7 +2656,7 @@ void Control::getXml(const QDomElement &elem)
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
-                else if(subSubElem.tagName() == "TEST_EQUAL")
+                else if((subSubElem.tagName() == "TEST_EQUAL") && (!newerThanVersion(version, QString("0.10.0"))))
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
@@ -2677,7 +2664,7 @@ void Control::getXml(const QDomElement &elem)
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
-                else if(subSubElem.tagName() == "TEST_VELOCITY")
+                else if((subSubElem.tagName() == "TEST_VELOCITY") && (!newerThanVersion(version, QString("0.10.0"))))
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
@@ -2685,7 +2672,7 @@ void Control::getXml(const QDomElement &elem)
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
-                else if(subSubElem.tagName() == "TEST_INSIDE")
+                else if((subSubElem.tagName() == "TEST_INSIDE") && (!newerThanVersion(version, QString("0.10.0"))))
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
@@ -2693,7 +2680,7 @@ void Control::getXml(const QDomElement &elem)
                             subSubElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
                     }
                 }
-                else if(subSubElem.tagName() == "TEST_LENGTH")
+                else if((subSubElem.tagName() == "TEST_LENGTH") && (!newerThanVersion(version, QString("0.10.0"))))
                 {
                     if(subSubElem.hasAttribute("ENABLED"))
                     {
@@ -2958,6 +2945,10 @@ void Control::getXml(const QDomElement &elem)
                 }
             }
         }
+        else if(subElem.tagName() == "CORRECTION")
+        {
+            mCorrectionWidget->getXml(subElem);
+        }
         else
         {
             SPDLOG_WARN("Unknown CONTROL tag: {}", subSubElem.tagName());
diff --git a/src/correction.cpp b/src/correction.cpp
index ad6129bc2..9312ac41e 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-#include "include/correction.h"
+#include "correction.h"
 
 #include "animation.h"
 #include "control.h"
@@ -105,7 +105,7 @@ bool FailedChecksTableModel::removeRows(int row, int count, const QModelIndex &p
 
     for(int i = 0; i < count; ++i)
     {
-        mFailedChecks.erase(mFailedChecks.cbegin() + row);
+        mFailedChecks.erase(mFailedChecks.begin() + row);
     }
 
     endRemoveRows();
@@ -117,7 +117,6 @@ std::vector<plausibility::FailedCheck> FailedChecksTableModel::getFailedChecks()
     return mFailedChecks;
 }
 
-
 Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPeTrack(petrack), mUi(new Ui::Correction)
 {
     mUi->setupUi(this);
@@ -389,6 +388,90 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
     mTableModel->setFailedChecks(failedChecks);
 }
 
+void Correction::clear()
+{
+    auto success = mUi->tblFailedChecks->model()->removeRows(0, mUi->tblFailedChecks->model()->rowCount());
+    if(!success)
+    {
+        PWarning(this, "Correction", "Could not clear table.");
+    }
+}
+
+void Correction::setXml(QDomElement &elem) const
+{
+    auto equalElement = (elem.ownerDocument()).createElement("EQUALITY");
+    equalElement.setAttribute("ENABLED", mUi->chbEqual->isChecked());
+    equalElement.setAttribute("DISTANCE", mUi->spbxEqualityDistance->value());
+    elem.appendChild(equalElement);
+
+    auto velocityElement = (elem.ownerDocument()).createElement("VELOCITY");
+    velocityElement.setAttribute("ENABLED", mUi->chbVelocity->isChecked());
+    elem.appendChild(velocityElement);
+
+    auto lengthElement = (elem.ownerDocument()).createElement("LENGTH");
+    lengthElement.setAttribute("ENABLED", mUi->chbLength->isChecked());
+    lengthElement.setAttribute("MIN_LENGTH", mUi->spbxMinFrameLength->value());
+    elem.appendChild(lengthElement);
+
+    auto insideElement = (elem.ownerDocument()).createElement("INSIDE");
+    insideElement.setAttribute("ENABLED", mUi->chbInside->isChecked());
+    insideElement.setAttribute("MARGIN", mUi->spbxInsideMargin->value());
+    elem.appendChild(insideElement);
+}
+
+bool Correction::getXml(const QDomElement &correctionElem)
+{
+    for(auto subElem = correctionElem.firstChildElement(); !subElem.isNull(); subElem = subElem.nextSiblingElement())
+    {
+        SPDLOG_WARN(subElem.tagName().toStdString());
+        if(subElem.tagName() == "EQUALITY")
+        {
+            if(subElem.hasAttribute("ENABLED"))
+            {
+                mUi->chbEqual->setCheckState(subElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
+            }
+            if(subElem.hasAttribute("DISTANCE"))
+            {
+                setValue(mUi->spbxEqualityDistance, subElem.attribute("DISTANCE").toDouble());
+            }
+        }
+        else if(subElem.tagName() == "VELOCITY")
+        {
+            if(subElem.hasAttribute("ENABLED"))
+            {
+                mUi->chbVelocity->setCheckState(subElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
+            }
+        }
+        else if(subElem.tagName() == "LENGTH")
+        {
+            if(subElem.hasAttribute("ENABLED"))
+            {
+                mUi->chbLength->setCheckState(subElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
+            }
+            if(subElem.hasAttribute("MIN_LENGTH"))
+            {
+                setValue(mUi->spbxMinFrameLength, subElem.attribute("MIN_LENGTH").toDouble());
+            }
+        }
+        else if(subElem.tagName() == "INSIDE")
+        {
+            if(subElem.hasAttribute("ENABLED"))
+            {
+                mUi->chbInside->setCheckState(subElem.attribute("ENABLED").toInt() ? Qt::Checked : Qt::Unchecked);
+            }
+            if(subElem.hasAttribute("MARGIN"))
+            {
+                setValue(mUi->spbxInsideMargin, subElem.attribute("MARGIN").toDouble());
+            }
+        }
+        else
+        {
+            SPDLOG_WARN("Unknown CORRECTION tag: {}", subElem.tagName().toStdString());
+        }
+    }
+    return true;
+}
+
 Correction::~Correction()
 {
     delete mUi;
diff --git a/src/petrack.cpp b/src/petrack.cpp
index 656eab636..640006450 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -455,6 +455,8 @@ void Petrack::openXml(QDomDocument &doc, bool openSeq)
     int         zoom = 250, rotate = 0, hScroll = 0, vScroll = 0;
     enum Camera cam = cameraUnset;
     setLoading(true);
+    auto petVersion = root.attribute("VERSION");
+
     for(QDomElement elem = root.firstChildElement(); !elem.isNull(); elem = elem.nextSiblingElement())
     {
         if(elem.tagName() == "MAIN")
@@ -522,7 +524,7 @@ void Petrack::openXml(QDomDocument &doc, bool openSeq)
         }
         else if(elem.tagName() == "CONTROL")
         {
-            mControlWidget->getXml(elem);
+            mControlWidget->getXml(elem, petVersion);
             QDomElement tmpElem = (elem.firstChildElement("TRACKING")).firstChildElement("PATH");
             if(tmpElem.hasAttribute("ONLY_PEOPLE_NR"))
             {
diff --git a/tests/unit_test/tst_extrCalibration.cpp b/tests/unit_test/tst_extrCalibration.cpp
index 89de02f67..706d4acc5 100644
--- a/tests/unit_test/tst_extrCalibration.cpp
+++ b/tests/unit_test/tst_extrCalibration.cpp
@@ -77,7 +77,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
 
         // negative rotation
         doc.setContent(testConfig.arg("0", "0", QString::number(-PI)));
-        control->getXml(doc.documentElement(), <#initializer #>);
+        control->getXml(doc.documentElement(), QString("0.10.0"));
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 0, 0)) - cv::Vec3d(-1, 0, 0)) ==
             Approx(0).margin(VEC_MARGIN));
@@ -91,7 +91,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
     {
         // vector (1, 1, 1) with length pi/2
         doc.setContent(testConfig.arg("0.9067", "0.9067", "0.9067"));
-        control->getXml(doc.documentElement(), <#initializer #>);
+        control->getXml(doc.documentElement(), QString("0.10.0"));
 
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 1, 1)) - cv::Vec3d(1, 1, 1)) ==
@@ -114,7 +114,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
                         </CALIBRATION>
                     </CONTROL>)"};
             doc.setContent(testConfig.arg("0.9067", "0.9067", "0.9067"));
-            control->getXml(doc.documentElement(), <#initializer #>);
+            control->getXml(doc.documentElement(), QString("0.10.0"));
             REQUIRE(
                 cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 0, 0)) - cv::Vec3d(0.33, -0.24, 0.91)) ==
                 Approx(0).margin(VEC_MARGIN));
@@ -128,7 +128,7 @@ TEST_CASE("src/extrCalibration/camToWorldRotation", "[extrCalibration]")
     SECTION("Another Wild Rotation")
     {
         doc.setContent(testConfig.arg("0.5", "-2", "1.1"));
-        control->getXml(doc.documentElement(), <#initializer #>);
+        control->getXml(doc.documentElement(), QString("0.10.0"));
 
         REQUIRE(
             cv::norm(calib->camToWorldRotation(cv::Vec3d(1, 1, 1)) - cv::Vec3d(0.2, -0.63, -1.6)) ==
-- 
GitLab


From 667bcf2e442b4cf7f9999554b084f749d7f59ef9 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Sun, 11 Jun 2023 10:49:30 +0200
Subject: [PATCH 30/45] Resolve reviewer comments

---
 include/correction.h   |  19 ++---
 include/plausibility.h |   2 +
 src/control.cpp        |   1 -
 src/correction.cpp     |  18 +++--
 src/plausibility.cpp   |  17 +++--
 ui/control.ui          |   5 --
 ui/correction.ui       | 162 ++++++++++++++++++-----------------------
 7 files changed, 100 insertions(+), 124 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index bbf4eb0e1..c49df5f5f 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -23,10 +23,11 @@
 
 #include <QAbstractTableModel>
 #include <QDomElement>
-#include <QFrame>
-#include <ui_correction.h>
 
-Q_DECLARE_METATYPE(plausibility::FailedCheck)
+namespace Ui
+{
+class Correction;
+}
 
 class FailedChecksTableModel : public QAbstractTableModel
 {
@@ -37,7 +38,7 @@ private:
 public:
     explicit FailedChecksTableModel(QObject *parent) : QAbstractTableModel(parent) {}
 
-    void setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks);
+    void setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks);
 
     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
     int      rowCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -49,17 +50,13 @@ public:
     std::vector<plausibility::FailedCheck> getFailedChecks();
 };
 
-namespace Ui
-{
-class Correction;
-}
 
 class Correction : public QWidget
 {
     Q_OBJECT
 
 public:
-    Correction(Petrack *petrack, QWidget *parent = nullptr);
+    explicit Correction(Petrack *petrack, QWidget *parent = nullptr);
 
     Correction(Correction const &other)            = delete;
     Correction &operator=(Correction const &other) = delete;
@@ -67,7 +64,7 @@ public:
     Correction &operator=(Correction &&other)      = delete;
     ~Correction();
 
-    void setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks);
+    void setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks);
 
     bool getTestEqualChecked() const;
     void setTestEqualCheckState(Qt::CheckState testEqual);
@@ -91,7 +88,7 @@ private:
 
 private slots:
     void selectedRowChanged();
-    void on_btnCheck_clicked();
+    void checkButtonClicked();
     void openContextMenu();
     void markResolved(QList<QModelIndex> pos);
     void removePerson(size_t index);
diff --git a/include/plausibility.h b/include/plausibility.h
index adfd446f3..5a5bad3c7 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -65,4 +65,6 @@ std::vector<FailedCheck> checkEquality(
 
 } // namespace plausibility
 
+Q_DECLARE_METATYPE(plausibility::FailedCheck)
+
 #endif // PLAUSIBILITY_H
diff --git a/src/control.cpp b/src/control.cpp
index 6cae1722e..3c2157b7d 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -250,7 +250,6 @@ Control::Control(
     mUi->tabs->removeTab(3);
 
     mCorrectionWidget = new Correction(mMainWindow, this);
-    mCorrectionWidget->setObjectName(QString::fromUtf8("frame"));
     mUi->tabs->insertTab(3, mCorrectionWidget, "correction");
 }
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 9312ac41e..828996fb9 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -28,6 +28,7 @@
 
 #include <QByteArray>
 #include <QFile>
+#include <QFrame>
 #include <QVector>
 #include <string>
 
@@ -86,7 +87,7 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
     return QVariant();
 }
 
-void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedCheck> failedChecks)
+void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks)
 {
     emit layoutAboutToBeChanged();
 
@@ -124,6 +125,8 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
 
     mUi->tblFailedChecks->setModel(mTableModel);
 
+    connect(mUi->btnCheck, &QPushButton::clicked, this, &Correction::checkButtonClicked);
+
     connect(
         mUi->tblFailedChecks->selectionModel(),
         &QItemSelectionModel::selectionChanged,
@@ -140,9 +143,9 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
         &Correction::removePersonInFrameRange);
 }
 
-void Correction::setFailedChecks(const std::vector<plausibility::FailedCheck> &failedChecks)
+void Correction::setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks)
 {
-    mTableModel->setFailedChecks(failedChecks);
+    mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
 bool Correction::getTestEqualChecked() const
@@ -224,7 +227,7 @@ void Correction::markResolved(QList<QModelIndex> pos)
     }
 }
 
-void Correction::on_btnCheck_clicked()
+void Correction::checkButtonClicked()
 {
     std::vector<plausibility::FailedCheck> failedChecks;
 
@@ -269,7 +272,7 @@ void Correction::on_btnCheck_clicked()
             mPeTrack->getPersonStorage(), &progress, *mPeTrack, mUi->spbxEqualityDistance->value())};
         failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
     }
-    mTableModel->setFailedChecks(failedChecks);
+    mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
 void Correction::removePerson(size_t index)
@@ -311,12 +314,11 @@ void Correction::removePerson(size_t index)
             }),
         failedChecks.end());
 
-    mTableModel->setFailedChecks(failedChecks);
+    mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
 void Correction::removePersonInFrameRange(size_t index, int startFrame, int endFrame)
 {
-    SPDLOG_WARN(fmt::format("Delete person {} in frame range {}-{}", index, startFrame, endFrame));
     auto failedChecks = mTableModel->getFailedChecks();
 
     // Handle equality checks differently as they take too long to be re-run after each removal of a frame range
@@ -385,7 +387,7 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
 
-    mTableModel->setFailedChecks(failedChecks);
+    mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
 void Correction::clear()
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index e126b5484..e8c4086d9 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -15,12 +15,13 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-
 #include "plausibility.h"
 
-#include "animation.h"
 #include "personStorage.h"
-#include "roiItem.h"
+#include "petrack.h"
+
+#include <QApplication> // for qApp
+#include <QProgressDialog>
 
 namespace plausibility
 {
@@ -62,7 +63,7 @@ std::vector<FailedCheck> checkLength(const PersonStorage &personStorage, QProgre
  * @param progressDialog dialog for showing progress of all checks
  * @param sequenceSize size of the sequence
  * @param imageBorderSize border size
- * @param rect rectangle used for checking
+ * @param rect rectangle used for checking, currently reco ROI
  * @param lastFrame last frame of sequence
  * @param margin distance to image border, in which the trajectory may get lost
  *
@@ -161,8 +162,10 @@ std::vector<FailedCheck> checkVelocityVariation(const PersonStorage &personStora
             double d12 = personStorage.at(i).at(j + 1).distanceToPoint(personStorage.at(i).at(j));
             double d23 = personStorage.at(i).at(j + 2).distanceToPoint(personStorage.at(i).at(j + 1));
 
-            // TODO!!!
-            if(!((1.8 * (d01 + d23) / 2.) < d12) && ((d12 > 6.) || ((d01 + d23) / 2. > 3.)))
+            const bool largeVariation = (1.8 * (d01 + d23) / 2.) < d12;
+            const bool moving         = (d12 > 6.) || ((d01 + d23) / 2. > 3.);
+
+            if(largeVariation && moving)
             {
                 failedChecks.push_back(
                     {i + 1,
@@ -225,4 +228,4 @@ std::vector<FailedCheck> checkEquality(
 
     return failedChecks;
 }
-} // namespace plausibility
\ No newline at end of file
+} // namespace plausibility
diff --git a/ui/control.ui b/ui/control.ui
index 43e3e8680..a51053269 100644
--- a/ui/control.ui
+++ b/ui/control.ui
@@ -4978,11 +4978,6 @@
   <tabstop>exportComment</tabstop>
   <tabstop>exportMarkerID</tabstop>
   <tabstop>missingFramesReset</tabstop>
-  <tabstop>trackTest</tabstop>
-  <tabstop>testEqual</tabstop>
-  <tabstop>testVelocity</tabstop>
-  <tabstop>testInside</tabstop>
-  <tabstop>testLength</tabstop>
   <tabstop>trackShowSearchSize</tabstop>
   <tabstop>adaptiveLevel</tabstop>
   <tabstop>trackShow</tabstop>
diff --git a/ui/correction.ui b/ui/correction.ui
index d81d70a34..610c6ad99 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -20,16 +20,16 @@
    <string>Frame</string>
   </property>
   <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0">
-   <item row="1" column="0">
-    <widget class="QCheckBox" name="chbVelocity">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
-     <property name="text">
-      <string>velocity</string>
+   <item row="9" column="0" colspan="4">
+    <widget class="Line" name="line">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
      </property>
-     <property name="checked">
-      <bool>true</bool>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
      </property>
     </widget>
    </item>
@@ -64,41 +64,46 @@
      </attribute>
     </widget>
    </item>
-   <item row="12" column="0" colspan="4">
-    <widget class="QLabel" name="label">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="frameShape">
-      <enum>QFrame::Box</enum>
-     </property>
-     <property name="frameShadow">
-      <enum>QFrame::Raised</enum>
-     </property>
+   <item row="2" column="1">
+    <widget class="QLabel" name="label_2">
      <property name="text">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600;&quot;&gt;Warning: &lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
-     <property name="wordWrap">
-      <bool>true</bool>
+      <string>min. length [frames]:</string>
      </property>
     </widget>
    </item>
-   <item row="2" column="0">
-    <widget class="QCheckBox" name="chbLength">
+   <item row="0" column="0">
+    <widget class="QCheckBox" name="chbEqual">
      <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if two trajectories are close to each other&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="text">
-      <string>length</string>
+      <string>equality</string>
      </property>
      <property name="checked">
       <bool>true</bool>
      </property>
     </widget>
    </item>
+   <item row="2" column="2" colspan="2">
+    <widget class="PSpinBox" name="spbxMinFrameLength">
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+     <property name="maximum">
+      <number>999999</number>
+     </property>
+     <property name="value">
+      <number>10</number>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>margin [px]:</string>
+     </property>
+    </widget>
+   </item>
    <item row="10" column="2" colspan="2">
     <spacer name="spacer">
      <property name="orientation">
@@ -112,29 +117,10 @@
      </property>
     </spacer>
    </item>
-   <item row="9" column="0" colspan="4">
-    <widget class="Line" name="line">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-    </widget>
-   </item>
-   <item row="0" column="0">
-    <widget class="QCheckBox" name="chbEqual">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if two trajectories are close to each other&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
+   <item row="0" column="1">
+    <widget class="QLabel" name="label_4">
      <property name="text">
-      <string>equality</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
+      <string>distance [headsize]:</string>
      </property>
     </widget>
    </item>
@@ -145,79 +131,71 @@
      </property>
     </widget>
    </item>
-   <item row="3" column="0">
-    <widget class="QCheckBox" name="chbInside">
+   <item row="2" column="0">
+    <widget class="QCheckBox" name="chbLength">
      <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;&quot;&gt;&lt;span style=&quot; background-color:#2b2b2b;&quot;&gt;check, if the trajectory starts and ends outside of the recognition area&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="text">
-      <string>inside</string>
+      <string>length</string>
      </property>
      <property name="checked">
       <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="2" column="1">
-    <widget class="QLabel" name="label_2">
-     <property name="text">
-      <string>min. length [frames]:</string>
-     </property>
-    </widget>
-   </item>
-   <item row="2" column="2" colspan="2">
-    <widget class="PSpinBox" name="spbxMinFrameLength">
-     <property name="alignment">
-      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+   <item row="1" column="0">
+    <widget class="QCheckBox" name="chbVelocity">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
-     <property name="maximum">
-      <number>999999</number>
+     <property name="text">
+      <string>velocity</string>
      </property>
-     <property name="value">
-      <number>10</number>
+     <property name="checked">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="3" column="2" colspan="2">
-    <widget class="PSpinBox" name="spbxInsideMargin">
+   <item row="0" column="2" colspan="2">
+    <widget class="PDoubleSpinBox" name="spbxEqualityDistance">
      <property name="alignment">
       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
      <property name="maximum">
-      <number>9999999</number>
+      <double>10.000000000000000</double>
+     </property>
+     <property name="singleStep">
+      <double>0.100000000000000</double>
      </property>
      <property name="value">
-      <number>30</number>
+      <double>0.500000000000000</double>
      </property>
     </widget>
    </item>
-   <item row="3" column="1">
-    <widget class="QLabel" name="label_3">
-     <property name="text">
-      <string>margin [pixel]:</string>
+   <item row="3" column="0">
+    <widget class="QCheckBox" name="chbInside">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;&quot;&gt;&lt;span style=&quot; background-color:#2b2b2b;&quot;&gt;check, if the trajectory starts and ends outside of the recognition area&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
-    </widget>
-   </item>
-   <item row="0" column="1">
-    <widget class="QLabel" name="label_4">
      <property name="text">
-      <string>distance [headsize]:</string>
+      <string>inside</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="0" column="2" colspan="2">
-    <widget class="PDoubleSpinBox" name="spbxEqualityDistance">
+   <item row="3" column="2" colspan="2">
+    <widget class="PSpinBox" name="spbxInsideMargin">
      <property name="alignment">
       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
      <property name="maximum">
-      <double>10.000000000000000</double>
-     </property>
-     <property name="singleStep">
-      <double>0.100000000000000</double>
+      <number>9999999</number>
      </property>
      <property name="value">
-      <double>0.500000000000000</double>
+      <number>30</number>
      </property>
     </widget>
    </item>
-- 
GitLab


From 38418617dcce650a726d05443c33e42e56fb624d Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 13 Jun 2023 09:15:46 +0200
Subject: [PATCH 31/45] Update empty.pet to correct pet-version

---
 demo/00_files/00_empty.pet              | 12 +++++++-----
 tests/regression_test/tests/test_pet.py |  4 ++--
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/demo/00_files/00_empty.pet b/demo/00_files/00_empty.pet
index 411205237..17d06d394 100644
--- a/demo/00_files/00_empty.pet
+++ b/demo/00_files/00_empty.pet
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE PETRACK>
-<PETRACK VERSION="0.9.4">
+<PETRACK VERSION="0.10.0">
     <MAIN SRC="" STATUS_HEIGHT="0"/>
     <CONTROL TAB="0">
         <CALIBRATION>
@@ -42,10 +42,6 @@
             <EXPORT_USE_METER ENABLED="0"/>
             <EXPORT_COMMENT ENABLED="0"/>
             <EXPORT_MARKERID ENABLED="0"/>
-            <TEST_EQUAL ENABLED="1"/>
-            <TEST_VELOCITY ENABLED="1"/>
-            <TEST_INSIDE ENABLED="1"/>
-            <TEST_LENGTH ENABLED="1"/>
             <TRACK_FILE FILENAME=""/>
             <SEARCH_REGION ADAPTIVE="0" LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/>
             <PATH AFTER="15" BEFORE="15" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_LINE_WIDTH="1" COLOR_MARKER_SIZE="14" CURRENT_POINT_LINE_WIDTH="1" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" SHOW_POINTS_LINE_WIDTH="1" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/>
@@ -55,6 +51,12 @@
             <MARK_ACTUAL ENABLED="0"/>
             <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/>
         </ANALYSIS>
+        <CORRECTION>
+            <EQUALITY DISTANCE="0.5" ENABLED="1"/>
+            <VELOCITY ENABLED="1"/>
+            <LENGTH ENABLED="1" MIN_LENGTH="10"/>
+            <INSIDE ENABLED="1" MARGIN="30"/>
+        </CORRECTION>
     </CONTROL>
     <EXTR_CALIBRATION>
         <REPROJECTION_ERROR AVG_DH="0" AVG_PH="0" AVG_PX="0" MAX_DH="0" MAX_PH="0" MAX_PX="0" SD_DH="0" SD_PH="0" SD_PX="0" USED_HEIGHT="0"/>
diff --git a/tests/regression_test/tests/test_pet.py b/tests/regression_test/tests/test_pet.py
index af286fbbf..534c41372 100644
--- a/tests/regression_test/tests/test_pet.py
+++ b/tests/regression_test/tests/test_pet.py
@@ -40,11 +40,11 @@ def compare_xml(test: ET.ElementTree, truth: ET.ElementTree):
                 truth_value = float(truth_attrib[1])
                 assert test_value == approx(
                     truth_value, abs=0.0001
-                ), f"Failed comparion on {test_elem.tag}/{test_attrib[0]}"
+                ), f"Failed comparison on {test_elem.tag}/{test_attrib[0]}"
             except:
                 assert (
                     test_attrib[1] == truth_attrib[1]
-                ), f"Failed comparion on {test_elem.tag}/{test_attrib[0]}"
+                ), f"Failed comparison on {test_elem.tag}/{test_attrib[0]}"
 
 
 def test_defaultPet(pytestconfig):
-- 
GitLab


From 880c363a44d779b57cfd6be1568333e96171d45e Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 13 Jun 2023 10:30:44 +0200
Subject: [PATCH 32/45] Improve Inside Check

- make it more readable
- use frame in and frame out as bounds
---
 include/plausibility.h |  1 +
 src/correction.cpp     | 16 ++++++----------
 src/plausibility.cpp   | 14 ++++++++------
 3 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 5a5bad3c7..073ccb633 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -52,6 +52,7 @@ std::vector<FailedCheck> checkInside(
     const cv::Size      &sequenceSize,
     int                  imageBorderSize,
     QRectF               rect,
+    int                  firstFrame,
     int                  lastFrame,
     int                  margin);
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 828996fb9..826d606db 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -247,19 +247,17 @@ void Correction::checkButtonClicked()
 
     if(mUi->chbInside->isChecked())
     {
-        int lastFrame = mPeTrack->getAnimation()->getNumFrames() - 1;
-
         auto failedInsideChecks{plausibility::checkInside(
             mPeTrack->getPersonStorage(),
             &progress,
-            mPeTrack->getImg().size(),
+            mPeTrack->getImageFiltered().size(),
             mPeTrack->getImageBorderSize(),
             mPeTrack->getRecoRoiItem()->rect(),
-            lastFrame,
+            mPeTrack->getPlayer()->getFrameInNum(),
+            mPeTrack->getPlayer()->getFrameOutNum(),
             mUi->spbxInsideMargin->value())};
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
-
     if(mUi->chbVelocity->isChecked())
     {
         auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
@@ -368,15 +366,14 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
 
     if(mUi->chbInside->isChecked())
     {
-        int lastFrame = mPeTrack->getAnimation()->getNumFrames() - 1;
-
         auto failedInsideChecks{plausibility::checkInside(
             mPeTrack->getPersonStorage(),
             &progress,
-            mPeTrack->getImg().size(),
+            mPeTrack->getImageFiltered().size(),
             mPeTrack->getImageBorderSize(),
             mPeTrack->getRecoRoiItem()->rect(),
-            lastFrame,
+            mPeTrack->getPlayer()->getFrameInNum(),
+            mPeTrack->getPlayer()->getFrameOutNum(),
             mUi->spbxInsideMargin->value())};
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
@@ -425,7 +422,6 @@ bool Correction::getXml(const QDomElement &correctionElem)
 {
     for(auto subElem = correctionElem.firstChildElement(); !subElem.isNull(); subElem = subElem.nextSiblingElement())
     {
-        SPDLOG_WARN(subElem.tagName().toStdString());
         if(subElem.tagName() == "EQUALITY")
         {
             if(subElem.hasAttribute("ENABLED"))
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index e8c4086d9..7d474301f 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -75,6 +75,7 @@ std::vector<FailedCheck> checkInside(
     const cv::Size      &sequenceSize,
     int                  imageBorderSize,
     QRectF               rect,
+    int                  firstFrame,
     int                  lastFrame,
     int                  margin)
 {
@@ -84,6 +85,11 @@ std::vector<FailedCheck> checkInside(
     progressDialog->setLabelText("Check if trajectories are inside image...");
     qApp->processEvents();
 
+    const int    imgWidth  = sequenceSize.width - 1 - 2 * imageBorderSize - margin;
+    const int    imgHeight = sequenceSize.height - 1 - 2 * imageBorderSize - margin;
+    const QRectF imgRect(margin, margin, imgWidth, imgHeight);
+    const QRectF checkRect = imgRect.intersected(rect);
+
     for(size_t i = 0; i < personStorage.nbPersons(); ++i)
     {
         qApp->processEvents();
@@ -91,9 +97,7 @@ std::vector<FailedCheck> checkInside(
         double x = personStorage.at(i).first().x();
         double y = personStorage.at(i).first().y();
 
-        if((personStorage.at(i).firstFrame() != 0 && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-            x <= MIN(sequenceSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
-            y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height())))
+        if(personStorage.at(i).firstFrame() != firstFrame && checkRect.contains(x, y))
         {
             failedChecks.push_back(
                 {i + 1,
@@ -105,9 +109,7 @@ std::vector<FailedCheck> checkInside(
         x = personStorage.at(i).last().x();
         y = personStorage.at(i).last().y();
 
-        if(personStorage.at(i).lastFrame() != lastFrame && x >= MAX(margin, rect.x()) && y >= MAX(margin, rect.y()) &&
-           x <= MIN(sequenceSize.width - 1 - 2 * imageBorderSize - margin, rect.x() + rect.width()) &&
-           y <= MIN(sequenceSize.height - 1 - 2 * imageBorderSize - margin, rect.y() + rect.height()))
+        if(personStorage.at(i).lastFrame() != lastFrame && checkRect.contains(x, y))
         {
             failedChecks.push_back(
                 {i + 1,
-- 
GitLab


From eb8300eef48f6c70260b5602dd39b27e43ddb70d Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 14 Jun 2023 11:29:52 +0200
Subject: [PATCH 33/45] Second round of reviews

---
 include/correction.h   |  8 +++--
 include/plausibility.h |  1 +
 src/control.cpp        |  2 +-
 src/correction.cpp     | 81 ++++++++++++++++++------------------------
 src/plausibility.cpp   |  4 +--
 5 files changed, 44 insertions(+), 52 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index c49df5f5f..578652f1f 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -56,13 +56,13 @@ class Correction : public QWidget
     Q_OBJECT
 
 public:
-    explicit Correction(Petrack *petrack, QWidget *parent = nullptr);
+    explicit Correction(Petrack *petrack, const PersonStorage &personStorage, QWidget *parent = nullptr);
 
     Correction(Correction const &other)            = delete;
     Correction &operator=(Correction const &other) = delete;
     Correction(Correction &&other)                 = delete;
     Correction &operator=(Correction &&other)      = delete;
-    ~Correction();
+    ~Correction() override;
 
     void setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks);
 
@@ -82,7 +82,9 @@ public:
     bool getXml(const QDomElement &elem);
 
 private:
-    Petrack                *mPeTrack;
+    Petrack             *mPetrack;
+    const PersonStorage &mPersonStorage;
+
     Ui::Correction         *mUi;
     FailedChecksTableModel *mTableModel;
 
diff --git a/include/plausibility.h b/include/plausibility.h
index 073ccb633..e97ad5faf 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 class QProgressDialog;
+class PersonStorage;
 
 namespace plausibility
 {
diff --git a/src/control.cpp b/src/control.cpp
index 3c2157b7d..63538dd35 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -249,7 +249,7 @@ Control::Control(
     // "Hide" analysis tab until it is fixed
     mUi->tabs->removeTab(3);
 
-    mCorrectionWidget = new Correction(mMainWindow, this);
+    mCorrectionWidget = new Correction(mMainWindow, mMainWindow->getPersonStorage(), this);
     mUi->tabs->insertTab(3, mCorrectionWidget, "correction");
 }
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 826d606db..55a7560a1 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -53,7 +53,7 @@ QVariant FailedChecksTableModel::headerData(int section, Qt::Orientation orienta
 int FailedChecksTableModel::rowCount(const QModelIndex &parent) const
 {
     Q_UNUSED(parent)
-    return mFailedChecks.size();
+    return static_cast<int>(mFailedChecks.size());
 }
 
 int FailedChecksTableModel::columnCount(const QModelIndex &parent) const
@@ -118,7 +118,8 @@ std::vector<plausibility::FailedCheck> FailedChecksTableModel::getFailedChecks()
     return mFailedChecks;
 }
 
-Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPeTrack(petrack), mUi(new Ui::Correction)
+Correction::Correction(Petrack *petrack, const PersonStorage &personStorage, QWidget *parent) :
+    QWidget(parent), mPetrack(petrack), mPersonStorage(personStorage), mUi(new Ui::Correction)
 {
     mUi->setupUi(this);
     mTableModel = new FailedChecksTableModel(this); // NOLINTLINE
@@ -135,12 +136,8 @@ Correction::Correction(Petrack *petrack, QWidget *parent) : QWidget(parent), mPe
 
     connect(mUi->tblFailedChecks, &QTableWidget::customContextMenuRequested, this, &Correction::openContextMenu);
 
-    connect(&petrack->getPersonStorage(), &PersonStorage::deletedPerson, this, &Correction::removePerson);
-    connect(
-        &petrack->getPersonStorage(),
-        &PersonStorage::deletedPersonFrameRange,
-        this,
-        &Correction::removePersonInFrameRange);
+    connect(&personStorage, &PersonStorage::deletedPerson, this, &Correction::removePerson);
+    connect(&personStorage, &PersonStorage::deletedPersonFrameRange, this, &Correction::removePersonInFrameRange);
 }
 
 void Correction::setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks)
@@ -192,9 +189,9 @@ void Correction::selectedRowChanged()
 
         int pers  = mUi->tblFailedChecks->model()->data(selectedIndex[0]).toInt();
         int frame = mUi->tblFailedChecks->model()->data(selectedIndex[1]).toInt();
-        mPeTrack->getControlWidget()->setTrackShowOnly(Qt::Checked);
-        mPeTrack->getControlWidget()->setTrackShowOnlyNr(pers);
-        mPeTrack->getPlayer()->skipToFrame(frame);
+        mPetrack->getControlWidget()->setTrackShowOnly(Qt::Checked);
+        mPetrack->getControlWidget()->setTrackShowOnlyNr(pers);
+        mPetrack->getPlayer()->skipToFrame(frame);
     }
 }
 
@@ -231,7 +228,7 @@ void Correction::checkButtonClicked()
 {
     std::vector<plausibility::FailedCheck> failedChecks;
 
-    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPeTrack);
+    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPetrack);
     progress.setWindowTitle("Check plausibility");
     progress.setWindowModality(Qt::WindowModal);
     progress.setVisible(true);
@@ -240,34 +237,33 @@ void Correction::checkButtonClicked()
 
     if(mUi->chbLength->isChecked())
     {
-        auto failedLengthChecks{
-            plausibility::checkLength(mPeTrack->getPersonStorage(), &progress, mUi->spbxMinFrameLength->value())};
+        auto failedLengthChecks{plausibility::checkLength(mPersonStorage, &progress, mUi->spbxMinFrameLength->value())};
         failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
     }
 
     if(mUi->chbInside->isChecked())
     {
         auto failedInsideChecks{plausibility::checkInside(
-            mPeTrack->getPersonStorage(),
+            mPersonStorage,
             &progress,
-            mPeTrack->getImageFiltered().size(),
-            mPeTrack->getImageBorderSize(),
-            mPeTrack->getRecoRoiItem()->rect(),
-            mPeTrack->getPlayer()->getFrameInNum(),
-            mPeTrack->getPlayer()->getFrameOutNum(),
+            mPetrack->getImageFiltered().size(),
+            mPetrack->getImageBorderSize(),
+            mPetrack->getRecoRoiItem()->rect(),
+            mPetrack->getPlayer()->getFrameInNum(),
+            mPetrack->getPlayer()->getFrameOutNum(),
             mUi->spbxInsideMargin->value())};
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
     if(mUi->chbVelocity->isChecked())
     {
-        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
+        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPersonStorage, &progress)};
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
 
     if(mUi->chbEqual->isChecked())
     {
-        auto failedEqualityChecks{plausibility::checkEquality(
-            mPeTrack->getPersonStorage(), &progress, *mPeTrack, mUi->spbxEqualityDistance->value())};
+        auto failedEqualityChecks{
+            plausibility::checkEquality(mPersonStorage, &progress, *mPetrack, mUi->spbxEqualityDistance->value())};
         failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
     }
     mTableModel->setFailedChecks(std::move(failedChecks));
@@ -275,8 +271,6 @@ void Correction::checkButtonClicked()
 
 void Correction::removePerson(size_t index)
 {
-    SPDLOG_WARN(fmt::format("Delete person {}", index));
-
     auto failedChecks = mTableModel->getFailedChecks();
 
     // Delete every row where person == index + 1
@@ -288,16 +282,13 @@ void Correction::removePerson(size_t index)
         failedChecks.end());
 
     // Update every row where person > index + 1 by decreasing person by one
-    std::for_each(
-        failedChecks.begin(),
-        failedChecks.end(),
-        [index](plausibility::FailedCheck &failedCheck)
+    for(plausibility::FailedCheck &failedCheck : failedChecks)
+    {
+        if(failedCheck.pers > (index + 1))
         {
-            if(failedCheck.pers > (index + 1))
-            {
-                failedCheck.pers--;
-            }
-        });
+            failedCheck.pers--;
+        }
+    }
 
     // Delete all failed equality checks where the deleted person is mentioned
     failedChecks.erase(
@@ -329,8 +320,7 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
             {
                 bool samePerson   = failedCheck.pers == (index + 1);
                 bool inFrameRange = (startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame);
-                bool checks       = failedCheck.type == plausibility::CheckType::Velocity ||
-                              failedCheck.type == plausibility::CheckType::Equality;
+                bool checks       = failedCheck.type == plausibility::CheckType::Equality;
                 return samePerson && inFrameRange && checks;
             }),
         failedChecks.end());
@@ -350,7 +340,7 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
         failedChecks.end());
 
     // Rerun-other test
-    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPeTrack);
+    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPetrack);
     progress.setWindowTitle("Check plausibility");
     progress.setWindowModality(Qt::WindowModal);
     progress.setVisible(true);
@@ -359,28 +349,27 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
 
     if(mUi->chbLength->isChecked())
     {
-        auto failedLengthChecks{
-            plausibility::checkLength(mPeTrack->getPersonStorage(), &progress, mUi->spbxMinFrameLength->value())};
+        auto failedLengthChecks{plausibility::checkLength(mPersonStorage, &progress, mUi->spbxMinFrameLength->value())};
         failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
     }
 
     if(mUi->chbInside->isChecked())
     {
         auto failedInsideChecks{plausibility::checkInside(
-            mPeTrack->getPersonStorage(),
+            mPersonStorage,
             &progress,
-            mPeTrack->getImageFiltered().size(),
-            mPeTrack->getImageBorderSize(),
-            mPeTrack->getRecoRoiItem()->rect(),
-            mPeTrack->getPlayer()->getFrameInNum(),
-            mPeTrack->getPlayer()->getFrameOutNum(),
+            mPetrack->getImageFiltered().size(),
+            mPetrack->getImageBorderSize(),
+            mPetrack->getRecoRoiItem()->rect(),
+            mPetrack->getPlayer()->getFrameInNum(),
+            mPetrack->getPlayer()->getFrameOutNum(),
             mUi->spbxInsideMargin->value())};
         failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
     }
 
     if(mUi->chbVelocity->isChecked())
     {
-        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPeTrack->getPersonStorage(), &progress)};
+        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPersonStorage, &progress)};
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
 
diff --git a/src/plausibility.cpp b/src/plausibility.cpp
index 7d474301f..e05401511 100644
--- a/src/plausibility.cpp
+++ b/src/plausibility.cpp
@@ -215,12 +215,12 @@ std::vector<FailedCheck> checkEquality(
                 if(personStorage.at(i).trackPointExist(frame) && personStorage.at(j).trackPointExist(frame))
                 {
                     if(personStorage.at(i).trackPointAt(frame).distanceToPoint(personStorage.at(j).trackPointAt(
-                           frame)) < headSizeFactor * petrack.getHeadSize(nullptr, i, frame))
+                           frame)) < headSizeFactor * petrack.getHeadSize(nullptr, static_cast<int>(i), frame))
                     {
                         failedChecks.push_back(
                             {i + 1,
                              frame,
-                             fmt::format("Trajectory is every close to Person {}!", j + 1),
+                             fmt::format("Trajectory is very close to Person {}!", j + 1),
                              plausibility::CheckType::Equality});
                     }
                 }
-- 
GitLab


From 7febe54d8ac333ecf5e4a2ca4d90ba6b65ef6690 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 14 Jun 2023 13:04:12 +0200
Subject: [PATCH 34/45] Improved tooltips

---
 ui/correction.ui | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ui/correction.ui b/ui/correction.ui
index 610c6ad99..d3928f06a 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -176,7 +176,7 @@
    <item row="3" column="0">
     <widget class="QCheckBox" name="chbInside">
      <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;&quot;&gt;&lt;span style=&quot; background-color:#2b2b2b;&quot;&gt;check, if the trajectory starts and ends outside of the recognition area&lt;/span&gt;&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;check, if the trajectory starts and ends outside the recognition area&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="text">
       <string>inside</string>
@@ -197,6 +197,9 @@
      <property name="value">
       <number>30</number>
      </property>
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
     </widget>
    </item>
   </layout>
-- 
GitLab


From 955b266a47facf038ab250c493cdabc6f8cde743 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 14 Jun 2023 14:49:02 +0200
Subject: [PATCH 35/45] Select both person when selecting the equality check

---
 include/correction.h |  1 +
 src/correction.cpp   | 34 +++++++++++++++++++++++++++++-----
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 578652f1f..12c89e165 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -48,6 +48,7 @@ public:
 
     bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
     std::vector<plausibility::FailedCheck> getFailedChecks();
+    const plausibility::FailedCheck       &getFailedCheck(const QModelIndex &row);
 };
 
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 55a7560a1..da2a73da2 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -30,9 +30,9 @@
 #include <QFile>
 #include <QFrame>
 #include <QVector>
+#include <regex>
 #include <string>
 
-
 QVariant FailedChecksTableModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
     if(role == Qt::DisplayRole && orientation == Qt::Horizontal)
@@ -87,6 +87,7 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
     return QVariant();
 }
 
+
 void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks)
 {
     emit layoutAboutToBeChanged();
@@ -113,6 +114,11 @@ bool FailedChecksTableModel::removeRows(int row, int count, const QModelIndex &p
     return true;
 }
 
+const plausibility::FailedCheck &FailedChecksTableModel::getFailedCheck(const QModelIndex &index)
+{
+    return mFailedChecks.at(index.row());
+}
+
 std::vector<plausibility::FailedCheck> FailedChecksTableModel::getFailedChecks()
 {
     return mFailedChecks;
@@ -186,11 +192,29 @@ void Correction::selectedRowChanged()
     if(mUi->tblFailedChecks->selectionModel()->hasSelection())
     {
         auto selectedIndex = mUi->tblFailedChecks->selectionModel()->selectedIndexes();
+        auto selectedCheck = mTableModel->getFailedCheck(selectedIndex[0]);
+
+        int pers  = selectedCheck.pers;
+        int frame = selectedCheck.frame;
+
+        if(selectedCheck.type == plausibility::CheckType::Equality)
+        {
+            if(std::smatch match; std::regex_search(selectedCheck.message, match, std::regex("\\d+")))
+            {
+                int secondPerson = std::stoi(match[0].str());
+                mPetrack->getControlWidget()->trackShowOnlyNrList()->setText(
+                    QString::fromStdString(fmt::format("{},{}", pers, secondPerson)));
+            }
+            mPetrack->getControlWidget()->setTrackShowOnly(Qt::Unchecked);
+            mPetrack->getControlWidget()->setTrackShowOnlyListChecked(Qt::Checked);
+        }
+        else
+        {
+            mPetrack->getControlWidget()->setTrackShowOnlyNr(pers);
+            mPetrack->getControlWidget()->setTrackShowOnlyListChecked(Qt::Unchecked);
 
-        int pers  = mUi->tblFailedChecks->model()->data(selectedIndex[0]).toInt();
-        int frame = mUi->tblFailedChecks->model()->data(selectedIndex[1]).toInt();
-        mPetrack->getControlWidget()->setTrackShowOnly(Qt::Checked);
-        mPetrack->getControlWidget()->setTrackShowOnlyNr(pers);
+            mPetrack->getControlWidget()->setTrackShowOnly(Qt::Unchecked);
+        }
         mPetrack->getPlayer()->skipToFrame(frame);
     }
 }
-- 
GitLab


From 0a780917b0f9f4a04a32f3116e14736069a01ab7 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 20 Jun 2023 09:40:14 +0200
Subject: [PATCH 36/45] Fix minor review issues

---
 src/correction.cpp | 10 +++++-----
 ui/correction.ui   |  9 ++++++---
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/correction.cpp b/src/correction.cpp
index da2a73da2..3315cc624 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -194,8 +194,8 @@ void Correction::selectedRowChanged()
         auto selectedIndex = mUi->tblFailedChecks->selectionModel()->selectedIndexes();
         auto selectedCheck = mTableModel->getFailedCheck(selectedIndex[0]);
 
-        int pers  = selectedCheck.pers;
-        int frame = selectedCheck.frame;
+        size_t pers  = selectedCheck.pers;
+        int    frame = selectedCheck.frame;
 
         if(selectedCheck.type == plausibility::CheckType::Equality)
         {
@@ -206,14 +206,14 @@ void Correction::selectedRowChanged()
                     QString::fromStdString(fmt::format("{},{}", pers, secondPerson)));
             }
             mPetrack->getControlWidget()->setTrackShowOnly(Qt::Unchecked);
-            mPetrack->getControlWidget()->setTrackShowOnlyListChecked(Qt::Checked);
+            mPetrack->getControlWidget()->setTrackShowOnlyListChecked(true);
         }
         else
         {
             mPetrack->getControlWidget()->setTrackShowOnlyNr(pers);
-            mPetrack->getControlWidget()->setTrackShowOnlyListChecked(Qt::Unchecked);
+            mPetrack->getControlWidget()->setTrackShowOnlyListChecked(false);
 
-            mPetrack->getControlWidget()->setTrackShowOnly(Qt::Unchecked);
+            mPetrack->getControlWidget()->setTrackShowOnly(Qt::Checked);
         }
         mPetrack->getPlayer()->skipToFrame(frame);
     }
diff --git a/ui/correction.ui b/ui/correction.ui
index d3928f06a..0fc424222 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -99,6 +99,9 @@
    </item>
    <item row="3" column="1">
     <widget class="QLabel" name="label_3">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
      <property name="text">
       <string>margin [px]:</string>
      </property>
@@ -188,6 +191,9 @@
    </item>
    <item row="3" column="2" colspan="2">
     <widget class="PSpinBox" name="spbxInsideMargin">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
      <property name="alignment">
       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
@@ -197,9 +203,6 @@
      <property name="value">
       <number>30</number>
      </property>
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
     </widget>
    </item>
   </layout>
-- 
GitLab


From 10ec9dfa7842ac3f15706d771ebd9ac20ef947b8 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 20 Jun 2023 09:50:56 +0200
Subject: [PATCH 37/45] Clear the correction table, when a new project is
 loaded

---
 include/control.h    | 2 +-
 include/correction.h | 3 ++-
 src/control.cpp      | 5 +++++
 src/petrack.cpp      | 1 +
 4 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/control.h b/include/control.h
index 6e9c3e53c..c9802ba57 100644
--- a/include/control.h
+++ b/include/control.h
@@ -257,7 +257,6 @@ public:
     IntrinsicCameraParams getIntrinsicCameraParams() const;
     void                  runAutoCalib();
 
-
 #ifdef QWT
     AnalysePlot *getAnalysePlot() const;
 #endif
@@ -273,6 +272,7 @@ public:
         return mMainWindow;
     }
 
+    void resetCorrection();
 
 private slots:
     void on_anaCalculate_clicked();
diff --git a/include/correction.h b/include/correction.h
index 12c89e165..8afb22f3f 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -82,6 +82,8 @@ public:
     void setXml(QDomElement &elem) const;
     bool getXml(const QDomElement &elem);
 
+    void clear();
+
 private:
     Petrack             *mPetrack;
     const PersonStorage &mPersonStorage;
@@ -96,7 +98,6 @@ private slots:
     void markResolved(QList<QModelIndex> pos);
     void removePerson(size_t index);
     void removePersonInFrameRange(size_t index, int startFrame, int endFrame);
-    void clear();
 };
 
 #endif // CORRECTION_H
diff --git a/src/control.cpp b/src/control.cpp
index 63538dd35..b061a03ed 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -3499,4 +3499,9 @@ void Control::toggleTrackROIButtons()
     mUi->trackRoiToFullImageSize->setEnabled(enabled);
 }
 
+void Control::resetCorrection()
+{
+    mCorrectionWidget->clear();
+}
+
 #include "moc_control.cpp"
diff --git a/src/petrack.cpp b/src/petrack.cpp
index 640006450..3675a6b6d 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -1660,6 +1660,7 @@ void Petrack::resetSettings()
 {
     mAnimation->reset();
     openXml(mDefaultSettings, false);
+    mControlWidget->resetCorrection();
 }
 
 void Petrack::about()
-- 
GitLab


From c2f9c2f942427351f03fad468ac664640be01c9d Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 20 Jun 2023 14:42:44 +0200
Subject: [PATCH 38/45] Introduce a status for the different tests, if resolved
 they are still in the list

---
 include/correction.h    |  3 ++
 include/personStorage.h |  1 +
 include/plausibility.h  |  9 ++++++
 src/correction.cpp      | 65 ++++++++++++++++++++++++++++++++++++++---
 src/personStorage.cpp   |  8 +++++
 5 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 8afb22f3f..8cb559cf1 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -49,6 +49,8 @@ public:
     bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
     std::vector<plausibility::FailedCheck> getFailedChecks();
     const plausibility::FailedCheck       &getFailedCheck(const QModelIndex &row);
+
+    void updateState(const QModelIndex &row, plausibility::CheckStatus state);
 };
 
 
@@ -96,6 +98,7 @@ private slots:
     void checkButtonClicked();
     void openContextMenu();
     void markResolved(QList<QModelIndex> pos);
+    void changePersonState(size_t index);
     void removePerson(size_t index);
     void removePersonInFrameRange(size_t index, int startFrame, int endFrame);
 };
diff --git a/include/personStorage.h b/include/personStorage.h
index a7d2a8e93..ba2936954 100644
--- a/include/personStorage.h
+++ b/include/personStorage.h
@@ -124,6 +124,7 @@ public:
 signals:
     void deletedPerson(size_t index);
     void deletedPersonFrameRange(size_t index, int startFrame, int endFrame);
+    void changedPerson(size_t index);
 
 private:
     std::vector<TrackPerson> mPersons;
diff --git a/include/plausibility.h b/include/plausibility.h
index e97ad5faf..4efe0b23d 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -29,6 +29,13 @@ class PersonStorage;
 
 namespace plausibility
 {
+enum class CheckStatus
+{
+    New,
+    Resolved,
+    Changed
+};
+
 enum class CheckType
 {
     Velocity,
@@ -36,12 +43,14 @@ enum class CheckType
     Inside,
     Equality
 };
+
 struct FailedCheck
 {
     size_t      pers{};
     int         frame{};
     std::string message{};
     CheckType   type{};
+    CheckStatus status = CheckStatus::New; //< all checks are new when created
 };
 
 std::vector<FailedCheck>
diff --git a/src/correction.cpp b/src/correction.cpp
index 3315cc624..ba17fc389 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -44,6 +44,8 @@ QVariant FailedChecksTableModel::headerData(int section, Qt::Orientation orienta
             case 1:
                 return QString("Frame");
             case 2:
+                return QString("Status");
+            case 3:
                 return QString("Failed check");
         }
     }
@@ -59,7 +61,7 @@ int FailedChecksTableModel::rowCount(const QModelIndex &parent) const
 int FailedChecksTableModel::columnCount(const QModelIndex &parent) const
 {
     Q_UNUSED(parent)
-    return 3;
+    return 4;
 }
 
 QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
@@ -69,6 +71,29 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
         return QVariant();
     }
 
+
+    if(role == Qt::BackgroundRole)
+    {
+        QColor backgroundColor;
+        switch(mFailedChecks[index.row()].status)
+        {
+            case plausibility::CheckStatus::New:
+                backgroundColor = QColor(Qt::red);
+                break;
+            case plausibility::CheckStatus::Changed:
+                backgroundColor = QColor(Qt::GlobalColor::yellow);
+                break;
+            case plausibility::CheckStatus::Resolved:
+                backgroundColor = QColor(Qt::GlobalColor::green);
+                break;
+        }
+
+        if(index.column() == 2)
+        {
+            return backgroundColor;
+        }
+    }
+
     if(role != Qt::DisplayRole)
     {
         return QVariant();
@@ -81,6 +106,8 @@ QVariant FailedChecksTableModel::data(const QModelIndex &index, int role) const
         case 1:
             return QVariant::fromValue(mFailedChecks[index.row()].frame);
         case 2:
+            return QVariant();
+        case 3:
             return QString::fromStdString(mFailedChecks[index.row()].message);
     }
 
@@ -124,6 +151,16 @@ std::vector<plausibility::FailedCheck> FailedChecksTableModel::getFailedChecks()
     return mFailedChecks;
 }
 
+void FailedChecksTableModel::updateState(const QModelIndex &row, plausibility::CheckStatus state)
+{
+    emit layoutAboutToBeChanged();
+
+    mFailedChecks.at(row.row()).status = state;
+
+    emit dataChanged(row, row);
+    emit layoutChanged();
+}
+
 Correction::Correction(Petrack *petrack, const PersonStorage &personStorage, QWidget *parent) :
     QWidget(parent), mPetrack(petrack), mPersonStorage(personStorage), mUi(new Ui::Correction)
 {
@@ -132,6 +169,11 @@ Correction::Correction(Petrack *petrack, const PersonStorage &personStorage, QWi
 
     mUi->tblFailedChecks->setModel(mTableModel);
 
+    mUi->tblFailedChecks->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
+    mUi->tblFailedChecks->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);
+    mUi->tblFailedChecks->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents);
+    mUi->tblFailedChecks->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeMode::Stretch);
+
     connect(mUi->btnCheck, &QPushButton::clicked, this, &Correction::checkButtonClicked);
 
     connect(
@@ -144,6 +186,7 @@ Correction::Correction(Petrack *petrack, const PersonStorage &personStorage, QWi
 
     connect(&personStorage, &PersonStorage::deletedPerson, this, &Correction::removePerson);
     connect(&personStorage, &PersonStorage::deletedPersonFrameRange, this, &Correction::removePersonInFrameRange);
+    connect(&personStorage, &PersonStorage::changedPerson, this, &Correction::changePersonState);
 }
 
 void Correction::setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks)
@@ -241,11 +284,25 @@ void Correction::openContextMenu()
 
 void Correction::markResolved(QList<QModelIndex> pos)
 {
-    auto success = mUi->tblFailedChecks->model()->removeRows(pos[0].row(), 1);
-    if(!success)
+    mTableModel->updateState(pos[0], plausibility::CheckStatus::Resolved);
+}
+
+void Correction::changePersonState(size_t index)
+{
+    auto failedChecks = mTableModel->getFailedChecks();
+
+    for(auto &failedCheck : failedChecks)
     {
-        PWarning(this, "Correction", "Could not mark check as resolved.");
+        bool person          = failedCheck.pers == (index + 1);
+        bool personMentioned = failedCheck.message.find(std::to_string(index + 1)) != std::string::npos &&
+                               failedCheck.type == plausibility::CheckType::Equality;
+
+        if(person || personMentioned)
+        {
+            failedCheck.status = plausibility::CheckStatus::Changed;
+        }
     }
+    mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
 void Correction::checkButtonClicked()
diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index 6a7fb84ef..1fc082d50 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -46,6 +46,8 @@ void PersonStorage::splitPerson(size_t pers, int frame)
         // neu angehaengte/gedoppelte trajektorie
         deletePersonFrameRange(mPersons.size() - 1, mPersons[pers].firstFrame(), frame - 1);
     }
+
+    emit changedPerson(pers);
 }
 
 /**
@@ -381,6 +383,7 @@ void PersonStorage::moveTrackPoint(int personID, int frame, const Vec2F &newPosi
     if(person.trackPointExist(frame))
     {
         person.replaceTrackPoint(frame, newPoint);
+        emit changedPerson(personID);
     }
     else
     {
@@ -1064,6 +1067,7 @@ int PersonStorage::merge(int pers1, int pers2)
     auto      &other       = mPersons.at(pers2);
     const bool extrapolate = mMainWindow.getControlWidget()->isTrackExtrapolationChecked();
     int        deleteIndex;
+    int        keepIndex;
     if(other.firstFrame() < person.firstFrame() && other.lastFrame() > person.lastFrame())
     {
         for(int k = 0; k < person.size(); ++k)
@@ -1072,6 +1076,7 @@ int PersonStorage::merge(int pers1, int pers2)
             other.insertAtFrame(person.firstFrame() + k, person.at(k), pers2, extrapolate);
         }
         deleteIndex = pers1;
+        keepIndex   = pers2;
     }
     else if(other.firstFrame() < person.firstFrame())
     {
@@ -1081,6 +1086,7 @@ int PersonStorage::merge(int pers1, int pers2)
             person.insertAtFrame(other.firstFrame() + k, other.at(k), pers1, extrapolate);
         }
         deleteIndex = pers2;
+        keepIndex   = pers1;
     }
     else
     {
@@ -1090,8 +1096,10 @@ int PersonStorage::merge(int pers1, int pers2)
             person.insertAtFrame(other.firstFrame() + k, other.at(k), pers1, extrapolate);
         }
         deleteIndex = pers2;
+        keepIndex   = pers1;
     }
     deletePerson(deleteIndex);
+    emit changedPerson(keepIndex);
 
     return deleteIndex;
 }
-- 
GitLab


From abf105f06a932e72e869a29b8e37141a6cdfe61e Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Tue, 20 Jun 2023 15:21:30 +0200
Subject: [PATCH 39/45] When tests are re-run, the status of the existing
 states will be kept

---
 include/correction.h   |   2 -
 include/plausibility.h |   5 +
 src/correction.cpp     |  17 ++-
 ui/correction.ui       | 285 ++++++++++++++++++++++++++++-------------
 4 files changed, 213 insertions(+), 96 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 8cb559cf1..8cd530632 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -67,8 +67,6 @@ public:
     Correction &operator=(Correction &&other)      = delete;
     ~Correction() override;
 
-    void setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks);
-
     bool getTestEqualChecked() const;
     void setTestEqualCheckState(Qt::CheckState testEqual);
 
diff --git a/include/plausibility.h b/include/plausibility.h
index 4efe0b23d..9e304b81c 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -51,6 +51,11 @@ struct FailedCheck
     std::string message{};
     CheckType   type{};
     CheckStatus status = CheckStatus::New; //< all checks are new when created
+
+    bool operator==(const FailedCheck &other) const
+    {
+        return (this->pers == other.pers && this->frame == other.frame && this->type == other.type);
+    }
 };
 
 std::vector<FailedCheck>
diff --git a/src/correction.cpp b/src/correction.cpp
index ba17fc389..3ad7ffdb0 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -189,11 +189,6 @@ Correction::Correction(Petrack *petrack, const PersonStorage &personStorage, QWi
     connect(&personStorage, &PersonStorage::changedPerson, this, &Correction::changePersonState);
 }
 
-void Correction::setFailedChecks(std::vector<plausibility::FailedCheck> &&failedChecks)
-{
-    mTableModel->setFailedChecks(std::move(failedChecks));
-}
-
 bool Correction::getTestEqualChecked() const
 {
     return mUi->chbEqual->isChecked();
@@ -347,6 +342,18 @@ void Correction::checkButtonClicked()
             plausibility::checkEquality(mPersonStorage, &progress, *mPetrack, mUi->spbxEqualityDistance->value())};
         failedChecks.insert(failedChecks.end(), failedEqualityChecks.begin(), failedEqualityChecks.end());
     }
+
+    // Restore the status if the same check for a person in a frame was already in the table
+    const auto &previousChecks = mTableModel->getFailedChecks();
+    for(auto &failedCheck : failedChecks)
+    {
+        auto previousCheck = std::find(previousChecks.cbegin(), previousChecks.end(), failedCheck);
+        if(previousCheck != previousChecks.cend())
+        {
+            failedCheck.status = previousCheck->status;
+        }
+    }
+
     mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
diff --git a/ui/correction.ui b/ui/correction.ui
index 0fc424222..4ac126fa8 100644
--- a/ui/correction.ui
+++ b/ui/correction.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>400</width>
-    <height>579</height>
+    <height>727</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -20,54 +20,45 @@
    <string>Frame</string>
   </property>
   <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0">
-   <item row="9" column="0" colspan="4">
-    <widget class="Line" name="line">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
+   <item row="2" column="0">
+    <widget class="QCheckBox" name="chbLength">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
+     <property name="text">
+      <string>length</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
      </property>
     </widget>
    </item>
-   <item row="11" column="0" colspan="4">
-    <widget class="QTableView" name="tblFailedChecks">
-     <property name="contextMenuPolicy">
-      <enum>Qt::CustomContextMenu</enum>
-     </property>
-     <property name="verticalScrollBarPolicy">
-      <enum>Qt::ScrollBarAlwaysOn</enum>
-     </property>
-     <property name="horizontalScrollBarPolicy">
-      <enum>Qt::ScrollBarAsNeeded</enum>
+   <item row="2" column="2" colspan="2">
+    <widget class="PSpinBox" name="spbxMinFrameLength">
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
-     <property name="selectionMode">
-      <enum>QAbstractItemView::SingleSelection</enum>
+     <property name="maximum">
+      <number>999999</number>
      </property>
-     <property name="selectionBehavior">
-      <enum>QAbstractItemView::SelectRows</enum>
+     <property name="value">
+      <number>10</number>
      </property>
-     <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
-      <bool>false</bool>
-     </attribute>
-     <attribute name="horizontalHeaderStretchLastSection">
-      <bool>true</bool>
-     </attribute>
-     <attribute name="verticalHeaderVisible">
-      <bool>false</bool>
-     </attribute>
-     <attribute name="verticalHeaderHighlightSections">
-      <bool>false</bool>
-     </attribute>
     </widget>
    </item>
-   <item row="2" column="1">
-    <widget class="QLabel" name="label_2">
-     <property name="text">
-      <string>min. length [frames]:</string>
+   <item row="3" column="2" colspan="2">
+    <widget class="PSpinBox" name="spbxInsideMargin">
+     <property name="toolTip">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+     </property>
+     <property name="maximum">
+      <number>9999999</number>
+     </property>
+     <property name="value">
+      <number>30</number>
      </property>
     </widget>
    </item>
@@ -84,26 +75,36 @@
      </property>
     </widget>
    </item>
-   <item row="2" column="2" colspan="2">
-    <widget class="PSpinBox" name="spbxMinFrameLength">
-     <property name="alignment">
-      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-     </property>
-     <property name="maximum">
-      <number>999999</number>
-     </property>
-     <property name="value">
-      <number>10</number>
+   <item row="0" column="1">
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>distance [headsize]:</string>
      </property>
     </widget>
    </item>
-   <item row="3" column="1">
-    <widget class="QLabel" name="label_3">
+   <item row="1" column="0">
+    <widget class="QCheckBox" name="chbVelocity">
      <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="text">
-      <string>margin [px]:</string>
+      <string>velocity</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="9" column="0" colspan="4">
+    <widget class="Line" name="line">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
      </property>
     </widget>
    </item>
@@ -120,13 +121,6 @@
      </property>
     </spacer>
    </item>
-   <item row="0" column="1">
-    <widget class="QLabel" name="label_4">
-     <property name="text">
-      <string>distance [headsize]:</string>
-     </property>
-    </widget>
-   </item>
    <item row="10" column="0" colspan="2">
     <widget class="QPushButton" name="btnCheck">
      <property name="text">
@@ -134,29 +128,20 @@
      </property>
     </widget>
    </item>
-   <item row="2" column="0">
-    <widget class="QCheckBox" name="chbLength">
+   <item row="3" column="1">
+    <widget class="QLabel" name="label_3">
      <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;test, if the trajectory is very short (less than 10 points)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="text">
-      <string>length</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
+      <string>margin [px]:</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="0">
-    <widget class="QCheckBox" name="chbVelocity">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;check, if trajectory has large variations of the velocity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
+   <item row="2" column="1">
+    <widget class="QLabel" name="label_2">
      <property name="text">
-      <string>velocity</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
+      <string>min. length [frames]:</string>
      </property>
     </widget>
    </item>
@@ -176,6 +161,43 @@
      </property>
     </widget>
    </item>
+   <item row="11" column="0" colspan="4">
+    <widget class="QTableView" name="tblFailedChecks">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="contextMenuPolicy">
+      <enum>Qt::CustomContextMenu</enum>
+     </property>
+     <property name="verticalScrollBarPolicy">
+      <enum>Qt::ScrollBarAlwaysOn</enum>
+     </property>
+     <property name="horizontalScrollBarPolicy">
+      <enum>Qt::ScrollBarAsNeeded</enum>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::SingleSelection</enum>
+     </property>
+     <property name="selectionBehavior">
+      <enum>QAbstractItemView::SelectRows</enum>
+     </property>
+     <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="horizontalHeaderStretchLastSection">
+      <bool>true</bool>
+     </attribute>
+     <attribute name="verticalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="verticalHeaderHighlightSections">
+      <bool>false</bool>
+     </attribute>
+    </widget>
+   </item>
    <item row="3" column="0">
     <widget class="QCheckBox" name="chbInside">
      <property name="toolTip">
@@ -189,20 +211,105 @@
      </property>
     </widget>
    </item>
-   <item row="3" column="2" colspan="2">
-    <widget class="PSpinBox" name="spbxInsideMargin">
-     <property name="toolTip">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;&gt;minimum distance to image border to count as inside&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-     </property>
-     <property name="alignment">
-      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-     </property>
-     <property name="maximum">
-      <number>9999999</number>
+   <item row="12" column="0" colspan="4">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
      </property>
-     <property name="value">
-      <number>30</number>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>170</height>
+      </size>
      </property>
+     <property name="title">
+      <string>Legend</string>
+     </property>
+     <widget class="QWidget" name="gridLayoutWidget">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>30</y>
+        <width>371</width>
+        <height>131</height>
+       </rect>
+      </property>
+      <layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0" columnstretch="1,10" columnminimumwidth="0,0">
+       <property name="horizontalSpacing">
+        <number>6</number>
+       </property>
+       <item row="1" column="1">
+        <widget class="QLabel" name="label_8">
+         <property name="text">
+          <string>resolved check where the person was changed afterwards</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="label_5">
+         <property name="styleSheet">
+          <string notr="true">QLabel{ background-color : yellow;}</string>
+         </property>
+         <property name="text">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="0">
+        <widget class="QLabel" name="label">
+         <property name="autoFillBackground">
+          <bool>false</bool>
+         </property>
+         <property name="styleSheet">
+          <string notr="true">QLabel{ background-color : red;}</string>
+         </property>
+         <property name="text">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="label_6">
+         <property name="styleSheet">
+          <string notr="true">QLabel{ background-color : green;}</string>
+         </property>
+         <property name="text">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QLabel" name="label_7">
+         <property name="text">
+          <string>newly added failed check</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QLabel" name="label_9">
+         <property name="text">
+          <string>resolved check (mark by right click)</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0" colspan="2">
+        <widget class="QLabel" name="label_10">
+         <property name="text">
+          <string>Be aware, that some changes in the trajectory might not be propagated towards this table.</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
   </layout>
-- 
GitLab


From 5f10f12b93bada8783831362d4eb4bed22533149 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 21 Jun 2023 16:36:15 +0200
Subject: [PATCH 40/45] Change minor review comments

---
 include/plausibility.h | 10 +++++-----
 src/correction.cpp     |  4 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index 9e304b81c..d0676fb79 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -51,13 +51,13 @@ struct FailedCheck
     std::string message{};
     CheckType   type{};
     CheckStatus status = CheckStatus::New; //< all checks are new when created
-
-    bool operator==(const FailedCheck &other) const
-    {
-        return (this->pers == other.pers && this->frame == other.frame && this->type == other.type);
-    }
 };
 
+inline bool operator==(const FailedCheck &first, const FailedCheck &second)
+{
+    return (first.pers == second.pers && first.frame == second.frame && first.type == second.type);
+}
+
 std::vector<FailedCheck>
 checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog, int minLength);
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 3ad7ffdb0..0e1c6fecd 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -248,7 +248,7 @@ void Correction::selectedRowChanged()
         }
         else
         {
-            mPetrack->getControlWidget()->setTrackShowOnlyNr(pers);
+            mPetrack->getControlWidget()->setTrackShowOnlyNr(static_cast<int>(pers));
             mPetrack->getControlWidget()->setTrackShowOnlyListChecked(false);
 
             mPetrack->getControlWidget()->setTrackShowOnly(Qt::Checked);
@@ -347,7 +347,7 @@ void Correction::checkButtonClicked()
     const auto &previousChecks = mTableModel->getFailedChecks();
     for(auto &failedCheck : failedChecks)
     {
-        auto previousCheck = std::find(previousChecks.cbegin(), previousChecks.end(), failedCheck);
+        auto previousCheck = std::find(previousChecks.cbegin(), previousChecks.cend(), failedCheck);
         if(previousCheck != previousChecks.cend())
         {
             failedCheck.status = previousCheck->status;
-- 
GitLab


From c644adb832441431db712c19b10775ff748f32d5 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 21 Jun 2023 18:05:35 +0200
Subject: [PATCH 41/45] Improve handling when deleting a person

---
 src/correction.cpp    | 64 +++++++++++++++++++++----------------------
 src/personStorage.cpp |  4 +++
 2 files changed, 35 insertions(+), 33 deletions(-)

diff --git a/src/correction.cpp b/src/correction.cpp
index 0e1c6fecd..42328e3bf 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -396,45 +396,17 @@ void Correction::removePerson(size_t index)
 
 void Correction::removePersonInFrameRange(size_t index, int startFrame, int endFrame)
 {
-    auto failedChecks = mTableModel->getFailedChecks();
-
-    // Handle equality checks differently as they take too long to be re-run after each removal of a frame range
-    // Delete equality checks of person in frame range
-    failedChecks.erase(
-        std::remove_if(
-            failedChecks.begin(),
-            failedChecks.end(),
-            [index, startFrame, endFrame](const plausibility::FailedCheck &failedCheck)
-            {
-                bool samePerson   = failedCheck.pers == (index + 1);
-                bool inFrameRange = (startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame);
-                bool checks       = failedCheck.type == plausibility::CheckType::Equality;
-                return samePerson && inFrameRange && checks;
-            }),
-        failedChecks.end());
-
-    // Delete all failed equality checks where the deleted person is mentioned
-    failedChecks.erase(
-        std::remove_if(
-            failedChecks.begin(),
-            failedChecks.end(),
-            [index, startFrame, endFrame](const plausibility::FailedCheck &failedCheck)
-            {
-                bool personMentioned = failedCheck.message.find(std::to_string(index + 1)) != std::string::npos;
-                bool inFrameRange    = (startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame);
-                bool checks          = failedCheck.type == plausibility::CheckType::Equality;
-                return personMentioned && inFrameRange && checks;
-            }),
-        failedChecks.end());
-
-    // Rerun-other test
+    SPDLOG_WARN("start: {}\tend: {}", startFrame, endFrame);
+    // Rerun tests (except equality)
     QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPetrack);
     progress.setWindowTitle("Check plausibility");
     progress.setWindowModality(Qt::WindowModal);
-    progress.setVisible(true);
+    progress.setVisible(false);
     progress.setValue(0);
     progress.setLabelText("Check Plausibility...");
 
+    auto failedChecks = std::vector<plausibility::FailedCheck>();
+
     if(mUi->chbLength->isChecked())
     {
         auto failedLengthChecks{plausibility::checkLength(mPersonStorage, &progress, mUi->spbxMinFrameLength->value())};
@@ -461,6 +433,32 @@ void Correction::removePersonInFrameRange(size_t index, int startFrame, int endF
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
 
+
+    // Handle equality checks differently as they take too long to be re-run after each removal of a frame range
+    // Delete equality checks of person in frame range
+    const auto &previousChecks = mTableModel->getFailedChecks();
+
+    std::copy_if(
+        previousChecks.begin(),
+        previousChecks.end(),
+        std::back_inserter(failedChecks),
+        [startFrame, endFrame](const plausibility::FailedCheck &failedCheck)
+        {
+            bool equalityCheck   = (failedCheck.type == plausibility::CheckType::Equality);
+            bool notInFrameRange = !((startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame));
+            return equalityCheck && notInFrameRange;
+        });
+
+    // Restore the status if the same check for a person in a frame was already in the table
+    for(auto &failedCheck : failedChecks)
+    {
+        auto previousCheck = std::find(previousChecks.cbegin(), previousChecks.cend(), failedCheck);
+        if(previousCheck != previousChecks.cend())
+        {
+            failedCheck.status = previousCheck->status;
+        }
+    }
+
     mTableModel->setFailedChecks(std::move(failedChecks));
 }
 
diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index 1fc082d50..753a0e4db 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -611,6 +611,10 @@ bool PersonStorage::addPoint(
         return false;
     }
 
+    if(found)
+    {
+        emit changedPerson(iNearest);
+    }
     return !found;
 }
 
-- 
GitLab


From b03a5f8997cef6121a30de42167a2b77bdd26429 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 21 Jun 2023 18:44:08 +0200
Subject: [PATCH 42/45] Allow handling for splitting trajectories

---
 include/correction.h    |   4 ++
 include/personStorage.h |   1 +
 src/correction.cpp      | 150 +++++++++++++++++++++++++++++++---------
 src/personStorage.cpp   |  17 +++--
 4 files changed, 132 insertions(+), 40 deletions(-)

diff --git a/include/correction.h b/include/correction.h
index 8cd530632..965f8bb22 100644
--- a/include/correction.h
+++ b/include/correction.h
@@ -90,6 +90,9 @@ private:
 
     Ui::Correction         *mUi;
     FailedChecksTableModel *mTableModel;
+    bool                    mChecksExecuted = false;
+
+    std::vector<plausibility::FailedCheck> rerunChecks();
 
 private slots:
     void selectedRowChanged();
@@ -99,6 +102,7 @@ private slots:
     void changePersonState(size_t index);
     void removePerson(size_t index);
     void removePersonInFrameRange(size_t index, int startFrame, int endFrame);
+    void splitPerson(size_t, size_t newIndex, int frame);
 };
 
 #endif // CORRECTION_H
diff --git a/include/personStorage.h b/include/personStorage.h
index ba2936954..bce22c5c5 100644
--- a/include/personStorage.h
+++ b/include/personStorage.h
@@ -125,6 +125,7 @@ signals:
     void deletedPerson(size_t index);
     void deletedPersonFrameRange(size_t index, int startFrame, int endFrame);
     void changedPerson(size_t index);
+    void splitPersonAtFrame(size_t index, size_t newIndex, int frame);
 
 private:
     std::vector<TrackPerson> mPersons;
diff --git a/src/correction.cpp b/src/correction.cpp
index 42328e3bf..27b63c344 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -187,6 +187,7 @@ Correction::Correction(Petrack *petrack, const PersonStorage &personStorage, QWi
     connect(&personStorage, &PersonStorage::deletedPerson, this, &Correction::removePerson);
     connect(&personStorage, &PersonStorage::deletedPersonFrameRange, this, &Correction::removePersonInFrameRange);
     connect(&personStorage, &PersonStorage::changedPerson, this, &Correction::changePersonState);
+    connect(&personStorage, &PersonStorage::splitPersonAtFrame, this, &Correction::splitPerson);
 }
 
 bool Correction::getTestEqualChecked() const
@@ -284,6 +285,11 @@ void Correction::markResolved(QList<QModelIndex> pos)
 
 void Correction::changePersonState(size_t index)
 {
+    if(!mChecksExecuted)
+    {
+        return;
+    }
+
     auto failedChecks = mTableModel->getFailedChecks();
 
     for(auto &failedCheck : failedChecks)
@@ -355,10 +361,16 @@ void Correction::checkButtonClicked()
     }
 
     mTableModel->setFailedChecks(std::move(failedChecks));
+    mChecksExecuted = true;
 }
 
 void Correction::removePerson(size_t index)
 {
+    if(!mChecksExecuted)
+    {
+        return;
+    }
+
     auto failedChecks = mTableModel->getFailedChecks();
 
     // Delete every row where person == index + 1
@@ -396,57 +408,86 @@ void Correction::removePerson(size_t index)
 
 void Correction::removePersonInFrameRange(size_t index, int startFrame, int endFrame)
 {
-    SPDLOG_WARN("start: {}\tend: {}", startFrame, endFrame);
-    // Rerun tests (except equality)
-    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPetrack);
-    progress.setWindowTitle("Check plausibility");
-    progress.setWindowModality(Qt::WindowModal);
-    progress.setVisible(false);
-    progress.setValue(0);
-    progress.setLabelText("Check Plausibility...");
-
-    auto failedChecks = std::vector<plausibility::FailedCheck>();
-
-    if(mUi->chbLength->isChecked())
+    if(!mChecksExecuted)
     {
-        auto failedLengthChecks{plausibility::checkLength(mPersonStorage, &progress, mUi->spbxMinFrameLength->value())};
-        failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
+        return;
     }
 
-    if(mUi->chbInside->isChecked())
+    auto failedChecks = rerunChecks();
+
+    // Handle equality checks differently as they take too long to be re-run after each removal of a frame range
+    // Delete equality checks of person in frame range
+    const auto &previousChecks = mTableModel->getFailedChecks();
+
+    std::copy_if(
+        previousChecks.begin(),
+        previousChecks.end(),
+        std::back_inserter(failedChecks),
+        [startFrame, endFrame, index](const plausibility::FailedCheck &failedCheck)
+        {
+            bool person          = failedCheck.pers == index + 1;
+            bool personMentioned = failedCheck.message.find(std::to_string(index + 1)) != std::string::npos;
+
+            bool equalityCheck   = (failedCheck.type == plausibility::CheckType::Equality);
+            bool notInFrameRange = !((startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame));
+            return equalityCheck && (notInFrameRange || (!person && !personMentioned));
+        });
+
+    // Restore the status if the same check for a person in a frame was already in the table
+    for(auto &failedCheck : failedChecks)
     {
-        auto failedInsideChecks{plausibility::checkInside(
-            mPersonStorage,
-            &progress,
-            mPetrack->getImageFiltered().size(),
-            mPetrack->getImageBorderSize(),
-            mPetrack->getRecoRoiItem()->rect(),
-            mPetrack->getPlayer()->getFrameInNum(),
-            mPetrack->getPlayer()->getFrameOutNum(),
-            mUi->spbxInsideMargin->value())};
-        failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
+        auto previousCheck = std::find(previousChecks.cbegin(), previousChecks.cend(), failedCheck);
+        if(previousCheck != previousChecks.cend())
+        {
+            failedCheck.status = previousCheck->status;
+        }
     }
 
-    if(mUi->chbVelocity->isChecked())
+    mTableModel->setFailedChecks(std::move(failedChecks));
+}
+
+void Correction::splitPerson(size_t index, size_t newIndex, int frame)
+{
+    if(!mChecksExecuted)
     {
-        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPersonStorage, &progress)};
-        failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
+        return;
     }
-
+    auto failedChecks = rerunChecks();
 
     // Handle equality checks differently as they take too long to be re-run after each removal of a frame range
     // Delete equality checks of person in frame range
-    const auto &previousChecks = mTableModel->getFailedChecks();
+    auto previousChecks = mTableModel->getFailedChecks();
+
+    for(auto &previousCheck : previousChecks)
+    {
+        if(previousCheck.frame > frame)
+        {
+            if(previousCheck.pers == (index + 1))
+            {
+                previousCheck.pers = (newIndex + 1);
+            }
+
+            if(previousCheck.message.find(std::to_string(index + 1)) != std::string::npos)
+            {
+                previousCheck.message = fmt::format("Trajectory is very close to Person {}!", newIndex + 1);
+            }
+        }
+    }
 
     std::copy_if(
         previousChecks.begin(),
         previousChecks.end(),
         std::back_inserter(failedChecks),
-        [startFrame, endFrame](const plausibility::FailedCheck &failedCheck)
+        [index, newIndex](const plausibility::FailedCheck &failedCheck)
         {
-            bool equalityCheck   = (failedCheck.type == plausibility::CheckType::Equality);
-            bool notInFrameRange = !((startFrame <= failedCheck.frame) && (failedCheck.frame <= endFrame));
-            return equalityCheck && notInFrameRange;
+            bool person          = failedCheck.pers == (index + 1);
+            bool personMentioned = failedCheck.message.find(std::to_string(index + 1)) != std::string::npos;
+
+            bool newPerson          = failedCheck.pers == (newIndex + 1);
+            bool newPersonMentioned = failedCheck.message.find(std::to_string(newIndex + 1)) != std::string::npos;
+
+            bool equalityCheck = (failedCheck.type == plausibility::CheckType::Equality);
+            return equalityCheck && (person || personMentioned || newPerson || newPersonMentioned);
         });
 
     // Restore the status if the same check for a person in a frame was already in the table
@@ -469,6 +510,7 @@ void Correction::clear()
     {
         PWarning(this, "Correction", "Could not clear table.");
     }
+    mChecksExecuted = false;
 }
 
 void Correction::setXml(QDomElement &elem) const
@@ -545,6 +587,46 @@ bool Correction::getXml(const QDomElement &correctionElem)
     return true;
 }
 
+std::vector<plausibility::FailedCheck> Correction::rerunChecks()
+{
+    // Rerun tests (except equality)
+    QProgressDialog progress("Check Plausibility", nullptr, 0, 400, mPetrack);
+    progress.setWindowTitle("Check plausibility");
+    progress.setWindowModality(Qt::WindowModal);
+    progress.setVisible(false);
+    progress.setValue(0);
+    progress.setLabelText("Check Plausibility...");
+
+    auto failedChecks = std::vector<plausibility::FailedCheck>();
+
+    if(mUi->chbLength->isChecked())
+    {
+        auto failedLengthChecks{plausibility::checkLength(mPersonStorage, &progress, mUi->spbxMinFrameLength->value())};
+        failedChecks.insert(failedChecks.end(), failedLengthChecks.begin(), failedLengthChecks.end());
+    }
+
+    if(mUi->chbInside->isChecked())
+    {
+        auto failedInsideChecks{plausibility::checkInside(
+            mPersonStorage,
+            &progress,
+            mPetrack->getImageFiltered().size(),
+            mPetrack->getImageBorderSize(),
+            mPetrack->getRecoRoiItem()->rect(),
+            mPetrack->getPlayer()->getFrameInNum(),
+            mPetrack->getPlayer()->getFrameOutNum(),
+            mUi->spbxInsideMargin->value())};
+        failedChecks.insert(failedChecks.end(), failedInsideChecks.begin(), failedInsideChecks.end());
+    }
+
+    if(mUi->chbVelocity->isChecked())
+    {
+        auto failedVelocityChecks{plausibility::checkVelocityVariation(mPersonStorage, &progress)};
+        failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
+    }
+    return std::move(failedChecks);
+}
+
 Correction::~Correction()
 {
     delete mUi;
diff --git a/src/personStorage.cpp b/src/personStorage.cpp
index 753a0e4db..a7e8d9cb9 100644
--- a/src/personStorage.cpp
+++ b/src/personStorage.cpp
@@ -36,18 +36,23 @@ void PersonStorage::splitPerson(size_t pers, int frame)
 {
     mAutosave.trackPersonModified();
 
-    if(mPersons.at(pers).firstFrame() < frame)
     {
-        mPersons.push_back(mPersons.at(pers));
+        const QSignalBlocker blocker(this);
+        if(mPersons.at(pers).firstFrame() < frame)
+        {
+            mPersons.push_back(mPersons.at(pers));
 
-        // alte trj einkuerzen und ab aktuellem frame zukunft loeschen
-        deletePersonFrameRange(pers, frame, mPersons[pers].lastFrame());
+            // alte trj einkuerzen und ab aktuellem frame zukunft loeschen
+            deletePersonFrameRange(pers, frame, mPersons[pers].lastFrame());
 
-        // neu angehaengte/gedoppelte trajektorie
-        deletePersonFrameRange(mPersons.size() - 1, mPersons[pers].firstFrame(), frame - 1);
+            // neu angehaengte/gedoppelte trajektorie
+            deletePersonFrameRange(mPersons.size() - 1, mPersons[pers].firstFrame(), frame - 1);
+        }
     }
 
+    emit splitPersonAtFrame(pers, mPersons.size() - 1, frame);
     emit changedPerson(pers);
+    emit changedPerson(mPersons.size() - 1);
 }
 
 /**
-- 
GitLab


From aaeab2e96c324223fb463d1d53ebd0cfb9321f89 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 21 Jun 2023 18:48:29 +0200
Subject: [PATCH 43/45] Sort the rows by person number and frame

---
 include/plausibility.h | 6 ++++++
 src/correction.cpp     | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/plausibility.h b/include/plausibility.h
index d0676fb79..1490c99d0 100644
--- a/include/plausibility.h
+++ b/include/plausibility.h
@@ -58,6 +58,12 @@ inline bool operator==(const FailedCheck &first, const FailedCheck &second)
     return (first.pers == second.pers && first.frame == second.frame && first.type == second.type);
 }
 
+inline bool operator<(const FailedCheck &first, const FailedCheck &second)
+{
+    return std::tie(first.pers, first.frame) < std::tie(second.pers, second.frame);
+}
+
+
 std::vector<FailedCheck>
 checkLength(const PersonStorage &personStorage, QProgressDialog *progressDialog, int minLength);
 
diff --git a/src/correction.cpp b/src/correction.cpp
index 27b63c344..03ab0478a 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -120,7 +120,7 @@ void FailedChecksTableModel::setFailedChecks(std::vector<plausibility::FailedChe
     emit layoutAboutToBeChanged();
 
     mFailedChecks = failedChecks;
-
+    std::sort(mFailedChecks.begin(), mFailedChecks.end());
     QModelIndex topLeft     = index(0, 0);
     QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);
 
-- 
GitLab


From a1a5d6f1bd20ecbc3d3fe742fd09df1e54d758b0 Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Wed, 21 Jun 2023 21:36:34 +0200
Subject: [PATCH 44/45] Remove not needed move call

---
 src/correction.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/correction.cpp b/src/correction.cpp
index 03ab0478a..36a056e63 100644
--- a/src/correction.cpp
+++ b/src/correction.cpp
@@ -624,7 +624,7 @@ std::vector<plausibility::FailedCheck> Correction::rerunChecks()
         auto failedVelocityChecks{plausibility::checkVelocityVariation(mPersonStorage, &progress)};
         failedChecks.insert(failedChecks.end(), failedVelocityChecks.begin(), failedVelocityChecks.end());
     }
-    return std::move(failedChecks);
+    return failedChecks;
 }
 
 Correction::~Correction()
-- 
GitLab


From 2223c202336cee80a462dc1241a96978f17cfe4b Mon Sep 17 00:00:00 2001
From: schroedtert <t.schroedter@fz-juelich.de>
Date: Thu, 22 Jun 2023 08:41:44 +0200
Subject: [PATCH 45/45] Fix rebase introduced error

---
 include/control.h | 2 +-
 src/control.cpp   | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/control.h b/include/control.h
index c9802ba57..5000b1189 100644
--- a/include/control.h
+++ b/include/control.h
@@ -576,7 +576,7 @@ private:
     ExtrinsicBox        *mExtr;
     CoordinateSystemBox *mCoordSys;
     QGraphicsScene      *mScene;
-    Correction          *CorrectionWidget;
+    Correction          *mCorrectionWidget;
 
     bool mColorChanging;
     bool mIndexChanging; // shows, if the index of the color model is really changing; nor while constructor (initialer
diff --git a/src/control.cpp b/src/control.cpp
index b061a03ed..c47e5cbff 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -26,10 +26,9 @@
 #include "colorPlot.h"
 #include "colorRangeWidget.h"
 #include "coordinateSystemBox.h"
-#include "extrinsicBox.h"
 #include "correction.h"
-#include "extrinsicParameters.h"
 #include "extrinsicBox.h"
+#include "extrinsicParameters.h"
 #include "filterBeforeBox.h"
 #include "intrinsicBox.h"
 #include "logger.h"
-- 
GitLab