Skip to content
Snippets Groups Projects
petrack.cpp 151 KiB
Newer Older
d.kilic's avatar
d.kilic committed
    mStatusLabelPos->setFont(f);
    mStatusLabelPos->setMinimumWidth(100);
    mStatusLabelColor->setFont(f);
    mStatusLabelColor->setMinimumWidth(90);
    mStatusLabelColor->setAutoFillBackground(true);
}

void Petrack::resetUI()
{
d.kilic's avatar
d.kilic committed
    ///
    ///  Reset all UI elements to default settings
    ///  Noetig damit alle UI Elemente, welche in der neu geladenen Projekt-Datei z.B. noch nicht vorhanden sind, auf
    ///  sinnvolle Werte gesetzt werden. Anderenfalls kommt es evtl. beim nacheinander laden verschiedener Projekte zu
    ///  einem Programmabsturz
d.kilic's avatar
d.kilic committed
    ///
    return;
d.kilic's avatar
d.kilic committed
    mSeqFileName = "";
    mAnimation->free();
d.kilic's avatar
d.kilic committed
    {
        mImage->fill(QColor::fromRgb(255, 255, 255));
d.kilic's avatar
d.kilic committed
        mImageItem->setImage(mImage);
        mLogoItem->show();
    }
    mStatusPosRealHeight->setValue(180.0);
    /// calibration params
    /// image filters
    mControlWidget->filterBrightContrast->setCheckState(Qt::Unchecked);
    mControlWidget->filterBrightParam->setValue(0);
    mControlWidget->filterContrastParam->setValue(0);

    mControlWidget->filterBorder->setCheckState(Qt::Unchecked);
    mControlWidget->filterBorderParamSize->setValue(0);
    QColor defaultBorder = Qt::black;
    getBorderFilter()->getBorderColR()->setValue(defaultBorder.red());
    getBorderFilter()->getBorderColG()->setValue(defaultBorder.green());
    getBorderFilter()->getBorderColB()->setValue(defaultBorder.blue());

    mControlWidget->filterBg->setCheckState(Qt::Unchecked);
    mControlWidget->filterBgDeleteNumber->setValue(3);
    mControlWidget->filterBgDeleteTrj->setCheckState(Qt::Checked);
    mControlWidget->filterBgShow->setCheckState(Qt::Unchecked);
    mControlWidget->filterBgUpdate->setCheckState(Qt::Unchecked);
    getBackgroundFilter()->setFilename(nullptr);
d.kilic's avatar
d.kilic committed
    getBackgroundFilter()->reset();

    mControlWidget->filterSwap->setCheckState(Qt::Unchecked);
    mControlWidget->filterSwapH->setCheckState(Qt::Unchecked);
    mControlWidget->filterSwapV->setCheckState(Qt::Unchecked);

    /// intrinsic params
    mControlWidget->apply->setCheckState(Qt::Unchecked);
    mControlWidget->fx->setValue(1000);
    mControlWidget->fy->setValue(1000);
    mControlWidget->cx->setValue(960);
    mControlWidget->cx->setMinimum(0);
    mControlWidget->cx->setMaximum(mControlWidget->cx->value() * 2);
d.kilic's avatar
d.kilic committed
    mControlWidget->cy->setValue(540);
    mControlWidget->cx->setMinimum(0);
    mControlWidget->cy->setMaximum(mControlWidget->cy->value() * 2);
d.kilic's avatar
d.kilic committed
    mControlWidget->r2->setValue(0);
    mControlWidget->r4->setValue(0);
    mControlWidget->r6->setValue(0);
    mControlWidget->tx->setValue(0);
    mControlWidget->ty->setValue(0);
    mControlWidget->k4->setValue(0);
    mControlWidget->k5->setValue(0);
    mControlWidget->k6->setValue(0);
    mControlWidget->s1->setValue(0);
    mControlWidget->s2->setValue(0);
    mControlWidget->s3->setValue(0);
    mControlWidget->s4->setValue(0);
    mControlWidget->taux->setValue(0);
    mControlWidget->tauy->setValue(0);
d.kilic's avatar
d.kilic committed
    mControlWidget->quadAspectRatio->setCheckState(Qt::Unchecked);
    mControlWidget->fixCenter->setCheckState(Qt::Unchecked);
    mControlWidget->tangDist->setCheckState(Qt::Checked);
    getAutoCalib()->setBoardSizeX(6);
    getAutoCalib()->setBoardSizeY(8);
    getAutoCalib()->setSquareSize(5.0);
    getAutoCalib()->setCalibFiles(QStringList());

    /// extrinsic params
    mControlWidget->trans1->setValue(0);
    mControlWidget->trans2->setValue(0);
    mControlWidget->trans3->setValue(-500);
    mControlWidget->rot1->setValue(0);
    mControlWidget->rot2->setValue(0);
    mControlWidget->rot3->setValue(0);
    getExtrCalibration()->setExtrCalibFile(nullptr);
d.kilic's avatar
d.kilic committed

    /// coord system
    mControlWidget->coordShow->setCheckState(Qt::Unchecked);
    mControlWidget->coordFix->setCheckState(Qt::Unchecked);
    mControlWidget->coordTab->setCurrentIndex(0);
    // 3D
    mControlWidget->coord3DTransX->setValue(0);
    mControlWidget->coord3DTransY->setValue(0);
    mControlWidget->coord3DTransZ->setValue(0);
    mControlWidget->coord3DAxeLen->setValue(200);
    mControlWidget->coord3DSwapX->setCheckState(Qt::Unchecked);
    mControlWidget->coord3DSwapY->setCheckState(Qt::Unchecked);
    mControlWidget->coord3DSwapZ->setCheckState(Qt::Unchecked);
    mControlWidget->extCalibPointsShow->setCheckState(Qt::Unchecked);
    mControlWidget->extVanishPointsShow->setCheckState(Qt::Unchecked);
    // 2D
    mControlWidget->coordTransX->setValue(0);
    mControlWidget->coordTransY->setValue(0);
    mControlWidget->coordRotate->setValue(0);
    mControlWidget->coordScale->setValue(100);
    mControlWidget->coordAltitude->setValue(535);
    mControlWidget->coordUnit->setValue(100);
    mControlWidget->coordUseIntrinsic->setCheckState(Qt::Unchecked);

    /// alignment grid
    mControlWidget->gridShow->setCheckState(Qt::Unchecked);
    mControlWidget->gridFix->setCheckState(Qt::Unchecked);
    mControlWidget->gridTab->setCurrentIndex(0);
    // 3D
    mControlWidget->grid3DTransX->setValue(0);
    mControlWidget->grid3DTransY->setValue(0);
    mControlWidget->grid3DTransZ->setValue(0);
    mControlWidget->grid3DResolution->setValue(100);
    // 2D
    mControlWidget->gridTransX->setValue(0);
    mControlWidget->gridTransY->setValue(0);
    mControlWidget->gridRotate->setValue(0);
    mControlWidget->gridScale->setValue(100);

    ///
    /// recognition params
    ///
    mControlWidget->performRecognition->setCheckState(Qt::Unchecked);
    mControlWidget->recoStep->setValue(1);

    // region of interest
    mControlWidget->roiFix->setCheckState(Qt::Unchecked);
    mControlWidget->roiShow->setCheckState(Qt::Unchecked);
    getRecoRoiItem()->setRect(0, 0, 0, 0);
d.kilic's avatar
d.kilic committed

    // marker, default multicolor marker (until 11/2016 hermes marker)
    mControlWidget->recoMethod->setCurrentIndex(
        mControlWidget->recoMethod->findData(QVariant::fromValue(reco::RecognitionMethod::MultiColor)));
d.kilic's avatar
d.kilic committed
    mControlWidget->markerBrightness->setValue(100);
    mControlWidget->markerIgnoreWithout->setCheckState(Qt::Checked);

    // size and color
    mControlWidget->recoShowColor->setCheckState(Qt::Checked);
    mControlWidget->recoAutoWB->setCheckState(Qt::Checked);
    mControlWidget->recoColorX->setCurrentIndex(0);
    mControlWidget->recoColorY->setCurrentIndex(1);
    mControlWidget->recoColorZ->setValue(255);
    mControlWidget->recoGreyLevel->setValue(50);
    mControlWidget->recoSymbolSize->setValue(10);

    // map
    mControlWidget->recoColorModel->setCurrentIndex(0);
    mControlWidget->colorPlot->getMapItem()->delMaps();
    mControlWidget->mapNr->setValue(0);
    mControlWidget->mapNr->setMinimum(0);
    mControlWidget->mapNr->setMaximum(0);
    mControlWidget->mapX->setValue(0);
    mControlWidget->mapY->setValue(0);
    mControlWidget->mapW->setValue(0);
    mControlWidget->mapH->setValue(0);
    mControlWidget->mapColor->setCheckState(Qt::Checked);
    mControlWidget->mapHeight->setValue(180);
    mControlWidget->mapDefaultHeight->setValue(180);

    ///
    /// tracking params
    ///
    mControlWidget->trackOnlineCalc->setCheckState(Qt::Checked);
    mControlWidget->trackRepeat->setCheckState(Qt::Checked);
    mControlWidget->trackRepeatQual->setValue(50);
    mControlWidget->trackExtrapolation->setCheckState(Qt::Checked);
    mControlWidget->trackMerge->setCheckState(Qt::Unchecked);
    mControlWidget->trackOnlySelected->setCheckState(Qt::Checked);
    getTrackRoiItem()->setRect(0, 0, 0, 0);
d.kilic's avatar
d.kilic committed

    // export options
    mControlWidget->trackMissingFrames->setCheckState(Qt::Checked);
    mControlWidget->trackRecalcHeight->setCheckState(Qt::Checked);
    mControlWidget->trackAlternateHeight->setCheckState(Qt::Unchecked);
    mControlWidget->exportElimTp->setCheckState(Qt::Unchecked);
    mControlWidget->exportElimTrj->setCheckState(Qt::Unchecked);
    mControlWidget->exportSmooth->setCheckState(Qt::Checked);
    mControlWidget->exportViewDir->setCheckState(Qt::Unchecked);
    mControlWidget->exportAngleOfView->setCheckState(Qt::Unchecked);
    mControlWidget->exportUseM->setCheckState(Qt::Unchecked);
    mControlWidget->exportComment->setCheckState(Qt::Unchecked);
    mControlWidget->exportMarkerID->setCheckState(Qt::Unchecked);

    // test options
    mControlWidget->testEqual->setCheckState(Qt::Checked);
    mControlWidget->testVelocity->setCheckState(Qt::Checked);
    mControlWidget->testInside->setCheckState(Qt::Checked);
    mControlWidget->testLength->setCheckState(Qt::Checked);
    setTrackFileName(nullptr);
d.kilic's avatar
d.kilic committed

    // search region
    mControlWidget->trackRegionScale->setValue(16);
    mControlWidget->trackRegionLevels->setValue(3);
    mControlWidget->trackErrorExponent->setValue(0);
    mControlWidget->trackShowSearchSize->setCheckState(Qt::Unchecked);

    // path params
    mControlWidget->trackShow->setCheckState(Qt::Checked);
    mControlWidget->trackFix->setCheckState(Qt::Unchecked);

    mControlWidget->trackShowOnlyVisible->setCheckState(Qt::Unchecked);
    mControlWidget->trackShowOnly->setCheckState(Qt::Unchecked);
    mControlWidget->trackShowOnlyNr->setValue(1);
    mControlWidget->trackShowOnlyList->setCheckState(Qt::Unchecked);
    mControlWidget->trackShowOnlyNrList->setEnabled(false);
    mControlWidget->trackShowOnlyListButton->setEnabled(false);

    mControlWidget->trackShowCurrentPoint->setCheckState(Qt::Checked);
    mControlWidget->trackShowPoints->setCheckState(Qt::Unchecked);
    mControlWidget->trackShowPath->setCheckState(Qt::Checked);
    mControlWidget->trackShowColColor->setCheckState(Qt::Checked);
    mControlWidget->trackShowColorMarker->setCheckState(Qt::Checked);
    mControlWidget->trackShowNumber->setCheckState(Qt::Checked);
    mControlWidget->trackShowGroundPosition->setCheckState(Qt::Unchecked);
    mControlWidget->trackShowGroundPath->setCheckState(Qt::Unchecked);

    mControlWidget->setTrackPathColor(Qt::red);
    mControlWidget->setTrackGroundPathColor(Qt::green);
    mControlWidget->trackHeadSized->setCheckState(Qt::Checked);
    mControlWidget->trackCurrentPointSize->setValue(60);
    mControlWidget->trackPointSize->setValue(7);
    mControlWidget->trackPathWidth->setValue(2);
    mControlWidget->trackColColorSize->setValue(11);
    mControlWidget->trackColorMarkerSize->setValue(14);
    mControlWidget->trackNumberSize->setValue(14);
    mControlWidget->trackGroundPositionSize->setValue(1);
    mControlWidget->trackGroundPathSize->setValue(1);

    mControlWidget->trackShowPointsColored->setCheckState(Qt::Checked);
    mControlWidget->trackNumberBold->setCheckState(Qt::Checked);
    mControlWidget->trackShowBefore->setValue(15);
    mControlWidget->trackShowAfter->setValue(15);

    /// analysis params
    mControlWidget->anaMissingFrames->setCheckState(Qt::Checked);
    mControlWidget->anaMarkAct->setCheckState(Qt::Unchecked);
    mControlWidget->anaStep->setValue(25);
    mControlWidget->anaConsiderX->setCheckState(Qt::Unchecked);
    mControlWidget->anaConsiderY->setCheckState(Qt::Checked);
    mControlWidget->anaConsiderAbs->setCheckState(Qt::Unchecked);
    mControlWidget->anaConsiderRev->setCheckState(Qt::Unchecked);
    mControlWidget->showVoronoiCells->setCheckState(Qt::Unchecked);
}

