Newer
Older
Schrödter, Tobias
committed
out << "# raw trajectory file: " << QFileInfo(getTrackFileName()).fileName() << Qt::endl;
out << "# framerate: " << mAnimation->getFPS() << " fps" << Qt::endl;
Schrödter, Tobias
committed
if(mControlWidget->isExportCommentChecked())
{
out << "# personal information:" << Qt::endl;
out << "# ID| Comment" << Qt::endl;
Schrödter, Tobias
committed
// std out
SPDLOG_INFO("Printing comment table...");
SPDLOG_INFO("ID | Comment");
SPDLOG_INFO("----|----------------");
Schrödter, Tobias
committed
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;
SPDLOG_INFO("{:04d}|{}", (i + 1), commentSplit.at(0));
commentSplit.pop_front();
for(const QString &line : commentSplit)
Schrödter, Tobias
committed
out << "#" << qSetFieldWidth(3) << " " << qSetFieldWidth(0) << "|" << line << Qt::endl;
SPDLOG_INFO(" |{}", line);
Schrödter, Tobias
committed
}
mTrackerReal->exportTxt(
out,
mControlWidget->getTrackAlternateHeight(),
mStereoWidget->stereoUseForExport->isChecked(),
mControlWidget->isExportViewDirChecked(),
mControlWidget->isExportAngleOfViewChecked(),
mControlWidget->isExportUseMeterChecked(),
mControlWidget->isExportMarkerIDChecked());
// out << *mTrackerReal;
file.flush();
file.close();
Schrödter, Tobias
committed
if(QFile::exists(dest))
{
QFile::remove(dest);
}
if(!file.copy(dest))
{
PCritical(
this,
tr("PeTrack"),
tr("Could not export tracking data.\n"
"Please try again!"));
}
else
{
statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
}
SPDLOG_INFO("finished");
}
else if(dest.endsWith(".dat", Qt::CaseInsensitive))
{
QTemporaryFile fileDat;
Schrödter, Tobias
committed
if(!fileDat.open()) //! fileDat.open(QIODevice::WriteOnly | QIODevice::Text))
{
PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileDat.errorString()));
return;
Schrödter, Tobias
committed
// 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())
Schrödter, Tobias
committed
mPersonStorage.recalcHeight(mControlWidget->getCameraAltitude());
}
mTrackerReal->calculate(
this,
mTracker,
mWorldImageCorrespondence,
Schrödter, Tobias
committed
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
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.endsWith(".trav", Qt::CaseInsensitive))
Schrödter, Tobias
committed
{
// 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
mTrackerReal->calculate(
this,
mTracker,
mWorldImageCorrespondence,
Schrödter, Tobias
committed
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
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
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
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)
mImgFiltered = mCalibFilter.apply(mImgFiltered);
mImgFiltered = mCalibFilter.getLastResult();
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
cv::Mat map1 = mCalibFilter.getMap1();
int anz = mTracker->track(
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
mCmPerPixel = mWorldImageCorrespondence->getCmPerPixel();
// 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) /
mWorldImageCorrespondence->getCmPerPixel();
return (HEAD_SIZE * mControlWidget->getCameraAltitude() / (mControlWidget->getCameraAltitude() - h)) /
mWorldImageCorrespondence->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();
}
const WorldImageCorrespondence &Petrack::getWorldImageCorrespondence()
{
return *mWorldImageCorrespondence;
}
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");
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
/**
* @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());