123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- #include "sequenz.h"
- #include <tinyxml2.h>
- #include <QtConcurrent/QtConcurrent>
- #include <QProgressDialog>
- #include <fstream>
- Sequenz::Sequenz( QString p, QList< Kamera* > c, QList< Object > o )
- : ref( 1 ),
- path( p ),
- frameIndex( 0 ),
- cameraIndex( 0 ),
- cams( c ),
- objects( o )
- {
- addClass( "packingbox" );
- }
- Sequenz::~Sequenz()
- {
- for( auto k = cams.begin(); k != cams.end(); k++ )
- (*k)->refRelease();
- }
- // Gibt eine Liste mit allen bekannten Objekt Klassen zurück
- QList< Sequenz::SegmentationClass > Sequenz::getClasses() const
- {
- return classes;
- }
- // Setzt den Namen der Objekt Klasse mit der ID id auf name
- bool Sequenz::setClassName( int id, QString name )
- {
- int i = getClassId( name );
- if( i == id )
- return true;
- if( i != -1 )
- return false;
- for( auto c = classes.begin(); c != classes.end(); c++ )
- {
- if( c->id == id )
- {
- c->name = name;
- return true;
- }
- }
- return false;
- }
- // Prüft, ob bereits annotierte Objekte in der Sequenz vorhanden sind
- QString Sequenz::getClassName( int id ) const
- {
- for( auto c = classes.begin(); c != classes.end(); c++ )
- {
- if( c->id == id )
- return c->name;
- }
- return "NULL";
- }
- // Gibt den Namen der Objekt Klasse mit der ID id zurück
- int Sequenz::getClassId( QString name ) const
- {
- for( auto c = classes.begin(); c != classes.end(); c++ )
- {
- if( c->name == name )
- return c->id;
- }
- return -1;
- }
- // Gibt die ID der Objekt Klasse mit dem Namen name zurück
- int Sequenz::getClassOfObject( QString id ) const
- {
- for( auto obj = objects.begin(); obj != objects.end(); obj++ )
- {
- if( obj->getId() == id )
- return obj->getClassId();
- }
- return -1;
- }
- // Gibt die ID der Klasse des Objektes mit der ID objektId zurück
- void Sequenz::setClassOfObject( QString id, int classId )
- {
- for( auto obj = objects.begin(); obj != objects.end(); obj++ )
- {
- if( obj->getId() == id )
- obj->setClassId( classId );
- }
- }
- // Setzt die ID der Klasse des Objektes mit der ID objektId auf classId
- bool Sequenz::hasAnnotatedObjects() const
- {
- for( Object o : objects )
- {
- if( o.getId() != "-1" )
- return true;
- }
- return false;
- }
- // Fügt eine neue Objekt Klasse mit Namen name hinzu
- int Sequenz::addClass( QString name )
- {
- if( getClassId( name ) != -1 )
- return -1;
- int max = -1;
- for( auto c = classes.begin(); c != classes.end(); c++ )
- {
- if( c->id > max )
- max = c->id;
- }
- max++;
- classes.append( { max, name } );
- return max;
- }
- // Entfernt die Objektklasse mit der ID id
- bool Sequenz::removeClass( int id )
- {
- for( auto c = classes.begin(); c != classes.end(); c++ )
- {
- if( c->id == id )
- {
- classes.erase( c );
- int newId = 0;
- if( classes.size() > 0 )
- newId = classes.first().id;
- for( auto obj = objects.begin(); obj != objects.end(); obj++ )
- {
- if( obj->getClassId() == id )
- obj->setClassId(newId);
- }
- return true;
- }
- }
- return false;
- }
- // Wählt das frame-te Bild der cam-ten Kamera aus
- void Sequenz::selectFrame( int cam, int frame )
- {
- cameraIndex = cam;
- frameIndex = frame;
- }
- // Gibt das ausgewählte Bild zurück
- Frame *Sequenz::getFrame() const
- {
- return cams.at( cameraIndex )->getFrame( frameIndex );
- }
- // Gibt das vom ausgewählten Bild um offset Bilder entfernte Bild zurück
- Frame *Sequenz::getFrame( int offset ) const
- {
- int currCam = cameraIndex;
- int currFrame = frameIndex;
- int oldCOunt = offset;
- do
- { // Schleife durch alle bilder (in die angegebene Richtung) bis ein Bild gefunden wird auf dem das Objekt vorkommt
- if( currFrame >= cams.at( currCam )->getChildCount() )
- {
- currCam++;
- if( currCam >= cams.size() )
- currCam = 0;
- currFrame = 0;
- }
- Frame *f = cams.at( currCam )->getFrame( currFrame );
- offset--;
- currFrame++;
- if( offset <= 0 ) // das gesuchte Bild wurde erreicht
- return f;
- if( currFrame == frameIndex && currCam == cameraIndex )
- {
- if( oldCOunt == offset )
- break;
- }
- } while( offset > 0 );
- return 0;
- }
- // Gibt den Index der ausgewählten Kamera zurück
- int Sequenz::getSelectedCamera() const
- {
- return cameraIndex;
- }
- // Gibt den Index des Ausgewählten Bildes (innerhalb der Kamera) zurück
- int Sequenz::getSelectedFrame() const
- {
- return frameIndex;
- }
- // Gibt eine Liste mit Kameras zurück
- const QList< Kamera* > &Sequenz::getCameras() const
- {
- return cams;
- }
- // Wählt das nachfolgende Bild aus
- void Sequenz::nextFrame()
- {
- if( !hasNextFrame() )
- return;
- if( ++frameIndex == cams.at( cameraIndex )->getChildCount() )
- {
- frameIndex = 0;
- cameraIndex++;
- }
- }
- // Wählt das vorherige Bild aus
- void Sequenz::previousFrame()
- {
- if( !hasPreviousFrame() )
- return;
- if( --frameIndex < 0 )
- frameIndex = cams.at( --cameraIndex )->getChildCount() - 1;
- }
- // Gibt 1 zurück, wenn in der Sequenz ein nachfolgendes Bild existiert
- bool Sequenz::hasNextFrame() const
- {
- return cameraIndex < cams.count() - 1 || frameIndex < cams.at( cameraIndex )->getChildCount() - 1;
- }
- // Gibt 1 zurück, wenn in der Sequenz ein vorheriges Bild existiert
- bool Sequenz::hasPreviousFrame() const
- {
- return frameIndex > 0 || cameraIndex > 0;
- }
- // Gibt eine Liste mit allen vergebenen ObjektIds zurück
- QList< QString > Sequenz::getObjectNames() const
- {
- QList<QString> result;
- foreach( Object obj, objects )
- result.append( obj.getId() );
- return result;
- }
- // Gibt von dem ausgewählten Bild aus das count-nächste Bild von dem Objekt mit ID objektId zurück.
- QImage Sequenz::previousObjectImage( QString packetName, int count ) const
- {
- int currCam = cameraIndex;
- int currFrame = frameIndex;
- QImage img;
- int dir = 1;
- if( count < 0 )
- { // falls count negativ ist, wird weiter vorne in der sequenz gesucht
- dir = -1;
- count = -count;
- }
- int oldCOunt = count;
- do
- { // Schleife durch alle bilder (in die angegebene Richtung) bis ein Bild gefunden wird auf dem das Objekt vorkommt
- if( (currFrame += dir) < 0 || currFrame >= cams.at( currCam )->getChildCount() )
- {
- if( (currCam += dir) < 0 || currCam >= cams.size() )
- {
- currCam = cams.size() - 1;
- if( dir > 0 )
- currCam = 0;
- }
- currFrame = cams.at( currCam )->getChildCount() - 1;
- if( dir > 0 )
- currFrame = 0;
- }
- Frame *f = cams.at( currCam )->getFrame( currFrame );
- if( f->hasObject( packetName ) )
- {
- count--;
- if( count <= 0 ) // das gesuchte Bild wurde erreicht
- img = f->getObjectImage( packetName );
- }
- if( currFrame == frameIndex && currCam == cameraIndex )
- {
- if( oldCOunt == count )
- break;
- }
- } while( count > 0 );
- return img;
- }
- // Gibt die größte vergebene Objekt Id zurück;
- int Sequenz::getMaxObjectId() const
- {
- int max = -1;
- for( auto o : objects )
- {
- if( o.getId().toInt() > max )
- max = o.getId().toInt();
- }
- return max;
- }
- // Fügt eine neue ObjektID mit der Klassen ID classID hinzu
- void Sequenz::addObjectName( QString name, int classId )
- {
- if( objects.indexOf( Object( name, classId ) ) < 0 )
- objects.append( Object( name, classId ) );
- }
- // Fügt eine neue ObjektID hinzu
- void Sequenz::addObjectName( QString name )
- {
- if( classes.size() > 0 )
- addObjectName( name, classes.first().id );
- else
- addObjectName( name, 0 );
- }
- // Speichert die Sequenz.
- // status: Ein Label, in denen Fortschrittsinformationen geschrieben werden
- void Sequenz::saveToPath( QLabel *status ) const
- {
- int numOps = 0;
- for( Kamera *k : cams )
- numOps += k->getChildCount();
- QProgressDialog progress( "Annotation wird gespeichert...", "", 0, numOps );
- progress.setWindowModality(Qt::WindowModal);
- progress.setCancelButton( 0 );
- if( !QFile( path + "/ImageSets/Main/train.txt" ).exists() )
- QDir( path + "/ImageSets/Main" ).mkpath(".");
- std::ofstream trainTxt( (path + "/ImageSets/Main/train.txt").toStdString().c_str() );
- for( int cam = 0; cam < cams.size(); cam++ )
- { // Schleife durch alle Kameras
- Kamera *currentCam = cams.at( cam );
- int frameCount = currentCam->getChildCount();
- for( int frame = 0; frame < frameCount; frame++ )
- { // Schleife durch alle Bilder
- if( status )
- {
- QString text = "save Annotations " + QString::number( cam + 1 ) + "/" + QString::number( cams.size() ) + " " + QString::number( frame + 1 ) + "/" + QString::number( cams.at( cam )->getChildCount() );
- QMetaObject::invokeMethod( status, "setText", Q_ARG( QString, text ) );
- }
- Frame *currentFrame = currentCam->getFrame( frame );
- if( !currentFrame->isNotAnnotated() || currentFrame->getObjects().size() > 0 )
- {
- trainTxt << ( currentFrame->getName().mid( 0, currentFrame->getName().indexOf( "." ) ) + "\n" ).toStdString().c_str();
- }
- if( currentFrame->wasChangedSinceLastSave() )
- { // Falls das Bild seid dem letzten speichern verändert wurde
- tinyxml2::XMLDocument doc; // Erstelle die xml datei
- doc.LinkEndChild( doc.NewDeclaration( "xml version=\"1.0\" " ) );
- tinyxml2::XMLElement *annotation = doc.NewElement( "annotation");
- annotation->LinkEndChild( doc.NewElement( "folder" ) )->LinkEndChild( doc.NewText( "VOC2007" ) );
- annotation->LinkEndChild( doc.NewElement( "filename" ) )->LinkEndChild( doc.NewText( currentFrame->getName().toStdString().c_str() ) );
- tinyxml2::XMLElement *source = doc.NewElement( "source" );
- source->LinkEndChild( doc.NewElement( "database" ) )->LinkEndChild( doc.NewText( "The VOC2007 Database" ) );
- source->LinkEndChild( doc.NewElement( "annotation" ) )->LinkEndChild( doc.NewText( "PASCAL VOC 2007" ) );
- source->LinkEndChild( doc.NewElement( "image" ) )->LinkEndChild( doc.NewText( currentFrame->getName().toStdString().c_str() ) );
- annotation->LinkEndChild( source );
- annotation->LinkEndChild( doc.NewElement( "owner" ) )->LinkEndChild( doc.NewElement( "name" ) )->LinkEndChild( doc.NewText( "Kolja Strohm" ) );
- annotation->LinkEndChild( doc.NewElement( "camera_id" ) )->LinkEndChild( doc.NewText( currentCam->getName().toStdString().c_str() ) );
- tinyxml2::XMLElement *size = doc.NewElement( "size" );
- QImage img = currentFrame->getImage();
- size->LinkEndChild( doc.NewElement( "width" ) )->LinkEndChild( doc.NewText( std::to_string( img.width() ).c_str() ) );
- size->LinkEndChild( doc.NewElement( "height" ) )->LinkEndChild( doc.NewText( std::to_string( img.height() ).c_str() ) );
- size->LinkEndChild( doc.NewElement( "depth" ) )->LinkEndChild( doc.NewText( std::to_string( img.depth() ).c_str() ) );
- annotation->LinkEndChild( size );
- annotation->LinkEndChild( doc.NewElement( "segmented" ) )->LinkEndChild( doc.NewText( "0" ) );
- annotation->LinkEndChild( doc.NewElement( "timestamp" ) )->LinkEndChild( doc.NewText( currentFrame->getTimestamp().toStdString().c_str() ) );
- QList<ObjectPolygon> objects = currentFrame->getObjects();
- for( ObjectPolygon o : objects )
- { // Schleife durch alle Objekte
- tinyxml2::XMLElement *object = doc.NewElement( "object" );
- object->LinkEndChild( doc.NewElement( "name" ) )->LinkEndChild( doc.NewText( getClassName( getClassOfObject( o->getId() ) ).toStdString().c_str() ) );
- object->LinkEndChild( doc.NewElement( "id" ) )->LinkEndChild( doc.NewText( o->getId().toStdString().c_str() ) );
- object->LinkEndChild( doc.NewElement( "pose" ) )->LinkEndChild( doc.NewText( "Unspecified" ) );
- object->LinkEndChild( doc.NewElement( "truncated" ) )->LinkEndChild( doc.NewText( std::to_string( (int)o->isTruncated() ).c_str() ) );
- object->LinkEndChild( doc.NewElement( "difficult" ) )->LinkEndChild( doc.NewText( "0" ) );
- int xMin = img.width();
- int yMin = img.height();
- int xMax = 0;
- int yMax = 0;
- std::vector< tinyxml2::XMLElement* > polygons;
- for( QPolygon pol : o->getPolygonList() )
- { // Schleife durch alle Polygone
- tinyxml2::XMLElement *polygon = doc.NewElement( "polygon" );
- for( QPoint point : pol )
- { // Schleife durch alle Eckpunkte
- tinyxml2::XMLElement *pointE = doc.NewElement( "point" );
- pointE->LinkEndChild( doc.NewElement( "x" ) )->LinkEndChild( doc.NewText( std::to_string( point.x() ).c_str() ) );
- pointE->LinkEndChild( doc.NewElement( "y" ) )->LinkEndChild( doc.NewText( std::to_string( point.y() ).c_str() ) );
- polygon->LinkEndChild( pointE );
- if( xMin > point.x() ) // ermittle die Bounding box
- xMin = point.x();
- if( yMin > point.y() )
- yMin = point.y();
- if( xMax < point.x() )
- xMax = point.x();
- if( yMax < point.y() )
- yMax = point.y();
- }
- polygons.push_back( polygon );
- }
- tinyxml2::XMLElement *bndbox = doc.NewElement( "bndbox" );
- bndbox->LinkEndChild( doc.NewElement( "xmin" ) )->LinkEndChild( doc.NewText( std::to_string( xMin ).c_str() ) );
- bndbox->LinkEndChild( doc.NewElement( "ymin" ) )->LinkEndChild( doc.NewText( std::to_string( yMin ).c_str() ) );
- bndbox->LinkEndChild( doc.NewElement( "xmax" ) )->LinkEndChild( doc.NewText( std::to_string( xMax ).c_str() ) );
- bndbox->LinkEndChild( doc.NewElement( "ymax" ) )->LinkEndChild( doc.NewText( std::to_string( yMax ).c_str() ) );
- object->LinkEndChild( bndbox );
- for( tinyxml2::XMLElement *polygon : polygons )
- object->LinkEndChild( polygon );
- annotation->LinkEndChild( object );
- }
- if( objects.size() == 0 && currentFrame->isNotAnnotated() )
- annotation->LinkEndChild( doc.NewElement( "noobject" ) )->LinkEndChild( doc.NewText( "need Annotation" ) );
- doc.LinkEndChild( annotation );
- QString name = currentFrame->getName();
- QDir().mkpath( path + "/Annotations" );
- doc.SaveFile( (path + "/Annotations/" + name.mid( 0, name.lastIndexOf( '.' ) ) + ".xml").toStdString().c_str() );
- }
- progress.setValue( progress.value() + 1 );
- }
- }
- trainTxt.close();
- }
- // Erhöht den Reference Counter um 1
- void Sequenz::refNew()
- {
- ref++;
- }
- // Verringert den Reference Counter um 1 (bei 0 löscht sich das Objekt selbst)
- void Sequenz::refRelease()
- {
- if( !--ref )
- delete this;
- }
|