void Petrack::setStatusStereo(float x, float y, float z)
{
    if(mStatusLabelStereo)
d.kilic's avatar
d.kilic committed
    {
d.kilic's avatar
d.kilic committed
            mStatusLabelStereo->setText(QString("x= novalue  y= novalue  z= novalue  "));
d.kilic's avatar
d.kilic committed
        else
            mStatusLabelStereo->setText(
                QString("x=%1cm  y=%2cm  z=%3cm  ").arg(x, 6, 'f', 1).arg(y, 6, 'f', 1).arg(z, 6, 'f', 1));
d.kilic's avatar
d.kilic committed
    }
}

void Petrack::setStatusTime()
{
    if(mStatusLabelTime)
d.kilic's avatar
d.kilic committed
        mStatusLabelTime->setText(mAnimation->getTimeString());
d.kilic's avatar
d.kilic committed
}

void Petrack::setStatusFPS()
{
    if(mStatusLabelFPS)
d.kilic's avatar
d.kilic committed
    {
        mStatusLabelFPS->setText(QString("%1fps  ").arg(mShowFPS, 5, 'f', 1));

        QPalette pal = mStatusLabelFPS->palette(); // static moeglich?
d.kilic's avatar
d.kilic committed

        double diff    = mShowFPS - mAnimation->getFPS();
        int    opacity = mPlayerWidget->getPlayerSpeedLimited() ? 128 : 20;
d.kilic's avatar
d.kilic committed

        if(diff < -6) // very slow ==> red
            color.setRgb(200, 0, 0, opacity);
        else if(diff < -2) // better ==> yellow
            color.setRgb(200, 200, 0, opacity);
        else if(diff > -2) // nearly ok ==> green
            color.setRgb(0, 200, 0, opacity);
d.kilic's avatar
d.kilic committed

        pal.setColor(QPalette::Window, color);

        mStatusLabelFPS->setPalette(pal);
    }
}
void Petrack::setShowFPS(double fps)
{
    if((fps == 0.) || (mShowFPS == 0))
d.kilic's avatar
d.kilic committed
        mShowFPS = fps;
d.kilic's avatar
d.kilic committed
    else
        mShowFPS = mShowFPS * .9 + fps * .1; // glaetten durch Hinzunahme des alten Wertes
d.kilic's avatar
d.kilic committed
    setStatusFPS();
}

