Newer
Older
/*
* PeTrack - Software for tracking pedestrians movement in videos
* Copyright (C) 2010-2020 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 "petrack.h"
#include "control.h"
#include "view.h"
#include "trackerItem.h"
#include "tracker.h"
#include "recognitionRoiItem.h"
#include "trackingRoiItem.h"
// in x und y gleichermassen skaliertes koordinatensystem,
// da von einer vorherigen intrinsischen kamerakalibrierung ausgegenagen wird,
// so dass pixel quadratisch
TrackerItem::TrackerItem(QWidget *wParent, Tracker *tracker, QGraphicsItem * parent)
: QGraphicsItem(parent)
{
mMainWindow = (class Petrack*) wParent;
mControlWidget = mMainWindow->getControlWidget();
mTracker = tracker;
}
/**
* @brief Bounding box of drawn to area.
*
* This bounding box is used to determine if this Item needs to be redrawn or not.
* See the official Qt Docs for QGraphicsItem
*
* @return (updated) bounding rect of this item
*/
QRectF TrackerItem::boundingRect() const
{
if (mMainWindow->getImage())
return QRectF(-mMainWindow->getImageBorderSize(), -mMainWindow->getImageBorderSize(), mMainWindow->getImage()->width(), mMainWindow->getImage()->height());
else
return QRectF(0, 0, 0, 0);
}
void TrackerItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
if( !(event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::AltModifier) )
{
TrackPoint p((Vec2F) event->pos(), 110); // 110 ist ueber 100 (hoechste Qualitaetsstufe) und wird nach einfuegen auf 100 gesetzt
bool found = false;
int i, iNearest = -1;
float dist, minDist = 1000000.;
QSet<int> onlyVisible = mMainWindow->getOnlyVisible();
int frame = mMainWindow->getAnimation()->getCurrentFrameNum();
for (i = 0; i < mTracker->size(); ++i) // !found && // ueber TrackPerson
if (((onlyVisible.empty()) || (onlyVisible.contains(i))) && mTracker->at(i).trackPointExist(frame))
dist = mTracker->at(i).trackPointAt(frame).distanceToPoint(p);
if (( dist < mMainWindow->getHeadSize(nullptr, i, frame)/2.) ||
( (mTracker->at(i).trackPointAt(frame).distanceToPoint(p.colPoint()) < mMainWindow->getHeadSize(nullptr, i, frame)/2.)))
debout << "Warning: more possible trackpoints for point" << std::endl;
debout << " " << p << " in frame " << frame << " with low distance:" << std::endl;
debout << " person " << i+1 << " (distance: " << dist << "), " << std::endl;
debout << " person " << iNearest+1 << " (distance: " << minDist << "), " << std::endl;
if (minDist > dist)
{
minDist = dist;
iNearest = i;
}
}
else
// WAR: break inner loop
found = true;
QMenu menu;
TrackPerson tp;
float height = 0.f;
bool height_set_by_user = false;
QAction *delTrj = nullptr, *delFutureTrj = nullptr, *delPastTrj = nullptr, *creTrj = nullptr, *infoTrj = nullptr, *addComment = nullptr, *setHeight = nullptr, *resetHeight = nullptr;
i = iNearest;
tp = mTracker->at(i);
height = tp.height();
if (height < MIN_HEIGHT+1)
{
if (tp.color().isValid())
height = mControlWidget->getColorPlot()->map(tp.color());
}else
{
height_set_by_user = true;
}
infoTrj = menu.addAction(QString("PersonNr: %1 height: %2 frames: [%3..%4]").arg(i+1).arg(height).arg(tp.firstFrame()).arg(tp.lastFrame()));
delTrj = menu.addAction("Delete whole trajectory");
delFutureTrj = menu.addAction("Delete past part of the trajectory");
delPastTrj = menu.addAction("Delete future part of the trajectory");
setHeight = menu.addAction("Set person height");
if(height_set_by_user) resetHeight = menu.addAction("Reset height");
addComment = menu.addAction("Edit comment");
}
else
creTrj = menu.addAction("Create new trajectory");
QAction *selectedAction = menu.exec(event->screenPos());
if( selectedAction == creTrj )
mMainWindow->addOrMoveManualTrackPoint(event->scenePos());
}else if( selectedAction == delTrj )
mMainWindow->deleteTrackPoint(event->scenePos(),0);
}else if( selectedAction == delFutureTrj )
mMainWindow->deleteTrackPoint(event->scenePos(),-1);
}else if( selectedAction == delPastTrj )
mMainWindow->deleteTrackPoint(event->scenePos(),1);
}else if( selectedAction == addComment )
{
mMainWindow->editTrackPersonComment(event->scenePos());
}else if( selectedAction == setHeight )
{
mMainWindow->setTrackPersonHeight(event->scenePos());
}else if( selectedAction == resetHeight )
{
mMainWindow->resetTrackPersonHeight(event->scenePos());
}else if( selectedAction == infoTrj )
{
if (found)
{
QString out;
QMessageBox msgBox;
msgBox.setText(QString("Info for trajectory number %1:").arg(i+1));
if(height_set_by_user)
{
out = QString("<table>"
"<tr><td>height:</td><td>%0 cm (edited by user)</td></tr>"
"<tr><td>frames:</td><td>[%1...%2]</td></tr>"
"<tr><td>color:</td><td><font style='display:inline;background:%3;color:#fff;'>%4</font></td></tr>"
"<tr><td>comment:</td><td>%5</td></tr>"
"<tr><td></td><td></td></tr>");
}
else
{
out = QString("<table>"
"<tr><td>height:</td><td>%0 cm</td></tr>"
"<tr><td>frames:</td><td>[%1...%2]</td></tr>"
"<tr><td>color:</td><td><font style='display:inline;background:%3;color:#fff;'>%4</font></td></tr>"
"<tr><td>comment:</td><td>%5</td></tr>"
"<tr><td></td><td></td></tr>");
}
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
if( tp.lastFrame()-tp.firstFrame() > 5 )
{
out.append(QString("<tr><td>frame [%6]:</td><td>[%7, %8]</td></tr>"
"<tr><td>frame [%9]:</td><td>[%10, %11]</td></tr>"
"<tr><td colspan='2'>...</td></tr>"
"<tr><td colspan='2'>...</td></tr>"
"<tr><td>frame [%12]:</td><td>[%13, %14]</td></tr>"
"<tr><td>frame [%15]:</td><td>[%16, %17]]</td></tr>"
"</table>").toLatin1());
msgBox.setInformativeText( out.arg(height)
.arg(tp.firstFrame())
.arg(tp.lastFrame())
.arg(tp.color().name())
.arg(tp.color().name())
.arg(tp.comment())
.arg(tp.firstFrame())
.arg(tp.at(0).x())
.arg(tp.at(0).y())
.arg(tp.firstFrame()+1)
.arg(tp.at(1).x())
.arg(tp.at(1).y())
.arg(tp.lastFrame()-1)
.arg(tp.at(tp.size()-2).x())
.arg(tp.at(tp.size()-2).y())
.arg(tp.lastFrame())
.arg(tp.at(tp.size()-1).x())
.arg(tp.at(tp.size()-1).y()));
}
else
{
out.append(QString("</table>"));
msgBox.setInformativeText( out.arg(height)
.arg(tp.firstFrame())
.arg(tp.lastFrame())
.arg(tp.color().name())
.arg(tp.color().name())
.arg(tp.comment()));
}
out = QString();
for(int frameTrackperson=tp.firstFrame(); frameTrackperson <= tp.lastFrame(); frameTrackperson++)
{
out.append(QString("frame [%0]: [%1, %2]\n").arg(frameTrackperson).arg(tp.at(frameTrackperson - tp.firstFrame()).x()).arg(tp.at(frameTrackperson - tp.firstFrame()).y()));
}
msgBox.setDetailedText(out);
msgBox.setWindowTitle("PeTrack");
msgBox.setIcon(QMessageBox::Information);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setEscapeButton(QMessageBox::Ok);
msgBox.exec();
}
void TrackerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
{
int from, to;
int curFrame = mMainWindow->getAnimation()->getCurrentFrameNum();
QPen ellipsePen;
QRectF rect;
Vec2F n;
int i, j;
QPen linePen;
QPen numberPen;
QPen groundPositionPen;
QPen groundPathPen;
double pSP = (double) mControlWidget->trackCurrentPointSize->value();
double pS = (double) mControlWidget->trackPointSize->value();
double pSC = (double) mControlWidget->trackColColorSize->value();
double pSM = (double) mControlWidget->trackColorMarkerSize->value();
double pSN = (double) mControlWidget->trackNumberSize->value();
double pSG = (double) mControlWidget->trackGroundPositionSize->value();
double pSGP = (double) mControlWidget->trackGroundPathSize->value();
QColor pGPC = mControlWidget->getTrackGroundPathColor();
QColor pTPC = mControlWidget->getTrackPathColor();
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
QFont font, heightFont;
float x_offset=0, y_offset=0;
float y_switch=0, x_switch=0;
double hS;
painter->drawRect( boundingRect() );
linePen.setColor(pTPC);
linePen.setWidth(mControlWidget->trackPathWidth->value());
ellipsePen.setWidth(3);
if (mControlWidget->trackNumberBold->checkState() == Qt::Checked)
font.setBold(true);
else
font.setBold(false);
font.setPixelSize(mControlWidget->trackNumberSize->value());
heightFont.setPixelSize(mControlWidget->trackColColorSize->value());
painter->setFont(font);
numberPen.setColor(Qt::red);
groundPositionPen.setColor(Qt::green);
groundPositionPen.setWidth(pSG);
groundPathPen.setColor(pGPC);
groundPathPen.setWidth(pSGP);
if(mControlWidget->showVoronoiCells->isChecked() && !mTracker->isEmpty())
{
// ToDo: adjust subdiv rect to correct area
QRectF qrect = mMainWindow->getRecoRoiItem()->rect();
cv::Point3f leftTop = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(qrect.left(),qrect.top()),0);
cv::Point3f rightBottom = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(qrect.right(),qrect.bottom()),0);
x_offset = -std::min(leftTop.x,rightBottom.x);
y_offset = -std::min(leftTop.y,rightBottom.y);
x_switch = rightBottom.x < leftTop.x ? abs(rightBottom.x-leftTop.x) : 0;
y_switch = rightBottom.y < leftTop.y ? abs(leftTop.y-rightBottom.y) : 0;
debout << "x_offset: " << x_offset << ", y_offset: " << y_offset << ", x_switch: " << x_switch << ", y_switch: " << y_switch << std::endl;
cv::Rect rect(cv::Rect(leftTop.x+x_offset,leftTop.y+y_offset,x_switch>0 ? x_switch : (rightBottom.x-leftTop.x),y_switch>0 ? y_switch : (rightBottom.y-leftTop.y)));
debout << "Rect size: P(" << rect.x << ", " << rect.y << "), width: " << rect.width << ", height: " << rect.height << std::endl;
subdiv.initDelaunay(rect);
}
for (i = 0; i < mTracker->size(); ++i) // ueber TrackPerson
{
// show current frame
if ((!(mControlWidget->trackShowOnly->checkState() == Qt::Checked) && !(mControlWidget->trackShowOnlyList->checkState() == Qt::Checked)) ||
(((mControlWidget->trackShowOnly->checkState() == Qt::Checked) || (mControlWidget->trackShowOnlyList->checkState() == Qt::Checked)) &&
mMainWindow->getOnlyVisible().contains((i))))
{
if (mTracker->at(i).trackPointExist(curFrame))
{
if (mControlWidget->trackHeadSized->checkState() == Qt::Checked)
pSP = mMainWindow->getHeadSize(nullptr, i, curFrame); //headSize;
const TrackPoint &tp = (*mTracker)[i][curFrame-mTracker->at(i).firstFrame()];
if (mControlWidget->trackShowCurrentPoint->checkState() == Qt::Checked) //(mControlWidget->recoShowColor->checkState() == Qt::Checked)
{
painter->setBrush(Qt::NoBrush);
if (mTracker->at(i).newReco())
painter->setPen(Qt::green);
else
painter->setPen(Qt::blue);
rect.setRect(tp.x()-pSP/2., tp.y()-pSP/2., pSP, pSP);
painter->drawEllipse(rect); // direkt waere nur int erlaubt tp.x()-5., tp.y()-5., 10., 10.
}
if (mControlWidget->trackShowSearchSize->checkState() == Qt::Checked)
{
painter->setBrush(Qt::NoBrush);
painter->setPen(Qt::yellow);
hS = mMainWindow->winSize(nullptr, i, curFrame);
if (hS < 2)
hS = 2; // entspricht Vorgehen in tracker.cpp
for (j = 0; j <= mControlWidget->trackRegionLevels->value(); ++j)
{
rect.setRect(tp.x()-hS/2., tp.y()-hS/2., hS, hS);
painter->drawRect(rect);
if (mControlWidget->trackShowColorMarker->checkState() == Qt::Checked)
{
// farbe des trackpoints
if (tp.color().isValid())
{
painter->setBrush(Qt::NoBrush);
ellipsePen.setColor(tp.color());
painter->setPen(ellipsePen);
rect.setRect(tp.colPoint().x()-pSM/2., tp.colPoint().y()-pSM/2., pSM, pSM);
painter->drawEllipse(rect);
}
}
// berechnung der normalen, die zur positionierung der nummerieung und der gesamtfarbe dient
if (((mControlWidget->trackShowColColor->checkState() == Qt::Checked) && (mTracker->at(i).color().isValid())) ||
(mControlWidget->trackShowNumber->checkState() == Qt::Checked) ||
((mControlWidget->trackShowColColor->checkState() == Qt::Checked) &&
((mTracker->at(i).height() > MIN_HEIGHT) || ((tp.sp().z() > 0.) && (mControlWidget->trackShowHeightIndividual->checkState() == Qt::Checked))))) // Hoehe kann auf Treppen auch negativ werden, wenn koord weiter oben angesetzt wird
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
{
if (tp.color().isValid())
{
n = (tp-tp.colPoint()).normal();
n.normalize();
if (n.length()<.001) // wenn to und colpoint aufeinander liegen z bei colorMarker!
n.set(1., 0.);
}
else
{
// man koennte auch lastNormal von anderem trackpath nehmen statt 1, 0
n.set(1., 0.);
// den vorherigen trackpoint finden, wo reco farbe erzeugt hat und somit colpoint vorliegt
for (j = curFrame-mTracker->at(i).firstFrame(); j > -1; --j)
if (mTracker->at(i).at(j).color().isValid())
{
n = (mTracker->at(i).at(j)-mTracker->at(i).at(j).colPoint()).normal();
n.normalize();
break;
}
// einen nachfolgenden trackpoint suchen, wenn vorher keiner mit farbe war
// zB wenn rueckwaerts abgespielt wird
if ((n.x()==1.) && (n.y()==0.))
{
for (j = curFrame-mTracker->at(i).firstFrame()+1; j < mTracker->at(i).size(); ++j)
if (mTracker->at(i).at(j).color().isValid())
{
n = (mTracker->at(i).at(j)-mTracker->at(i).at(j).colPoint()).normal();
n.normalize();
break;
}
}
}
}
// farbe der gesamten trackperson
double height = mTracker->at(i).height();
if (mControlWidget->trackShowColColor->checkState() == Qt::Checked)
{
painter->setPen(numberPen);
painter->setBrush(Qt::NoBrush);
rect.setRect(tp.x()+10,tp.y()+10,15*pSC,10*pSC);
painter->drawText(rect,mTracker->at(i).comment());
rect.setRect(tp.x()-pSC,tp.y()-pSC,50,50);
painter->drawText(rect,QString("id=%1").arg(tp.getMarkerID()));
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
}
}
if ((mControlWidget->trackShowColColor->checkState() == Qt::Checked) && (mTracker->at(i).color().isValid()))
{
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(mTracker->at(i).color()));
rect.setRect(tp.x()+(pSP+pSC)*0.6*n.x()-pSC/2., tp.y()+(pSP+pSC)*0.6*n.y()-pSC/2., pSC, pSC); // 11
painter->drawEllipse(rect);
}
else if ((mControlWidget->trackShowColColor->checkState() == Qt::Checked) &&
((height > MIN_HEIGHT) || ((tp.sp().z() > 0.) && (mControlWidget->trackShowHeightIndividual->checkState() == Qt::Checked)))) // Hoehe && (mTracker->at(i).height() > 0.) Hoehe kann auf Treppen auch negativ werden, wenn koord weiter oben angesetzt wird
{
painter->setFont(heightFont);
if ((mControlWidget->trackShowHeightIndividual->checkState() == Qt::Checked) && (tp.sp().z() > 0.)) // Hoehe incl individual fuer jeden trackpoint
{
painter->setPen(numberPen);
painter->setBrush(Qt::NoBrush);
rect.setRect(tp.x()+(pSP+pSC)*0.6*n.x()-pSC/2., tp.y()+(pSP+pSC)*0.6*n.y()-pSC/2., 3*pSC, 2.5*pSC); // 11
if (height < MIN_HEIGHT+1)
{
if (mControlWidget->getCalibCoordDimension() == 0) // 3D
painter->drawText(rect, Qt::AlignHCenter, QString("-\n%2").arg(-mControlWidget->getCalibExtrTrans3()-tp.sp().z(), 6, 'f', 1));
else
painter->drawText(rect, Qt::AlignHCenter, QString("-\n%2").arg(mControlWidget->coordAltitude->value()-tp.sp().z(), 6, 'f', 1));
}else
{
if (mControlWidget->getCalibCoordDimension() == 0) // 3D
painter->drawText(rect, Qt::AlignHCenter, QString("%1\n%2").arg(height, 6, 'f', 1).arg(-mControlWidget->getCalibExtrTrans3()-tp.sp().z(), 6, 'f', 1));
else
painter->drawText(rect, Qt::AlignHCenter, QString("%1\n%2").arg(height, 6, 'f', 1).arg(mControlWidget->coordAltitude->value()-tp.sp().z(), 6, 'f', 1));
}
}
else
{
painter->setPen(numberPen);
painter->setBrush(Qt::NoBrush);
rect.setRect(tp.x()+(pSP+pSC)*0.6*n.x()-pSC/2., tp.y()+(pSP+pSC)*0.6*n.y()-pSC/2., 3*pSC, 2*pSC); // 11
painter->drawText(rect, Qt::AlignHCenter, QString("%1").arg(height, 6, 'f', 1));
}
painter->setFont(font);
}
if (mControlWidget->trackShowNumber->checkState() == Qt::Checked)
{
// listennummer
painter->setPen(numberPen);
painter->setBrush(Qt::NoBrush);
rect.setRect(tp.x()-(pSP+pSN)*0.6*n.x()-pSN, tp.y()-(pSP+pSN)*0.6*n.y()-pSN/2., 2.*pSN, pSN); // 11
painter->drawText(rect, Qt::AlignHCenter, QString("%1").arg(i+1));
}
if (mControlWidget->trackShowGroundPosition->checkState() == Qt::Checked)
{
// ground position
painter->setPen(groundPositionPen);
painter->setBrush(Qt::NoBrush);
if( mControlWidget->getCalibCoordDimension() == 0) // 3D
{
double cross_size = 15+pSG*0.25;
p3d_height = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(tp.x(),tp.y()),mControlWidget->getColorPlot()->map(mTracker->at(i).color()));
p3d_height = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(tp.x(),tp.y()),-mControlWidget->getCalibExtrTrans3()-tp.sp().z());
p3d_height = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(tp.x(),tp.y()),height/*mControlWidget->mapDefaultHeight->value()*/);
cv::Point2f p2d_ground = mMainWindow->getExtrCalibration()->getImagePoint(p3d_height);
QPointF axis = mMainWindow->getImageItem()->getCmPerPixel(p2d_ground.x, p2d_ground.y, 0);
painter->drawLine(QLineF(p2d_ground.x-cross_size*0.5*pow(axis.x(),-1),p2d_ground.y-cross_size*0.5*pow(axis.y(),-1),p2d_ground.x+cross_size*0.5*pow(axis.x(),-1),p2d_ground.y+cross_size*0.5*pow(axis.y(),-1)));
painter->drawLine(QLineF(p2d_ground.x-cross_size*0.5*pow(axis.x(),-1),p2d_ground.y+cross_size*0.5*pow(axis.y(),-1),p2d_ground.x+cross_size*0.5*pow(axis.x(),-1),p2d_ground.y-cross_size*0.5*pow(axis.y(),-1)));
painter->drawLine(QLineF(p2d_ground.x,p2d_ground.y,tp.x(),tp.y()));
}else // 2D
{
}
}
if( mControlWidget->showVoronoiCells->checkState() == Qt::Checked)
{
if( mControlWidget->getCalibCoordDimension() == 0 ) // 3D
{
p3d_height = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(tp.x(),tp.y()),mControlWidget->getColorPlot()->map(mTracker->at(i).color()));
p3d_height = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(tp.x(),tp.y()),-mControlWidget->getCalibExtrTrans3()-tp.sp().z());
p3d_height = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(tp.x(),tp.y()),height/*mControlWidget->mapDefaultHeight->value()*/);
debout << "insert P(" << p3d_height.x+x_offset << ", " << p3d_height.y+y_offset << ") to subdiv" << std::endl;
subdiv.insert(cv::Point2f(x_switch>0 ? x_switch-p3d_height.x+x_offset : p3d_height.x+x_offset, y_switch>0 ? y_switch-p3d_height.y+y_offset : p3d_height.y+y_offset));// p2d_ground);
}
}
}
if (((mControlWidget->trackShowPoints->checkState() == Qt::Checked) || (mControlWidget->trackShowPath->checkState() == Qt::Checked) || (mControlWidget->trackShowGroundPath->checkState() == Qt::Checked)) && ((mTracker->at(i).trackPointExist(curFrame)) || (mControlWidget->trackShowOnlyVisible->checkState() == Qt::Unchecked)))
{
if (mControlWidget->trackShowBefore->value() == -1)
from = 0;
else
{
from = curFrame-mTracker->at(i).firstFrame()-mControlWidget->trackShowBefore->value();
if (from < 0)
from = 0;
}
if (mControlWidget->trackShowAfter->value() == -1)
to = mTracker->at(i).size();
else
{
to = curFrame-mTracker->at(i).firstFrame()+mControlWidget->trackShowAfter->value()+1;
if (to > mTracker->at(i).size())
to = mTracker->at(i).size();
}
for (j = from; j < to; ++j) // ueber TrackPoint
{
// path
if (mControlWidget->trackShowPath->checkState() == Qt::Checked)
{
if (j != from) // autom. > 0
{
painter->setPen(linePen);
painter->setBrush(Qt::NoBrush);
// nur Linie zeichnen, wenn x oder y sich unterscheidet, sonst Punkt
// die Unterscheidung ist noetig, da Qt sonst grosses quadrat beim ranzoomen zeichnet
if ((mTracker->at(i).at(j-1).toQPointF().x() != mTracker->at(i).at(j).toQPointF().x()) ||
(mTracker->at(i).at(j-1).toQPointF().y() != mTracker->at(i).at(j).toQPointF().y()))
painter->drawLine(mTracker->at(i).at(j-1).toQPointF(), mTracker->at(i).at(j).toQPointF());
else
painter->drawPoint(mTracker->at(i).at(j-1).toQPointF());
}
}
// path on ground
if (mControlWidget->trackShowGroundPath->checkState() == Qt::Checked)
{
if (j != from)
{
// ground position
painter->setPen(groundPathPen);
painter->setBrush(Qt::NoBrush);
if( mControlWidget->getCalibCoordDimension() == 0) // 3D
{
cv::Point3f p3d_height_p1, p3d_height_p2;
p3d_height_p1 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(i).at(j-1).x(),mTracker->at(i).at(j-1).y()),mControlWidget->getColorPlot()->map(mTracker->at(i).color()));
p3d_height_p2 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(i).at(j).x(),mTracker->at(i).at(j).y()),mControlWidget->getColorPlot()->map(mTracker->at(i).color()));
}else
{
if ( mTracker->at(i).at(j-1).sp().z() > 0 && mTracker->at(i).at(j).sp().z() > 0 )
{
p3d_height_p1 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(i).at(j-1).x(),mTracker->at(i).at(j-1).y()),-mControlWidget->getCalibExtrTrans3()-mTracker->at(i).at(j-1).sp().z());
p3d_height_p2 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(i).at(j).x(),mTracker->at(i).at(j).y()),-mControlWidget->getCalibExtrTrans3()-mTracker->at(i).at(j).sp().z());
p3d_height_p1 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(i).at(j-1).x(),mTracker->at(i).at(j-1).y()),mTracker->at(i).height());
p3d_height_p2 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(mTracker->at(i).at(j).x(),mTracker->at(i).at(j).y()),mTracker->at(i).height());
cv::Point2f p2d_ground_p1 = mMainWindow->getExtrCalibration()->getImagePoint(p3d_height_p1);
cv::Point2f p2d_ground_p2 = mMainWindow->getExtrCalibration()->getImagePoint(p3d_height_p2);
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
// nur Linie zeichnen, wenn x oder y sich unterscheidet, sonst Punkt
// die Unterscheidung ist noetig, da Qt sonst grosses quadrat beim ranzoomen zeichnet
if (p2d_ground_p1.x != p2d_ground_p2.x || p2d_ground_p1.y != p2d_ground_p2.y )
painter->drawLine(QLineF(p2d_ground_p1.x,p2d_ground_p1.y,p2d_ground_p2.x,p2d_ground_p2.y));
else
painter->drawPoint(p2d_ground_p1.x,p2d_ground_p1.y);
}else // 2D
{
}
}
}
// points before and after
if (mControlWidget->trackShowPoints->checkState() == Qt::Checked)
{
if (mTracker->at(i).firstFrame()+j != curFrame)
{
if ((mControlWidget->trackShowPointsColored->checkState() == Qt::Checked) && (mTracker->at(i).at(j).color().isValid()))
{
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(mTracker->at(i).at(j).color()));
rect.setRect(mTracker->at(i).at(j).x()-pS/2., mTracker->at(i).at(j).y()-pS/2., pS, pS); // 7
}
else
{
painter->setPen(Qt::red);
painter->setBrush(Qt::NoBrush);
// war noetig fuer alte qt-version: rect.setRect(mTracker->at(i).at(j).x()-(pS-1.)/2., mTracker->at(i).at(j).y()-(pS-1.)/2., pS-1., pS-1.); // 6
rect.setRect(mTracker->at(i).at(j).x()-pS/2., mTracker->at(i).at(j).y()-pS/2., pS, pS);
}
painter->drawEllipse(rect);
}
}
}
}
}
}
// Mat& img, Subdiv2D& subdiv )
if( mControlWidget->showVoronoiCells->checkState() == Qt::Checked && !mTracker->isEmpty() )
{
std::vector<std::vector<cv::Point2f> > facets3D;
std::vector<cv::Point2f> centers3D;
// get Voronoi cell info from subDiv in 3D coordinates on ground (z=0)
subdiv.getVoronoiFacetList(std::vector<int>(), facets3D, centers3D);
painter->setClipRect(mMainWindow->getRecoRoiItem()->rect());//0,0,mMainWindow->getImage()->width(),mMainWindow->getImage()->height());
// cell by cell
for( size_t i = 0; i < facets3D.size(); i++ )
{
centers3D.at(i).x = x_switch>0 ? x_switch-centers3D.at(i).x-x_offset : centers3D.at(i).x-x_offset;
centers3D.at(i).y = y_switch>0 ? y_switch-centers3D.at(i).y-y_offset : centers3D.at(i).y-y_offset;
// voronoi cell center in 2D
cv::Point2f center2D = mMainWindow->getExtrCalibration()->getImagePoint(cv::Point3f(centers3D.at(i).x,
QPointF circleStart, circleEnd;
float area = 0;
float r = 50, m = 0, n = 0, s1_x = 0, s2_x = 0, s1_y = 0, s2_y = 0;
bool circleStarted = false;
for( size_t j = 0; j < facets3D[i].size(); j++ )
{
facets3D.at(i).at(j).x = x_switch>0 ? x_switch-facets3D.at(i).at(j).x-x_offset : facets3D.at(i).at(j).x-x_offset;
facets3D.at(i).at(j).y = y_switch>0 ? y_switch-facets3D.at(i).at(j).y-y_offset : facets3D.at(i).at(j).y-y_offset;
cv::Point2f point2D = mMainWindow->getExtrCalibration()->getImagePoint(cv::Point3f(facets3D.at(i).at(j).x,facets3D.at(i).at(j).y,0));
debout << "facets3D.at(" << i << ").at(" << j << ").x = " << facets3D.at(i).at(j).x << ", .y = " << facets3D.at(i).at(j).y << std::endl;
debout << "point2D.x = " << point2D.x << " , .y = " << point2D.y << std::endl;
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
if ( false && sqrt(pow((facets3D.at(i).at(j).x - centers3D.at(i).x),2) +
pow((facets3D.at(i).at(j).y - centers3D.at(i).y),2)) > r )
{
if (circleStarted)
{
m = (facets3D.at(i).at(j).y - facets3D.at(i).at((j-1)%facets3D.at(i).size()).y) /
(facets3D.at(i).at(j).x - facets3D.at(i).at((j-1)%facets3D.at(i).size()).x);
// End punkt berechnen (Schnittpunkt Gerade-Kreis)
// Steigung der Geraden
m = (facets3D.at(i).at(j).y - facets3D.at(i).at((j+1)%facets3D.at(i).size()).y) /
(facets3D.at(i).at(j).x - facets3D.at(i).at((j+1)%facets3D.at(i).size()).x);
// Achsenabschnitt der Geraden
n = facets3D.at(i).at(j).y - m * facets3D.at(i).at(j).x;
float p = -( (m*n - m*centers3D.at(i).y - centers3D.at(i).x)/(1+pow(m,2)) );
float q = sqrt((pow(r,2)-pow(centers3D.at(i).x,2)-pow(centers3D.at(i).y,2)-pow(n,2)-2*n*centers3D.at(i).y) / (1+pow(m,2)) +
pow((m*n-m*centers3D.at(i).y-centers3D.at(i).x)/(1+pow(m,2)),2));
// Schnittpunkte mit Kreis
s1_x = p + q;
s1_y = m*s1_x+n;
s2_x = p - q;
s2_y = m*s2_x+n;
facets3D[i][j] = cv::Point2f(s1_x,s1_y);
point2D = mMainWindow->getExtrCalibration()->getImagePoint(cv::Point3f(s1_x,s1_y,0));
circleEnd = QPointF(point2D.x,point2D.y);
ifacet2D.push_back(QPointF(center2D.x,center2D.y));
ifacet2D.push_back(QPointF(point2D.x,point2D.y));
debout << "End point: (" << s1_x << ", " << s1_y << ")" << std::endl;
}else
{
// start punkt berechnen
m = (facets3D.at(i).at(j).y - facets3D.at(i).at((j-1)%facets3D.at(i).size()).y) /
(facets3D.at(i).at(j).x - facets3D.at(i).at((j-1)%facets3D.at(i).size()).x);
n = facets3D.at(i).at(j).y - m * facets3D.at(i).at(j).x;
float p = -( (m*n - m*centers3D.at(i).y - centers3D.at(i).x)/(1+pow(m,2)) );
float q = sqrt((pow(r,2)-pow(centers3D.at(i).x,2)-pow(centers3D.at(i).y,2)-pow(n,2)-2*n*centers3D.at(i).y) / (1+pow(m,2)) +
pow((m*n-m*centers3D.at(i).y-centers3D.at(i).x)/(1+pow(m,2)),2));
// Schnittpunkte mit Kreis
s1_x = p + q;
s1_y = m*s1_x+n;
s2_x = p - q;
s2_y = m*s2_x+n;
debout << "x=" << s1_x << " G(x)=" << (m*s1_x+n) << " K(x)=" << pow(s1_x-centers3D.at(i).x,2)+pow(s1_y-centers3D.at(i).y,2) << " = " << pow(r,2) << std::endl;
debout << "x=" << s2_x << " G(x)=" << (m*s2_x+n) << " K(x)=" << pow(s2_x-centers3D.at(i).x,2)+pow(s2_y-centers3D.at(i).y,2) << " = " << pow(r,2) << std::endl;
facets3D[i][j] = cv::Point2f(s1_x,s1_y);
point2D = mMainWindow->getExtrCalibration()->getImagePoint(cv::Point3f(s1_x,s1_y,0));
ifacet2D.push_back(QPointF(point2D.x,point2D.y));
circleStart = QPointF(point2D.x,point2D.y);
circleStarted = true;
debout << "Start point: (" << s1_x << ", " << s1_y << ")" << std::endl;
}
}else
{
ifacet2D.push_back(QPointF(point2D.x,point2D.y));
area += (facets3D.at(i).at(j).x*facets3D.at(i).at((j+1)%facets3D[i].size()).y);
area -= (facets3D.at(i).at((j+1)%facets3D[i].size()).x*facets3D.at(i).at(j).y);
}
}
area *= 0.5;
color.setHsv((255-area*25.5)<0?0:(255-area*25.5),255,255,128);
for(size_t i=0; i<ifacet2D.size(); i++)
painter->setBrush(color);
painter->setPen(Qt::black);
if( ifacet2D.size() == 0 )
painter->drawEllipse(QPointF(center2D.x,center2D.y),100,100);
painter->drawConvexPolygon(QPolygonF(ifacet_vec));
// voronoi cell point
painter->setBrush(Qt::black);
painter->setPen(Qt::red);
painter->drawEllipse(QPointF(center2D.x,center2D.y),5,5);
}
}
}