Newer
Older
/*
* PeTrack - Software for tracking pedestrians movement in videos
* Copyright (C) 2010-2022 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 <QtOpenGL>
#include <QtWidgets>
#include "aboutDialog.h"
#include "animation.h"
#include "autoCalib.h"
#include "backgroundItem.h"
#include "calibFilter.h"
#include "codeMarkerWidget.h"
#include "control.h"
#include "gridItem.h"
#include "imageItem.h"
#include "logoItem.h"
#include "multiColorMarkerItem.h"
#include "multiColorMarkerWidget.h"
#include "openMoCapDialog.h"
#include "pMessageBox.h"
#include "petrack.h"
#include "player.h"
#include "roiItem.h"
#include "stereoItem.h"
#include "stereoWidget.h"
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrinter>
#ifdef AVI
#include "aviFile.h"
#else
#include "aviFileWriter.h"
#endif
// temp muss spaeter herausgenommen werden,
// dient dazu, in anderen dateien um schnell ueber cw->temp1->value() an einstellbare daten zu kommen
Control *cw;
int Petrack::trcVersion = 0;
// Reihenfolge des anlegens der objekte ist sehr wichtig
Petrack::Petrack() :
mExtrCalibration(mPersonStorage),
mAuthors(IO::readAuthors(QCoreApplication::applicationDirPath() + "/.zenodo.json"))
mHeadSize = -1;
mCmPerPixel = -1;
mScene = nullptr;
mTracker = nullptr;
mTrackerReal = nullptr; // damit beim zeichnen von control mit analysePlot nicht auf einen feheler laeuft
mStatusLabelFPS = nullptr;
mStatusLabelPosReal = nullptr;
mImageItem = nullptr;
mRecognitionChanged = true;
mTrackChanged = true;
mCoordItem = nullptr;
mImage = nullptr;
setLoading(true);
setAcceptDrops(true);
int space = 2;
mBrightContrastFilter.disable();
mBorderFilter.disable();
mSwapFilter.disable();
mBackgroundFilter.disable();
mCalibFilter = new CalibFilter; // schoener waere erst zu erzeugen, wenn video geladen wird, da sonst bei stereo
// erst normealer und dann stereo objekt erzeugt wird
mCalibFilter->disable(); // aber control widget greift schon bei erzeugung auf alle objekte zur einstellung zurueck
mTrackingRoiItem = new RoiItem(this, Qt::blue);
connect(mTrackingRoiItem, &RoiItem::changed, this, [=]() { this->setTrackChanged(true); });
mTrackingRoiItem->setZValue(4); // groesser heisst weiter oben
mRecognitionRoiItem = new RoiItem(this, Qt::green);
connect(mRecognitionRoiItem, &RoiItem::changed, this, [=]() { this->setRecognitionChanged(true); });
mRecognitionRoiItem->setZValue(5); // groesser heisst weiter oben
mControlWidget = new Control(*this, *mScene, mReco, *mTrackingRoiItem, *mRecognitionRoiItem);
cw = mControlWidget; // muss spaeter geloescht werden
mStereoWidget = new StereoWidget(this);
mStereoWidget->setWindowFlags(Qt::Window);
mStereoWidget->setWindowTitle("Stereo parameter");
mColorRangeWidget = new ColorRangeWidget(this);
mColorRangeWidget->setWindowFlags(Qt::Window);
mColorRangeWidget->setWindowTitle("Color range");
mColorMarkerWidget = new ColorMarkerWidget(this);
mColorMarkerWidget->setWindowFlags(Qt::Window);
mColorMarkerWidget->setWindowTitle("Color marker parameter");
mCodeMarkerWidget = new CodeMarkerWidget(this, mReco.getCodeMarkerOptions(), nullptr);
mCodeMarkerWidget->setWindowFlags(Qt::Window);
mCodeMarkerWidget->setWindowTitle("Code marker parameter");
mMultiColorMarkerWidget = new MultiColorMarkerWidget(this);
mMultiColorMarkerWidget->setWindowFlags(Qt::Window);
mMultiColorMarkerWidget->setWindowTitle("MultiColor marker parameter");
mImageItem = new ImageItem(this); // durch uebergabe von scene wird indirekt ein scene->addItem() aufgerufen
mAnimation = new Animation(this);
mLogoItem = new LogoItem(this); // durch uebergabe von scene wird indirekt ein scene->addItem() aufgerufen
mLogoItem->setZValue(6); // groesser heisst weiter oben
mExtrCalibration.setMainWindow(this);
mGridItem = new GridItem(this);
mGridItem->setZValue(2.5); // durch uebergabe von scene wird indirekt ein scene->addItem() aufgerufen
mCoordItem = new CoordItem(this);
mCoordItem->setZValue(3); // groesser heisst weiter oben
mImageItem->setCoordItem(mCoordItem);
mViewWidget = new ViewWidget(this);
connect(mView, &GraphicsView::mouseDoubleClick, this, [this]() { this->openSequence(); });
connect(mView, &GraphicsView::mouseShiftDoubleClick, this, &Petrack::addManualTrackPointOnlyVisible);
connect(mView, &GraphicsView::mouseShiftControlDoubleClick, this, &Petrack::splitTrackPerson);
connect(mView, &GraphicsView::mouseControlDoubleClick, this, &Petrack::addOrMoveManualTrackPoint);
connect(mView, &GraphicsView::mouseRightDoubleClick, this, &Petrack::deleteTrackPoint);
connect(mView, &GraphicsView::mouseMiddleDoubleClick, this, &Petrack::deleteTrackPointAll);
connect(mView, &GraphicsView::mouseShiftWheel, this, &Petrack::skipToFrameWheel);
connect(mView, &GraphicsView::mouseAltDoubleClick, this, &Petrack::skipToFrameFromTrajectory);
mPlayerWidget = new Player(mAnimation, this);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->setSpacing(space);
vLayout->addWidget(mViewWidget);
vLayout->addWidget(mPlayerWidget);
//---------------------------
mTracker = new Tracker(this, mPersonStorage);
mTrackerReal = new TrackerReal(this, mPersonStorage);
mTrackerItem = new TrackerItem(this, mPersonStorage);
mControlWidget->getColorPlot()->setPersonStorage(&mPersonStorage);
#ifdef QWT
mControlWidget->getAnalysePlot()->setTrackerReal(mTrackerReal);
#endif
//---------------------------
mStereoItem = new StereoItem(this);
mStereoItem->setZValue(2); // groesser heisst weiter oben
//---------------------------
mColorMarkerItem = new ColorMarkerItem(this);
mColorMarkerItem->setZValue(2); // groesser heisst weiter oben
mColorMarkerItem->setVisible(false);
//---------------------------
mCodeMarkerItem = new CodeMarkerItem(this, mReco.getCodeMarkerOptions());
mCodeMarkerItem->setZValue(2); // groesser heisst weiter oben
mCodeMarkerItem->setVisible(false);
//---------------------------
mMultiColorMarkerItem = new MultiColorMarkerItem(this);
mMultiColorMarkerItem->setZValue(2); // groesser heisst weiter oben
mMultiColorMarkerItem->setVisible(false);
//---------------------------
mBackgroundItem = new BackgroundItem(this);
mBackgroundItem->setZValue(2.2); // um so groesser um so hoeher um so eher zu sehen
mBackgroundItem->setVisible(false);
//---------------------------
mMoCapItem = new MoCapItem(*this, *mAnimation, mMoCapController);
mMoCapItem->setZValue(3); // um so groesser um so hoeher um so eher zu sehen
/// Add Items
mScene->addItem(mImageItem);
mScene->addItem(mLogoItem);
mScene->addItem(mGridItem);
mScene->addItem(mCoordItem);
mScene->addItem(mTrackingRoiItem);
mScene->addItem(mRecognitionRoiItem);
mScene->addItem(mTrackerItem);
mScene->addItem(mStereoItem);
mScene->addItem(mColorMarkerItem);
mScene->addItem(mCodeMarkerItem);
mScene->addItem(mMultiColorMarkerItem);
mScene->addItem(mBackgroundItem);
//---------------------------
mCentralLayout = new QHBoxLayout;
mCentralLayout->setMargin(space);
mCentralWidget = new QFrame;
mCentralWidget->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
mCentralWidget->setLayout(mCentralLayout);
setCentralWidget(mCentralWidget);
mSplitter = new QSplitter(this);
// create playAndView-Widget to wrap layout, since QSplitter only accepts widgets
QWidget *playAndView = new QWidget(this);
playAndView->setLayout(vLayout);
mSplitter->addWidget(playAndView);
mSplitter->addWidget(mControlWidget);
mSplitter->setStretchFactor(0, 1);
mSplitter->setStretchFactor(1, 0);
mCentralLayout->addWidget(mSplitter);
setWindowTitle(tr("PeTrack"));
//---------------------------
mAutoCalib.setMainWindow(this);
//---------------------------
createActions();
createMenus();
createStatusBar();
// TODO delete once we get Options to be value only (i.e. no Pointer/Ref anymore)
mReco.getCodeMarkerOptions().setControlWidget(mControlWidget);
mReco.getCodeMarkerOptions().setCodeMarkerItem(mCodeMarkerItem);
mSeqFileName = QDir::currentPath(); // fuer allerersten Aufruf des Programms
saveXml(mDefaultSettings); // noch nicht noetig, da eh noch nicht fkt
mShowFPS = 0;
mTrcFileName = "";
// initialer Aufruf, damit beim reinen Laden einer Videodatei die Defaultwerte in control genommen werden zum Setzen
setHeadSize();
// um im background subtraction filter das hoehenbild zu beruecksichtigen
mBackgroundFilter.setStereoContext(&mStereoContext);
mAutoBackTrack = true; // ist der default, dann wenn in XML-Datei nicht drin steht
mAutoTrackOptimizeColor = false; // ist der default, dann wenn in XML-Datei nicht drin steht
setLoading(false);
}
Petrack::~Petrack()
{
delete mImage;
delete cw;
// hier muessten weitere stehen insb die im konstruktor erzeugt werden
// aber da petrack nur vernichtet wird, wenn programm beendet wird, kann man sich das auch schenken
}
void Petrack::dragEnterEvent(QDragEnterEvent *event)
{
/**
* @brief Accepts dropped .pet, .trc and media files
*
* Opens the project for a .pet. Imports the trajectories for a .trc
* and tries to open the sequence for any other kind of file.
*
* @param event
*/
if(event->mimeData()->urls().first().toLocalFile().right(4) == ".pet")
else if(event->mimeData()->urls().first().toLocalFile().right(4) == ".trc")
event->acceptProposedAction();
}
}
void Petrack::updateSceneRect()
{
{
iW = mImage->width();
iH = mImage->height();
bS = getImageBorderSize();
}
if(mControlWidget->getCalibCoordShow())
double scale = mControlWidget->getCalibCoordScale() / 10.;
double tX = mControlWidget->getCalibCoordTransX() / 10.;
double tY = mControlWidget->getCalibCoordTransY() / 10.;
// setzen der bounding box der scene
// Faktor 1.1 dient dazu, dass auch Zahl "1" bei coord gut in sichtbaren Bereich passt
double xMin = (tX - 1.1 * scale < -bS) ? tX - 1.1 * scale : -bS;
double yMin = (tY - 1.1 * scale < -bS) ? tY - 1.1 * scale : -bS;
double xMax = (tX + 1.1 * scale > iW - bS) ? tX + 1.1 * scale : iW - bS;
double yMax = (tY + 1.1 * scale > iH - bS) ? tY + 1.1 * scale : iH - bS;
mScene->setSceneRect(xMin, yMin, xMax - xMin, yMax - yMin);
/**
* @brief Loads the content of a .pet file into petrack
*
* @param doc the DOM of the .pet file
* @param openSeq true, if sequence given in doc should be opened
*/
void Petrack::openXml(QDomDocument &doc, bool openSeq)
{
QDomElement root = doc.firstChildElement("PETRACK");
QString seq;
int frame = -1, sourceFrameIn = -1, sourceFrameOut = -1;
double fps = DEFAULT_FPS;
int onlyPeopleNr = 1;
QString onlyPeopleNrList = "1";
int zoom = 250, rotate = 0, hScroll = 0, vScroll = 0;
enum Camera cam = cameraUnset;
setLoading(true);
for(QDomElement elem = root.firstChildElement(); !elem.isNull(); elem = elem.nextSiblingElement())
{
if(elem.hasAttribute("STATUS_HEIGHT"))
if(mStatusPosRealHeight) // null kann eigentlich nicht vorkommen, da im constructor von petrack erzeugt
// wird
mStatusPosRealHeight->setValue(elem.attribute("STATUS_HEIGHT").toDouble());
else if(elem.tagName() == "STEREO")
else if(elem.tagName() == "COLOR_MARKER")
else if(elem.tagName() == "CODE_MARKER")
else if(elem.tagName() == "MULTI_COLOR_MARKER")
else if(elem.tagName() == "MOCAP")
{
mMoCapController.getXml(elem);
}
else if(elem.tagName() == "CONTROL")
{
mControlWidget->getXml(elem);
QDomElement tmpElem = (elem.firstChildElement("TRACKING")).firstChildElement("PATH");
if(tmpElem.hasAttribute("ONLY_PEOPLE_NR"))
if(tmpElem.hasAttribute("ONLY_PEOPLE_NR_LIST"))
else if(elem.tagName() == "EXTR_CALIBRATION")
{
mExtrCalibration.getXml(elem);
}
else if(elem.tagName() == "PLAYER")
if(elem.hasAttribute("SOURCE_FRAME_IN"))
{
sourceFrameIn = elem.attribute("SOURCE_FRAME_IN").toInt();
}
if(elem.hasAttribute("SOURCE_FRAME_OUT"))
{
sourceFrameOut = elem.attribute("SOURCE_FRAME_OUT").toInt();
}
if(elem.hasAttribute("PLAYER_SPEED_FIXED"))
mPlayerWidget->setPlayerSpeedLimited(elem.attribute("PLAYER_SPEED_FIXED").toInt());
else if(elem.tagName() == "VIEW")
if(elem.hasAttribute("ANTIALIAS"))
mAntialiasAct->setChecked(elem.attribute("ANTIALIAS").toInt() == Qt::Checked);
mOpenGLAct->setChecked(elem.attribute("OPENGL").toInt() == Qt::Checked);
if(elem.hasAttribute("SAVE_TRANSFORMED"))
mCropZoomViewAct->setChecked(elem.attribute("SAVE_TRANSFORMED") == Qt::Checked);
if(elem.hasAttribute("TRANSFORMATION"))
QString matStr = elem.attribute("TRANSFORMATION");
QTextStream in(&matStr);
in >> zoom >> rotate >> hScroll >> vScroll;
}
{
cam = (enum Camera) elem.attribute("CAMERA").toInt();
}
if(elem.hasAttribute("HIDE_CONTROLS"))
mHideControlsAct->setChecked(elem.attribute("HIDE_CONTROLS").toInt() == Qt::Checked);
}
else if(elem.tagName() == "AUTO_TRACK")
if(elem.hasAttribute("BACK_TRACK"))
{
mAutoBackTrack = elem.attribute("BACK_TRACK").toInt();
}
if(elem.hasAttribute("OPTIMZE_COLOR"))
{
mAutoTrackOptimizeColor = elem.attribute("OPTIMZE_COLOR").toInt();
}
}
else
debout << "Unknown PETRACK tag " << elem.tagName() << std::endl;
}
// open koennte am schluss passieren, dann wuerde nicht erst unveraendertes bild angezeigt,
// dafuer koennte es aber sein, dass werte zb bei fx nicht einstellbar sind!
mSeqFileName = seq;
openSequence(seq); // wenn leer, dann kommt abfrage hoch, welche datei; abbrechen, wenn aktuelle gewuenscht
mViewWidget->setZoomLevel(zoom);
mViewWidget->setRotateLevel(rotate);
mView->horizontalScrollBar()->setValue(hScroll);
mView->verticalScrollBar()->setValue(vScroll);
bool loaded = false;
if(!mBackgroundFilter.getFilename().isEmpty())
if(!(loaded = mBackgroundFilter.load(mBackgroundFilter.getFilename())))
debout << "Error: loading background file " << mBackgroundFilter.getFilename() << "!" << std::endl;
mPlayerWidget->setFrameInNum(sourceFrameIn == -1 ? mAnimation->getSourceInFrameNum() : sourceFrameIn);
mPlayerWidget->setFrameOutNum(sourceFrameOut == -1 ? mAnimation->getSourceOutFrameNum() : sourceFrameOut);
if(mControlWidget->filterBg->isChecked() &&
!loaded) // mit dem anfangs geladenen bild wurde bereits faelschlicherweise bg bestimmt
{
mBackgroundFilter.reset(); // erst nach dem springen zu einem frame background bestimmen
mPlayerWidget->skipToFrame(frame); // hier wird updateImage ausgefuehrt
}
// nicht schon in control, sonst loescht opensequence wieder tracker
{
// vorher loeschen aller trajektorien, da sonst nach start im ersten bild
// mgl zwei trackpoints
// beim haendischen importieren sind weiterhin parallele trajektorien moeglich (warnung wird ausgegeben)
frame = 0; // default
if((mPersonStorage.largestLastFrame() >= frame) && (getPersonStorage().smallestFirstFrame() <= frame))
mTracker->reset();
}
importTracker(mTrcFileName);
}
mControlWidget->trackShowOnlyNr->setValue(onlyPeopleNr);
mControlWidget->trackShowOnlyNrList->setText(onlyPeopleNrList);
setCamera();
mPlayerWidget->setFPS(fps); // erst spaet setzen, damit Wert den des geladenen Videos ueberschreiben kann
setLoading(false);
}
void Petrack::openProject(QString fileName, bool openSeq) // default fileName="", openSequence = true
{
if(!QFileInfo(mProFileName).isDir()) // a project is already loaded
fileName = QFileDialog::getOpenFileName(
this,
tr("Select project file"),
QFileInfo(mProFileName).path(),
tr("PeTrack project file (*.pet);;All files (*.*)"));
if(!file.open(QIODevice::ReadOnly))
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(fileName, file.errorString()));
return;
}
resetSettings();
QDomDocument doc("PETRACK"); // eigentlich Pfad zu Beschreibungsdatei fuer Dateiaufbau
PCritical(this, tr("PeTrack"), tr("Cannot read content from %1.").arg(fileName));
debout << "open " << fileName << std::endl;
if(root.attribute("VERSION") != mPetrackVersion)
PWarning(
this,
tr("PeTrack"),
tr("Reading %1:\nDifferent version numbers %2 (application) and %3 (file) may cause problems.")
.arg(fileName, mPetrackVersion, root.attribute("VERSION")));
mLastTrackerExport = mTrcFileName;
if(mControlWidget->getCalibS1Value() == 0 && mControlWidget->getCalibS2Value() == 0 &&
mControlWidget->getCalibS3Value() == 0 && mControlWidget->getCalibS4Value() == 0 &&
mControlWidget->getCalibTAUXValue() == 0 && mControlWidget->getCalibTAUYValue() == 0)
{
PWarning(
this,
tr("PeTrack"),
tr("You are using an old project! Therefore the old intr. calibration model is set the default"));
mControlWidget->setNewModelChecked(false);
}
updateWindowTitle();
}
}
void Petrack::saveXml(QDomDocument &doc)
{
QDomElement elem;
QDomElement root = doc.createElement("PETRACK");
root.setAttribute("VERSION", mPetrackVersion);
doc.appendChild(root);
// main settings (window size, status hight)
elem = doc.createElement("MAIN");
QString seq = getFileList(mSeqFileName, mProFileName);
elem.setAttribute("SRC", seq);
elem.setAttribute("STATUS_HEIGHT", mStatusPosRealHeight->value());
root.appendChild(elem);
// control settings (right control widget)
elem = doc.createElement("CONTROL");
mControlWidget->setXml(elem);
root.appendChild(elem);
// Reprojection error extrinsic calib
elem = doc.createElement("EXTR_CALIBRATION");
mExtrCalibration.setXml(elem);
root.appendChild(elem);
// settings for stereo
elem = doc.createElement("STEREO");
mStereoWidget->setXml(elem);
root.appendChild(elem);
// settings for color marker
elem = doc.createElement("COLOR_MARKER");
mColorMarkerWidget->setXml(elem);
root.appendChild(elem);
// settings for code marker
elem = doc.createElement("CODE_MARKER");
mCodeMarkerWidget->setXml(elem);
root.appendChild(elem);
// settings for multicolor marker
elem = doc.createElement("MULTI_COLOR_MARKER");
mMultiColorMarkerWidget->setXml(elem);
root.appendChild(elem);
// settings for MoCap-Visualization
elem = doc.createElement("MOCAP");
mMoCapController.setXml(elem);
root.appendChild(elem);
// player settings (which frame, frame range)
elem = doc.createElement("PLAYER");
elem.setAttribute("FRAME", mPlayerWidget->getPos()); // == mAnimation->getCurrentFrameNum()
elem.setAttribute("FPS", mAnimation->getFPS());
elem.setAttribute("SOURCE_FRAME_IN", mPlayerWidget->getFrameInNum());
elem.setAttribute("SOURCE_FRAME_OUT", mPlayerWidget->getFrameOutNum());
elem.setAttribute("PLAYER_SPEED_FIXED", mPlayerWidget->getPlayerSpeedLimited());
root.appendChild(elem);
// view settings (zoom, rotate, alias, opengl)
elem = doc.createElement("VIEW");
elem.setAttribute("ANTIALIAS", mAntialiasAct->isChecked());
elem.setAttribute("OPENGL", mOpenGLAct->isChecked());
elem.setAttribute("SAVE_TRANSFORMED", mCropZoomViewAct->isChecked());
elem.setAttribute(
"TRANSFORMATION",
QString("%1 %2 %3 %4")
.arg(mViewWidget->getZoomLevel())
.arg(mViewWidget->getRotateLevel())
.arg(mView->horizontalScrollBar()->value())
.arg(mView->verticalScrollBar()->value()));
#ifndef STEREO_DISABLED
#else
elem.setAttribute("CAMERA", cameraUnset);
#endif
elem.setAttribute("HIDE_CONTROLS", mHideControlsAct->isChecked());
root.appendChild(elem);
// auto track settings
elem = doc.createElement("AUTO_TRACK");
elem.setAttribute("BACK_TRACK", mAutoBackTrack);
elem.setAttribute("OPTIMZE_COLOR", mAutoTrackOptimizeColor);
root.appendChild(elem);
}
/// rueckgabewert zeigt an, ob gesichert werden konnte
bool Petrack::saveSameProject()
{
return saveProject(mProFileName);
}
bool Petrack::saveProjectAs()
{
auto fileName = QFileDialog::getSaveFileName(
this, tr("Select project file"), mProFileName, tr("PeTrack project file (*.pet);;All files (*.*)"));
return saveProject(fileName);
}
/// rueckgabewert zeigt an, ob gesichert werden konnte
bool Petrack::saveProject(QString fileName) // default fileName=""
{
// if no destination file or folder is given
if(fileName.isEmpty() && QFileInfo(mProFileName).isDir())
fileName = QFileDialog::getSaveFileName(
this, tr("Select project file"), mProFileName, tr("PeTrack project file (*.pet);;All files (*.*)"));
QDomDocument doc("PETRACK"); // eigentlich Pfad zu Beschreibungsdatei fuer Dateiaufbau
saveXml(doc);
// file output
QByteArray byteArray;
QXmlStreamWriter xmlStream(&byteArray);
xmlStream.setAutoFormatting(true);
xmlStream.setAutoFormattingIndent(4);
xmlStream.writeStartDocument();
xmlStream.writeDTD("<!DOCTYPE PETRACK>");
QDomElement element = doc.documentElement();
writeXmlElement(xmlStream, element);
xmlStream.writeEndDocument();
QFile file(fileName);
if(!file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text))
PCritical(this, tr("PeTrack"), tr("Cannot save %1:\n%2.").arg(fileName, file.errorString()));
file.close();
return false;
}
file.write(byteArray);
file.close(); // also flushes the file
statusBar()->showMessage(tr("Saved project to %1.").arg(fileName), 5000);
debout << "save project to " << fileName << std::endl;
void Petrack::writeXmlElement(QXmlStreamWriter &xmlStream, QDomElement element)
QVector<QString> attribute_names;
for(int i = 0; i < attributes.size(); ++i)
{
attribute_names.push_back(attributes.item(i).toAttr().name());
}
// TODO: check if sorting of elements fits our needs
std::stable_sort(attribute_names.begin(), attribute_names.end()); // for a canonical XML
// Wants this macro instead of range-based for loop
foreach(QString name, attribute_names)
{
QDomAttr attr = element.attributeNode(name);
xmlStream.writeAttribute(attr.name(), attr.value());
}
// order of child nodes is defined at creation
if(element.hasChildNodes())
{
for(int i = 0; i < children.size(); ++i)
{
writeXmlElement(xmlStream, children.at(i).toElement());
}
}
xmlStream.writeEndElement();
}
/**
* @brief Opens camera livestream from cam with camID
* @param camID id of camera to use (defaults to 0)
*/
void Petrack::openCameraLiveStream(int camID /* =-1*/)
debout << "No camera ID delivered: Set CameraID to 0 (default Camera)" << std::endl;
if(!mAnimation->openCameraStream(camID))
PCritical(this, tr("PeTrack"), tr("Cannot start Camera Livestream."));
debout << "open " << mSeqFileName << " (" << mAnimation->getNumFrames() << " frames; " << mAnimation->getFPS()
<< " fps; " << mAnimation->getSize().width() << "x" << mAnimation->getSize().height() << " pixel)"
<< std::endl; // size
updateSequence();
updateWindowTitle();
mPlayerWidget->setFPS(mAnimation->getFPS());
}
void Petrack::openSequence(QString fileName) // default fileName = ""
{
fileName = QFileDialog::getOpenFileName(
this,
tr("Open video or image sequence"),
QFileInfo(mSeqFileName).path(),
tr("All supported types (*.avi *.mpg *.mts *.m2t *.m2ts *.wmv *.mp4 *.mov *.mxf *.bmp *.dib *.jpeg *.jpg "
"*.jpe *.png *.pbm *.pgm *.ppm *.sr *.ras *.tiff *.tif *.exr *.jp2);;Video (*.avi *.mpg *.mts *.m2ts "
"*.m2t *.wmv *.mov *.mp4 *.mxf);;Images (*.bmp *.dib *.jpeg *.jpg *.jpe *.png *.pbm *.pgm *.ppm *.sr "
"*.ras *.tiff *.tif *.exr *.jp2);;Windows bitmaps (*.bmp *.dib);;JPEG (*.jpeg *.jpg *.jpe);;Portable "
"network graphics (*.png);;Portable image format (*.pbm *.pgm *.ppm);;Sun rasters (*.sr *.ras);;TIFF "
"(*.tiff *.tif);;OpenEXR HDR (*.exr);;JPEG 2000 (*.jp2);;All files (*.*)"));
if(!mAnimation->openAnimation(fileName))
PCritical(this, tr("PeTrack"), tr("Cannot load %1.").arg(fileName));
return;
}
mCameraGroupView->setEnabled(mAnimation->isStereoVideo());
mCameraMenu->setEnabled(mAnimation->isStereoVideo());
#ifdef STEREO
delete mStereoContext;
mStereoContext = new pet::StereoContext(this);
}
bool lastIsStereoVideo = mAnimation->isStereoVideo();
if(mCalibFilter == NULL || (mAnimation->isStereoVideo() != lastIsStereoVideo))
{
lastCalibFilterEnabled = mCalibFilter->getEnabled();
delete mCalibFilter;
}
{
mCalibFilter = new CalibStereoFilter;
((CalibStereoFilter *) mCalibFilter)->setStereoContext(mStereoContext);
}
else
mCalibFilter = new CalibFilter;
mCalibFilter->setEnabled(lastCalibFilterEnabled);
}
#endif
mSeqFileName = fileName;
debout << "open " << mSeqFileName << " (" << mAnimation->getNumFrames() << " frames; " << mAnimation->getFPS()
<< " fps; " << mAnimation->getSize().width() << "x" << mAnimation->getSize().height() << " pixel)"
<< std::endl; // size
updateSequence();
updateWindowTitle();
mPlayerWidget->setFPS(mAnimation->getFPS());
void Petrack::openMoCapFile()
{
OpenMoCapDialog dialog(this, mMoCapController);
dialog.exec();
}
QSize size = mAnimation->getSize();
if(QFileInfo(mProFileName).isDir())
title = tr("PeTrack (v") + mPetrackVersion + tr("): ");
title = tr("PeTrack (v") + mPetrackVersion + tr("): ") + QFileInfo(mProFileName).fileName();
if(mAnimation->isVideo() || mAnimation->isImageSequence())
title += "sequence: " + mAnimation->getCurrentFileName() + tr(" (%1").arg(mAnimation->getNumFrames()) +
tr(" frames; %1x%2").arg(size.width()).arg(size.height()) + " pixel)";
else if(mAnimation->isImageSequence())
title += "sequence: " + mAnimation->getCurrentFileName() + tr(" ... (%1").arg(mAnimation->getNumFrames()) +
tr(" frames; %1x%2").arg(size.width()).arg(size.height()) + " pixel)";
setWindowTitle(title);
}
void Petrack::saveVideo()
{
saveSequence(true, false);
}
void Petrack::saveVideoView()
{
saveSequence(true, true);
}
void Petrack::saveImageSequence()
{
saveSequence(false, false);
}
void Petrack::saveViewSequence()
{
saveSequence(false, true);
}
/**
* @brief Saves current sequence as avi-file or image sequence
*
* Saves the loaded image sequence or video from current frame on till the end.
* One can save the sequence as is or one can save the view shown in PeTrack.
*
* @param saveVideo true, if wanting to save a video. Ignored when dest isn't empty
* @param saveView true, if sequence should be saved as shown in PeTrack (with trajectories etc.)
* @param dest destination file; if empty, the user chooses via a dialog
*/
void Petrack::saveSequence(bool saveVideo, bool saveView, QString dest) // default saveView= false, dest=""
{
static QString lastDir;
if(lastDir.isEmpty() && !mSeqFileName.isEmpty())
dest = QFileDialog::getSaveFileName(
this,
tr("Select video file"),
lastDir,
tr("Video (*.avi);;All files (*.*)")); //? *.mpg *.mpeg
dest = QFileDialog::getExistingDirectory(
this,
tr("Select directory to save view sequence"),
lastDir,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
dest = QFileDialog::getExistingDirectory(
this,
tr("Select directory to save image sequence"),
lastDir,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
}
}
else // uebergabe von saveVideo spielt keine roll mehr, sondern wird hier analysiert anhand von Dateiendung
{
// autoSave = true; // command line option
if(dest.right(4) == ".avi")
int rest = mAnimation->getNumFrames() - 1;
int numLength = 1;
int memPos = mPlayerWidget->getPos();
QString fileName = "";
#ifdef AVI
AviFile aviFile;
#else
AviFileWriter aviFile;
#endif
bool formatIsSaveAble = false;
bool saveRet;
QPainter *painter = nullptr;
int progEnd = mAnimation->getSourceOutFrameNum() -
mPlayerWidget->getPos(); // nur wenn nicht an anfang gesprungen wird:-mPlayerWidget->getPos()
bool writeFrameRet = false;
bool convert8To24bit = false;
int mult;
if(mCropZoomViewAct->isChecked())
viewImage =
new QImage(mView->viewport()->width(), mView->viewport()->height(), QImage::Format_RGB32);
viewImage = new QImage((int) mScene->width(), (int) mScene->height(), QImage::Format_RGB32);
ok = aviFile.open(
dest.toStdString().c_str(),
viewImage->width(),
viewImage->height(),
viewImage->depth(),
mAnimation->getFPS());
ok = aviFile.open(
dest.toStdString().c_str(), mImg.cols, mImg.rows, mult * 8 * mImg.channels(), mAnimation->getFPS());
debout << "Error: opening AVI file: " << dest.toStdString().c_str() << std::endl;
if(mCropZoomViewAct->isChecked())
viewImage =
new QImage(mView->viewport()->width(), mView->viewport()->height(), QImage::Format_RGB32);
viewImage = new QImage((int) mScene->width(), (int) mScene->height(), QImage::Format_RGB32);
painter = new QPainter();
}
// test, if fileformat is supported
fileName = (dest + "/" + mAnimation->getFileBase() + "%1.png")
.arg(mPlayerWidget->getPos(), numLength, 10, QChar('0'));
if(mCropZoomViewAct->isChecked())
if(viewImage->save(fileName)) //, const char * format = 0 (format wird aus dateinamen geholt), int
// quality = -1 default normal (0..100)
{
formatIsSaveAble = true;
mPlayerWidget->frameForward();
}
}
else if(mImage->save(fileName)) //, const char * format = 0 (format wird aus dateinamen geholt), int quality
//= -1 default normal (0..100)
{
formatIsSaveAble = true;
mPlayerWidget->frameForward();
}
}
else if((mImgFiltered.channels() == 1) /*&& convert8To24bit*/)
size.height = mImgFiltered.rows;
iplImgFilteredBGR.create(size, CV_8UC3);
}
QProgressDialog progress("", "Abort save", 0, progEnd, this);
progress.setWindowModality(Qt::WindowModal); // blocks main window
progress.setValue(
mPlayerWidget->getPos() - memPos); // -mempos nur, wenn nicht an den anfang gesprungen wird
if(mCropZoomViewAct->isChecked())
if((mImgFiltered.channels() == 1) /* && convert8To24bit*/)
cv::cvtColor(mImg, iplImgFilteredBGR, cv::COLOR_GRAY2BGR);
writeFrameRet = aviFile.appendFrame(
(const unsigned char *) viewImage->bits(),
true); // 2. param besagt, ob vertikal gespiegel werden soll
writeFrameRet = aviFile.appendFrame(
(const unsigned char *) iplImgFilteredBGR.data,
true); // 2. param besagt, ob vertikal gespiegel werden soll
if(saveView)
{
writeFrameRet = aviFile.appendFrame(
(const unsigned char *) viewImage->bits(),
true); // 2. param besagt, ob vertikal gespiegel werden soll
}
else
{
writeFrameRet = aviFile.appendFrame(
(const unsigned char *) mImg.data,
true); // 2. param besagt, ob vertikal gespiegel werden soll
PCritical(
this,
tr("PeTrack"),
tr("Cannot save %1 maybe because of wrong file extension or unsupported codec.").arg(dest));
break;
}
}
else
{
// single frame sequence
if(mCropZoomViewAct->isChecked())
fileName = (dest + "/" + mAnimation->getFileBase() + "%1.png")
.arg(mPlayerWidget->getPos(), numLength, 10, QChar('0'));
if(saveView)
{
fileName = dest + "/" + mAnimation->getCurrentFileName();
}
else
{
fileName = dest + "/" + QFileInfo(mAnimation->getCurrentFileName()).completeBaseName() + ".png";
saveRet = mImage->save(fileName, "PNG"); //, int quality = -1 default normal (0..100)
PCritical(this, tr("PeTrack"), tr("Cannot save %1.").arg(fileName));
} while(mPlayerWidget->frameForward());
{
delete viewImage;
delete painter;
}
// bei abbruch koennen es auch mPlayerWidget->getPos() frames sein, die bisher geschrieben wurden
//-memPos nur, wenn nicht an den anfang gesprungen wird
debout << "wrote " << mPlayerWidget->getPos() + 1 - memPos << " of " << mAnimation->getNumFrames() << " frames."
<< std::endl;
{
aviFile.close();
}
mPlayerWidget->skipToFrame(memPos);
lastDir = dest;
}
}
/**
* @brief Saves the current View, including visualizations, in a file (.g. pdf)
*
* @param dest name of the saved file; if empty, a dialogue for the user opens
*/
void Petrack::saveView(QString dest) // default = ""
{
static QString lastFile;
if(mImage)
{
// if no destination file or folder is given
if(lastFile.isEmpty() && !mSeqFileName.isEmpty())
// alle unetrstuetzen fileformate erhaelt man mit
// QImageReader::supportedImageFormats() and QImageWriter::supportedImageFormats()
// gif muss nicht dabei sein, dazu muss qt mit -qt-gif uebersetzt worden sein
dest = QFileDialog::getSaveFileName(
this,
tr("Select image file"),
lastFile,
tr("PDF (*.pdf);;Postscript (*.ps *.eps);;Windows bitmaps (*.bmp);;JPEG (*.jpeg *.jpg);;Portable "
"network graphics (*.png);;Portable image format (*.pbm *.pgm *.ppm);;X11 Bitmap or Pixmap (*.xbm "
"*.xpm);;Pixel Images (*.bmp *.jpeg *.jpg *.png *.pbm *.pgm *.ppm *.xbm *.xpm);;All supported types "
"(*pdf *ps *.eps *.bmp *.jpeg *.jpg *.png *.pbm *.pgm *.ppm *.xbm *.xpm);;All files (*.*)"));
if(dest.right(4) == ".pdf" || dest.right(3) == ".ps" || dest.right(4) == ".eps")
QPdfWriter pdfWriter(dest);
pdfWriter.setPageMargins({0, 0, 0, 0});
QPageSize pageSize{mImage->size()};
pdfWriter.setPageSize(pageSize);
QPainter painter(&pdfWriter);
if(mCropZoomViewAct->isChecked())
}
else
{
// schwarzer rand links und unten?!
QImage *img;
if(mCropZoomViewAct->isChecked())
img = new QImage(mView->viewport()->width(), mView->viewport()->height(), QImage::Format_RGB32);
img = new QImage((int) mScene->width(), (int) mScene->height(), QImage::Format_RGB32);
if(mCropZoomViewAct->isChecked())
PCritical(
this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension.").arg(dest));
delete img;
}
lastFile = dest;
}
}
}
void Petrack::saveImage(QString dest) // default = ""
{
static QString lastFile;
if(mImage)
{
// if no destination file or folder is given
if(lastFile.isEmpty() && !mSeqFileName.isEmpty())
// alle unetrstuetzen fileformate erhaelt man mit
// QImageReader::supportedImageFormats() and QImageWriter::supportedImageFormats()
// gif muss nict dabei sein, dazu muss qt mit -qt-gif uebesetz worden sein
dest = QFileDialog::getSaveFileName(
this,
tr("Select image file"),
lastFile,
tr("PDF (*.pdf);;Postscript (*.ps *.eps);;Windows bitmaps (*.bmp);;JPEG (*.jpeg *.jpg);;Portable "
"network graphics (*.png);;Portable image format (*.pbm *.pgm *.ppm);;X11 Bitmap or Pixmap (*.xbm "
"*.xpm);;Pixel Images (*.bmp *.jpeg *.jpg *.png *.pbm *.pgm *.ppm *.xbm *.xpm);;All supported types "
"(*pdf *ps *.eps *.bmp *.jpeg *.jpg *.png *.pbm *.pgm *.ppm *.xbm *.xpm);;All files (*.*)"));
if(dest.right(4) == ".pdf" || dest.right(3) == ".ps" || dest.right(4) == ".eps")
QPdfWriter pdfWriter(dest);
pdfWriter.setPageMargins({0, 0, 0, 0});
QPageSize pageSize{mImage->size()};
pdfWriter.setPageSize(pageSize);
QPainter painter(&pdfWriter);
QRect rect = painter.viewport();
QSize size = mImage->size();
size.scale(rect.size(), Qt::KeepAspectRatio);
painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
painter.setWindow(mImage->rect());
painter.drawImage(0, 0, *mImage);
}
else
{
if(!mImage->save(dest)) //, "PNG"
PCritical(
this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension.").arg(dest));
}
lastFile = dest;
}
}
}
void Petrack::print()
{
if(mImage)
{
// HighResolution font zu gross! und laengere laufzeit und eher overflow
// aber so pixelig und keine schoenen linien
QPrinter printer(QPrinter::ScreenResolution); // ScreenResolution, HighResolution// liefert zu hause:
// QWin32PrintEngine::initialize: GetPrinter failed ()
printer.setPageSize(QPageSize{QPageSize::PageSizeId::A4});
QPainter painter(&printer);
mView->render(&painter);
}
}
else
PCritical(this, tr("PeTrack"), tr("Nothing to print!"));
}
void Petrack::resetSettings()
{
mAnimation->reset();
openXml(mDefaultSettings, false);
auto about = new AboutDialog(
this,
mPetrackVersion,
mGitCommitID,
mGitCommitDate,
mGitCommitBranch,
mCompilerID,
mCompilerVersion,
mCompileDate,
mAuthors);
about->show();
PMessageBox *mb = new PMessageBox{this, tr("Command line options"), commandLineOptionsString, QIcon()};
mb->setModal(false);
mb->show();
const QString out = tr(
"<p>Beside the space bar all bindings only affect inside the image.</p>"
"<dl><dt><kbd>Space bar</kbd></dt><dd>toggles between pause and last play direction</dd>"
"<dt><kbd>Mouse scroll wheel</kbd></dt><dd>zooms in and out to or from the pixel of the image at the position "
"of the mouse pointer</dd>"
"<dt><kbd>Shift + mouse scroll wheel</kbd></dt><dd>plays forwards or backwards frame by frame</dd>"
"<dt><kbd>Holding left mouse button</kbd></dt><dd>moves image</dd>"
"<dt><kbd>Arrows up/down</kbd></dt><dd>zoom in/out</dd>"
"<dt><kbd>Arrows left/right</kbd></dt><dd>frame back/forward</dd>"
"<dt><kbd>Double-click left mouse button</kbd></dt><dd>opens video or image sequence</dd>"
"<dt><kbd>Ctrl + double-click left mouse button</kbd></dt><dd>inserts new or moves near trackpoint</dd>"
"<dt><kbd>Ctrl + Shift + double-click left mouse button</kbd></dt><dd>splits near trackpoint before actual "
"frame</dd>"
"<dt><kbd>Ctrl + double-click right mouse button</kbd></dt><dd>deletes a trajectory of a near trackpoint</dd>"
"<dt><kbd>Shift + double-click right mouse button</kbd></dt><dd>deletes the past part of a trajectory of a "
"near trackpoint</dd>"
"<dt><kbd>Alt + double-click right mouse button</kbd></dt><dd>deletes the future part of a trajectory of a "
"near trackpoint</dd>"
"<dt><kbd>Ctrl + double-click middle mouse button</kbd></dt><dd>deletes all trajectories</dd>"
"<dt><kbd>Shift + double-click middle mouse button</kbd></dt><dd>deletes the past part of all trajectories</dd>"
"<dt><kbd>Alt + double-click middle mouse button</kbd></dt><dd>deletes the future part of all trajectories</dd>"
"<dt><kbd>Shift + t</kbd></dt><dd>toggles tracking online calculation</dd>"
"<dt><kbd>Shift + double-click left mouse button</kbd></dt><dd>inserts new or moves near trackpoint and "
"enables showing only the modified trajectory</dd></dl>"
"<p>Further key bindings you will find next to the entries of the menus.</p>");
PMessageBox *mb = new PMessageBox(this, tr("Key Bindings"), out, QIcon());
mb->setModal(false);
mb->show();
}
void Petrack::onlineHelp()
{
static QUrl url("https://jugit.fz-juelich.de/ped-dyn-emp/petrack/-/wikis/home");
if(!(QDesktopServices::openUrl(url)))
PCritical(this, tr("PeTrack"), tr("Cannot open external browser<br>with url ") + url.toString() + "!");
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
}
void Petrack::antialias()
{
mView->setRenderHint(QPainter::Antialiasing, mAntialiasAct->isChecked());
}
void Petrack::opengl()
{
mView->setViewport(mOpenGLAct->isChecked() ? new QGLWidget(QGLFormat(QGL::SampleBuffers)) : new QWidget);
// alten freigeben wegen new????
}
void Petrack::reset()
{
mViewWidget->resetView();
}
void Petrack::fitInView()
{
mViewWidget->fitInView();
}
void Petrack::fitInROI()
{
mViewWidget->fitInROI(getRecoRoiItem()->rect());
// what about trackingRoi???
}
void Petrack::setGlobalFont()
{
this->setFont(font); // font is set to the font the user selected
// the user canceled the dialog; font is set to the initial
// value, in this case Times, 12.
}
}
void Petrack::showHideControlWidget()
{
// show | hide Control
mViewWidget->hideControls(mHideControlsAct->isChecked());
}
void Petrack::setCamera()
{
#ifndef STEREO_DISABLED
if(mCameraLeftViewAct->isChecked())
if((mAnimation->getCamera()) != cameraLeft)
mAnimation->setCamera(cameraLeft); // war: hier wird direkt bei Umstellung neu gelesen
else
return;
}
else if(mCameraRightViewAct->isChecked())
if((mAnimation->getCamera()) != cameraRight)
mAnimation->setCamera(cameraRight); // war: hier wird direkt bei Umstellung neu gelesen
else
return;
}
else // kann eigentlich nicht vorkommen
{
mAnimation->setCamera(cameraUnset);
return;
}
updateImage(mAnimation->getFrameAtIndex(
mAnimation->getCurrentFrameNum())); // wird nur aufgerufen, wenn left / right sich geaendert hat
// mPlayerWidget->updateImage();
// mPlayerWidget->skipToFrame(mPlayerWidget->getPos()); // machtpasue!!
// updateImage(true); // nur dies aufrufen, wenn nicht links rechts gleichzeitig gehalten wird
/**
* @brief Helper function to create Actions for the menu bar
* @see Petrack::createMenus()
*/
void Petrack::createActions()
{
mOpenSeqAct = new QAction(tr("&Open Sequence"), this);
mOpenSeqAct->setShortcut(tr("Ctrl+Shift+O"));
connect(mOpenSeqAct, SIGNAL(triggered()), this, SLOT(openSequence()));
mOpenCameraAct = new QAction(tr("Open Camera Stream"), this);
// mOpenCameraAct->setShortcut(tr("Ctrl+C")); // because of some reason it is sometimes fired with
// Ctrl+LeftMouseButton ==> so disabled (it's also not really needed)
connect(mOpenCameraAct, SIGNAL(triggered()), this, SLOT(openCameraLiveStream()));
mOpenMoCapAct = new QAction(tr("Manage MoCap Files"), this);
connect(mOpenMoCapAct, &QAction::triggered, this, &Petrack::openMoCapFile);
// mSaveSeqVidAct->setShortcut(tr("Ctrl+E"));
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
mSaveSeqVidAct->setEnabled(false);
connect(mSaveSeqVidAct, SIGNAL(triggered()), this, SLOT(saveVideo()));
mSaveSeqVidViewAct = new QAction(tr("Save Video View"), this);
mSaveSeqVidViewAct->setShortcut(tr("Ctrl+E"));
mSaveSeqVidViewAct->setEnabled(false);
connect(mSaveSeqVidViewAct, SIGNAL(triggered()), this, SLOT(saveVideoView()));
mSaveSeqImgAct = new QAction(tr("Save Image S&equence"), this);
mSaveSeqImgAct->setShortcut(tr("Ctrl+F"));
mSaveSeqImgAct->setEnabled(false);
connect(mSaveSeqImgAct, SIGNAL(triggered()), this, SLOT(saveImageSequence()));
mSaveSeqViewAct = new QAction(tr("Save View S&equence"), this);
// mSaveSeqViewAct->setShortcut(tr("Ctrl+F"));
mSaveSeqViewAct->setEnabled(false);
connect(mSaveSeqViewAct, SIGNAL(triggered()), this, SLOT(saveViewSequence()));
mOpenPrAct = new QAction(tr("&Open Project"), this);
mOpenPrAct->setShortcut(tr("Ctrl+O"));
connect(mOpenPrAct, SIGNAL(triggered()), this, SLOT(openProject()));
mSavePrAct = new QAction(tr("&Save Project As"), this);
mSavePrAct->setShortcut(tr("Ctrl+Shift+S"));
connect(mSavePrAct, &QAction::triggered, this, &Petrack::saveProjectAs);
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
mSaveAct = new QAction(tr("&Save Project"), this);
mSaveAct->setShortcut(tr("Ctrl+S"));
connect(mSaveAct, SIGNAL(triggered()), this, SLOT(saveSameProject()));
mSaveImageAct = new QAction(tr("&Save Image"), this);
mSaveImageAct->setShortcut(tr("Ctrl+I"));
mSaveImageAct->setEnabled(false);
connect(mSaveImageAct, SIGNAL(triggered()), this, SLOT(saveImage()));
mSaveViewAct = new QAction(tr("&Save View"), this);
mSaveViewAct->setShortcut(tr("Ctrl+V"));
mSaveViewAct->setEnabled(false);
connect(mSaveViewAct, SIGNAL(triggered()), this, SLOT(saveView()));
mPrintAct = new QAction(tr("&Print"), this);
mPrintAct->setShortcut(tr("Ctrl+P"));
mPrintAct->setEnabled(false);
connect(mPrintAct, SIGNAL(triggered()), this, SLOT(print()));
mResetSettingsAct = new QAction(tr("&Reset Settings"), this);
// mResetSettingsAct->setShortcut(tr("Ctrl+R"));
mResetSettingsAct->setEnabled(false); // da es noch nicht fehlerfrei funktioniert
connect(mResetSettingsAct, SIGNAL(triggered()), this, SLOT(resetSettings()));
mExitAct = new QAction(tr("E&xit"), this);
mExitAct->setShortcut(tr("Ctrl+Q"));
connect(mExitAct, SIGNAL(triggered()), this, SLOT(close()));
mAntialiasAct = new QAction(tr("&Antialias"), this);
mAntialiasAct->setShortcut(tr("Ctrl+A"));
mAntialiasAct->setCheckable(true);
connect(mAntialiasAct, SIGNAL(triggered()), this, SLOT(antialias()));
mFontAct = new QAction(tr("&Font"), this);
connect(mFontAct, SIGNAL(triggered()), this, SLOT(setGlobalFont()));
mHideControlsAct = new QAction(tr("&Hide controls"), this);
mHideControlsAct->setShortcut(tr("Ctrl+H"));
mHideControlsAct->setCheckable(true);
connect(mHideControlsAct, SIGNAL(triggered()), this, SLOT(showHideControlWidget()));
connect(mHideControlsAct, SIGNAL(changed()), this, SLOT(showHideControlWidget()));
mCropZoomViewAct = new QAction(tr("&Transform while saving"), this); // Crop and zoom while saving
mCropZoomViewAct->setCheckable(true);
mOpenGLAct = new QAction(tr("Open&GL"), this);
mOpenGLAct->setShortcut(tr("Ctrl+G"));
mOpenGLAct->setCheckable(true);
connect(mOpenGLAct, SIGNAL(triggered()), this, SLOT(opengl()));
mResetAct = new QAction(tr("&Reset"), this);
mResetAct->setShortcut(tr("Ctrl+R"));
connect(mResetAct, SIGNAL(triggered()), this, SLOT(reset()));
mFitViewAct =
new QAction(tr("Fit in window"), this); // Resize to window; fit in view; show all; in fenster einpassen
mFitViewAct->setShortcut(tr("Ctrl+0"));
connect(mFitViewAct, SIGNAL(triggered()), this, SLOT(fitInView()));
mFitROIAct = new QAction(tr("Fit in region of interest"), this); // Resize ROI to window; fit in view;
mFitROIAct->setShortcut(tr("Ctrl+1"));
connect(mFitROIAct, SIGNAL(triggered()), this, SLOT(fitInROI()));
mCameraGroupView = new QActionGroup(this);
// mCameraGroupView->addAction(mCameraLeftViewAct);
// mCameraGroupView->addAction(mCameraRightViewAct);
mCameraLeftViewAct = new QAction(tr("&Left"), mCameraGroupView);
mCameraLeftViewAct->setShortcut(tr("Ctrl++Shift+L"));
mCameraLeftViewAct->setCheckable(true);
connect(mCameraLeftViewAct, SIGNAL(triggered()), this, SLOT(setCamera()));
mCameraRightViewAct = new QAction(tr("&Right"), mCameraGroupView);
mCameraRightViewAct->setShortcut(tr("Ctrl++Shift+R"));
mCameraRightViewAct->setCheckable(true);
connect(mCameraRightViewAct, SIGNAL(triggered()), this, SLOT(setCamera()));
mCameraRightViewAct->setChecked(true); // right wird als default genommen, da reference image in triclops auch right
// ist // erste trj wurden mit left gerechnet
mLimitPlaybackSpeed = new QAction(tr("&Limit playback speed"));
// Not checkable like Fix since this is also controlled through clicking on FPS and syncing currently would be
// bothersome
connect(
mLimitPlaybackSpeed,
&QAction::triggered,
mPlayerWidget,
[&]() { mPlayerWidget->setPlayerSpeedLimited(!mPlayerWidget->getPlayerSpeedLimited()); });
mFixPlaybackSpeed = new QAction(tr("&Fix playback speed"));
mFixPlaybackSpeed->setCheckable(true);
connect(mFixPlaybackSpeed, &QAction::toggled, mPlayerWidget, &Player::setPlayerSpeedFixed);
mSetToRealtime = new QAction(tr("&Realtime"));
connect(
mSetToRealtime, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(1.0); });
connect(mSetTo2p00, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(2.0); });
connect(mSetTo1p75, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(1.75); });
connect(mSetTo1p50, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(1.5); });
connect(mSetTo1p25, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(1.25); });
connect(mSetTo0p75, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(0.75); });
connect(mSetTo0p50, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(0.5); });
connect(mSetTo0p25, &QAction::triggered, mPlayerWidget, [&]() { mPlayerWidget->setSpeedRelativeToRealtime(0.25); });
mPlayerLooping = new QAction(tr("&Loop"));
mPlayerLooping->setCheckable(true);
connect(mPlayerLooping, &QAction::triggered, mPlayerWidget, &Player::setLooping);
// -------------------------------------------------------------------------------------------------------
mDelPastAct = new QAction(tr("&Past part of all trj."), this);
connect(
mDelPastAct,
&QAction::triggered,
this,
[this]() { this->deleteTrackPointAll(PersonStorage::Direction::Previous); });
mDelFutureAct = new QAction(tr("&Future part of all trj."), this);
connect(
mDelFutureAct,
&QAction::triggered,
this,
[this]() { this->deleteTrackPointAll(PersonStorage::Direction::Following); });
mDelAllRoiAct = new QAction(tr("&Trj. moving through ROI"), this);
connect(mDelAllRoiAct, &QAction::triggered, this, &Petrack::deleteTrackPointROI);
mDelPartRoiAct = new QAction(tr("Part of Trj. inside &ROI"), this);
connect(mDelPartRoiAct, &QAction::triggered, this, &Petrack::deleteTrackPointInsideROI);
// -------------------------------------------------------------------------------------------------------
mCommandAct = new QAction(tr("&Command line options"), this);
connect(mCommandAct, SIGNAL(triggered()), this, SLOT(commandLineOptions()));
mKeyAct = new QAction(tr("&Key bindings"), this);
connect(mKeyAct, SIGNAL(triggered()), this, SLOT(keyBindings()));
mAboutAct = new QAction(tr("&About"), this);
connect(mAboutAct, SIGNAL(triggered()), this, SLOT(about()));
mOnlineHelpAct = new QAction(tr("Online &Help"), this);
mOnlineHelpAct->setShortcut(tr("Ctrl+H"));
connect(mOnlineHelpAct, SIGNAL(triggered()), this, SLOT(onlineHelp()));
}
/**
* @brief Helper function building menues out of QActions
* @see Petrack::createActions()
*/
void Petrack::createMenus()
{
mFileMenu = new QMenu(tr("&File"), this);
mFileMenu->addAction(mOpenPrAct);
mFileMenu->addAction(mSaveAct);
mFileMenu->addAction(mSavePrAct);
mFileMenu->addSeparator();
mFileMenu->addAction(mOpenSeqAct);
mFileMenu->addAction(mOpenCameraAct);
mFileMenu->addAction(mSaveSeqVidAct);
mFileMenu->addAction(mSaveSeqVidViewAct);
mFileMenu->addAction(mSaveImageAct);
mFileMenu->addAction(mSaveSeqImgAct);
mFileMenu->addAction(mSaveViewAct);
mFileMenu->addAction(mSaveSeqViewAct);
mFileMenu->addAction(mPrintAct);
mFileMenu->addSeparator();
mFileMenu->addAction(mResetSettingsAct);
mFileMenu->addSeparator();
mFileMenu->addAction(mExitAct);
mViewMenu = new QMenu(tr("&View"), this);
mViewMenu->addAction(mAntialiasAct);
mViewMenu->addAction(mOpenGLAct);
mViewMenu->addAction(mCropZoomViewAct);
mCameraMenu = mViewMenu->addMenu(tr("&Camera"));
mCameraMenu->addAction(mCameraLeftViewAct);
mCameraMenu->addAction(mCameraRightViewAct);
mViewMenu->addAction(mFixPlaybackSpeed);
mViewMenu->addAction(mLimitPlaybackSpeed);
mPlaybackSpeedMenu = mViewMenu->addMenu(tr("&Playback speed"));
mPlaybackSpeedMenu->addAction(mSetToRealtime);
mPlaybackSpeedMenu->addAction(mSetTo2p00);
mPlaybackSpeedMenu->addAction(mSetTo1p75);
mPlaybackSpeedMenu->addAction(mSetTo1p50);
mPlaybackSpeedMenu->addAction(mSetTo1p25);
mPlaybackSpeedMenu->addAction(mSetTo0p75);
mPlaybackSpeedMenu->addAction(mSetTo0p50);
mPlaybackSpeedMenu->addAction(mSetTo0p25);
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
mViewMenu->addSeparator();
mViewMenu->addAction(mFitViewAct);
mViewMenu->addAction(mFitROIAct);
mViewMenu->addAction(mResetAct);
mViewMenu->addSeparator();
mViewMenu->addAction(mFontAct);
mViewMenu->addSeparator();
mViewMenu->addAction(mHideControlsAct);
mDeleteMenu = new QMenu(tr("&Delete"), this);
mDeleteMenu->addAction(mDelPastAct);
mDeleteMenu->addAction(mDelFutureAct);
mDeleteMenu->addAction(mDelAllRoiAct);
mDeleteMenu->addAction(mDelPartRoiAct);
mHelpMenu = new QMenu(tr("&Help"), this);
mHelpMenu->addAction(mCommandAct);
mHelpMenu->addAction(mKeyAct);
mHelpMenu->addAction(mAboutAct);
mHelpMenu->addAction(mOnlineHelpAct);
menuBar()->addMenu(mFileMenu);
menuBar()->addMenu(mViewMenu);
menuBar()->addMenu(mDeleteMenu);
menuBar()->addMenu(mHelpMenu);
mCameraMenu->setEnabled(false);
}
/**
* @brief Helper function to create status bar at the bottom of the window
*/
QFont f("Courier", 12, QFont::Bold); // Times Helvetica, Normal
statusBar()->setMaximumHeight(28);
statusBar()->showMessage(tr("Ready"));
statusBar()->addPermanentWidget(mStatusLabelStereo = new QLabel(" "));
statusBar()->addPermanentWidget(mStatusLabelTime = new QLabel(" "));
statusBar()->addPermanentWidget(mStatusLabelFPS = new QLabel(" "));
statusBar()->addPermanentWidget(mStatusPosRealHeight = new QDoubleSpinBox());
connect(mStatusPosRealHeight, SIGNAL(valueChanged(double)), this, SLOT(setStatusPosReal()));
statusBar()->addPermanentWidget(mStatusLabelPosReal = new QLabel(" "));
statusBar()->addPermanentWidget(mStatusLabelPos = new QLabel(" "));
statusBar()->addPermanentWidget(mStatusLabelColor = new QLabel(" "));
mStatusLabelStereo->setFont(f);
mStatusLabelStereo->setMinimumWidth(200);
mStatusLabelTime->setFont(f);
mStatusLabelTime->setMinimumWidth(200);
mStatusLabelFPS->setFont(f);
mStatusLabelFPS->setMinimumWidth(80);
mStatusLabelFPS->setAutoFillBackground(true);
mStatusLabelFPS->setToolTip("Click to adapt play rate to fps rate");
mStatusPosRealHeight->setRange(-999.9, 9999.9); // in cm
mStatusPosRealHeight->setDecimals(1);
mStatusPosRealHeight->setFont(f);
mStatusLabelPosReal->setFont(f);
mStatusLabelPosReal->setMinimumWidth(340);
mStatusLabelPos->setFont(f);
mStatusLabelPos->setMinimumWidth(100);
mStatusLabelColor->setFont(f);
mStatusLabelColor->setMinimumWidth(90);
mStatusLabelColor->setAutoFillBackground(true);
}
void Petrack::resetUI()
{
/// Reset all UI elements to default settings
/// Noetig damit alle UI Elemente, welche in der neu geladenen Projekt-Datei z.B. noch nicht vorhanden sind, auf
/// sinnvolle Werte gesetzt werden. Anderenfalls kommt es evtl. beim nacheinander laden verschiedener Projekte zu
/// einem Programmabsturz
mImage->fill(QColor::fromRgb(255, 255, 255));
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
mImageItem->setImage(mImage);
mLogoItem->show();
}
mStatusPosRealHeight->setValue(180.0);
/// calibration params
/// image filters
mControlWidget->filterBrightContrast->setCheckState(Qt::Unchecked);
mControlWidget->filterBrightParam->setValue(0);
mControlWidget->filterContrastParam->setValue(0);
mControlWidget->filterBorder->setCheckState(Qt::Unchecked);
mControlWidget->filterBorderParamSize->setValue(0);
QColor defaultBorder = Qt::black;
getBorderFilter()->getBorderColR()->setValue(defaultBorder.red());
getBorderFilter()->getBorderColG()->setValue(defaultBorder.green());
getBorderFilter()->getBorderColB()->setValue(defaultBorder.blue());
mControlWidget->filterBg->setCheckState(Qt::Unchecked);
mControlWidget->filterBgDeleteNumber->setValue(3);
mControlWidget->filterBgDeleteTrj->setCheckState(Qt::Checked);
mControlWidget->filterBgShow->setCheckState(Qt::Unchecked);
mControlWidget->filterBgUpdate->setCheckState(Qt::Unchecked);
getBackgroundFilter()->setFilename(nullptr);
getBackgroundFilter()->reset();
mControlWidget->filterSwap->setCheckState(Qt::Unchecked);
mControlWidget->filterSwapH->setCheckState(Qt::Unchecked);
mControlWidget->filterSwapV->setCheckState(Qt::Unchecked);
/// intrinsic params
mControlWidget->apply->setCheckState(Qt::Unchecked);
mControlWidget->fx->setValue(1000);
mControlWidget->fy->setValue(1000);
mControlWidget->cx->setValue(960);
mControlWidget->cx->setMinimum(0);
mControlWidget->cx->setMaximum(mControlWidget->cx->value() * 2);
mControlWidget->cy->setValue(540);
mControlWidget->cx->setMinimum(0);
mControlWidget->cy->setMaximum(mControlWidget->cy->value() * 2);
mControlWidget->r2->setValue(0);
mControlWidget->r4->setValue(0);
mControlWidget->r6->setValue(0);
mControlWidget->tx->setValue(0);
mControlWidget->ty->setValue(0);
mControlWidget->k4->setValue(0);
mControlWidget->k5->setValue(0);
mControlWidget->k6->setValue(0);
mControlWidget->s1->setValue(0);
mControlWidget->s2->setValue(0);
mControlWidget->s3->setValue(0);
mControlWidget->s4->setValue(0);
mControlWidget->taux->setValue(0);
mControlWidget->tauy->setValue(0);
mControlWidget->quadAspectRatio->setCheckState(Qt::Unchecked);
mControlWidget->fixCenter->setCheckState(Qt::Unchecked);
mControlWidget->tangDist->setCheckState(Qt::Checked);
getAutoCalib()->setBoardSizeX(6);
getAutoCalib()->setBoardSizeY(8);
getAutoCalib()->setSquareSize(5.0);
getAutoCalib()->setCalibFiles(QStringList());
/// extrinsic params
mControlWidget->trans1->setValue(0);
mControlWidget->trans2->setValue(0);
mControlWidget->trans3->setValue(-500);
mControlWidget->rot1->setValue(0);
mControlWidget->rot2->setValue(0);
mControlWidget->rot3->setValue(0);
getExtrCalibration()->setExtrCalibFile(nullptr);
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
/// coord system
mControlWidget->coordShow->setCheckState(Qt::Unchecked);
mControlWidget->coordFix->setCheckState(Qt::Unchecked);
mControlWidget->coordTab->setCurrentIndex(0);
// 3D
mControlWidget->coord3DTransX->setValue(0);
mControlWidget->coord3DTransY->setValue(0);
mControlWidget->coord3DTransZ->setValue(0);
mControlWidget->coord3DAxeLen->setValue(200);
mControlWidget->coord3DSwapX->setCheckState(Qt::Unchecked);
mControlWidget->coord3DSwapY->setCheckState(Qt::Unchecked);
mControlWidget->coord3DSwapZ->setCheckState(Qt::Unchecked);
mControlWidget->extCalibPointsShow->setCheckState(Qt::Unchecked);
mControlWidget->extVanishPointsShow->setCheckState(Qt::Unchecked);
// 2D
mControlWidget->coordTransX->setValue(0);
mControlWidget->coordTransY->setValue(0);
mControlWidget->coordRotate->setValue(0);
mControlWidget->coordScale->setValue(100);
mControlWidget->coordAltitude->setValue(535);
mControlWidget->coordUnit->setValue(100);
mControlWidget->coordUseIntrinsic->setCheckState(Qt::Unchecked);
/// alignment grid
mControlWidget->gridShow->setCheckState(Qt::Unchecked);
mControlWidget->gridFix->setCheckState(Qt::Unchecked);
mControlWidget->gridTab->setCurrentIndex(0);
// 3D
mControlWidget->grid3DTransX->setValue(0);
mControlWidget->grid3DTransY->setValue(0);
mControlWidget->grid3DTransZ->setValue(0);
mControlWidget->grid3DResolution->setValue(100);
// 2D
mControlWidget->gridTransX->setValue(0);
mControlWidget->gridTransY->setValue(0);
mControlWidget->gridRotate->setValue(0);
mControlWidget->gridScale->setValue(100);
///
/// recognition params
///
mControlWidget->performRecognition->setCheckState(Qt::Unchecked);
mControlWidget->recoStep->setValue(1);
// region of interest
mControlWidget->roiFix->setCheckState(Qt::Unchecked);
mControlWidget->roiShow->setCheckState(Qt::Unchecked);
getRecoRoiItem()->setRect(0, 0, 0, 0);
// marker, default multicolor marker (until 11/2016 hermes marker)
mControlWidget->recoMethod->setCurrentIndex(
mControlWidget->recoMethod->findData(QVariant::fromValue(reco::RecognitionMethod::MultiColor)));
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
mControlWidget->markerBrightness->setValue(100);
mControlWidget->markerIgnoreWithout->setCheckState(Qt::Checked);
// size and color
mControlWidget->recoShowColor->setCheckState(Qt::Checked);
mControlWidget->recoAutoWB->setCheckState(Qt::Checked);
mControlWidget->recoColorX->setCurrentIndex(0);
mControlWidget->recoColorY->setCurrentIndex(1);
mControlWidget->recoColorZ->setValue(255);
mControlWidget->recoGreyLevel->setValue(50);
mControlWidget->recoSymbolSize->setValue(10);
// map
mControlWidget->recoColorModel->setCurrentIndex(0);
mControlWidget->colorPlot->getMapItem()->delMaps();
mControlWidget->mapNr->setValue(0);
mControlWidget->mapNr->setMinimum(0);
mControlWidget->mapNr->setMaximum(0);
mControlWidget->mapX->setValue(0);
mControlWidget->mapY->setValue(0);
mControlWidget->mapW->setValue(0);
mControlWidget->mapH->setValue(0);
mControlWidget->mapColor->setCheckState(Qt::Checked);
mControlWidget->mapHeight->setValue(180);
mControlWidget->mapDefaultHeight->setValue(180);
///
/// tracking params
///
mControlWidget->trackOnlineCalc->setCheckState(Qt::Checked);
mControlWidget->trackRepeat->setCheckState(Qt::Checked);
mControlWidget->trackRepeatQual->setValue(50);
mControlWidget->trackExtrapolation->setCheckState(Qt::Checked);
mControlWidget->trackMerge->setCheckState(Qt::Unchecked);
mControlWidget->trackOnlySelected->setCheckState(Qt::Checked);
getTrackRoiItem()->setRect(0, 0, 0, 0);
// export options
mControlWidget->trackMissingFrames->setCheckState(Qt::Checked);
mControlWidget->trackRecalcHeight->setCheckState(Qt::Checked);
mControlWidget->trackAlternateHeight->setCheckState(Qt::Unchecked);
mControlWidget->exportElimTp->setCheckState(Qt::Unchecked);
mControlWidget->exportElimTrj->setCheckState(Qt::Unchecked);
mControlWidget->exportSmooth->setCheckState(Qt::Checked);
mControlWidget->exportViewDir->setCheckState(Qt::Unchecked);
mControlWidget->exportAngleOfView->setCheckState(Qt::Unchecked);
mControlWidget->exportUseM->setCheckState(Qt::Unchecked);
mControlWidget->exportComment->setCheckState(Qt::Unchecked);
mControlWidget->exportMarkerID->setCheckState(Qt::Unchecked);
// test options
mControlWidget->testEqual->setCheckState(Qt::Checked);
mControlWidget->testVelocity->setCheckState(Qt::Checked);
mControlWidget->testInside->setCheckState(Qt::Checked);
mControlWidget->testLength->setCheckState(Qt::Checked);
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
// search region
mControlWidget->trackRegionScale->setValue(16);
mControlWidget->trackRegionLevels->setValue(3);
mControlWidget->trackErrorExponent->setValue(0);
mControlWidget->trackShowSearchSize->setCheckState(Qt::Unchecked);
// path params
mControlWidget->trackShow->setCheckState(Qt::Checked);
mControlWidget->trackFix->setCheckState(Qt::Unchecked);
mControlWidget->trackShowOnlyVisible->setCheckState(Qt::Unchecked);
mControlWidget->trackShowOnly->setCheckState(Qt::Unchecked);
mControlWidget->trackShowOnlyNr->setValue(1);
mControlWidget->trackShowOnlyList->setCheckState(Qt::Unchecked);
mControlWidget->trackShowOnlyNrList->setEnabled(false);
mControlWidget->trackShowOnlyListButton->setEnabled(false);
mControlWidget->trackShowCurrentPoint->setCheckState(Qt::Checked);
mControlWidget->trackShowPoints->setCheckState(Qt::Unchecked);
mControlWidget->trackShowPath->setCheckState(Qt::Checked);
mControlWidget->trackShowColColor->setCheckState(Qt::Checked);
mControlWidget->trackShowColorMarker->setCheckState(Qt::Checked);
mControlWidget->trackShowNumber->setCheckState(Qt::Checked);
mControlWidget->trackShowGroundPosition->setCheckState(Qt::Unchecked);
mControlWidget->trackShowGroundPath->setCheckState(Qt::Unchecked);
mControlWidget->setTrackPathColor(Qt::red);
mControlWidget->setTrackGroundPathColor(Qt::green);
mControlWidget->trackHeadSized->setCheckState(Qt::Checked);
mControlWidget->trackCurrentPointSize->setValue(60);
mControlWidget->trackPointSize->setValue(7);
mControlWidget->trackPathWidth->setValue(2);
mControlWidget->trackColColorSize->setValue(11);
mControlWidget->trackColorMarkerSize->setValue(14);
mControlWidget->trackNumberSize->setValue(14);
mControlWidget->trackGroundPositionSize->setValue(1);
mControlWidget->trackGroundPathSize->setValue(1);
mControlWidget->trackShowPointsColored->setCheckState(Qt::Checked);
mControlWidget->trackNumberBold->setCheckState(Qt::Checked);
mControlWidget->trackShowBefore->setValue(15);
mControlWidget->trackShowAfter->setValue(15);
/// analysis params
mControlWidget->anaMissingFrames->setCheckState(Qt::Checked);
mControlWidget->anaMarkAct->setCheckState(Qt::Unchecked);
mControlWidget->anaStep->setValue(25);
mControlWidget->anaConsiderX->setCheckState(Qt::Unchecked);
mControlWidget->anaConsiderY->setCheckState(Qt::Checked);
mControlWidget->anaConsiderAbs->setCheckState(Qt::Unchecked);
mControlWidget->anaConsiderRev->setCheckState(Qt::Unchecked);
mControlWidget->showVoronoiCells->setCheckState(Qt::Unchecked);
}
void Petrack::setStatusStereo(float x, float y, float z)
{
mStatusLabelStereo->setText(QString("x= novalue y= novalue z= novalue "));
mStatusLabelStereo->setText(
QString("x=%1cm y=%2cm z=%3cm ").arg(x, 6, 'f', 1).arg(y, 6, 'f', 1).arg(z, 6, 'f', 1));
{
mStatusLabelFPS->setText(QString("%1fps ").arg(mShowFPS, 5, 'f', 1));
QPalette pal = mStatusLabelFPS->palette(); // static moeglich?
double diff = mShowFPS - mAnimation->getFPS();
int opacity = mPlayerWidget->getPlayerSpeedLimited() ? 128 : 20;
if(diff < -6) // very slow ==> red
color.setRgb(200, 0, 0, opacity);
else if(diff < -2) // better ==> yellow
color.setRgb(200, 200, 0, opacity);
else if(diff > -2) // nearly ok ==> green
color.setRgb(0, 200, 0, opacity);
pal.setColor(QPalette::Window, color);
mStatusLabelFPS->setPalette(pal);
}
}
void Petrack::setShowFPS(double fps)
{
if((fps == 0.) || (mShowFPS == 0))
mShowFPS = mShowFPS * .9 + fps * .1; // glaetten durch Hinzunahme des alten Wertes
/**
* @brief Updates the FPS shown to the User
*
* This method calculates the FPS by remembering how long
* it has been since it was called last time. If skipped is
* true, it doesn't directly update the FPS since 2
* skipped frames have essentially a time delay of 0 between
* them, which would make calculations wonky.
*
* @param skipped True, if this is a skipped frame; default false
*/
void Petrack::updateShowFPS(bool skipped)
{
static QElapsedTimer lastTime;
lastTime.invalidate();
int numFrames = skippedFrames > 0 ? skippedFrames + 1 : 1;
setShowFPS(numFrames * 1000. / lastTime.elapsed());
}
}
lastTime.start();
}
}
// ohne neue positionsangabe, sinnvoll, wenn berechnungsweise sich in getPosReal geaendert hat
// gebraucht in control.cpp
void Petrack::setStatusPosReal() // pos in cm
{
setStatusPosReal(mImageItem->getPosReal(mMousePosOnImage, getStatusPosRealHeight()));
void Petrack::setStatusPosReal(const QPointF &pos) // pos in cm
{
QChar deg(0xB0);
QString labelText = QString(" cm from ground:%1cm,%2cm,%3")
.arg(pos.x(), 6, 'f', 1)
.arg(pos.y(), 6, 'f', 1)
.arg(
getImageItem()->getAngleToGround(
mMousePosOnImage.x(), mMousePosOnImage.y(), getStatusPosRealHeight()),
5,
'f',
1);
labelText.append(deg);
mStatusLabelPosReal->setText(labelText);
}
}
void Petrack::setStatusPos(const QPoint &pos) // pos in pixel
{
mStatusLabelPos->setText(QString("%1x%2").arg(pos.x(), 4).arg(pos.y(), 4));
}
void Petrack::setStatusColor(const QRgb &col)
{
QString s("#%1%2%3"); // static moeglich?
s = s.arg(qRed(col), 2, 16, QChar('0')).arg(qGreen(col), 2, 16, QChar('0')).arg(qBlue(col), 2, 16, QChar('0'));
if((qRed(col) + qGreen(col) + qBlue(col)) / 3 < 128)
mStatusLabelColor->setText(QString("<font color=\"#ffffff\"> %1</font>").arg(s));
mStatusLabelColor->setText(QString("<font color=\"#000000\"> %1</font>").arg(s));
QPalette pal = mStatusLabelColor->palette(); // static moeglich?
QColor color(qRed(col), qGreen(col), qBlue(col));
pal.setColor(QPalette::Window, color);
mStatusLabelColor->setPalette(pal);
mControlWidget->getColorPlot()->setCursor(color);
mControlWidget->getColorPlot()->replot();
}
void Petrack::setStatusColor()
{
QPointF pos = getMousePosOnImage();
if(pos.x() >= 0 && pos.x() < mImage->width() && pos.y() > 0 && pos.y() < mImage->height())
setStatusColor(mImage->pixel(pos.toPoint()));
}
}
double Petrack::getStatusPosRealHeight()
{
/**
* @brief Reads (and applies) settings form platform-independent persistent storage
*
* The saved size and position of the application window get reconstructed. As well as
* the options about antialiasing and the usage of OpenGL.
* mSeqFileName and mProFileName get set, so the "Open Project" and "Open Sequence"
* dialogues start at correct folder. The old project/sequence is NOT actually loaded.
*/
void Petrack::readSettings()
{
QSettings settings("Forschungszentrum Juelich GmbH", "PeTrack by Maik Boltes, Daniel Salden");
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
QSize size = settings.value("size", QSize(400, 400)).toSize();
mAntialiasAct->setChecked(settings.value("antialias", false).toBool());
mOpenGLAct->setChecked(settings.value("opengl", false).toBool());
mSeqFileName = settings.value("seqFileName", QDir::currentPath()).toString();
setProFileName(settings.value("proFilePath", QDir::currentPath()).toString());
// nicht ganz sauber, da so immer schon zu anfang in calib file list etwas drin steht und somit auto ausgefuehrt
// werden kann wird aber beim ersten openCalib... ueberschrieben
mAutoCalib.addCalibFile(settings.value("calibFile", QDir::currentPath()).toString());
resize(size);
move(pos);
antialias();
opengl();
mSplitter->restoreState(settings.value("controlSplitterSizes").toByteArray());
/**
* @brief Writes persistent setting.
* @see Petrack::readSettings
*/
void Petrack::writeSettings()
{
QSettings settings("Forschungszentrum Juelich GmbH", "PeTrack by Maik Boltes, Daniel Salden");
settings.setValue("pos", pos());
settings.setValue("size", size());
settings.setValue("antialias", mAntialiasAct->isChecked());
settings.setValue("opengl", mOpenGLAct->isChecked());
settings.setValue("seqFileName", mSeqFileName);
settings.setValue("proFilePath", QFileInfo(mProFileName).path()); // nur path, damit bei saveCurrentProject
if(!mAutoCalib.isEmptyCalibFiles()) //! mCalibFiles.isEmpty()
settings.setValue("controlSplitterSizes", mSplitter->saveState());
int ret = PWarning(
this,
tr("PeTrack"),
tr("Do you want to save "
"the current project?\n"
"Be sure to save trajectories, background "
"and 3D calibration point separately!"),
PMessageBox::StandardButton::Yes | PMessageBox::StandardButton::No | PMessageBox::StandardButton::Cancel,
PMessageBox::StandardButton::Yes);
if(ret == PMessageBox::StandardButton::Yes)
else if(ret == PMessageBox::StandardButton::Cancel)
}
void Petrack::closeEvent(QCloseEvent *event)
{
/**
* @brief Sets the mMousePosOnImage member variable and displayed pixel/real coordinates
*
* Gets called from ImageItem::hoverMoveEvent() and enables an easy access
* to the mouse position.
* @param pos Position of mouse cursor in image pixel coordinates
*/
{
mMousePosOnImage = pos;
setStatusPosReal(mImageItem->getPosReal(pos, getStatusPosRealHeight()));
// pixel coordinate
QPoint pos1((int) (pos.x()) + 1, (int) (pos.y()) + 1);
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
void Petrack::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Left:
mPlayerWidget->frameBackward();
break;
case Qt::Key_Right:
mPlayerWidget->frameForward();
break;
case Qt::Key_Down:
mViewWidget->zoomOut(1);
break;
case Qt::Key_Up:
mViewWidget->zoomIn(1);
break;
case Qt::Key_Space:
// space wird von buttons, wenn focus drauf ist als Aktivierung vorher abgegriffen und nicht durchgereicht
mPlayerWidget->togglePlayPause();
break;
case Qt::Key_D:
break;
default:;
}
}
void Petrack::mousePressEvent(QMouseEvent *event)
{
// mouse click in fps status label ?
if(event->pos().x() >= mStatusLabelFPS->pos().x() &&
event->pos().x() <= mStatusLabelFPS->pos().x() + mStatusLabelFPS->width())
mPlayerWidget->togglePlayerSpeedLimited();
const QString &Petrack::getLastTrackerExport() const
{
return mLastTrackerExport;
}
void Petrack::setLastTrackerExport(const QString &newLastTrackerExport)
{
mLastTrackerExport = newLastTrackerExport;
}
/// update control widget, if image size changed (especially because of changing border)
void Petrack::updateControlImage(cv::Mat &img)
{
// auch moeglich hoehe und breite von bild stat border veraenderungen zu checken
static int lastBorderSize = -1;
int diffBorderSize = 0;
int iW = img.cols;
int iH = img.rows;
// wird auch nochmal in ImageWidget gemacht, aber ist hier frueher noetig
double cX = mControlWidget->getCalibCxValue(); // merken, da min/max value verandernkann wenn aus dem rahmen
double cY = mControlWidget->getCalibCyValue();
mControlWidget->setCalibCxMin(0 /*iW/2.-50.*/);
mControlWidget->setCalibCyMin(0 /*iH/2.-50.*/);
if(mControlWidget->fixCenter->checkState() == Qt::Checked)
mControlWidget->setCalibCxValue((iW - 1) / 2.);
mControlWidget->setCalibCyValue((iH - 1) / 2.);
diffBorderSize = getImageBorderSize() - lastBorderSize;
mControlWidget->setCalibCxValue(cX + diffBorderSize);
mControlWidget->setCalibCyValue(cY + diffBorderSize);
void Petrack::importTracker(QString dest) // default = ""
dest = QFileDialog::getOpenFileName(
this,
tr("Select file for importing tracking pathes"),
lastFile,
tr("PeTrack tracker (*.trc *.txt);;All files (*.*)"));
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
// errorstring ist je nach Betriebssystem in einer anderen Sprache!!!!
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString()));
setTrackChanged(true); // flag changes of track parameters
mTracker->reset();
QTextStream in(&file);
TrackPerson tp;
bool ok; // shows if int stands in first line - that was in the first version of trc file
sz = firstLine.toInt(&ok);
if(!ok)
if(firstLine.contains("version 4", Qt::CaseInsensitive))
{
trcVersion = 4;
}
else if(firstLine.contains("version 3", Qt::CaseInsensitive))
else if(firstLine.contains("version 2", Qt::CaseInsensitive))
}
else
debout << "Error: wrong header while reading TRC file." << std::endl;
QMessageBox::critical(
this,
tr("PeTrack"),
tr("Could not import tracker:\nNot supported trc version in file: %1.").arg(dest));
Schrödter, Tobias
committed
return;
if((sz > 0) && (mPersonStorage.nbPersons() != 0))
debout << "Warning: Overlapping trajectories will be joined not until tracking adds new trackpoints."
<< std::endl;
mPersonStorage.addPerson(tp);
tp.clear(); // loeschen, sonst immer weitere pfade angehangen werden
mControlWidget->trackNumberAll->setText(QString("%1").arg(mPersonStorage.nbPersons()));
mControlWidget->trackShowOnlyNr->setMaximum(MAX(mPersonStorage.nbPersons(), 1));
mControlWidget->trackNumberVisible->setText(
QString("%1").arg(mPersonStorage.visible(mAnimation->getCurrentFrameNum())));
debout << "import " << dest << " (" << sz << " person(s), file version " << trcVersion << ")" << std::endl;
mTrcFileName =
dest; // fuer Project-File, dann koennte track path direkt mitgeladen werden, wenn er noch da ist
}
else if(dest.right(4) == ".txt") // 3D Koordinaten als Tracking-Daten importieren Zeilenformat: Personennr,
// Framenr, x, y, z
PWarning(
this,
tr("PeTrack"),
tr("Are you sure you want to import 3D data from TXT-File? You have to make sure that the coordinate "
"system now is exactly at the same position and orientation than at export time!"));
QFile file(dest);
// size of person list
int sz = 0;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
// errorstring ist je nach Betriebssystem in einer anderen Sprache!!!!
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString()));
setTrackChanged(true); // flag changes of track parameters
mTracker->reset();
QTextStream in(&file);
TrackPerson tp;
bool exec_once_flag = false;
double conversionFactorTo_cm = 1.0;
int personNr = -1, frameNr = -1, current_personNr = 1;
float x, y, z;
{
// Falls Datei am Ende letzte Person abspeichern und Lese-Schleife beenden
mPersonStorage.addPerson(tp);
++sz;
tp.clear();
break;
}
line = in.readLine();
// Kommentare ueberlesen
if(line.startsWith("#", Qt::CaseInsensitive))
if((!exec_once_flag) && (!headerline.contains("cm")))
exec_once_flag = true;
PWarning(
this,
tr("PeTrack"),
tr("PeTrack will interpret position data as unit [m]. No header with [cm] found."));
}
QTextStream stream(&line);
// Zeile als Stream einlesen Format: [id frame x y z]
stream >> personNr >> frameNr >> x >> y >> z;
// convert data to cm
x = x * conversionFactorTo_cm;
y = y * conversionFactorTo_cm;
z = z * conversionFactorTo_cm;
// 3-dimensionale Berechnung/Anzeige des Punktes
if(mControlWidget->getCalibCoordDimension() == 0)
p2d = mExtrCalibration.getImagePoint(cv::Point3f(x, y, z));
}
// 2-dimensionale Berechnung/Anzeige des Punktes
else
{
QPointF pos = mImageItem->getPosImage(QPointF(x, y), z);
p2d.x = pos.x();
p2d.y = pos.y();
tPoint = TrackPoint(Vec2F(p2d.x, p2d.y), 100);
tPoint.setSp(
x,
y,
-mControlWidget->getCalibExtrTrans3() -
z); // fuer den Abstand zur Kamera in z-Richtung wie bei einer Stereokamera
mPersonStorage.addPerson(tp);
++sz;
current_personNr++;
tp.clear();
}
// TrackPerson leer ? ==> Neue TrackPerson erstellen
{
tp = TrackPerson(personNr, frameNr, tPoint);
tp.setFirstFrame(frameNr);
tp.setHeight(z);
}
// TrackPoint an TrackPerson anhaengen
else
{
tp.setLastFrame(frameNr);
tp.append(tPoint);
}
}
mControlWidget->trackNumberAll->setText(QString("%1").arg(mPersonStorage.nbPersons()));
mControlWidget->trackShowOnlyNr->setMaximum(MAX(mPersonStorage.nbPersons(), 1));
mControlWidget->trackNumberVisible->setText(
QString("%1").arg(mPersonStorage.visible(mAnimation->getCurrentFrameNum())));
debout << "import " << dest << " (" << sz << " person(s) )" << std::endl;
mTrcFileName =
dest; // fuer Project-File, dann koennte track path direkt mitgeladen werden, wenn er noch da ist
PCritical(this, tr("PeTrack"), tr("Cannot load %1 maybe because of wrong file extension.").arg(dest));
}
lastFile = dest;
}
}
void Petrack::testTracker()
{
static int idx = 0; // index in Fehlerliste, die als letztes angesprungen wurde
mPersonStorage.checkPlausibility(
pers,
frame,
mControlWidget->testEqual->isChecked(),
mControlWidget->testVelocity->isChecked(),
mControlWidget->testInside->isChecked(),
mControlWidget->testLength->isChecked());
if(pers.length() <= idx)
{
mControlWidget->trackShowOnly->setCheckState(Qt::Checked);
mControlWidget->trackShowOnlyNr->setValue(pers[idx]);
++idx;
}
}
int Petrack::calculateRealTracker()
{
bool autoCorrectOnlyExport = (mReco.getRecoMethod() == reco::RecognitionMethod::MultiColor) && // multicolor
mMultiColorMarkerWidget->autoCorrect->isChecked() &&
mMultiColorMarkerWidget->autoCorrectOnlyExport->isChecked();
int anz = mTrackerReal->calculate(
mTracker,
mImageItem,
mControlWidget->getColorPlot(),
getImageBorderSize(),
mControlWidget->anaMissingFrames->checkState(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->trackAlternateHeight->checkState(),
mControlWidget->coordAltitude->value(),
mStereoWidget->stereoUseCalibrationCenter->isChecked(),
mControlWidget->exportElimTp->isChecked(),
mControlWidget->exportElimTrj->isChecked(),
mControlWidget->exportSmooth->isChecked(),
mControlWidget->exportViewDir->isChecked(),
mControlWidget->exportAngleOfView->isChecked(),
mControlWidget->exportMarkerID->isChecked(),
autoCorrectOnlyExport);
void Petrack::exportTracker(QString dest) // default = ""
QFileDialog fileDialog(
this,
tr("Select file for exporting tracking pathes"),
tr("Tracker (*.*);;Petrack tracker (*.trc);;Text (*.txt);;Text for gnuplot(*.dat);;XML Travisto "
"(*.trav);;All supported types (*.txt *.trc *.dat *.trav *.);;All files (*.*)"));
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
fileDialog.setFileMode(QFileDialog::AnyFile);
fileDialog.setDefaultSuffix("");
bool autoCorrectOnlyExport = (mReco.getRecoMethod() == reco::RecognitionMethod::MultiColor) && // multicolor
mMultiColorMarkerWidget->autoCorrect->isChecked() &&
mMultiColorMarkerWidget->autoCorrectOnlyExport->isChecked();
{
#ifdef TIME_MEASUREMENT
double time1 = 0.0, tstart;
if(!file.open() /*!file.open(QIODevice::WriteOnly | QIODevice::Text)*/)
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString()));
QProgressDialog progress("Export TRC-File", nullptr, 0, mPersonStorage.nbPersons() + 1, this->window());
progress.setWindowTitle("Export .trc-File");
progress.setWindowModality(Qt::WindowModal);
progress.setVisible(true);
progress.setValue(0);
progress.setLabelText(QString("Export tracking data ..."));
qApp->processEvents();
debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons()
<< " person(s), file version " << trcVersion << ")..." << std::endl;
out << "version " << trcVersion << Qt::endl;
out << mPersonStorage.nbPersons() << Qt::endl;
const auto &persons = mPersonStorage.getPersons();
for(size_t i = 0; i < persons.size(); ++i)
progress.setLabelText(
QString("Export person %1 of %2 ...").arg(i + 1).arg(mPersonStorage.nbPersons()));
out << persons[i] << Qt::endl;
}
file.flush();
file.close();
#ifdef TIME_MEASUREMENT
time1 += clock() - tstart;
tstart = clock();
#endif
progress.setLabelText(QString("Save file ..."));
qApp->processEvents();
PCritical(
this,
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
progress.setValue(mPersonStorage.nbPersons() + 1);
std::cout << " finished " << std::endl;
cout << " time(copying) = " << time1 << " sec." << endl;
// time1 = 0.0;
// tstart = clock();
#endif
#ifdef TIME_MEASUREMENT
// time1 += clock() - tstart;
// time1 = time1/CLOCKS_PER_SEC;
// cout << " time(checkPlausibility) = " << time1 << " sec." << endl;
#endif
mTrcFileName =
dest; // fuer Project-File, dann koennte track path direkt mitgeladen werden, wenn er noch da ist
else if(dest.right(4) == ".txt")
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString()));
debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons() << " person(s))..."
// recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend
// play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung
// einfliessen zu lassen)
if(mControlWidget->trackRecalcHeight->checkState())
if(mControlWidget->getCalibCoordDimension() == 0) // 3D
; // Nothing to be done because z already the right height
mPersonStorage.recalcHeight(mControlWidget->coordAltitude->value());
cout << " time(recalcHeight) = " << time1 << " sec." << endl;
mTracker,
mImageItem,
mControlWidget->getColorPlot(),
getImageBorderSize(),
mControlWidget->trackMissingFrames->checkState(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->trackAlternateHeight->checkState(),
mControlWidget->coordAltitude->value(),
mStereoWidget->stereoUseCalibrationCenter->isChecked(),
mControlWidget->exportElimTp->isChecked(),
mControlWidget->exportElimTrj->isChecked(),
mControlWidget->exportSmooth->isChecked(),
mControlWidget->exportViewDir->isChecked(),
mControlWidget->exportAngleOfView->isChecked(),
mControlWidget->exportMarkerID->isChecked(),
autoCorrectOnlyExport);
cout << " time(calculate) = " << time1 << " sec." << endl;
tstart = clock();
#endif
QTextStream out(&file);
out << "# PeTrack project: " << QFileInfo(getProFileName()).fileName() << Qt::endl;
out << "# raw trajectory file: " << QFileInfo(getTrackFileName()).fileName() << Qt::endl;
out << "# framerate: " << mAnimation->getFPS() << " fps" << Qt::endl;
if(mControlWidget->exportComment->isChecked())
out << "# personal information:" << Qt::endl;
out << "# ID| Comment" << Qt::endl;
std::cout << std::endl << "Printing comment table..." << std::endl << std::endl;
std::cout << "ID | Comment" << std::endl;
std::cout << "----|----------------" << std::endl;
for(int i = 0; i < static_cast<int>(mPersonStorage.nbPersons()); ++i)
auto commentSplit = mPersonStorage.at(i).comment().split("\n", Qt::KeepEmptyParts);
out << "#" << qSetFieldWidth(3) << (i + 1) << qSetFieldWidth(0) << "|" << commentSplit.at(0)
<< Qt::endl;
std::cout << std::setw(4) << (i + 1) << "|" << commentSplit.at(0) << std::endl;
for(const QString &line : commentSplit)
{
out << "#" << qSetFieldWidth(3) << " " << qSetFieldWidth(0) << "|" << line << Qt::endl;
std::cout << " |" << line << std::endl;
}
mTrackerReal->exportTxt(
out,
mControlWidget->trackAlternateHeight->checkState(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->exportViewDir->isChecked(),
mControlWidget->exportAngleOfView->isChecked(),
mControlWidget->exportUseM->isChecked(),
mControlWidget->exportMarkerID->isChecked());
// out << *mTrackerReal;
PCritical(
this,
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
std::cout << " finished" << std::endl;
cout << " time(export) = " << time1 << " sec." << endl;
// time1 = 0.0;
// tstart = clock();
#endif
#ifdef TIME_MEASUREMENT
// time1 += clock() - tstart;
// time1 = time1/CLOCKS_PER_SEC;
// cout << " time(checkPlausibility) = " << time1 << " sec." << endl;
#endif
}
else if(dest.right(4) == ".dat")
if(!fileDat.open()) //! fileDat.open(QIODevice::WriteOnly | QIODevice::Text))
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileDat.errorString()));
// recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend
// play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung
// einfliessen zu lassen)
if(mControlWidget->trackRecalcHeight->checkState())
mPersonStorage.recalcHeight(mControlWidget->coordAltitude->value());
mTracker,
mImageItem,
mControlWidget->getColorPlot(),
getImageBorderSize(),
mControlWidget->trackMissingFrames->checkState(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->trackAlternateHeight->checkState(),
mControlWidget->coordAltitude->value(),
mStereoWidget->stereoUseCalibrationCenter->isChecked(),
mControlWidget->exportElimTp->isChecked(),
mControlWidget->exportElimTrj->isChecked(),
mControlWidget->exportSmooth->isChecked(),
mControlWidget->exportViewDir->isChecked(),
mControlWidget->exportAngleOfView->isChecked(),
mControlWidget->exportMarkerID->isChecked(),
autoCorrectOnlyExport);
debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons() << " person(s))..."
mTrackerReal->exportDat(
outDat,
mControlWidget->trackAlternateHeight->checkState(),
mStereoWidget->stereoUseForExport->isChecked());
PCritical(
this,
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
std::cout << " finished" << std::endl;
else if(dest.right(5) == ".trav")
// recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend
// play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung
// einfliessen zu lassen)
if(mControlWidget->trackRecalcHeight->checkState())
mPersonStorage.recalcHeight(mControlWidget->coordAltitude->value());
mTracker,
mImageItem,
mControlWidget->getColorPlot(),
getImageBorderSize(),
mControlWidget->trackMissingFrames->checkState(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->trackAlternateHeight->checkState(),
mControlWidget->coordAltitude->value(),
mStereoWidget->stereoUseCalibrationCenter->isChecked(),
mControlWidget->exportElimTp->isChecked(),
mControlWidget->exportElimTrj->isChecked(),
mControlWidget->exportSmooth->isChecked(),
mControlWidget->exportViewDir->isChecked(),
mControlWidget->exportAngleOfView->isChecked(),
mControlWidget->exportMarkerID->isChecked(),
autoCorrectOnlyExport);
if(!fileXml.open()) //! fileXml.open(QIODevice::WriteOnly | QIODevice::Text))
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileXml.errorString()));
debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons() << " person(s))..."
<< std::endl;
// already done: mTrackerReal->calculate(mTracker, mImageItem, mControlWidget->getColorPlot(),
// getImageBorderSize(), mControlWidget->trackMissingFrames->checkState());
outXml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << Qt::endl;
outXml << "<trajectoriesDataset>" << Qt::endl;
outXml << " <header version=\"1.0\">" << Qt::endl;
outXml << " <roomCaption>PeTrack: " << mAnimation->getFileBase() << "</roomCaption>" << Qt::endl;
outXml << " <roomID>0</roomID>" << Qt::endl;
outXml << " <agents>" << mPersonStorage.nbPersons() << "</agents>" << Qt::endl;
outXml << " <frameRate>" << mAnimation->getFPS() << "</frameRate> <!--per second-->" << Qt::endl;
// outXml << " <timeStep>" << 1000./mAnimation->getFPS() << "</timeStep> <!-- millisecond-->"
// << endl; inverse von
outXml << " <timeFirstFrame sec=\"" << mAnimation->getFirstFrameSec() << "\" microsec=\""
<< mAnimation->getFirstFrameMicroSec() << "\"/> <!-- " << mAnimation->getTimeString(0) << " -->"
<< Qt::endl;
outXml << " </header>" << Qt::endl << Qt::endl;
mTrackerReal->exportXml(
outXml,
mControlWidget->trackAlternateHeight->checkState(),
mStereoWidget->stereoUseForExport->isChecked());
outXml << "</trajectoriesDataset>" << Qt::endl;
PCritical(
this,
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
std::cout << " finished" << std::endl;
}
else
{ // wenn keine Dateiendung, dann wird trc und txt herausgeschrieben
exportTracker(dest + ".trc");
exportTracker(dest + ".txt");
}
mLastTrackerExport = dest;
}
}
}
// fuer anschliessende groessenberechnung
void Petrack::playAll()
{
int memPos = mPlayerWidget->getPos();
int progVal = 0;
QProgressDialog progress("Playing whole sequence...", "Abort playing", 0, mAnimation->getNumFrames(), this);
progress.setWindowModality(Qt::WindowModal); // blocks main window
// vorwaertslaufen ab aktueller Stelle und trackOnlineCalc zum tracken nutzen
do
{
progress.setValue(++progVal); // mPlayerWidget->getPos()
} while(mPlayerWidget->frameForward());
/**
* @brief Activates tracking and reco; calcs through the video (in both ways)
*
* This method activates tracking and reco and plays the whole video (from current
* frame on) till the end. Then, if mAutoBackTrack is set, it jumps back to the
* largest first frame, i.e. the last time a new person was added/recognized, and
* tracks backwards till the beginning of the video.
*
* The old settings for tracking and reco will be restored. No interaction with the
* main window is possible for the time of tracking.
*/
int memPos = mPlayerWidget->getPos();
int progVal = 0;
enum Qt::CheckState memCheckState = mControlWidget->trackOnlineCalc->checkState();
enum Qt::CheckState memRecoState = mControlWidget->performRecognition->checkState();
mControlWidget->trackOnlineCalc->setCheckState(Qt::Checked);
mControlWidget->performRecognition->setCheckState(Qt::Checked);
QProgressDialog progress(
"Tracking pedestrians through all frames...",
"Abort tracking",
0,
2 * mAnimation->getNumFrames() - memPos,
this);
progress.setWindowModality(Qt::WindowModal); // blocks main window
// vorwaertslaufen ab aktueller Stelle und trackOnlineCalc zum tracken nutzen
do
{
progress.setValue(++progVal); // mPlayerWidget->getPos()
} while(mPlayerWidget->frameForward());
{
// zuruecksprinegn an die stelle, wo der letzte trackPath nicht vollstaendig
// etwas spaeter, da erste punkte in reco path meist nur ellipse ohne markererkennung
mControlWidget->trackOnlineCalc->setCheckState(Qt::Unchecked);
mPlayerWidget->skipToFrame(mPersonStorage.largestFirstFrame() + 5);
// progVal = 2*mAnimation->getNumFrames()-memPos-mPlayerWidget->getPos();
progVal += mAnimation->getNumFrames() - mPlayerWidget->getPos();
progress.setValue(progVal); // mPlayerWidget->getPos()
// recognition abstellen, bis an die stelle, wo trackAll begann
// UEBERPRUEFEN, OB TRACKPATH NICHT RECOGNITION PUNKTE UEBERSCHREIBT!!!!!!!!!!
// repeate und repaetQual koennte temporaer umgestellt werden
mControlWidget->performRecognition->setCheckState(Qt::Unchecked);
// rueckwaertslaufen
do
{
if(progVal + 1 < 2 * mAnimation->getNumFrames() - memPos)
progress.setValue(++progVal); // mPlayerWidget->getPos()
if(mPlayerWidget->getPos() == memPos + 1)
mControlWidget->performRecognition->setCheckState(Qt::Checked);
} while(mPlayerWidget->frameBackward());
// bei abbruch koennen es auch mPlayerWidget->getPos() frames sein, die bisher geschrieben wurden
progress.setValue(2 * mAnimation->getNumFrames() - memPos);
mPersonStorage.optimizeColor();
mControlWidget->performRecognition->setCheckState(memRecoState);
mControlWidget->trackOnlineCalc->setCheckState(Qt::Unchecked);
mPlayerWidget->skipToFrame(memPos);
mControlWidget->trackOnlineCalc->setCheckState(memCheckState);
}
// default: (QPointF *pos=NULL, int pers=-1, int frame=-1);
int Petrack::winSize(QPointF *pos, int pers, int frame, int level)
{
// default of mControlWidget->trackRegionScale->value() is 16, so that
// a factor of 1.6 of the headsize is used
return (int) ((getHeadSize(pos, pers, frame) / pow(2., level)) * (mControlWidget->trackRegionScale->value() / 10.));
}
void Petrack::updateImage(bool imageChanged) // default = false (only true for new animation frame)
{
#ifdef TIME_MEASUREMENT
// die reine Ausgabe folgender Zeile kostet 1-2 Millisekunden
// "==========: "
debout << "go update: " << getElapsedTime() << endl;
mCodeMarkerItem->resetSavedMarkers();
static int lastRecoFrame = -10000;
// need semaphore to guarrantee that updateImage only called once
// updateValue of control automatically calls updateImage!!!
static QSemaphore semaphore(1);
if(!mImg.empty() && mImage && semaphore.tryAcquire())
{
int frameNum = mAnimation->getCurrentFrameNum();
setStatusTime();
updateShowFPS();
mImgFiltered = mImg;
// have to store because evaluation sets the filter parameter to unchanged
bool brightContrastChanged = mBrightContrastFilter.changed();
bool swapChanged = mSwapFilter.changed();
bool borderChanged = mBorderFilter.changed();
bool calibChanged = mCalibFilter->changed();
// speicherverwaltung wird komplett von filtern ueberneommen
// Filter anwenden, Reihenfolge wichtig - Rechenintensive moeglichst frueh
// fkt so nur mit kopierenden filtern
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "vor filter: " << getElapsedTime() << endl;
if(imageChanged || swapChanged || brightContrastChanged)
if(imageChanged || swapChanged || brightContrastChanged || borderChanged)
// "==========: "
debout << "nch filter: " << getElapsedTime() << endl;
#ifndef STEREO_DISABLED
if(imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
// "==========: "
debout << "vor calib: " << getElapsedTime() << endl;
if(imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
// "==========: "
debout << "nach calib: " << getElapsedTime() << endl;
if(brightContrastChanged || swapChanged || borderChanged || calibChanged)
// abfrage hinzugenommen, damit beim laden von .pet bg-file angegeben werden kann fuer mehrere versuche und
// beim nachladen von versuch nicht bg geloescht wird
if(mBackgroundFilter.getFilename() != "")
debout << "Warning: No background reset, because of explicit loaded background image!" << std::endl;
mBackgroundFilter
.reset(); // alle gesammelten hintergrundinfos werden verworfen und bg.changed auf true gesetzt
if(imageChanged || mBackgroundFilter.changed())
// "==========: "
debout << "nach bg: " << getElapsedTime() << endl;
#endif
// delete track list, if intrinsic param have changed
if(calibChanged && mPersonStorage.nbPersons() > 0) // mCalibFilter.getEnabled() &&
{
// Evtl. nicht Tracker loeschen sondern entsprechend der neuen Calibration verschieben?!?!?
debout << "Warning: deleted all tracking pathes because intrinsic parameters have changed."
<< std::endl;
#ifndef STEREO_DISABLED
// calculate position in 3D space and height of person for "old" trackPoints, if checked "even"
if(mStereoContext && mStereoWidget->stereoUseForHeightEver->isChecked() &&
mStereoWidget->stereoUseForHeight->isChecked())
{
// buildt disparity picture if it should be used for height detection
mStereoContext->getDisparity();
mPersonStorage.calcPosition(frameNum);
// tracking vor recognition, da dann neu gefundene punkte mit getrackten bereits ueberprueft werden koennen
if((trackChanged() || imageChanged) &&
(mControlWidget->trackOnlineCalc->checkState() == Qt::Checked)) // borderChanged ???
QRect roi(
myRound(mTrackingRoiItem->rect().x() + getImageBorderSize()),
myRound(mTrackingRoiItem->rect().y() + getImageBorderSize()),
myRound(mTrackingRoiItem->rect().width()),
myRound(mTrackingRoiItem->rect().height()));
size.height = mImgFiltered.rows;
mTracker->resize(size);
mTrackingRoiItem->restoreSize();
#ifndef STEREO_DISABLED
// buildt disparity picture if it should be used for height detection
if(mStereoContext && mStereoWidget->stereoUseForHeight->isChecked())
getRoi(mImgFiltered, roi, rect);
// Ignore all tracking points outside of rect
// if (mPrevIplImgFiltered) // wenn ein vorheriges bild vorliegt
// mPrevIplImgFiltered == NULL zeigt an, dass neue bildfolge && mPrevFrame == -1 ebenso
// winSize(), wurde mal uebergeben
debout << "vor track: " << getElapsedTime() << endl;
// debout << "test" << endl;
int anz = mTracker->track(
mImgFiltered,
rect,
frameNum,
mControlWidget->trackRepeat->isChecked(),
mControlWidget->trackRepeatQual->value(),
getImageBorderSize(),
mReco.getRecoMethod(),
mControlWidget->trackRegionLevels->value(),
getPedestriansToTrack());
debout << "nach track: " << getElapsedTime() << endl;
#endif
mControlWidget->trackNumberNow->setText(QString("%1").arg(anz));
// hier muesste fuer ameisen etc allgemeinABC.getPosList(...)
if(((((lastRecoFrame + mControlWidget->recoStep->value()) <= frameNum) ||
((lastRecoFrame - mControlWidget->recoStep->value()) >= frameNum)) &&
imageChanged) ||
mAnimation->isCameraLiveStream() || swapChanged || brightContrastChanged || borderChanged || calibChanged ||
recognitionChanged())
#ifndef STEREO_DISABLED
// buildt disparity picture if it should be used for height detection or recognition
if(mStereoContext &&
(mStereoWidget->stereoUseForHeight->isChecked() || mStereoWidget->stereoUseForReco->isChecked()))
mStereoContext->getDisparity(); // wird nicht neu berechnet, wenn vor tracking schon berechnet wurde
mRecognitionRoiItem->restoreSize();
if(mControlWidget->performRecognition->checkState() == Qt::Checked)
QRect rect(
myRound(mRecognitionRoiItem->rect().x() + getImageBorderSize()),
myRound(mRecognitionRoiItem->rect().y() + getImageBorderSize()),
myRound(mRecognitionRoiItem->rect().width()),
myRound(mRecognitionRoiItem->rect().height()));
auto recoMethod = mReco.getRecoMethod();
debout << "vor reco: " << getElapsedTime() << endl;
if((recoMethod == reco::RecognitionMethod::Casern) || (recoMethod == reco::RecognitionMethod::Hermes) ||
(recoMethod == reco::RecognitionMethod::Color) || (recoMethod == reco::RecognitionMethod::Japan) ||
(recoMethod == reco::RecognitionMethod::MultiColor) ||
(recoMethod == reco::RecognitionMethod::Code)) // else
persList = mReco.getMarkerPos(
mImgFiltered, rect, mControlWidget, getImageBorderSize(), getBackgroundFilter());
#ifndef STEREO_DISABLED
if(mStereoContext && mStereoWidget->stereoUseForReco->isChecked())
pl.calcPersonPos(mImgFiltered, rect, &persList, mStereoContext, getBackgroundFilter(), markerLess);
debout << "nach reco: " << getElapsedTime() << endl;
mPersonStorage.addPoints(persList, frameNum, mReco.getRecoMethod());
// folgendes lieber im Anschluss, ggf beim exportieren oder statt test direkt del:
if(mStereoContext && mStereoWidget->stereoUseForReco->isChecked())
mPersonStorage.purge(frameNum); // bereinigen wenn weniger als 0.2 recognition und nur getrackt
mControlWidget->recoNumberNow->setText(QString("%1").arg(persList.size()));
mRecognitionChanged = false;
if(false) // hier muss Abfage hin ob kasernen marker genutzt wird
mControlWidget->getColorPlot()
->replot(); // oder nur wenn tab offen oder wenn sich mtracker geaendert hat???
mControlWidget->trackNumberAll->setText(
QString("%1").arg(mPersonStorage.nbPersons())); // kann sich durch reco und tracker aendern
mControlWidget->trackShowOnlyNr->setMaximum(
MAX(mPersonStorage.nbPersons(), 1)); // kann sich durch reco und tracker aendern
mControlWidget->trackNumberVisible->setText(
QString("%1").arg(mPersonStorage.visible(frameNum))); // kann sich durch reco und tracker aendern
// in anzuzeigendes Bild kopieren
// erst hier wird die bildgroesse von mimage an filteredimg mit border angepasst
copyToQImage(*mImage, mImgFiltered);
getScene()->update(); // repaint();
// update pixel color (because image pixel moves)
setStatusColor();
}
#ifdef QWT
mControlWidget->getAnalysePlot()->setActFrame(frameNum);
if(mControlWidget->anaMarkAct->isChecked())
{
mControlWidget->getAnalysePlot()->replot();
}
#endif
semaphore.release();
}
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "stp update: " << getElapsedTime() << endl;
void Petrack::updateImage(const cv::Mat &img)
{
mImg = img;
updateImage(true);
}
void Petrack::updateSequence()
{
QImage *oldImage = mImage;
QSize size = mAnimation->getSize();
size.setWidth(size.width() + 2 * getImageBorderSize()); // border is inside the mImage!
size.setHeight(size.height() + 2 * getImageBorderSize());
mImage = new QImage(size, QImage::Format_RGB888); // 32); //wird in updateImage gemacht
// set roi for recognition if image size changes or roi is zero
// in oldImage steckt border drin, mIplImg->height zeigt noch auf altes ursprungsbild
// mRecognitionRoiItem->rect().width() != 0 && oldImage == NULL wenn projektdatei eingelesen wird!!!!!
if((mRecognitionRoiItem->rect().width() == 0) || // default while initialization, after that >= MIN_SIZE
(oldImage && ((oldImage->width() != mImage->width()) || (oldImage->height() != mImage->height()))))
mRecognitionRoiItem->setRect(-getImageBorderSize(), -getImageBorderSize(), mImage->width(), mImage->height());
if((mTrackingRoiItem->rect().width() == 0) ||
(oldImage && ((oldImage->width() != mImage->width()) || (oldImage->height() != mImage->height()))))
mTrackingRoiItem->setRect(-getImageBorderSize(), -getImageBorderSize(), mImage->width(), mImage->height());
size2.width = mTrackingRoiItem->rect().width();
size2.height = mTrackingRoiItem->rect().height();
mTracker->init(size2);
mPlayerWidget->setAnim(mAnimation);
mPlayerWidget->skipToFrame(0);
mImageItem->setImage(mImage); // wird in updateImage gemacht
delete oldImage;
mSaveSeqVidAct->setEnabled(true);
mSaveSeqVidViewAct->setEnabled(true);
mSaveSeqImgAct->setEnabled(true);
mSaveSeqViewAct->setEnabled(true);
mSaveImageAct->setEnabled(true);
mSaveViewAct->setEnabled(true);
mPrintAct->setEnabled(true);
mResetSettingsAct->setEnabled(true);
}
/**
* @brief Gets cm per pixel. Only recalculates when calculating head size.
* @return cm per pixel
*/
double Petrack::getCmPerPixel() const
/**
* @brief Sets the size of the circle of the average head circumference in pixel.
*
* Assumption for default calculation: <br>
* 21cm avg head length <br>
* default height of person according to mapDefaultHeigt <br>
*
* Default case recalculates mCmPerPixel
*
* If headsize get recalulated also mCmPerPixel will be calculated!
* @see Petrack::getCmPerPixel
* @param hS new headsize, if hS==-1 mHeadSize will be calculated instead of set
// debout << mCmPerPixel <<endl;
mHeadSize = (HEAD_SIZE * mControlWidget->coordAltitude->value() /
(mControlWidget->coordAltitude->value() - mControlWidget->mapDefaultHeight->value())) /
mCmPerPixel;
}
// gibt Kopfgroesse zurueck
// default: (QPointF *pos=NULL, int pers=-1, int frame=-1)
double Petrack::getHeadSize(QPointF *pos, int pers, int frame)
{
double z, h;
if((pers >= 0) && (pers < static_cast<int>(mPersonStorage.nbPersons())) &&
mPersonStorage.at(pers).trackPointExist(frame))
if(mControlWidget->getCalibCoordDimension() == 0)
int diff;
cv::Point3f p3d = getExtrCalibration()->get3DPoint(
cv::Point2f(
mPersonStorage.at(pers).trackPointAt(frame).x(), mPersonStorage.at(pers).trackPointAt(frame).y()),
mControlWidget->mapDefaultHeight->value());
cv::Point2f p3d_x1 =
getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x + HEAD_SIZE * 0.5, p3d.y, p3d.z));
cv::Point2f p3d_x2 =
getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x - HEAD_SIZE * 0.5, p3d.y, p3d.z));
cv::Point2f p3d_y1 =
getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x, p3d.y + HEAD_SIZE * 0.5, p3d.z));
cv::Point2f p3d_y2 =
getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x, p3d.y - HEAD_SIZE * 0.5, p3d.z));
diff = (int) std::max(
sqrt(pow(p3d_x2.x - p3d_x1.x, 2) + pow(p3d_x2.y - p3d_x1.y, 2)),
sqrt(pow(p3d_y2.x - p3d_y1.x, 2) + pow(p3d_y2.y - p3d_y1.y, 2)));
return diff; // < 8 ? 8 : diff;
}
else
z = mPersonStorage.at(pers).trackPointAt(frame).sp().z();
h = mPersonStorage.at(pers).height();
return (HEAD_SIZE * mControlWidget->coordAltitude->value() / z) / getImageItem()->getCmPerPixel();
return (HEAD_SIZE * mControlWidget->coordAltitude->value() /
(mControlWidget->coordAltitude->value() - h)) /
getImageItem()->getCmPerPixel();
return mHeadSize; // muss noch aus density map gelesen werden!!!
}
else //(pos == NULL) && (pers == -1)
{
Schrödter, Tobias
committed
* @brief Return the user's selection of pedestrians/trajectories
Schrödter, Tobias
committed
* Only people selected via "show only people" (single person) or "show only
* people list"(multiple persons) are going to be selected.
Schrödter, Tobias
committed
* @return All user selected pedestrian (empty for all pedestrians)
Schrödter, Tobias
committed
QSet<int> Petrack::getPedestrianUserSelection()
if(mControlWidget->trackShowOnly->checkState() == Qt::Checked)
{
Schrödter, Tobias
committed
QSet<int> onlyVisible;
// subtraction needed as in UI ID start at 1 and internally at 0
Schrödter, Tobias
committed
onlyVisible.insert(mControlWidget->trackShowOnlyNr->value() - 1);
return onlyVisible;
}
if(mControlWidget->trackShowOnlyList->checkState() == Qt::Checked)
{
auto enteredIDs = util::splitStringToInt(mControlWidget->trackShowOnlyNrList->text());
if(enteredIDs.has_value())
QSet<int> selectedIDs;
for(auto id : enteredIDs.value())
// subtraction needed as in UI ID start at 1 and internally at 0
selectedIDs.insert(id - 1);
Schrödter, Tobias
committed
}
mControlWidget->trackShowOnlyNrList->setStyleSheet("");
return selectedIDs;
}
else
{
mControlWidget->trackShowOnlyNrList->setStyleSheet("border: 1px solid red");
}
}
return QSet<int>();
}
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
/**
* @brief Splits the given text to get a set of integers.
*
* The given text will be split on ',' and then each element will be checked if it is a range. Ranges are marked with
* '-' as divider. Only positive integer values are allowed.
*
* Examples:
* '1,5,6' -> (1, 5, 6)
* '1-5' -> (1, 2, 3, 4, 5)
*
* @param input given text
* @return Set of int in the given text
*/
std::optional<QSet<int>> util::splitStringToInt(const QString &input)
{
QSet<int> ids;
for(const auto &id : input.split(",", Qt::SkipEmptyParts))
{
bool ok = false;
int enteredID = id.toInt(&ok);
if(ok && enteredID >= 0) // parse single values
{
ids.insert(enteredID);
}
else // error or IDs range (e.g. 1-3, 6-10, etc.)
{
if(id.startsWith("-"))
{
ok = false;
}
auto range = id.split("-");
int first = range[0].toInt(&ok);
ok = ok && range.size() == 2 && !range[1].isEmpty();
if(ok)
{
int last = range[1].toInt(&ok);
if(ok)
Schrödter, Tobias
committed
{
std::swap(first, last);
}
for(int i = first; i <= last; i++)
{
ids.insert(i);
if(!ok)
{
return std::nullopt;
}
Schrödter, Tobias
committed
}
Schrödter, Tobias
committed
}
/**
* @brief Checks which pedestrians/trajectories are selected for evaluation.
*
* If "only for selected" is checked, then only selected people (@see
* Petrack::getPedestrianUserSelection()) are going to be tracked, all people
* otherwise.
*
* @return all trajectories which should be evaluated; empty when all should be evaluated
*/
QSet<int> Petrack::getPedestriansToTrack()
{
if(mControlWidget->trackOnlySelected->checkState() == Qt::Checked)
Schrödter, Tobias
committed
{
return getPedestrianUserSelection();
Schrödter, Tobias
committed
}
return QSet<int>();
void Petrack::addManualTrackPointOnlyVisible(const QPointF &pos)
int pers = addOrMoveManualTrackPoint(pos) + 1;
if(pers == 0)
pers = static_cast<int>(mPersonStorage.nbPersons()) + 1;
mControlWidget->trackShowOnlyNr->setValue(pers);
mControlWidget->trackShowOnly->setChecked(true);
}
void Petrack::updateControlWidget()
{
mControlWidget->trackNumberAll->setText(QString("%1").arg(mPersonStorage.nbPersons()));
mControlWidget->trackShowOnlyNr->setMaximum(MAX(mPersonStorage.nbPersons(), 1));
mControlWidget->trackNumberVisible->setText(
QString("%1").arg(mPersonStorage.visible(mAnimation->getCurrentFrameNum())));
mPersonStorage.splitPersonAt((Vec2F) pos, mAnimation->getCurrentFrameNum(), getPedestrianUserSelection());
* @brief Lets the user add or move a TrackPoint manually
*
* There is an check inside addPoint which inhibits adding a point,
* if only selected trajectories are visualized, since one wouldn't
* see the newly added TrackPoint.
*
* @param pos pixel position of mouse on image
* @return index of person whose point was moved; -1 if failed or new trajectory is started
int Petrack::addOrMoveManualTrackPoint(const QPointF &pos)
TrackPoint tP(Vec2F{pos}, 110); // 110 is higher than 100 (max. quality) and gets clamped to 100 after insertion
// allows replacemet of every point (check for better quality always passes)
tP, mAnimation->getCurrentFrameNum(), getPedestrianUserSelection(), mReco.getRecoMethod(), &pers);
}
// direction zeigt an, ob bis zum aktuellen (-1), ab dem aktuellen (1) oder ganzer trackpath (0)
// loeschen von Trackpoints einer Trajektorie
void Petrack::deleteTrackPoint(QPointF pos, int direction) // const QPoint &pos
mPersonStorage.delPoint((Vec2F) pos, direction, mAnimation->getCurrentFrameNum(), getPedestrianUserSelection());
updateControlWidget();
}
void Petrack::editTrackPersonComment(QPointF pos)
{
mPersonStorage.editTrackPersonComment((Vec2F) pos, mAnimation->getCurrentFrameNum(), getPedestrianUserSelection());
updateControlWidget();
}
void Petrack::setTrackPersonHeight(QPointF pos)
{
mPersonStorage.setTrackPersonHeight((Vec2F) pos, mAnimation->getCurrentFrameNum(), getPedestrianUserSelection());
updateControlWidget();
}
void Petrack::resetTrackPersonHeight(QPointF pos)
{
mPersonStorage.resetTrackPersonHeight((Vec2F) pos, mAnimation->getCurrentFrameNum(), getPedestrianUserSelection());
/**
* @brief Delete the following, previous or whole trajectory of **all** trajectories
* @param direction previous, following or whole
*/
void Petrack::deleteTrackPointAll(PersonStorage::Direction direction) // const QPoint &pos
mPersonStorage.delPointAll(direction, mAnimation->getCurrentFrameNum());
updateControlWidget();
}
void Petrack::deleteTrackPointROI()
{
mPersonStorage.delPointROI();
updateControlWidget();
mScene->update();
}
void Petrack::deleteTrackPointInsideROI()
{
getPersonStorage().delPointInsideROI();
updateControlWidget();
mScene->update();
}
void Petrack::updateSourceInOutFrames()
{
mPlayerWidget->setFrameInNum(mAnimation->getSourceInFrameNum());
mPlayerWidget->setFrameOutNum(mAnimation->getSourceOutFrameNum());
}
// delta gibt menge an Umdrehungen und richtung an
void Petrack::skipToFrameWheel(int delta)
{
mPlayerWidget->skipToFrame(mPlayerWidget->getPos() + delta);
void Petrack::skipToFrameFromTrajectory(QPointF pos)
{
auto peds = getPedestrianUserSelection();
const auto before = mControlWidget->trackShowBefore->value();
const auto after = mControlWidget->trackShowAfter->value();
const auto currFrame = mPlayerWidget->getPos();
auto res = mPersonStorage.getProximalPersons(pos, currFrame, peds, before, after);
if(res.size() == 1)
{
mPlayerWidget->skipToFrame(res.front().frame);
}
else if(res.size() > 1)
{
PWarning(
this,
tr("Too many trajectories"),
tr("PeTrack can't determine which point you meant. Try selecting fewer trajectories first."));
}
}
void Petrack::setPeTrackVersion(const std::string &petrackVersion)
{
mPetrackVersion = QString::fromStdString(petrackVersion);
}
void Petrack::setGitInformation(
const std::string &gitCommitID,
const std::string &gitCommitDate,
const std::string &gitCommitBranch)
mGitCommitID = QString::fromStdString(gitCommitID);
mGitCommitDate = QString::fromStdString(gitCommitDate);
mGitCommitBranch = QString::fromStdString(gitCommitBranch);
}
void Petrack::setCompileInformation(
const std::string &compileTimeStamp,
const std::string &compilerID,
const std::string &compilerVersion)
mCompileDate = QString::fromStdString(compileTimeStamp);
mCompilerID = QString::fromStdString(compilerID);
mCompilerVersion = QString::fromStdString(compilerVersion);
}
#include "moc_petrack.cpp"