/**
 * @brief Updates the FPS shown to the User
 *
 * This method calculates the FPS by remembering how long
 * it has been since it was called last time. If skipped is
 * true, it doesn't directly update the FPS since 2
 * skipped frames have essentially a time delay of 0 between
 * them, which would make calculations wonky.
 *
 * @param skipped True, if this is a skipped frame; default false
 */
void Petrack::updateShowFPS(bool skipped)
{
    static QElapsedTimer lastTime;
    static int           skippedFrames = 0;
        skippedFrames++;
        return;
    }
d.kilic's avatar
d.kilic committed

    if(mPlayerWidget->getPaused())
d.kilic's avatar
d.kilic committed
    {
        setShowFPS(0.);
d.kilic's avatar
d.kilic committed
    }
    else
    {
        if(lastTime.isValid())
            if(lastTime.elapsed() > 0)
                int numFrames = skippedFrames > 0 ? skippedFrames + 1 : 1;
                setShowFPS(numFrames * 1000. / lastTime.elapsed());
                skippedFrames = 0;
d.kilic's avatar
d.kilic committed
    }
}

// ohne neue positionsangabe, sinnvoll, wenn berechnungsweise sich in getPosReal geaendert hat
// gebraucht in control.cpp
void Petrack::setStatusPosReal() // pos in cm
{
    if(mImageItem)
d.kilic's avatar
d.kilic committed
        setStatusPosReal(mImageItem->getPosReal(mMousePosOnImage, getStatusPosRealHeight()));
d.kilic's avatar
d.kilic committed
}
d.kilic's avatar
d.kilic committed
void Petrack::setStatusPosReal(const QPointF &pos) // pos in cm
{
    if(mStatusLabelPosReal)
d.kilic's avatar
d.kilic committed
    {
        QChar   deg(0xB0);
        QString labelText = QString(" cm from ground:%1cm,%2cm,%3")
                                .arg(pos.x(), 6, 'f', 1)
                                .arg(pos.y(), 6, 'f', 1)
                                .arg(
                                    getImageItem()->getAngleToGround(
                                        mMousePosOnImage.x(), mMousePosOnImage.y(), getStatusPosRealHeight()),
                                    5,
                                    'f',
                                    1);
d.kilic's avatar
d.kilic committed
        labelText.append(deg);
        mStatusLabelPosReal->setText(labelText);
    }
}
d.kilic's avatar
d.kilic committed
void Petrack::setStatusPos(const QPoint &pos) // pos in pixel
{
    mStatusLabelPos->setText(QString("%1x%2").arg(pos.x(), 4).arg(pos.y(), 4));
}
d.kilic's avatar
d.kilic committed
void Petrack::setStatusColor(const QRgb &col)
{
    QString s("#%1%2%3"); // static moeglich?
    s = s.arg(qRed(col), 2, 16, QChar('0')).arg(qGreen(col), 2, 16, QChar('0')).arg(qBlue(col), 2, 16, QChar('0'));
    if((qRed(col) + qGreen(col) + qBlue(col)) / 3 < 128)
d.kilic's avatar
d.kilic committed
        mStatusLabelColor->setText(QString("<font color=\"#ffffff\">&nbsp;%1</font>").arg(s));
d.kilic's avatar
d.kilic committed
    else
d.kilic's avatar
d.kilic committed
        mStatusLabelColor->setText(QString("<font color=\"#000000\">&nbsp;%1</font>").arg(s));
d.kilic's avatar
d.kilic committed

    QPalette pal = mStatusLabelColor->palette(); // static moeglich?
    QColor   color(qRed(col), qGreen(col), qBlue(col));
d.kilic's avatar
d.kilic committed

    pal.setColor(QPalette::Window, color);
    mStatusLabelColor->setPalette(pal);

    mControlWidget->getColorPlot()->setCursor(color);
    mControlWidget->getColorPlot()->replot();
}
d.kilic's avatar
d.kilic committed
void Petrack::setStatusColor()
{
    QPointF pos = getMousePosOnImage();
    if(pos.x() >= 0 && pos.x() < mImage->width() && pos.y() > 0 && pos.y() < mImage->height())
d.kilic's avatar
d.kilic committed
    {
        setStatusColor(mImage->pixel(pos.toPoint()));
d.kilic's avatar
d.kilic committed
    }
}

