Newer
Older
Schrödter, Tobias
committed
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
mTrackerReal->calculate(
this,
mTracker,
mImageItem,
mControlWidget->getColorPlot(),
mMissingFrames,
getImageBorderSize(),
mControlWidget->isTrackMissingFramesChecked(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->getTrackAlternateHeight(),
mControlWidget->getCameraAltitude(),
mStereoWidget->stereoUseCalibrationCenter->isChecked(),
mControlWidget->isExportElimTpChecked(),
mControlWidget->isExportElimTrjChecked(),
mControlWidget->isExportSmoothChecked(),
mControlWidget->isExportViewDirChecked(),
mControlWidget->isExportAngleOfViewChecked(),
mControlWidget->isExportMarkerIDChecked(),
autoCorrectOnlyExport);
SPDLOG_INFO("export tracking data to {} ({} person(s))...", dest, mPersonStorage.nbPersons());
QTextStream outDat(&fileDat);
mTrackerReal->exportDat(
outDat, mControlWidget->getTrackAlternateHeight(), mStereoWidget->stereoUseForExport->isChecked());
fileDat.flush();
fileDat.close();
if(QFile::exists(dest))
{
QFile::remove(dest);
}
Schrödter, Tobias
committed
if(!fileDat.copy(dest))
{
PCritical(
Schrödter, Tobias
committed
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
}
else
{
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
}
Schrödter, Tobias
committed
SPDLOG_INFO("finished");
}
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->isTrackRecalcHeightChecked())
{
mPersonStorage.recalcHeight(mControlWidget->getCameraAltitude());
}
Schrödter, Tobias
committed
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
mTrackerReal->calculate(
this,
mTracker,
mImageItem,
mControlWidget->getColorPlot(),
mMissingFrames,
getImageBorderSize(),
mControlWidget->isTrackMissingFramesChecked(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->getTrackAlternateHeight(),
mControlWidget->getCameraAltitude(),
mStereoWidget->stereoUseCalibrationCenter->isChecked(),
mControlWidget->isExportElimTpChecked(),
mControlWidget->isExportElimTrjChecked(),
mControlWidget->isExportSmoothChecked(),
mControlWidget->isExportViewDirChecked(),
mControlWidget->isExportAngleOfViewChecked(),
mControlWidget->isExportMarkerIDChecked(),
autoCorrectOnlyExport);
QTemporaryFile fileXml;
if(!fileXml.open()) //! fileXml.open(QIODevice::WriteOnly | QIODevice::Text))
{
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileXml.errorString()));
return;
Schrödter, Tobias
committed
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
SPDLOG_INFO("export tracking data to {} ({} person(s))...", dest, mPersonStorage.nbPersons());
// already done: mTrackerReal->calculate(mTracker, mImageItem, mControlWidget->getColorPlot(),
// getImageBorderSize(), mControlWidget->trackMissingFrames->checkState());
QTextStream outXml(&fileXml);
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->getTrackAlternateHeight(), mStereoWidget->stereoUseForExport->isChecked());
outXml << "</trajectoriesDataset>" << Qt::endl;
fileXml.flush();
fileXml.close();
if(QFile::exists(dest))
Schrödter, Tobias
committed
QFile::remove(dest);
}
Schrödter, Tobias
committed
if(!fileXml.copy(dest))
{
PCritical(
Schrödter, Tobias
committed
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
Schrödter, Tobias
committed
{
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
Schrödter, Tobias
committed
SPDLOG_INFO("finished");
}
else
{ // wenn keine Dateiendung, dann wird trc und txt herausgeschrieben
exportTracker(dest + ".trc");
exportTracker(dest + ".txt");
Schrödter, Tobias
committed
mLastTrackerExport = dest;
}
catch(const std::runtime_error &error)
{
PCritical(this, "Failed to export trajectories", error.what());
}
}
// 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;
bool memCheckState = mControlWidget->isOnlineTrackingChecked();
bool memRecoState = mControlWidget->isPerformRecognitionChecked();
mControlWidget->setOnlineTrackingChecked(true);
mControlWidget->setPerformRecognitionChecked(true);
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->setOnlineTrackingChecked(false);
mPlayerWidget->skipToFrame(mPersonStorage.largestFirstFrame() + 5);
mControlWidget->setOnlineTrackingChecked(true);
// 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->setPerformRecognitionChecked(false);
if(progVal + 1 < 2 * mAnimation->getNumFrames() - memPos)
progress.setValue(++progVal); // mPlayerWidget->getPos()
if(mPlayerWidget->getPos() == memPos + 1)
mControlWidget->setPerformRecognitionChecked(true);
} 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->setPerformRecognitionChecked(memRecoState);
mControlWidget->setOnlineTrackingChecked(false);
mControlWidget->setOnlineTrackingChecked(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
level = mControlWidget->getTrackRegionLevels();
return (int) ((getHeadSize(pos, pers, frame) / pow(2., level)) * (mControlWidget->getTrackRegionScale() / 10.));
}
void Petrack::updateImage(bool imageChanged) // default = false (only true for new animation frame)
{
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
if(imageChanged || swapChanged || brightContrastChanged)
if(imageChanged || swapChanged || brightContrastChanged || borderChanged)
#ifndef STEREO_DISABLED
if(imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
if(imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
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() != "")
SPDLOG_WARN("no background reset, because of explicit loaded background image!");
mBackgroundFilter
.reset(); // alle gesammelten hintergrundinfos werden verworfen und bg.changed auf true gesetzt
if(imageChanged || mBackgroundFilter.changed())
if(calibChanged && mPersonStorage.nbPersons() > 0) // mCalibFilter.getEnabled() &&
{
// Evtl. nicht Tracker loeschen sondern entsprechend der neuen Calibration verschieben?!?!?
SPDLOG_WARN("deleted all tracking pathes because intrinsic parameters have changed.");
#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->isOnlineTrackingChecked())) // 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
int anz = mTracker->track(
mImgFiltered,
rect,
frameNum,
mControlWidget->isTrackRepeatChecked(),
mControlWidget->getTrackRepeatQual(),
getImageBorderSize(),
mReco.getRecoMethod(),
mControlWidget->getTrackRegionLevels(),
mControlWidget->setTrackNumberNow(QString("%1").arg(anz));
mControlWidget->setTrackNumberNow(QString("0"));
// hier muesste fuer ameisen etc allgemeinABC.getPosList(...)
if(((((lastRecoFrame + mControlWidget->getRecoStep()) <= frameNum) ||
((lastRecoFrame - mControlWidget->getRecoStep()) >= 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->isPerformRecognitionChecked())
QRect rect(
myRound(mRecognitionRoiItem->rect().x() + getImageBorderSize()),
myRound(mRecognitionRoiItem->rect().y() + getImageBorderSize()),
myRound(mRecognitionRoiItem->rect().width()),
myRound(mRecognitionRoiItem->rect().height()));
auto recoMethod = mReco.getRecoMethod();
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
mImgFiltered,
rect,
mControlWidget,
getImageBorderSize(),
getBackgroundFilter(),
mControlWidget->getIntrinsicCameraParams());
#ifndef STEREO_DISABLED
if(mStereoContext && mStereoWidget->stereoUseForReco->isChecked())
pl.calcPersonPos(mImgFiltered, rect, &persList, mStereoContext, getBackgroundFilter(), markerLess);
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->setRecoNumberNow(QString("%1").arg(persList.size()));
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->setRecoNumberNow(QString("0"));
mControlWidget->setRecoNumberNow(QString("0"));
mControlWidget->setTrackNumberAll(
QString("%1").arg(mPersonStorage.nbPersons())); // kann sich durch reco und tracker aendern
mControlWidget->setTrackShowOnlyNrMaximum(
static_cast<int>(MAX(mPersonStorage.nbPersons(), 1))); // kann sich durch reco und tracker aendern
mControlWidget->setTrackNumberVisible(
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()->views().first()->viewport()->repaint();
// update pixel color (because image pixel moves)
setStatusColor();
}
#ifdef QWT
mControlWidget->getAnalysePlot()->setActFrame(frameNum);
if(mControlWidget->isAnaMarkActChecked())
{
mControlWidget->getAnalysePlot()->replot();
}
#endif
semaphore.release();
}
}
void Petrack::updateImage(const cv::Mat &img)
{
mImg = img;
updateImage(true);
}
void Petrack::updateSequence()
{
QImage *oldImage = mImage;
QSize size = mAnimation->getSize();
if(size != QSize{0, 0})
{
size.setWidth(size.width() + 2 * getImageBorderSize()); // border is inside the mImage!
size.setHeight(size.height() + 2 * getImageBorderSize());
}
mImage = new QImage(size, QImage::Format_RGB888);
if(size == QSize{0, 0})
// separate handling because border should currently be ignored
// will be applied when a sequence is loaded in
mRecognitionRoiItem->setRect(0, 0, 0, 0);
mTrackingRoiItem->setRect(0, 0, 0, 0);
const bool imageSizeChanged = oldImage && (oldImage->rect() != mImage->rect());
// set roi for recognition if image size changes or roi is zero
if((mRecognitionRoiItem->rect().width() == 0) || imageSizeChanged)
{
mRecognitionRoiItem->setRect(
-getImageBorderSize(), -getImageBorderSize(), mImage->width(), mImage->height());
}
if((mTrackingRoiItem->rect().width() == 0) || imageSizeChanged)
{
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->getCameraAltitude() /
(mControlWidget->getCameraAltitude() - mControlWidget->getDefaultHeight())) /
}
// 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->getDefaultHeight());
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->getCameraAltitude() / z) / getImageItem()->getCmPerPixel();
return (HEAD_SIZE * mControlWidget->getCameraAltitude() / (mControlWidget->getCameraAltitude() - h)) /
getImageItem()->getCmPerPixel();
return mHeadSize; // muss noch aus density map gelesen werden!!!
}
else //(pos == NULL) && (pers == -1)
{
void Petrack::setProFileName(const QString &fileName)
{
// don't change project Name to an autosave
if(mAutosave.isAutosave(fileName) || fileName == mProFileName)
{
return;
}
// Change project => delete old autosave
mAutosave.deleteAutosave();
// NOTE: Use only the global variant in future?
// global one in helper.h because it is needed to use getFileList and shouldn't depend on Petrack
proFileName = fileName;
mProFileName = fileName;
updateWindowTitle();
}
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)
QSet<size_t> Petrack::getPedestrianUserSelection()
if(mControlWidget->isTrackShowOnlyChecked())
// subtraction needed as in UI ID start at 1 and internally at 0
onlyVisible.insert(mControlWidget->getTrackShowOnlyNr() - 1);
Schrödter, Tobias
committed
return onlyVisible;
}
if(mControlWidget->isTrackShowOnlyListChecked())
auto enteredIDs = util::splitStringToInt(mControlWidget->trackShowOnlyNrList()->text());
if(enteredIDs.has_value())
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");
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
/**
* @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
*/
Schrödter, Tobias
committed
{
if(mControlWidget->isTrackOnlySelectedChecked())
Schrödter, Tobias
committed
{
return getPedestrianUserSelection();
Schrödter, Tobias
committed
}
void Petrack::addManualTrackPointOnlyVisible(const QPointF &pos)
int pers = addOrMoveManualTrackPoint(pos) + 1;
if(pers == 0)
pers = static_cast<int>(mPersonStorage.nbPersons()) + 1;
mControlWidget->setTrackShowOnlyNr(pers);
mControlWidget->setTrackShowOnly(Qt::Checked);
mControlWidget->setTrackNumberAll(QString("%1").arg(mPersonStorage.nbPersons()));
mControlWidget->setTrackShowOnlyNrMaximum(static_cast<int>(MAX(mPersonStorage.nbPersons(), 1)));
mControlWidget->setTrackNumberVisible(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());
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();
d.kilic
committed
void Petrack::moveTrackPoint(QPointF pos)
{
mManualTrackPointMover.moveTrackPoint(pos, mPersonStorage);
mScene->update();
}
void Petrack::selectPersonForMoveTrackPoint(QPointF pos)
{
FrameRange range;
range.before = mControlWidget->getTrackShowBefore();
range.after = mControlWidget->getTrackShowAfter();
d.kilic
committed
range.current = mPlayerWidget->getPos();
auto successfullySelected =
mManualTrackPointMover.selectTrackPoint(pos, mPersonStorage, getPedestrianUserSelection(), range);
if(successfullySelected)
{
setCursor(QCursor{Qt::CursorShape::DragMoveCursor});
}
}
void Petrack::releaseTrackPoint()
{
mManualTrackPointMover.setTrackPoint();
mAutosave.trackPersonModified();
setCursor(QCursor{});
}
void Petrack::scrollShowOnly(int delta)
{
if(delta < 0)
{
mControlWidget->setTrackShowOnlyNr(mControlWidget->getTrackShowOnlyNr() - 1);
}
else
{
mControlWidget->setTrackShowOnlyNr(mControlWidget->getTrackShowOnlyNr() + 1);
}
}
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);