Skip to content
Snippets Groups Projects
petrack.cpp 141 KiB
Newer Older
d.kilic's avatar
d.kilic committed
    debout << "go  update: " << getElapsedTime() <<endl;
#endif

    mCodeMarkerItem->resetSavedMarkers();

d.kilic's avatar
d.kilic committed
    static int lastRecoFrame = -10000;
    static bool borderChangedForTracking = false;
d.kilic's avatar
d.kilic committed
    // 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
d.kilic's avatar
d.kilic committed
        if (imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
        {
            if (mStereoContext)
                mStereoContext->init(mImgFiltered);
        }
d.kilic's avatar
d.kilic committed

#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;
d.kilic's avatar
d.kilic committed
            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;
d.kilic's avatar
d.kilic committed
        }
        else
        {
#ifndef STEREO_DISABLED
d.kilic's avatar
d.kilic committed
            // 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);
            }
d.kilic's avatar
d.kilic committed
        }
        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)
            {
d.kilic's avatar
d.kilic committed
                size.width = mImgFiltered.cols;
                size.height = mImgFiltered.rows;
                mTracker->resize(size);

                mTrackingRoiItem->checkRect();
            }
#ifndef STEREO_DISABLED
d.kilic's avatar
d.kilic committed
            // buildt disparity picture if it should be used for height detection
            if (mStereoContext && mStereoWidget->stereoUseForHeight->isChecked())
                mStereoContext->getDisparity();
d.kilic's avatar
d.kilic committed

d.kilic's avatar
d.kilic committed
            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,
d.kilic's avatar
d.kilic committed
                                      mControlWidget->trackRepeat->isChecked(),
d.kilic's avatar
d.kilic committed
                                      mControlWidget->trackRepeatQual->value(), getImageBorderSize(),
                                      mReco.getRecoMethod(), mControlWidget->trackRegionLevels->value(),
                                      getOnlyVisible());
d.kilic's avatar
d.kilic committed
#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
d.kilic's avatar
d.kilic committed
            // 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
d.kilic's avatar
d.kilic committed
            if (borderChanged)
                mRecognitionRoiItem->checkRect();
d.kilic's avatar
d.kilic committed
            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;
                auto recoMethod = mReco.getRecoMethod();
d.kilic's avatar
d.kilic committed
#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());
d.kilic's avatar
d.kilic committed
                }
#ifndef STEREO_DISABLED
d.kilic's avatar
d.kilic committed
                if (mStereoContext && mStereoWidget->stereoUseForReco->isChecked())
                {
                    PersonList pl;
                    pl.calcPersonPos(mImgFiltered, rect, &persList, mStereoContext, getBackgroundFilter(), markerLess);
d.kilic's avatar
d.kilic committed
                }
d.kilic's avatar
d.kilic committed
#ifdef TIME_MEASUREMENT
                //        "==========: "
                debout << "nach  reco: " << getElapsedTime() <<endl;
#endif
                mTracker->addPoints(persList, frameNum, mReco.getRecoMethod());
d.kilic's avatar
d.kilic committed
                // 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;
d.kilic's avatar
d.kilic committed
                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);
d.kilic's avatar
d.kilic committed

        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)
d.kilic's avatar
d.kilic committed
{
    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());

d.kilic's avatar
d.kilic committed
    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
d.kilic's avatar
d.kilic committed
{
    return mCmPerPixel;
}

/**
 * @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!
 * @param hS new headsize, if hS==-1 mHeadSize will be calculated instead of set
d.kilic's avatar
d.kilic committed
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(),
d.kilic's avatar
d.kilic committed
                                                            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) );
d.kilic's avatar
d.kilic committed

            diff = (int) std::max(sqrt(pow(p3d_x2.x-p3d_x1.x,2)+pow(p3d_x2.y-p3d_x1.y,2)),
d.kilic's avatar
d.kilic committed
                           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;
        }
    }

    if (pos != nullptr)
d.kilic's avatar
d.kilic committed
        return mHeadSize; // muss noch aus density map gelesen werden!!!
    else //(pos == NULL) && (pers == -1)
        return mHeadSize;

}

d.kilic's avatar
d.kilic committed
/**
 * @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
 */
d.kilic's avatar
d.kilic committed
QSet<int> Petrack::getOnlyVisible()
{
    if  ((mControlWidget->trackOnlySelected->checkState() == Qt::Checked) && (mControlWidget->trackShowOnly->checkState() == Qt::Checked || mControlWidget->trackShowOnlyList->checkState() == Qt::Checked))
d.kilic's avatar
d.kilic committed
    {
        if( mControlWidget->trackShowOnlyList->checkState() == Qt::Checked)
        {
            QStringList list = mControlWidget->trackShowOnlyNrList->text().split(",", Qt::SkipEmptyParts);
d.kilic's avatar
d.kilic committed
            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);
d.kilic's avatar
d.kilic committed
                    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;
d.kilic's avatar
d.kilic committed
            }
            return onlyVisible; //in anzeige wird ab 1 gezaehlt, in datenstruktur ab 0
d.kilic's avatar
d.kilic committed

        }else
d.kilic's avatar
d.kilic committed
        {
            QSet<int> onlyVisible;
            onlyVisible.insert(mControlWidget->trackShowOnlyNr->value()-1);
            return onlyVisible;
        }
    }else
        return QSet<int>();
}

void Petrack::addManualTrackPointOnlyVisible(const QPointF& pos)
d.kilic's avatar
d.kilic committed
{
    int pers = addOrMoveManualTrackPoint(pos)+1;
d.kilic's avatar
d.kilic committed
    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)
d.kilic's avatar
d.kilic committed
{
    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);
    updateControlWidget();
    return pers;
d.kilic's avatar
d.kilic committed
}

// 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());
d.kilic's avatar
d.kilic committed
}

// delta gibt menge an Umdrehungen und richtung an
void Petrack::skipToFrameWheel(int delta)
{
    mPlayerWidget->skipToFrame(mPlayerWidget->getPos()+delta);
}
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"