double Petrack::getStatusPosRealHeight()
{
    if(mStatusPosRealHeight)
d.kilic's avatar
d.kilic committed
        return mStatusPosRealHeight->value();
d.kilic's avatar
d.kilic committed
    else
d.kilic's avatar
d.kilic committed
        return 0.;
d.kilic's avatar
d.kilic committed
}

/**
 * @brief Reads (and applies) settings form platform-independent persistent storage
 *
 * The saved size and position of the application window get reconstructed. As well as
 * the options about antialiasing and the usage of OpenGL.
 * mSeqFileName and mProFileName get set, so the "Open Project" and "Open Sequence"
 * dialogues start at correct folder. The old project/sequence is NOT actually loaded.
 */
d.kilic's avatar
d.kilic committed
void Petrack::readSettings()
{
    QSettings settings("Forschungszentrum Juelich GmbH", "PeTrack by Maik Boltes, Daniel Salden");
    QPoint    pos  = settings.value("pos", QPoint(200, 200)).toPoint();
    QSize     size = settings.value("size", QSize(400, 400)).toSize();
d.kilic's avatar
d.kilic committed
    mAntialiasAct->setChecked(settings.value("antialias", false).toBool());
    mOpenGLAct->setChecked(settings.value("opengl", false).toBool());
    mSeqFileName = settings.value("seqFileName", QDir::currentPath()).toString();
    setProFileName(settings.value("proFilePath", QDir::currentPath()).toString());
    // nicht ganz sauber, da so immer schon zu anfang in calib file list etwas drin steht und somit auto ausgefuehrt
    // werden kann wird aber beim ersten openCalib... ueberschrieben
d.kilic's avatar
d.kilic committed
    mAutoCalib.addCalibFile(settings.value("calibFile", QDir::currentPath()).toString());
    resize(size);
    move(pos);
    antialias();
    opengl();
    mSplitter->restoreState(settings.value("controlSplitterSizes").toByteArray());
d.kilic's avatar
d.kilic committed
}

