Skip to content
Snippets Groups Projects
trackerItem.cpp 47 KiB
Newer Older
/*
 * PeTrack - Software for tracking pedestrians movement in videos
 * Copyright (C) 2023 Forschungszentrum Jülich GmbH, IAS-7
 *
 * 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 "trackerItem.h"
d.kilic's avatar
d.kilic committed

Schrödter, Tobias's avatar
Schrödter, Tobias committed
#include "animation.h"
d.kilic's avatar
d.kilic committed
#include "control.h"
#include "logger.h"
#include "personStorage.h"
#include "petrack.h"
#include "tracker.h"
#include "view.h"

#include <QInputDialog>
#include <QtWidgets>
d.kilic's avatar
d.kilic committed

// in x und y gleichermassen skaliertes koordinatensystem,
// da von einer vorherigen intrinsischen kamerakalibrierung ausgegenagen wird,
// so dass pixel quadratisch
TrackerItem::TrackerItem(QWidget *wParent, PersonStorage &storage, QGraphicsItem *parent) :
    QGraphicsItem(parent), mPersonStorage(storage)
d.kilic's avatar
d.kilic committed
{
    mMainWindow    = (class Petrack *) wParent;
d.kilic's avatar
d.kilic committed
    mControlWidget = mMainWindow->getControlWidget();
}

/**
 * @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
 */
d.kilic's avatar
d.kilic committed
QRectF TrackerItem::boundingRect() const
{
    if(mMainWindow->getImage())
        return QRectF(
            -mMainWindow->getImageBorderSize(),
            -mMainWindow->getImageBorderSize(),
            mMainWindow->getImage()->width(),
            mMainWindow->getImage()->height());
d.kilic's avatar
d.kilic committed
    else
d.kilic's avatar
d.kilic committed
        return QRectF(0, 0, 0, 0);
d.kilic's avatar
d.kilic committed
}
void TrackerItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    if(!(event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier ||
         event->modifiers() & Qt::AltModifier))
d.kilic's avatar
d.kilic committed
    {
        TrackPoint p(
            (Vec2F) event->pos(),
            110); // 110 ist ueber 100 (hoechste Qualitaetsstufe) und wird nach einfuegen auf 100 gesetzt
        bool  found    = false;
        int   iNearest = -1;
        float dist, minDist = 1000000.;
d.kilic's avatar
d.kilic committed

d.kilic's avatar
d.kilic committed
        QSet<size_t> onlyVisible = mMainWindow->getPedestrianUserSelection();
        int          frame       = mMainWindow->getAnimation()->getCurrentFrameNum();
d.kilic's avatar
d.kilic committed

        const auto &persons = mPersonStorage.getPersons();
        size_t      i;
        for(i = 0; i < persons.size(); ++i)
d.kilic's avatar
d.kilic committed
        {
            const auto &person = persons[i];
            if(((onlyVisible.empty()) || (onlyVisible.contains(i))) && person.trackPointExist(frame))
d.kilic's avatar
d.kilic committed
            {
                dist = person.trackPointAt(frame).distanceToPoint(p);
d.kilic's avatar
d.kilic committed
                if((dist < mMainWindow->getHeadSize(nullptr, static_cast<int>(i), frame) / 2.) ||
                   ((person.trackPointAt(frame).distanceToPoint(p.colPoint()) <
d.kilic's avatar
d.kilic committed
                     mMainWindow->getHeadSize(nullptr, static_cast<int>(i), frame) / 2.)))
d.kilic's avatar
d.kilic committed
                {
                        SPDLOG_WARN("more possible TrackPoints for point");
                        SPDLOG_WARN("         {} in frame {} with low distance:", p, frame);
                        SPDLOG_WARN("         person {} (distance {}),", i + 1, dist);
                        SPDLOG_WARN("         person {} (distance {})", iNearest + 1, minDist);
                        if(minDist > dist)
                            minDist  = dist;
d.kilic's avatar
d.kilic committed
                            iNearest = static_cast<int>(i);
d.kilic's avatar
d.kilic committed
                    {
                        minDist  = dist;
d.kilic's avatar
d.kilic committed
                        iNearest = static_cast<int>(i);
                        // WAR: break inner loop
                        found = true;
d.kilic's avatar
d.kilic committed
                    }
                }
            }
        }
        QMenu    menu;
        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,
                *setMarkerID = nullptr;
d.kilic's avatar
d.kilic committed

d.kilic's avatar
d.kilic committed
        {
            i              = iNearest;
            TrackPerson tp = persons[i];
            height         = tp.height();
            if(height < MIN_HEIGHT + 1)
                if(tp.color().isValid())
                    height = mControlWidget->getColorPlot()->map(tp.color());
            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");
            setMarkerID  = menu.addAction("Set marker ID");
            if(height_set_by_user)
                resetHeight = menu.addAction("Reset height");
            addComment = menu.addAction("Edit comment");
d.kilic's avatar
d.kilic committed
        {
            creTrj = menu.addAction("Create new trajectory");
d.kilic's avatar
d.kilic committed
        }

        QAction *selectedAction = menu.exec(event->screenPos());
        if(selectedAction == nullptr)
        {
            return;
        }
        if(selectedAction == creTrj)
d.kilic's avatar
d.kilic committed
        {
            mMainWindow->addOrMoveManualTrackPoint(event->scenePos());
        }
        else if(selectedAction == delTrj)
d.kilic's avatar
d.kilic committed
        {
            mMainWindow->deleteTrackPoint(event->scenePos(), 0);
        }
        else if(selectedAction == delFutureTrj)
d.kilic's avatar
d.kilic committed
        {
            mMainWindow->deleteTrackPoint(event->scenePos(), -1);
        }
        else if(selectedAction == delPastTrj)
d.kilic's avatar
d.kilic committed
        {
            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 == setMarkerID)
        {
            int  currentID = mPersonStorage.getPersons()[i].getMarkerID();
            bool changeID  = true;

            if(currentID != -1)
            {
Loading
Loading full blame...