Skip to content
Snippets Groups Projects
petrack.cpp 149 KiB
Newer Older
  • Learn to ignore specific revisions
  •                     PCritical(
                            this,
                            tr("PeTrack"),
                            tr("Could not export tracking data.\n"
                               "Please try again!"));
    
    d.kilic's avatar
    d.kilic committed
                    else
    
    d.kilic's avatar
    d.kilic committed
                        statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    progress.setValue(mPersonStorage.nbPersons() + 1);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    std::cout << " finished " << std::endl;
    
    d.kilic's avatar
    d.kilic committed
    
    #ifdef TIME_MEASUREMENT
                    time1 += clock() - tstart;
    
                    time1 = time1 / CLOCKS_PER_SEC;
    
    d.kilic's avatar
    d.kilic committed
                    cout << "  time(copying) = " << time1 << " sec." << endl;
    
    //                time1 = 0.0;
    //                tstart = clock();
    #endif
    
    d.kilic's avatar
    d.kilic committed
    #ifdef TIME_MEASUREMENT
    //                time1 += clock() - tstart;
    //                time1 = time1/CLOCKS_PER_SEC;
    //                cout << "  time(checkPlausibility) = " << time1 << " sec." << endl;
    #endif
    
                    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 if(dest.right(4) == ".txt")
    
    d.kilic's avatar
    d.kilic committed
                {
                    QTemporaryFile file;
    
    
                    if(!file.open())
    
    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;
                    }
    
    
                    debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons() << " person(s))..."
    
    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
    
                    // recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend
                    // play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung
                    // einfliessen zu lassen)
                    if(mControlWidget->trackRecalcHeight->checkState())
    
    d.kilic's avatar
    d.kilic committed
                    {
    
                        if(mControlWidget->getCalibCoordDimension() == 0) // 3D
    
                            ; // Nothing to be done because z already the right height
    
                            mPersonStorage.recalcHeight(mControlWidget->coordAltitude->value());
    
    d.kilic's avatar
    d.kilic committed
                    }
    #ifdef TIME_MEASUREMENT
                    time1 += clock() - tstart;
    
                    time1 = time1 / CLOCKS_PER_SEC;
    
    d.kilic's avatar
    d.kilic committed
                    cout << "  time(recalcHeight) = " << time1 << " sec." << endl;
    
    
    d.kilic's avatar
    d.kilic committed
                    tstart = clock();
    
                    mTrackerReal->calculate(
                        mTracker,
                        mImageItem,
                        mControlWidget->getColorPlot(),
                        getImageBorderSize(),
                        mControlWidget->trackMissingFrames->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
    #ifdef TIME_MEASUREMENT
                    time1 += clock() - tstart;
    
                    time1 = time1 / CLOCKS_PER_SEC;
    
    d.kilic's avatar
    d.kilic committed
                    cout << "  time(calculate) = " << time1 << " sec." << endl;
    
    
    d.kilic's avatar
    d.kilic committed
                    tstart = clock();
    #endif
    
                    QTextStream out(&file);
    
    
                    out << "# PeTrack project: " << QFileInfo(getProFileName()).fileName() << Qt::endl;
    
                    out << "# raw trajectory file: " << QFileInfo(getTrackFileName()).fileName() << Qt::endl;
    
                    out << "# framerate: " << mAnimation->getFPS() << " fps" << Qt::endl;
    
    d.kilic's avatar
    d.kilic committed
    
    
                    if(mControlWidget->exportComment->isChecked())
    
    d.kilic's avatar
    d.kilic committed
                    {
    
                        out << "# personal information:" << Qt::endl;
                        out << "# ID| Comment" << Qt::endl;
    
    d.kilic's avatar
    d.kilic committed
    
                        // std out
    
                        std::cout << std::endl << "Printing comment table..." << std::endl << std::endl;
                        std::cout << "ID  | Comment" << std::endl;
                        std::cout << "----|----------------" << std::endl;
    
    d.kilic's avatar
    d.kilic committed
    
    
                        for(int i = 0; i < static_cast<int>(mPersonStorage.nbPersons()); ++i)
    
    d.kilic's avatar
    d.kilic committed
                        {
    
                            auto commentSplit = mPersonStorage.at(i).comment().split("\n", Qt::KeepEmptyParts);
    
                            out << "#" << qSetFieldWidth(3) << (i + 1) << qSetFieldWidth(0) << "|" << commentSplit.at(0)
                                << Qt::endl;
                            std::cout << std::setw(4) << (i + 1) << "|" << commentSplit.at(0) << std::endl;
    
    
                            commentSplit.pop_front();
    
                            for(const QString &line : commentSplit)
    
                            {
                                out << "#" << qSetFieldWidth(3) << " " << qSetFieldWidth(0) << "|" << line << Qt::endl;
                                std::cout << "    |" << line << std::endl;
                            }
    
    d.kilic's avatar
    d.kilic committed
                        }
                    }
    
                    mTrackerReal->exportTxt(
                        out,
                        mControlWidget->trackAlternateHeight->checkState(),
                        mStereoWidget->stereoUseForExport->isChecked(),
                        mControlWidget->exportViewDir->isChecked(),
                        mControlWidget->exportAngleOfView->isChecked(),
                        mControlWidget->exportUseM->isChecked(),
                        mControlWidget->exportMarkerID->isChecked());
                    // out << *mTrackerReal;
    
    d.kilic's avatar
    d.kilic committed
                    file.flush();
                    file.close();
    
    
                    if(QFile::exists(dest))
    
    d.kilic's avatar
    d.kilic committed
                        QFile::remove(dest);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    if(!file.copy(dest))
    
                        PCritical(
                            this,
                            tr("PeTrack"),
                            tr("Could not export tracking data.\n"
                               "Please try again!"));
    
    d.kilic's avatar
    d.kilic committed
                    else
    
    d.kilic's avatar
    d.kilic committed
                        statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    std::cout << " finished" << std::endl;
    
    d.kilic's avatar
    d.kilic committed
    
    #ifdef TIME_MEASUREMENT
                    time1 += clock() - tstart;
    
                    time1 = time1 / CLOCKS_PER_SEC;
    
    d.kilic's avatar
    d.kilic committed
                    cout << "  time(export) = " << time1 << " sec." << endl;
    
    //                time1 = 0.0;
    //                tstart = clock();
    #endif
    
    d.kilic's avatar
    d.kilic committed
    #ifdef TIME_MEASUREMENT
    //                time1 += clock() - tstart;
    //                time1 = time1/CLOCKS_PER_SEC;
    //                cout << "  time(checkPlausibility) = " << time1 << " sec." << endl;
    #endif
                }
    
                else if(dest.right(4) == ".dat")
    
    d.kilic's avatar
    d.kilic committed
                {
                    QTemporaryFile fileDat;
    
    
                    if(!fileDat.open()) //! fileDat.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(fileDat.errorString()));
    
    d.kilic's avatar
    d.kilic committed
                        return;
                    }
    
                    // recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend
                    // play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung
                    // einfliessen zu lassen)
                    if(mControlWidget->trackRecalcHeight->checkState())
    
    d.kilic's avatar
    d.kilic committed
                    {
    
                        mPersonStorage.recalcHeight(mControlWidget->coordAltitude->value());
    
    d.kilic's avatar
    d.kilic committed
                    }
    
                    mTrackerReal->calculate(
                        mTracker,
                        mImageItem,
                        mControlWidget->getColorPlot(),
                        getImageBorderSize(),
                        mControlWidget->trackMissingFrames->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);
    
    
                    debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons() << " person(s))..."
    
    d.kilic's avatar
    d.kilic committed
                    QTextStream outDat(&fileDat);
    
                    mTrackerReal->exportDat(
                        outDat,
                        mControlWidget->trackAlternateHeight->checkState(),
                        mStereoWidget->stereoUseForExport->isChecked());
    
    d.kilic's avatar
    d.kilic committed
                    fileDat.flush();
                    fileDat.close();
    
    
                    if(QFile::exists(dest))
    
    d.kilic's avatar
    d.kilic committed
                        QFile::remove(dest);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    if(!fileDat.copy(dest))
    
                        PCritical(
                            this,
                            tr("PeTrack"),
                            tr("Could not export tracking data.\n"
                               "Please try again!"));
    
    d.kilic's avatar
    d.kilic committed
                    else
    
    d.kilic's avatar
    d.kilic committed
                        statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    std::cout << " finished" << std::endl;
    
    d.kilic's avatar
    d.kilic committed
                }
    
                else if(dest.right(5) == ".trav")
    
    d.kilic's avatar
    d.kilic committed
                {
    
                    // recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend
                    // play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung
                    // einfliessen zu lassen)
                    if(mControlWidget->trackRecalcHeight->checkState())
    
    d.kilic's avatar
    d.kilic committed
                    {
    
                        mPersonStorage.recalcHeight(mControlWidget->coordAltitude->value());
    
    d.kilic's avatar
    d.kilic committed
                    }
    
    
                    mTrackerReal->calculate(
                        mTracker,
                        mImageItem,
                        mControlWidget->getColorPlot(),
                        getImageBorderSize(),
                        mControlWidget->trackMissingFrames->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
    
                    QTemporaryFile fileXml;
    
                    if(!fileXml.open()) //! fileXml.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(fileXml.errorString()));
    
    d.kilic's avatar
    d.kilic committed
                        return;
                    }
    
                    debout << "export tracking data to " << dest << " (" << mPersonStorage.nbPersons() << " person(s))..."
    
                           << std::endl;
                    // already done: mTrackerReal->calculate(mTracker, mImageItem, mControlWidget->getColorPlot(),
                    // getImageBorderSize(), mControlWidget->trackMissingFrames->checkState());
    
    d.kilic's avatar
    d.kilic committed
                    QTextStream outXml(&fileXml);
    
                    outXml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << Qt::endl;
                    outXml << "<trajectoriesDataset>" << Qt::endl;
                    outXml << "    <header version=\"1.0\">" << Qt::endl;
                    outXml << "        <roomCaption>PeTrack: " << mAnimation->getFileBase() << "</roomCaption>" << Qt::endl;
                    outXml << "        <roomID>0</roomID>" << Qt::endl;
    
                    outXml << "        <agents>" << mPersonStorage.nbPersons() << "</agents>" << Qt::endl;
    
                    outXml << "        <frameRate>" << mAnimation->getFPS() << "</frameRate> <!--per second-->" << Qt::endl;
    
                    // outXml << "        <timeStep>" << 1000./mAnimation->getFPS() << "</timeStep>   <!-- millisecond-->"
                    // << endl; inverse von
                    outXml << "        <timeFirstFrame sec=\"" << mAnimation->getFirstFrameSec() << "\" microsec=\""
                           << mAnimation->getFirstFrameMicroSec() << "\"/> <!-- " << mAnimation->getTimeString(0) << " -->"
                           << Qt::endl;
                    outXml << "    </header>" << Qt::endl << Qt::endl;
    
                    mTrackerReal->exportXml(
                        outXml,
                        mControlWidget->trackAlternateHeight->checkState(),
                        mStereoWidget->stereoUseForExport->isChecked());
    
    d.kilic's avatar
    d.kilic committed
    
    
                    outXml << "</trajectoriesDataset>" << Qt::endl;
    
    d.kilic's avatar
    d.kilic committed
                    fileXml.flush();
                    fileXml.close();
    
    
                    if(QFile::exists(dest))
    
    d.kilic's avatar
    d.kilic committed
                        QFile::remove(dest);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    if(!fileXml.copy(dest))
    
                        PCritical(
                            this,
                            tr("PeTrack"),
                            tr("Could not export tracking data.\n"
                               "Please try again!"));
    
    d.kilic's avatar
    d.kilic committed
                    else
    
    d.kilic's avatar
    d.kilic committed
                        statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    std::cout << " finished" << std::endl;
    
    d.kilic's avatar
    d.kilic committed
                }
                else
                { // wenn keine Dateiendung, dann wird trc und txt herausgeschrieben
                    exportTracker(dest + ".trc");
                    exportTracker(dest + ".txt");
                }
                lastFile = dest;
            }
        }
    }
    
    // fuer anschliessende groessenberechnung
    void Petrack::playAll()
    {
    
        int memPos  = mPlayerWidget->getPos();
    
    d.kilic's avatar
    d.kilic committed
        int progVal = 0;
    
        QProgressDialog progress("Playing whole sequence...", "Abort playing", 0, mAnimation->getNumFrames(), this);
        progress.setWindowModality(Qt::WindowModal); // blocks main window
    
        // vorwaertslaufen ab aktueller Stelle und trackOnlineCalc zum tracken nutzen
        do
        {
    
            progress.setValue(++progVal); // mPlayerWidget->getPos()
    
    d.kilic's avatar
    d.kilic committed
            qApp->processEvents();
    
            if(progress.wasCanceled())
    
    d.kilic's avatar
    d.kilic committed
                break;
    
        } while(mPlayerWidget->frameForward());
    
    d.kilic's avatar
    d.kilic committed
    
        mPlayerWidget->skipToFrame(memPos);
    }
    
    
    /**
     * @brief Activates tracking and reco; calcs through the video (in both ways)
     *
     * This method activates tracking and reco and plays the whole video (from current
     * frame on) till the end. Then, if mAutoBackTrack is set, it jumps back to the
     * largest first frame, i.e. the last time a new person was added/recognized, and
     * tracks backwards till the beginning of the video.
     *
     * The old settings for tracking and reco will be restored. No interaction with the
     * main window is possible for the time of tracking.
     */
    
    d.kilic's avatar
    d.kilic committed
    void Petrack::trackAll()
    {
    
        int                 memPos        = mPlayerWidget->getPos();
        int                 progVal       = 0;
    
    d.kilic's avatar
    d.kilic committed
        enum Qt::CheckState memCheckState = mControlWidget->trackOnlineCalc->checkState();
    
        enum Qt::CheckState memRecoState  = mControlWidget->performRecognition->checkState();
    
    d.kilic's avatar
    d.kilic committed
    
        mControlWidget->trackOnlineCalc->setCheckState(Qt::Checked);
        mControlWidget->performRecognition->setCheckState(Qt::Checked);
    
    
        QProgressDialog progress(
            "Tracking pedestrians through all frames...",
            "Abort tracking",
            0,
            2 * mAnimation->getNumFrames() - memPos,
            this);
    
    d.kilic's avatar
    d.kilic committed
        progress.setWindowModality(Qt::WindowModal); // blocks main window
    
        // vorwaertslaufen ab aktueller Stelle und trackOnlineCalc zum tracken nutzen
        do
        {
    
            progress.setValue(++progVal); // mPlayerWidget->getPos()
    
    d.kilic's avatar
    d.kilic committed
            qApp->processEvents();
    
            if(progress.wasCanceled())
    
    d.kilic's avatar
    d.kilic committed
                break;
    
        } while(mPlayerWidget->frameForward());
    
    d.kilic's avatar
    d.kilic committed
    
    
        if(mAutoBackTrack)
    
    d.kilic's avatar
    d.kilic committed
        {
            // zuruecksprinegn an die stelle, wo der letzte trackPath nicht vollstaendig
            // etwas spaeter, da erste punkte in reco path meist nur ellipse ohne markererkennung
            mControlWidget->trackOnlineCalc->setCheckState(Qt::Unchecked);
    
            mPlayerWidget->skipToFrame(mPersonStorage.largestFirstFrame() + 5);
    
    d.kilic's avatar
    d.kilic committed
            mControlWidget->trackOnlineCalc->setCheckState(Qt::Checked);
    
            // progVal = 2*mAnimation->getNumFrames()-memPos-mPlayerWidget->getPos();
            progVal += mAnimation->getNumFrames() - mPlayerWidget->getPos();
            progress.setValue(progVal); // mPlayerWidget->getPos()
    
    d.kilic's avatar
    d.kilic committed
    
            // recognition abstellen, bis an die stelle, wo trackAll begann
            // UEBERPRUEFEN, OB TRACKPATH NICHT RECOGNITION PUNKTE UEBERSCHREIBT!!!!!!!!!!
            // repeate und repaetQual koennte temporaer umgestellt werden
            mControlWidget->performRecognition->setCheckState(Qt::Unchecked);
    
            // rueckwaertslaufen
            do
            {
    
                if(progVal + 1 < 2 * mAnimation->getNumFrames() - memPos)
    
                    progress.setValue(++progVal); // mPlayerWidget->getPos()
    
    d.kilic's avatar
    d.kilic committed
                qApp->processEvents();
    
                if(progress.wasCanceled())
    
    d.kilic's avatar
    d.kilic committed
                    break;
    
                if(mPlayerWidget->getPos() == memPos + 1)
    
    d.kilic's avatar
    d.kilic committed
                    mControlWidget->performRecognition->setCheckState(Qt::Checked);
    
            } while(mPlayerWidget->frameBackward());
    
    d.kilic's avatar
    d.kilic committed
    
            // bei abbruch koennen es auch mPlayerWidget->getPos() frames sein, die bisher geschrieben wurden
    
            progress.setValue(2 * mAnimation->getNumFrames() - memPos);
    
    d.kilic's avatar
    d.kilic committed
        }
    
    
        if(mAutoTrackOptimizeColor)
    
            mPersonStorage.optimizeColor();
    
    d.kilic's avatar
    d.kilic committed
    
        mControlWidget->performRecognition->setCheckState(memRecoState);
        mControlWidget->trackOnlineCalc->setCheckState(Qt::Unchecked);
        mPlayerWidget->skipToFrame(memPos);
        mControlWidget->trackOnlineCalc->setCheckState(memCheckState);
    }
    
    // default: (QPointF *pos=NULL, int pers=-1, int frame=-1);
    int Petrack::winSize(QPointF *pos, int pers, int frame, int level)
    {
        // default of mControlWidget->trackRegionScale->value() is 16, so that
        // a factor of 1.6 of the headsize is used
    
        if(level == -1)
    
    d.kilic's avatar
    d.kilic committed
            level = mControlWidget->trackRegionLevels->value();
    
        return (int) ((getHeadSize(pos, pers, frame) / pow(2., level)) * (mControlWidget->trackRegionScale->value() / 10.));
    
    d.kilic's avatar
    d.kilic committed
    }
    
    void Petrack::updateImage(bool imageChanged) // default = false (only true for new animation frame)
    {
    #ifdef TIME_MEASUREMENT
        // die reine Ausgabe  folgender Zeile kostet 1-2 Millisekunden
        //        "==========: "
    
        debout << "go  update: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
    
        mCodeMarkerItem->resetSavedMarkers();
    
    
        static int  lastRecoFrame            = -10000;
    
    d.kilic's avatar
    d.kilic committed
        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())
    
    d.kilic's avatar
    d.kilic committed
        {
            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();
    
    d.kilic's avatar
    d.kilic committed
    
            // 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;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
    
            if(imageChanged || swapChanged)
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mSwapFilter.apply(mImgFiltered);
    
    d.kilic's avatar
    d.kilic committed
            else
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mSwapFilter.getLastResult();
    
    d.kilic's avatar
    d.kilic committed
    
    
            if(imageChanged || swapChanged || brightContrastChanged)
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mBrightContrastFilter.apply(mImgFiltered);
    
    d.kilic's avatar
    d.kilic committed
            else
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mBrightContrastFilter.getLastResult();
    
    d.kilic's avatar
    d.kilic committed
    
    
            if(imageChanged || swapChanged || brightContrastChanged || borderChanged)
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mBorderFilter.apply(mImgFiltered); // mIplImg
    
    d.kilic's avatar
    d.kilic committed
            else
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mBorderFilter.getLastResult();
    
    d.kilic's avatar
    d.kilic committed
    
    #ifdef TIME_MEASUREMENT
    
            //        "==========: "
            debout << "nch filter: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
            if(borderChanged)
    
    d.kilic's avatar
    d.kilic committed
                updateControlImage(mImgFiltered);
    
    #ifndef STEREO_DISABLED
    
            if(imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
    
    d.kilic's avatar
    d.kilic committed
            {
    
                if(mStereoContext)
    
    d.kilic's avatar
    d.kilic committed
                    mStereoContext->init(mImgFiltered);
            }
    
    d.kilic's avatar
    d.kilic committed
    
    #ifdef TIME_MEASUREMENT
    
            //        "==========: "
            debout << "vor  calib: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
            if(imageChanged || swapChanged || brightContrastChanged || borderChanged || calibChanged)
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mCalibFilter->apply(mImgFiltered);
    
    d.kilic's avatar
    d.kilic committed
            else
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mCalibFilter->getLastResult();
    
    d.kilic's avatar
    d.kilic committed
    
    #ifdef TIME_MEASUREMENT
    
            //        "==========: "
            debout << "nach calib: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
    
            if(brightContrastChanged || swapChanged || borderChanged || calibChanged)
    
    d.kilic's avatar
    d.kilic committed
            {
    
                // 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
    
    d.kilic's avatar
    d.kilic committed
            }
    
    
            if(imageChanged || mBackgroundFilter.changed())
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mBackgroundFilter.apply(mImgFiltered);
    
    d.kilic's avatar
    d.kilic committed
            else
    
    d.kilic's avatar
    d.kilic committed
                mImgFiltered = mBackgroundFilter.getLastResult();
    
    d.kilic's avatar
    d.kilic committed
    
    #ifdef TIME_MEASUREMENT
    
            //        "==========: "
            debout << "nach    bg: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
            // delete track list, if intrinsic param have changed
    
            if(calibChanged && mPersonStorage.nbPersons() > 0) // mCalibFilter.getEnabled() &&
    
    d.kilic's avatar
    d.kilic committed
            {
                // Evtl. nicht Tracker loeschen sondern entsprechend der neuen Calibration verschieben?!?!?
    
                mPersonStorage.clear();
    
    d.kilic's avatar
    d.kilic committed
                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())
    
    d.kilic's avatar
    d.kilic committed
                {
                    // buildt disparity picture if it should be used for height detection
                    mStereoContext->getDisparity();
    
    
                    mPersonStorage.calcPosition(frameNum);
    
    d.kilic's avatar
    d.kilic committed
                }
    
    d.kilic's avatar
    d.kilic committed
            }
    
            if(borderChanged)
    
    d.kilic's avatar
    d.kilic committed
                borderChangedForTracking = true;
    
    d.kilic's avatar
    d.kilic committed
            // tracking vor recognition, da dann neu gefundene punkte mit getrackten bereits ueberprueft werden koennen
    
            if((trackChanged() || imageChanged) &&
               (mControlWidget->trackOnlineCalc->checkState() == Qt::Checked)) // borderChanged ???
    
    d.kilic's avatar
    d.kilic committed
            {
                // Rect for tracking area
    
                QRect roi(
                    myRound(mTrackingRoiItem->rect().x() + getImageBorderSize()),
                    myRound(mTrackingRoiItem->rect().y() + getImageBorderSize()),
                    myRound(mTrackingRoiItem->rect().width()),
                    myRound(mTrackingRoiItem->rect().height()));
    
    d.kilic's avatar
    d.kilic committed
    
    
                if(borderChangedForTracking)
    
    d.kilic's avatar
    d.kilic committed
                {
    
                    size.width  = mImgFiltered.cols;
    
    d.kilic's avatar
    d.kilic committed
                    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())
    
    d.kilic's avatar
    d.kilic committed
                    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
    
    d.kilic's avatar
    d.kilic committed
    #ifdef TIME_MEASUREMENT
    
                debout << "vor  track: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
                //            debout << "test" << endl;
                int anz = mTracker->track(
                    mImgFiltered,
                    rect,
                    frameNum,
                    mControlWidget->trackRepeat->isChecked(),
                    mControlWidget->trackRepeatQual->value(),
                    getImageBorderSize(),
                    mReco.getRecoMethod(),
                    mControlWidget->trackRegionLevels->value(),
                    getPedestriansToTrack());
    
    d.kilic's avatar
    d.kilic committed
    #ifdef TIME_MEASUREMENT
    
                debout << "nach track: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #endif
                mControlWidget->trackNumberNow->setText(QString("%1").arg(anz));
    
                mTrackChanged            = false;
    
    d.kilic's avatar
    d.kilic committed
                borderChangedForTracking = false;
            }
            else
    
    d.kilic's avatar
    d.kilic committed
                mControlWidget->trackNumberNow->setText(QString("0"));
    
    d.kilic's avatar
    d.kilic committed
            // 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())
    
    d.kilic's avatar
    d.kilic committed
            {
    
    #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()))
    
    d.kilic's avatar
    d.kilic committed
                    mStereoContext->getDisparity(); // wird nicht neu berechnet, wenn vor tracking schon berechnet wurde
    
                if(borderChanged)
    
    d.kilic's avatar
    d.kilic committed
                    mRecognitionRoiItem->checkRect();
    
                if(mControlWidget->performRecognition->checkState() == Qt::Checked)
    
    d.kilic's avatar
    d.kilic committed
                {
    
                    QRect rect(
                        myRound(mRecognitionRoiItem->rect().x() + getImageBorderSize()),
                        myRound(mRecognitionRoiItem->rect().y() + getImageBorderSize()),
                        myRound(mRecognitionRoiItem->rect().width()),
                        myRound(mRecognitionRoiItem->rect().height()));
    
    d.kilic's avatar
    d.kilic committed
                    QList<TrackPoint> persList;
    
                    auto              recoMethod = mReco.getRecoMethod();
    
    d.kilic's avatar
    d.kilic committed
    #ifdef TIME_MEASUREMENT
                    //        "==========: "
    
                    debout << "vor   reco: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #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
    
                    if(mStereoContext && mStereoWidget->stereoUseForReco->isChecked())
    
    d.kilic's avatar
    d.kilic committed
                    {
                        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;
    
    d.kilic's avatar
    d.kilic committed
    #endif
    
                    mPersonStorage.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())
    
                        mPersonStorage.purge(frameNum); // bereinigen wenn weniger als 0.2 recognition und nur getrackt
    
    d.kilic's avatar
    d.kilic committed
    
                    mControlWidget->recoNumberNow->setText(QString("%1").arg(persList.size()));
                    mRecognitionChanged = false;
    
                    if(false) // hier muss Abfage hin ob kasernen marker genutzt wird
    
                        mControlWidget->getColorPlot()
                            ->replot(); // oder nur wenn tab offen oder wenn sich mtracker geaendert hat???
    
    d.kilic's avatar
    d.kilic committed
                }
                else
    
    d.kilic's avatar
    d.kilic committed
                    mControlWidget->recoNumberNow->setText(QString("0"));
    
    d.kilic's avatar
    d.kilic committed
                lastRecoFrame = frameNum;
            }
            else
    
    d.kilic's avatar
    d.kilic committed
                mControlWidget->recoNumberNow->setText(QString("0"));
    
    d.kilic's avatar
    d.kilic committed
    
    
            mControlWidget->trackNumberAll->setText(
    
                QString("%1").arg(mPersonStorage.nbPersons())); // kann sich durch reco und tracker aendern
    
            mControlWidget->trackShowOnlyNr->setMaximum(
    
                MAX(mPersonStorage.nbPersons(), 1)); // kann sich durch reco und tracker aendern
    
            mControlWidget->trackNumberVisible->setText(
    
                QString("%1").arg(mPersonStorage.visible(frameNum))); // kann sich durch reco und tracker aendern
    
    d.kilic's avatar
    d.kilic committed
    
            // 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)
    
    d.kilic's avatar
    d.kilic committed
                mImageItem->setImage(mImage);
    
    d.kilic's avatar
    d.kilic committed
            else
            {
    
                getScene()->update(); // repaint();
    
                qApp->processEvents();
    
    d.kilic's avatar
    d.kilic committed
                // update pixel color (because image pixel moves)
                setStatusColor();
            }
    
    #ifdef QWT
            mControlWidget->getAnalysePlot()->setActFrame(frameNum);
    
            if(mControlWidget->anaMarkAct->isChecked())
    
    d.kilic's avatar
    d.kilic committed
            {
                mControlWidget->getAnalysePlot()->replot();
            }
    #endif
    
            semaphore.release();
        }
    #ifdef TIME_MEASUREMENT
        //        "==========: "
    
        debout << "stp update: " << getElapsedTime() << endl;
    
    d.kilic's avatar
    d.kilic committed
    #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
    
    d.kilic's avatar
    d.kilic committed
    
        // set roi for recognition if image size changes or roi is zero
    
        // in oldImage steckt border drin, mIplImg->height zeigt noch auf altes ursprungsbild
    
    d.kilic's avatar
    d.kilic committed
        // 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()))))
    
    d.kilic's avatar
    d.kilic committed
            mRecognitionRoiItem->setRect(-getImageBorderSize(), -getImageBorderSize(), mImage->width(), mImage->height());
    
        if((mTrackingRoiItem->rect().width() == 0) ||
           (oldImage && ((oldImage->width() != mImage->width()) || (oldImage->height() != mImage->height()))))
    
    d.kilic's avatar
    d.kilic committed
            mTrackingRoiItem->setRect(-getImageBorderSize(), -getImageBorderSize(), mImage->width(), mImage->height());
    
    d.kilic's avatar
    d.kilic committed
    
    
        size2.width  = mTrackingRoiItem->rect().width();
    
    d.kilic's avatar
    d.kilic committed
        size2.height = mTrackingRoiItem->rect().height();
        mTracker->init(size2);
    
        mPlayerWidget->setAnim(mAnimation);
        mPlayerWidget->skipToFrame(0);
    
        mImageItem->setImage(mImage); // wird in updateImage gemacht
    
    d.kilic's avatar
    d.kilic committed
        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)
    {
    
    d.kilic's avatar
    d.kilic committed
        {
            mCmPerPixel = getImageItem()->getCmPerPixel();
    
            // debout << mCmPerPixel <<endl;
            mHeadSize = (HEAD_SIZE * mControlWidget->coordAltitude->value() /
                         (mControlWidget->coordAltitude->value() - mControlWidget->mapDefaultHeight->value())) /
                        mCmPerPixel;
    
    d.kilic's avatar
    d.kilic committed
        }
        else
    
    d.kilic's avatar
    d.kilic committed
            mHeadSize = hS;
    
    d.kilic's avatar
    d.kilic committed
    }
    // 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 < static_cast<int>(mPersonStorage.nbPersons())) &&
           mPersonStorage.at(pers).trackPointExist(frame))
    
    d.kilic's avatar
    d.kilic committed
        {
    
            if(mControlWidget->getCalibCoordDimension() == 0)
    
    d.kilic's avatar
    d.kilic committed
            {
    
                int         diff;
                cv::Point3f p3d = getExtrCalibration()->get3DPoint(
    
                    cv::Point2f(
                        mPersonStorage.at(pers).trackPointAt(frame).x(), mPersonStorage.at(pers).trackPointAt(frame).y()),
    
                    mControlWidget->mapDefaultHeight->value());
    
                cv::Point2f p3d_x1 =
                    getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x + HEAD_SIZE * 0.5, p3d.y, p3d.z));
                cv::Point2f p3d_x2 =
                    getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x - HEAD_SIZE * 0.5, p3d.y, p3d.z));
                cv::Point2f p3d_y1 =
                    getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x, p3d.y + HEAD_SIZE * 0.5, p3d.z));
                cv::Point2f p3d_y2 =
                    getExtrCalibration()->getImagePoint(cv::Point3f(p3d.x, p3d.y - HEAD_SIZE * 0.5, p3d.z));
    
                diff = (int) std::max(
                    sqrt(pow(p3d_x2.x - p3d_x1.x, 2) + pow(p3d_x2.y - p3d_x1.y, 2)),
                    sqrt(pow(p3d_y2.x - p3d_y1.x, 2) + pow(p3d_y2.y - p3d_y1.y, 2)));
                return diff; // < 8 ? 8 : diff;
            }
            else
    
    d.kilic's avatar
    d.kilic committed
            {
    
                z = mPersonStorage.at(pers).trackPointAt(frame).sp().z();
                h = mPersonStorage.at(pers).height();
    
                    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();
    
    d.kilic's avatar
    d.kilic committed
                else
    
    d.kilic's avatar
    d.kilic committed
                    return mHeadSize;
    
    d.kilic's avatar
    d.kilic committed
            }
        }
    
    
        if(pos != nullptr)
    
    d.kilic's avatar
    d.kilic committed
            return mHeadSize; // muss noch aus density map gelesen werden!!!
    
        }
        else //(pos == NULL) && (pers == -1)
        {
    
    d.kilic's avatar
    d.kilic committed
            return mHeadSize;
    
    d.kilic's avatar
    d.kilic committed
    }
    
    
    d.kilic's avatar
    d.kilic committed
    /**
    
     * @brief Return the user's selection of pedestrians/trajectories
    
     * Only people selected via "show only people" (single person) or "show only
     * people list"(multiple persons) are going to be selected.
    
     * @return All user selected pedestrian (empty for all pedestrians)
    
    d.kilic's avatar
    d.kilic committed
    {
    
        if(mControlWidget->trackShowOnly->checkState() == Qt::Checked)
        {
    
            QSet<int> onlyVisible;
            onlyVisible.insert(mControlWidget->trackShowOnlyNr->value() - 1);
            return onlyVisible;
        }
    
        if(mControlWidget->trackShowOnlyList->checkState() == Qt::Checked)
        {
            QStringList list = mControlWidget->trackShowOnlyNrList->text().split(",", Qt::SkipEmptyParts);
            QSet<int>   onlyVisible;
            foreach(QString s, list)
    
    d.kilic's avatar
    d.kilic committed
            {
    
                int  nr = s.toInt(&ok);
                if(ok /* && nr <= maxPed && nr > 0*/) // einzelne ID
    
    d.kilic's avatar
    d.kilic committed
                {
    
                    onlyVisible.insert(nr - 1);
                }
                else // error or IDs range (e.g. 1-3, 6-10, etc.)
                {
                    QStringList range = s.split("-", Qt::SkipEmptyParts);
    
                    int         last, first = range[0].toInt(&ok);
    
    d.kilic's avatar
    d.kilic committed
    
    
                    if(ok /* && first <= maxPed && nr > 0*/)
    
                        if(ok /* && last <= maxPed && nr > 0*/)
    
    d.kilic's avatar
    d.kilic committed
                        {
    
                            if(first > last)
                            {
                                std::swap(first, last);
                            }
    
                            for(int i = first; i <= last; i++)
                            {
                                onlyVisible.insert(i - 1);
                            }
    
    d.kilic's avatar
    d.kilic committed
                        }
                    }
                }
    
                    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
        }
        return QSet<int>();
    }