/**
 * @brief Writes persistent setting.
 * @see Petrack::readSettings
 */
d.kilic's avatar
d.kilic committed
void Petrack::writeSettings()
{
    QSettings settings("Forschungszentrum Juelich GmbH", "PeTrack by Maik Boltes, Daniel Salden");
    settings.setValue("pos", pos());
    settings.setValue("size", size());
    settings.setValue("antialias", mAntialiasAct->isChecked());
    settings.setValue("opengl", mOpenGLAct->isChecked());
    settings.setValue("seqFileName", mSeqFileName);
    settings.setValue("proFilePath", QFileInfo(mProFileName).path()); // nur path, damit bei saveCurrentProject
    if(!mAutoCalib.isEmptyCalibFiles())                               //! mCalibFiles.isEmpty()
d.kilic's avatar
d.kilic committed
        settings.setValue("calibFile", mAutoCalib.getCalibFile(0));
    settings.setValue("controlSplitterSizes", mSplitter->saveState());
d.kilic's avatar
d.kilic committed
}

bool Petrack::maybeSave()
{
    int ret = PWarning(
        this,
        tr("PeTrack"),
        tr("Do you want to save "
           "the current project?\n"
           "Be sure to save trajectories, background "
           "and 3D calibration point separately!"),
        PMessageBox::StandardButton::Yes | PMessageBox::StandardButton::No | PMessageBox::StandardButton::Cancel,
        PMessageBox::StandardButton::Yes);

    if(ret == PMessageBox::StandardButton::Yes)
d.kilic's avatar
d.kilic committed
    {
        if(saveSameProject())
d.kilic's avatar
d.kilic committed
            return true;
d.kilic's avatar
d.kilic committed
        else
d.kilic's avatar
d.kilic committed
            return false;
d.kilic's avatar
d.kilic committed
    }
    else if(ret == PMessageBox::StandardButton::Cancel)
d.kilic's avatar
d.kilic committed
        return false;
d.kilic's avatar
d.kilic committed
    else
d.kilic's avatar
d.kilic committed
        return true;
d.kilic's avatar
d.kilic committed
}

void Petrack::closeEvent(QCloseEvent *event)
{
    if(maybeSave())
d.kilic's avatar
d.kilic committed
    {
        writeSettings();
        event->accept();
    }
    else
d.kilic's avatar
d.kilic committed
        event->ignore();
d.kilic's avatar
d.kilic committed
}

/**
 * @brief Sets the mMousePosOnImage member variable and displayed pixel/real coordinates
 *
 * Gets called from ImageItem::hoverMoveEvent() and enables an easy access
 * to the mouse position.
 * @param pos Position of mouse cursor in image pixel coordinates
 */
d.kilic's avatar
d.kilic committed
void Petrack::setMousePosOnImage(QPointF pos)
{
d.kilic's avatar
d.kilic committed
    {
        mMousePosOnImage = pos;
        setStatusPosReal(mImageItem->getPosReal(pos, getStatusPosRealHeight()));

        // pixel coordinate
        QPoint pos1((int) (pos.x()) + 1, (int) (pos.y()) + 1);
        setStatusPos(pos1);
d.kilic's avatar
d.kilic committed
        // pixel color
        setStatusColor();
d.kilic's avatar
d.kilic committed
    }
}

void Petrack::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
        case Qt::Key_Left:
            mPlayerWidget->frameBackward();
            break;
        case Qt::Key_Right:
            mPlayerWidget->frameForward();
            break;
        case Qt::Key_Down:
            mViewWidget->zoomOut(1);
            break;
        case Qt::Key_Up:
            mViewWidget->zoomIn(1);
            break;
        case Qt::Key_Space:
            // space wird von buttons, wenn focus drauf ist als Aktivierung vorher abgegriffen und nicht durchgereicht
            mPlayerWidget->togglePlayPause();
            break;
        case Qt::Key_D:
            break;
        default:;
d.kilic's avatar
d.kilic committed
    }
}

void Petrack::mousePressEvent(QMouseEvent *event)
{
    // mouse click in fps status label ?
    if(event->pos().x() >= mStatusLabelFPS->pos().x() &&
       event->pos().x() <= mStatusLabelFPS->pos().x() + mStatusLabelFPS->width())
d.kilic's avatar
d.kilic committed
    {
        mPlayerWidget->togglePlayerSpeedLimited();
d.kilic's avatar
d.kilic committed
        setStatusFPS();
    }
}

