Newer
Older
debout << "go update: " << getElapsedTime() <<endl;
#endif
mCodeMarkerItem->resetSavedMarkers();
static int lastRecoFrame = -10000;
static bool borderChangedForTracking = false;
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
// 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;
#endif
if (imageChanged || swapChanged)
mImgFiltered = mSwapFilter.apply(mImgFiltered);
else
mImgFiltered = mSwapFilter.getLastResult();
if (imageChanged || swapChanged || brightContrastChanged)
mImgFiltered = mBrightContrastFilter.apply(mImgFiltered);
else
mImgFiltered = mBrightContrastFilter.getLastResult();
if (imageChanged || swapChanged || brightContrastChanged || borderChanged)
mImgFiltered = mBorderFilter.apply(mImgFiltered); // mIplImg
else
mImgFiltered = mBorderFilter.getLastResult();
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "nch filter: " << getElapsedTime() <<endl;
#endif
if (borderChanged)
updateControlImage(mImgFiltered);
#ifndef STEREO_DISABLED
if (imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
{
if (mStereoContext)
mStereoContext->init(mImgFiltered);
}
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "vor calib: " << getElapsedTime() <<endl;
#endif
if (imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
mImgFiltered = mCalibFilter->apply(mImgFiltered);
else
mImgFiltered = mCalibFilter->getLastResult();
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "nach calib: " << getElapsedTime() <<endl;
#endif
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;
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
else
mBackgroundFilter.reset(); // alle gesammelten hintergrundinfos werden verworfen und bg.changed auf true gesetzt
}
if (imageChanged || mBackgroundFilter.changed())
mImgFiltered = mBackgroundFilter.apply(mImgFiltered);
else
mImgFiltered = mBackgroundFilter.getLastResult();
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "nach bg: " << getElapsedTime() <<endl;
#endif
// delete track list, if intrinsic param have changed
if (calibChanged && mTracker->size() > 0) //mCalibFilter.getEnabled() &&
{
// Evtl. nicht Tracker loeschen sondern entsprechend der neuen Calibration verschieben?!?!?
mTracker->clear();
mTracker->reset();
if( !isLoading() )
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();
mTracker->calcPosition(frameNum);
}
}
if (borderChanged)
borderChangedForTracking = true;
// tracking vor recognition, da dann neu gefundene punkte mit getrackten bereits ueberprueft werden koennen
if ((trackChanged() || imageChanged) && (mControlWidget->trackOnlineCalc->checkState() == Qt::Checked)) // borderChanged ???
{
// Rect for tracking area
QRect roi(myRound(mTrackingRoiItem->rect().x()+getImageBorderSize()),
myRound(mTrackingRoiItem->rect().y()+getImageBorderSize()),
myRound(mTrackingRoiItem->rect().width()),
myRound(mTrackingRoiItem->rect().height()));
if (borderChangedForTracking)
{
size.width = mImgFiltered.cols;
size.height = mImgFiltered.rows;
mTracker->resize(size);
mTrackingRoiItem->checkRect();
}
#ifndef STEREO_DISABLED
// buildt disparity picture if it should be used for height detection
if (mStereoContext && mStereoWidget->stereoUseForHeight->isChecked())
mStereoContext->getDisparity();
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
#ifdef TIME_MEASUREMENT
debout << "vor track: " << getElapsedTime() <<endl;
#endif
// debout << "test" << endl;
int anz = mTracker->track(mImgFiltered, rect, frameNum,
mControlWidget->trackRepeatQual->value(), getImageBorderSize(),
mReco.getRecoMethod(), mControlWidget->trackRegionLevels->value(),
getOnlyVisible());
#ifdef TIME_MEASUREMENT
debout << "nach track: " << getElapsedTime() <<endl;
#endif
mControlWidget->trackNumberNow->setText(QString("%1").arg(anz));
mTrackChanged = false;
borderChangedForTracking = false;
}
else
mControlWidget->trackNumberNow->setText(QString("0"));
// 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
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()));
QList<TrackPoint> persList;
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "vor reco: " << getElapsedTime() <<endl;
#endif
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())
{
PersonList pl;
pl.calcPersonPos(mImgFiltered, rect, &persList, mStereoContext, getBackgroundFilter(), markerLess);
#ifdef TIME_MEASUREMENT
// "==========: "
debout << "nach reco: " << getElapsedTime() <<endl;
#endif
mTracker->addPoints(persList, frameNum, mReco.getRecoMethod());
// folgendes lieber im Anschluss, ggf beim exportieren oder statt test direkt del:
if (mStereoContext && mStereoWidget->stereoUseForReco->isChecked())
mTracker->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???
}
else
mControlWidget->recoNumberNow->setText(QString("0"));
lastRecoFrame = frameNum;
}
else
mControlWidget->recoNumberNow->setText(QString("0"));
mControlWidget->trackNumberAll->setText(QString("%1").arg(mTracker->size())); // kann sich durch reco und tracker aendern
mControlWidget->trackShowOnlyNr->setMaximum(MAX(mTracker->size(),1)); // kann sich durch reco und tracker aendern
mControlWidget->trackNumberVisible->setText(QString("%1").arg(mTracker->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);
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
if (borderChanged)
mImageItem->setImage(mImage);
else
{
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;
#endif
}
void Petrack::updateImage(const cv::Mat &img)
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
{
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
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
void Petrack::setHeadSize(double hS)
{
if (hS == -1)
{
mCmPerPixel = getImageItem()->getCmPerPixel();
//debout << mCmPerPixel <<endl;
mHeadSize = (HEAD_SIZE*mControlWidget->coordAltitude->value() / (mControlWidget->coordAltitude->value()-mControlWidget->mapDefaultHeight->value())) /
mCmPerPixel;
}
else
mHeadSize = hS;
}
// 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 < mTracker->size()) && mTracker->at(pers).trackPointExist(frame))
{
if( mControlWidget->getCalibCoordDimension() == 0 )
{
int diff;
cv::Point3f p3d = getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(pers).trackPointAt(frame).x(),
mTracker->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 = mTracker->at(pers).trackPointAt(frame).sp().z();
h = mTracker->at(pers).height();
if (z > 0)
return (HEAD_SIZE*mControlWidget->coordAltitude->value() / z) / getImageItem()->getCmPerPixel();
else if (h > MIN_HEIGHT)
return (HEAD_SIZE*mControlWidget->coordAltitude->value() / (mControlWidget->coordAltitude->value()-h)) / getImageItem()->getCmPerPixel();
else
return mHeadSize;
}
}
return mHeadSize; // muss noch aus density map gelesen werden!!!
else //(pos == NULL) && (pers == -1)
return mHeadSize;
}
/**
* @brief Petrack::getOnlyVisible Returns trajectories which should be evaluated
*
* If "only for visible people" is checked, then only people visible via
* "show only people" (single person) or "show only people list"(multiple persons)
* are going to be evaluated. If "only for visible people" is not checked,
* everyone gets evaluated, not only the ones selected for visibility.
*
* @return all trajectories which should be evaluated; empty when all should be evaluated
*/
if ((mControlWidget->trackOnlySelected->checkState() == Qt::Checked) && (mControlWidget->trackShowOnly->checkState() == Qt::Checked || mControlWidget->trackShowOnlyList->checkState() == Qt::Checked))
{
if( mControlWidget->trackShowOnlyList->checkState() == Qt::Checked)
{
QStringList list = mControlWidget->trackShowOnlyNrList->text().split(",", Qt::SkipEmptyParts);
QSet<int> onlyVisible;
foreach(QString s, list)
{
bool ok = false;
int nr = s.toInt(&ok);
if(ok/* && nr <= maxPed && nr > 0*/) // einzelne ID
onlyVisible.insert(nr-1);
else // error or IDs range (e.g. 1-3, 6-10, etc.)
{
QStringList range = s.split("-", Qt::SkipEmptyParts);
int last,first = range[0].toInt(&ok);
if(ok/* && first <= maxPed && nr > 0*/)
{
last = range[1].toInt(&ok);
if(ok/* && last <= maxPed && nr > 0*/)
{
if(first>last)
std::swap(first,last);
for(int i=first;i<=last;i++)
onlyVisible.insert(i-1);
}
}
}
if(!ok)
debout << "Warning: error while reading showOnlyVisible list from input line!" << std::endl;
return onlyVisible; //in anzeige wird ab 1 gezaehlt, in datenstruktur ab 0
{
QSet<int> onlyVisible;
onlyVisible.insert(mControlWidget->trackShowOnlyNr->value()-1);
return onlyVisible;
}
}else
return QSet<int>();
}
void Petrack::addManualTrackPointOnlyVisible(const QPointF& pos)
int pers = addOrMoveManualTrackPoint(pos)+1;
if (pers == 0)
pers = mTracker->size()+1;
pers = mControlWidget->trackShowOnlyNr->maximum();
mControlWidget->trackShowOnlyNr->setValue(pers);
mControlWidget->trackShowOnly->setChecked(true);
}
void Petrack::updateControlWidget()
{
mControlWidget->trackNumberAll->setText(QString("%1").arg(mTracker->size()));
mControlWidget->trackShowOnlyNr->setMaximum(MAX(mTracker->size(),1));
mControlWidget->trackNumberVisible->setText(QString("%1").arg(mTracker->visible(mAnimation->getCurrentFrameNum())));
}
void Petrack::splitTrackPerson(QPointF pos)
{
mTracker->splitPersonAt((Vec2F) pos, mAnimation->getCurrentFrameNum(), getOnlyVisible());
updateControlWidget();
}
* @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)
int pers = -1;
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)
mTracker->addPoint(tP, mAnimation->getCurrentFrameNum(), getOnlyVisible(), mReco.getRecoMethod(), &pers);
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
}
// 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
{
mTracker->delPoint((Vec2F) pos, direction, mAnimation->getCurrentFrameNum(), getOnlyVisible());
updateControlWidget();
}
void Petrack::editTrackPersonComment(QPointF pos)
{
mTracker->editTrackPersonComment((Vec2F) pos, mAnimation->getCurrentFrameNum(), getOnlyVisible());
updateControlWidget();
}
void Petrack::setTrackPersonHeight(QPointF pos)
{
mTracker->setTrackPersonHeight((Vec2F) pos, mAnimation->getCurrentFrameNum(), getOnlyVisible());
updateControlWidget();
}
void Petrack::resetTrackPersonHeight(QPointF pos)
{
mTracker->resetTrackPersonHeight((Vec2F) pos, mAnimation->getCurrentFrameNum(), getOnlyVisible());
updateControlWidget();
}
// direction zeigt an, ob bis zum aktuellen (-1), ab dem aktuellen (1) oder ganzer trackpath (0)
// loeschen von Trackpoints aller Trajektorien
void Petrack::deleteTrackPointAll(int direction) //const QPoint &pos
{
mTracker->delPointAll(direction, mAnimation->getCurrentFrameNum());
updateControlWidget();
}
void Petrack::deleteTrackPointROI()
{
mTracker->delPointROI();
updateControlWidget();
mScene->update();
}
void Petrack::deleteTrackPointInsideROI()
{
mTracker->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);
}
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
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"