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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></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><html><head/><body><p>check, if two trajectories are close to each other</p></body></html></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><html><head/><body><pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;"><span style=" background-color:#2b2b2b;">check, if the trajectory starts and ends outside of the recognition area</span></pre></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></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><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Warning: </span><span style=" font-size:12pt;">If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!</span></p></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Warning: </span><span style=" font-size:12pt;">If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!</span></p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></string> @@ -84,20 +99,7 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QCheckBox" name="chbEqual"> - <property name="toolTip"> - <string><html><head/><body><p>check, if two trajectories are close to each other</p></body></html></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><html><head/><body><pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;"><span style=" background-color:#2b2b2b;">check, if the trajectory starts and ends outside of the recognition area</span></pre></body></html></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><html><head/><body><p>check, if two trajectories are close to each other</p></body></html></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><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Warning: </span><span style=" font-size:12pt;">If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!</span></p></body></html></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><html><head/><body><pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;"><span style=" background-color:#2b2b2b;">check, if the trajectory starts and ends outside of the recognition area</span></pre></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Warning: </span><span style=" font-size:12pt;">If you delete/add a trajectory, please rerun the checks. Otherwise the click in the table may lead to a wrong person!</span></p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></string> + <string><html><head/><body><p>check, if two trajectories are close to each other</p></body></html></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><html><head/><body><p>check, if two trajectories are close to each other</p></body></html></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><html><head/><body><pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;"><span style=" background-color:#2b2b2b;">check, if the trajectory starts and ends outside of the recognition area</span></pre></body></html></string> + <string><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;"><span style=" background-color:#2b2b2b;">check, if the trajectory starts and ends outside of the recognition area</span></pre></body></html></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><html><head/><body><pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#2b2b2b;"><span style=" background-color:#2b2b2b;">check, if the trajectory starts and ends outside of the recognition area</span></pre></body></html></string> + <string><html><head/><body><>check, if the trajectory starts and ends outside the recognition area</p></body></html></string> </property> <property name="text"> <string>inside</string> @@ -197,6 +197,9 @@ <property name="value"> <number>30</number> </property> + <property name="toolTip"> + <string><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></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><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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><html><head/><body><>minimum distance to image border to count as inside</p></body></html></string> + <string><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><p>test, if the trajectory is very short (less than 10 points)</p></body></html></string> + <string><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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><html><head/><body><p>check, if trajectory has large variations of the velocity</p></body></html></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><html><head/><body><>minimum distance to image border to count as inside</p></body></html></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