/// update control widget, if image size changed (especially because of changing border)
void Petrack::updateControlImage(cv::Mat &img)
d.kilic's avatar
d.kilic committed
{
    // auch moeglich hoehe und breite von bild stat border veraenderungen zu checken
    static int lastBorderSize = -1;

    if(isLoading())
d.kilic's avatar
d.kilic committed
        lastBorderSize = -1;
d.kilic's avatar
d.kilic committed

    int diffBorderSize = 0;
    int iW             = img.cols;
    int iH             = img.rows;
d.kilic's avatar
d.kilic committed

    // wird auch nochmal in ImageWidget gemacht, aber ist hier frueher noetig
    double cX = mControlWidget->getCalibCxValue(); // merken, da min/max value verandernkann wenn aus dem rahmen
    double cY = mControlWidget->getCalibCyValue();

    mControlWidget->setCalibCxMin(0 /*iW/2.-50.*/);
d.kilic's avatar
d.kilic committed
    mControlWidget->setCalibCxMax(iW /*iW/2.+50.*/);
    mControlWidget->setCalibCyMin(0 /*iH/2.-50.*/);
d.kilic's avatar
d.kilic committed
    mControlWidget->setCalibCyMax(iH /*iH/2.+50.*/);

    if(mControlWidget->fixCenter->checkState() == Qt::Checked)
d.kilic's avatar
d.kilic committed
    {
        mControlWidget->setCalibCxValue((iW - 1) / 2.);
        mControlWidget->setCalibCyValue((iH - 1) / 2.);
d.kilic's avatar
d.kilic committed
    }
    else
    {
        if(lastBorderSize != -1)
            diffBorderSize = getImageBorderSize() - lastBorderSize;
d.kilic's avatar
d.kilic committed
        lastBorderSize = getImageBorderSize();

        mControlWidget->setCalibCxValue(cX + diffBorderSize);
        mControlWidget->setCalibCyValue(cY + diffBorderSize);
d.kilic's avatar
d.kilic committed
    }
}

void Petrack::importTracker(QString dest) // default = ""
d.kilic's avatar
d.kilic committed
{
    static QString lastFile;

    if(lastFile == "")
d.kilic's avatar
d.kilic committed
        lastFile = mTrcFileName;
d.kilic's avatar
d.kilic committed

    // if no destination file or folder is given
    if(dest.isEmpty())
d.kilic's avatar
d.kilic committed
    {
        dest = QFileDialog::getOpenFileName(
            this,
            tr("Select file for importing tracking pathes"),
            lastFile,
            tr("PeTrack tracker (*.trc *.txt);;All files (*.*)"));
d.kilic's avatar
d.kilic committed
    }

    if(!dest.isEmpty())
d.kilic's avatar
d.kilic committed
    {
        if(dest.right(4) == ".trc")
d.kilic's avatar
d.kilic committed
        {
            QFile file(dest);
d.kilic's avatar
d.kilic committed

            if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
d.kilic's avatar
d.kilic committed
            {
                // errorstring ist je nach Betriebssystem in einer anderen Sprache!!!!
                PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString()));
d.kilic's avatar
d.kilic committed
                return;
            }

            setTrackChanged(true); // flag changes of track parameters
d.kilic's avatar
d.kilic committed
            mTracker->reset();

            QTextStream in(&file);
            TrackPerson tp;
            QString     comment;
d.kilic's avatar
d.kilic committed

            bool    ok; // shows if int stands in first line - that was in the first version of trc file
d.kilic's avatar
d.kilic committed
            QString firstLine = in.readLine();
            sz                = firstLine.toInt(&ok);
            if(!ok)
d.kilic's avatar
d.kilic committed
            {
                if(firstLine.contains("version 4", Qt::CaseInsensitive))
                else if(firstLine.contains("version 3", Qt::CaseInsensitive))
d.kilic's avatar
d.kilic committed
                {
                    trcVersion = 3;
                else if(firstLine.contains("version 2", Qt::CaseInsensitive))
d.kilic's avatar
d.kilic committed
                {
                    trcVersion = 2;
d.kilic's avatar
d.kilic committed
                {
                    debout << "Error: wrong header while reading TRC file." << std::endl;
                    QMessageBox::critical(
                        this,
                        tr("PeTrack"),
                        tr("Could not import tracker:\nNot supported trc version in file: %1.").arg(dest));
d.kilic's avatar
d.kilic committed
                }
                in >> sz;
            }
            else
d.kilic's avatar
d.kilic committed
                trcVersion = 1;
d.kilic's avatar
d.kilic committed

            if((sz > 0) && (mPersonStorage.nbPersons() != 0))
                debout << "Warning: Overlapping trajectories will be joined not until tracking adds new trackpoints."
                       << std::endl;
            for(i = 0; i < sz; ++i)
d.kilic's avatar
d.kilic committed
            {
                if(trcVersion == 2)
d.kilic's avatar
d.kilic committed
                {
                    in >> tp;
                }
                else if(trcVersion >= 3)
d.kilic's avatar
d.kilic committed
                {
                    in >> tp;
                }
                mPersonStorage.addPerson(tp);
                tp.clear(); // loeschen, sonst immer weitere pfade angehangen werden
d.kilic's avatar
d.kilic committed
            }

            mControlWidget->trackNumberAll->setText(QString("%1").arg(mPersonStorage.nbPersons()));
            mControlWidget->trackShowOnlyNr->setMaximum(MAX(mPersonStorage.nbPersons(), 1));
            mControlWidget->trackNumberVisible->setText(
                QString("%1").arg(mPersonStorage.visible(mAnimation->getCurrentFrameNum())));
d.kilic's avatar
d.kilic committed
            mControlWidget->colorPlot->replot();
            file.close();
            debout << "import " << dest << " (" << sz << " person(s), file version " << trcVersion << ")" << std::endl;
            mTrcFileName =
                dest; // fuer Project-File, dann koennte track path direkt mitgeladen werden, wenn er noch da ist
        }
        else if(dest.right(4) == ".txt") // 3D Koordinaten als Tracking-Daten importieren Zeilenformat: Personennr,
                                         // Framenr, x, y, z
d.kilic's avatar
d.kilic committed
        {
            PWarning(
                this,
                tr("PeTrack"),
                tr("Are you sure you want to import 3D data from TXT-File? You have to make sure that the coordinate "
                   "system now is exactly at the same position and orientation than at export time!"));
d.kilic's avatar
d.kilic committed

            QFile file(dest);
            // size of person list
            int sz = 0;

            if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
d.kilic's avatar
d.kilic committed
            {
                // errorstring ist je nach Betriebssystem in einer anderen Sprache!!!!
                PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString()));
d.kilic's avatar
d.kilic committed
                return;
            }

            setTrackChanged(true); // flag changes of track parameters
d.kilic's avatar
d.kilic committed
            mTracker->reset();

            QTextStream in(&file);
            TrackPerson tp;
            TrackPoint  tPoint;
d.kilic's avatar
d.kilic committed

            QString line;
            QString headerline;
            bool    exec_once_flag        = false;
            double  conversionFactorTo_cm = 1.0;
            int     personNr = -1, frameNr = -1, current_personNr = 1;
            float   x, y, z;
d.kilic's avatar
d.kilic committed

d.kilic's avatar
d.kilic committed
            {
                // Falls Datei am Ende letzte Person abspeichern und Lese-Schleife beenden
                if(in.atEnd())
d.kilic's avatar
d.kilic committed
                {
                    tp.setLastFrame(frameNr);
                    mPersonStorage.addPerson(tp);
d.kilic's avatar
d.kilic committed
                    ++sz;
                    tp.clear();
                    break;
                }

                line = in.readLine();

                // Kommentare ueberlesen
                if(line.startsWith("#", Qt::CaseInsensitive))
d.kilic's avatar
d.kilic committed
                {
                    headerline = line;
                    continue;
                }

                if((!exec_once_flag) && (!headerline.contains("cm")))
d.kilic's avatar
d.kilic committed
                {
                    conversionFactorTo_cm = 100.0;
                    exec_once_flag        = true;
                    PWarning(
                        this,
                        tr("PeTrack"),
                        tr("PeTrack will interpret position data as unit [m]. No header with [cm] found."));
d.kilic's avatar
d.kilic committed
                }

                QTextStream stream(&line);

                // Zeile als Stream einlesen Format: [id frame x y z]
                stream >> personNr >> frameNr >> x >> y >> z;
d.kilic's avatar
d.kilic committed

                // convert data to cm
                x = x * conversionFactorTo_cm;
                y = y * conversionFactorTo_cm;
                z = z * conversionFactorTo_cm;

                // 3-dimensionale Berechnung/Anzeige des Punktes
                if(mControlWidget->getCalibCoordDimension() == 0)
d.kilic's avatar
d.kilic committed
                {
                    p2d = mExtrCalibration.getImagePoint(cv::Point3f(x, y, z));
d.kilic's avatar
d.kilic committed
                }
                // 2-dimensionale Berechnung/Anzeige des Punktes
                else
                {
                    QPointF pos = mImageItem->getPosImage(QPointF(x, y), z);
                    p2d.x       = pos.x();
                    p2d.y       = pos.y();
d.kilic's avatar
d.kilic committed
                }

                tPoint = TrackPoint(Vec2F(p2d.x, p2d.y), 100);
                tPoint.setSp(
                    x,
                    y,
                    -mControlWidget->getCalibExtrTrans3() -
                        z); // fuer den Abstand zur Kamera in z-Richtung wie bei einer Stereokamera
d.kilic's avatar
d.kilic committed

                // Neue ID ? ==> letzte Person beendet ==> abspeichern
                if(personNr > current_personNr)
d.kilic's avatar
d.kilic committed
                {
                    mPersonStorage.addPerson(tp);
d.kilic's avatar
d.kilic committed
                    ++sz;
                    current_personNr++;
                    tp.clear();
                }

                // TrackPerson leer ? ==> Neue TrackPerson erstellen
                if(tp.isEmpty())
d.kilic's avatar
d.kilic committed
                {
                    tp = TrackPerson(personNr, frameNr, tPoint);
                    tp.setFirstFrame(frameNr);
                    tp.setHeight(z);
                }
                // TrackPoint an TrackPerson anhaengen
                else
                {
                    tp.setLastFrame(frameNr);
                    tp.append(tPoint);
                }
            }

            mControlWidget->trackNumberAll->setText(QString("%1").arg(mPersonStorage.nbPersons()));
            mControlWidget->trackShowOnlyNr->setMaximum(MAX(mPersonStorage.nbPersons(), 1));
            mControlWidget->trackNumberVisible->setText(
                QString("%1").arg(mPersonStorage.visible(mAnimation->getCurrentFrameNum())));
d.kilic's avatar
d.kilic committed
            mControlWidget->colorPlot->replot();
            file.close();
            debout << "import " << dest << " (" << sz << " person(s) )" << std::endl;
            mTrcFileName =
                dest; // fuer Project-File, dann koennte track path direkt mitgeladen werden, wenn er noch da ist
d.kilic's avatar
d.kilic committed
        }
        else
        {
            PCritical(this, tr("PeTrack"), tr("Cannot load %1 maybe because of wrong file extension.").arg(dest));
d.kilic's avatar
d.kilic committed
        }
        lastFile = dest;
    }
}

void Petrack::testTracker()
{
    static int idx = 0; // index in Fehlerliste, die als letztes angesprungen wurde
d.kilic's avatar
d.kilic committed
    QList<int> pers, frame;

    mPersonStorage.checkPlausibility(
        pers,
        frame,
        mControlWidget->testEqual->isChecked(),
        mControlWidget->testVelocity->isChecked(),
        mControlWidget->testInside->isChecked(),
        mControlWidget->testLength->isChecked());
    if(pers.length() <= idx)
    if(pers.length() > idx)
d.kilic's avatar
d.kilic committed
    {
        mControlWidget->trackShowOnly->setCheckState(Qt::Checked);
        mControlWidget->trackShowOnlyNr->setValue(pers[idx]);
        mPlayerWidget->skipToFrame(frame[idx]);
d.kilic's avatar
d.kilic committed
        ++idx;
    }
}

int Petrack::calculateRealTracker()
{
    bool autoCorrectOnlyExport = (mReco.getRecoMethod() == reco::RecognitionMethod::MultiColor) && // multicolor
                                 mMultiColorMarkerWidget->autoCorrect->isChecked() &&
                                 mMultiColorMarkerWidget->autoCorrectOnlyExport->isChecked();
    int anz = mTrackerReal->calculate(
        mTracker,
        mImageItem,
        mControlWidget->getColorPlot(),
        getImageBorderSize(),
        mControlWidget->anaMissingFrames->checkState(),
        mStereoWidget->stereoUseForExport->isChecked(),
        mControlWidget->trackAlternateHeight->checkState(),
        mControlWidget->coordAltitude->value(),
        mStereoWidget->stereoUseCalibrationCenter->isChecked(),
        mControlWidget->exportElimTp->isChecked(),
        mControlWidget->exportElimTrj->isChecked(),
        mControlWidget->exportSmooth->isChecked(),
        mControlWidget->exportViewDir->isChecked(),
        mControlWidget->exportAngleOfView->isChecked(),
        mControlWidget->exportMarkerID->isChecked(),
        autoCorrectOnlyExport);
d.kilic's avatar
d.kilic committed

    mTrackerReal->calcMinMax();
    return anz;
}

void Petrack::exportTracker(QString dest) // default = ""
d.kilic's avatar
d.kilic committed
{
    static QString lastFile;

    if(lastFile == "")
d.kilic's avatar
d.kilic committed
        lastFile = mTrcFileName;
d.kilic's avatar
d.kilic committed

d.kilic's avatar
d.kilic committed
    {
        // if no destination file or folder is given
        if(dest.isEmpty())
d.kilic's avatar
d.kilic committed
        {
            QFileDialog fileDialog(
                this,
                tr("Select file for exporting tracking pathes"),
                lastFile,
                tr("Tracker (*.*);;Petrack tracker (*.trc);;Text (*.txt);;Text for gnuplot(*.dat);;XML Travisto "
                   "(*.trav);;All supported types (*.txt *.trc *.dat *.trav *.);;All files (*.*)"));
d.kilic's avatar
d.kilic committed
            fileDialog.setAcceptMode(QFileDialog::AcceptSave);
            fileDialog.setFileMode(QFileDialog::AnyFile);
            fileDialog.setDefaultSuffix("");

            if(fileDialog.exec())
            {
d.kilic's avatar
d.kilic committed
                dest = fileDialog.selectedFiles().at(0);
            }
d.kilic's avatar
d.kilic committed

        if(!dest.isEmpty())
d.kilic's avatar
d.kilic committed
        {
            QList<int> pers, frame;
            bool autoCorrectOnlyExport = (mReco.getRecoMethod() == reco::RecognitionMethod::MultiColor) && // multicolor
                                         mMultiColorMarkerWidget->autoCorrect->isChecked() &&
                                         mMultiColorMarkerWidget->autoCorrectOnlyExport->isChecked();
d.kilic's avatar
d.kilic committed

            if(dest.right(4) == ".trc")
d.kilic's avatar
d.kilic committed
            {
#ifdef TIME_MEASUREMENT
                double time1 = 0.0, tstart;
                tstart       = clock();
d.kilic's avatar
d.kilic committed
#endif
                QTemporaryFile file;

                if(!file.open() /*!file.open(QIODevice::WriteOnly | QIODevice::Text)*/)
d.kilic's avatar
d.kilic committed
                {
                    PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString()));
d.kilic's avatar
d.kilic committed
                    return;
                }
                QProgressDialog progress("Export TRC-File", nullptr, 0, mPersonStorage.nbPersons() + 1, this->window());
d.kilic's avatar
d.kilic committed
                progress.setWindowTitle("Export .trc-File");
                progress.setWindowModality(Qt::WindowModal);
                progress.setVisible(true);
                progress.setValue(0);
                progress.setLabelText(QString("Export tracking data ..."));

                qApp->processEvents();

                trcVersion = 4;
d.kilic's avatar
d.kilic committed

                debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons()
                       << " person(s), file version " << trcVersion << ")..." << std::endl;
d.kilic's avatar
d.kilic committed
                QTextStream out(&file);

                out << "version " << trcVersion << Qt::endl;
                out << mPersonStorage.nbPersons() << Qt::endl;
                const auto &persons = mPersonStorage.getPersons();
                for(size_t i = 0; i < persons.size(); ++i)
d.kilic's avatar
d.kilic committed
                {