16 Commity 73a0e2141d ... 9e03d98750

Autor SHA1 Wiadomość Data
  Sven Sickert 9e03d98750 removed dependencies on deprecated Filter.h 8 lat temu
  Sven Sickert 5d712edde4 minor name change 8 lat temu
  Sven Sickert 447307e38d fixed wrong call for preprocessing 3D image channels 8 lat temu
  Sven Sickert 118fb5a5c7 minor 8 lat temu
  Sven Sickert dde54ede0f added missing variable initialization 8 lat temu
  Sven Sickert 5918dcaa77 modified SemSegObliqueTree according CachedExample change 8 lat temu
  Sven Sickert f1bafd4965 adding zsize configuration for 2D scenarios in SemSegTools 8 lat temu
  Sven Sickert 5b88c97373 revised performance statistics 8 lat temu
  Sven Sickert a7f2f20e8f first running version of 3D oblique forests 9 lat temu
  Sven Sickert 067c5cf547 modified testSemSegObliqueTrees for the use of 3d images 9 lat temu
  Sven Sickert 72428f2f60 implemented function semanticseg for 3d images for oblique forests 9 lat temu
  Sven Sickert dc0c0bbf7b removed unused variable 9 lat temu
  Sven Sickert 33bbac6231 moved run3Dseg boolean to abstract class 9 lat temu
  Sven Sickert c1ed3f1f23 added function semanticseg() for 3d cached examples 9 lat temu
  Sven Sickert 863b38046c modified SemSegObliqueTree for the use of 3d images 9 lat temu
  Sven Sickert 07f8b63ad2 moved function getDepthVector() to SemSegTools 9 lat temu

+ 56 - 17
progs/testSemSegObliqueTrees.cpp

@@ -66,6 +66,14 @@ int main ( int argc, char **argv )
     NICE::Timer timer;
     std::cout << "\nCLASSIFICATION" << std::endl;
     std::cout << "##############\n" << std::endl;
+
+    std::vector<int> zsizeVec;
+    bool run3Dseg = semseg->isMode3D();
+    SemSegTools::getDepthVector ( testFiles, zsizeVec, run3Dseg );
+    int depthCount = 0, idx = 0;
+    std::vector<std::string> filelist;
+    NICE::MultiChannelImageT<int> segresult, gt;
+
     for (LabeledSet::const_iterator it = testFiles->begin(); it != testFiles->end(); it++)
     {
         for (std::vector<ImageInfo *>::const_iterator jt = it->second.begin();
@@ -73,8 +81,10 @@ int main ( int argc, char **argv )
         {
             ImageInfo & info = *(*jt);
             std::string file = info.img();
+            filelist.push_back(file);
+            depthCount++;
 
-            NICE::ImageT<int> segresult, gtruth;
+            NICE::ImageT<int> gtruth, res;
             if ( info.hasLocalizationInfo() )
             {
                 const LocalizationResult *l_gt = info.localization();
@@ -86,31 +96,60 @@ int main ( int argc, char **argv )
                 std::cerr << "testSemSegConvTrees: WARNING: NO localization info found for "
                           << file << std::endl;
             }
-            segresult = gtruth;
+            segresult.addChannel(gtruth);
+            gt.addChannel(gtruth);
+
+            int depthBoundary = 1;
+            if ( run3Dseg )
+                depthBoundary = zsizeVec[idx];
+
+            std::cout << "Slice " << depthCount << "/"
+                      << depthBoundary << std::endl;
+            if ( depthCount < depthBoundary )
+                continue;
 
             // actual testing
-            NICE::MultiChannelImageT<double> probabilities;
+            NICE::MultiChannelImage3DT<double> probabilities;
 
             timer.start();
-            semseg->semanticseg( file, segresult, probabilities );
+            semseg->semanticseg( filelist, segresult, probabilities );
             timer.stop();
             std::cout << "Time for Classification: " << timer.getLastAbsolute()
                       << "\n\n";
 
             // updating confusion matrix
-            SemSegTools::updateConfusionMatrix ( segresult, gtruth, M,
-                forbiddenClasses, classMapping );
-
-            // saving results to image file
-            NICE::ColorImage rgb;
-            NICE::ColorImage rgb_gt;
-            NICE::ColorImage orig ( file );
-            classNames.labelToRGB( segresult, rgb);
-            classNames.labelToRGB( gtruth, rgb_gt);
-            std::string fname = NICE::StringTools::baseName ( file, false );
-            std::string outStr;
-            SemSegTools::saveResultsToImageFile( &conf, "analysis", orig,
-                        rgb_gt, rgb, fname, outStr );
+            res = gtruth;
+            for ( int z = 0; z < segresult.channels(); z++ )
+            {
+                for ( int y = 0; y < res.height(); y++ )
+                    for ( int x = 0; x < res.width(); x++)
+                    {
+                        res.setPixel ( x, y, segresult.get(x,y,(unsigned int)z) );
+                        if ( run3Dseg )
+                            gtruth.setPixel ( x, y, gt.get(x,y,(unsigned int)z) );
+                    }
+
+                SemSegTools::updateConfusionMatrix ( res, gtruth, M,
+                    forbiddenClasses, classMapping );
+
+                // saving results to image file
+                NICE::ColorImage rgb;
+                NICE::ColorImage rgb_gt;
+                NICE::ColorImage orig ( filelist[z] );
+                classNames.labelToRGB( res, rgb);
+                classNames.labelToRGB( gtruth, rgb_gt);
+                std::string fname = NICE::StringTools::baseName ( filelist[z], false );
+                std::string outStr;
+                SemSegTools::saveResultsToImageFile( &conf, "analysis", orig,
+                            rgb_gt, rgb, fname, outStr );
+            }
+
+            // prepare for new 3d image
+            filelist.clear();
+            segresult.reInit(0,0,0);
+            gt.reInit(0,0,0);
+            depthCount = 0;
+            idx++;
         }
     }
 

+ 3 - 2
progs/testSemanticSegmentation3D.cpp

@@ -46,11 +46,11 @@ void startClassification (SemanticSegmentation *semseg,
     if (cvRuns > 1)
         write_results = false;
 
-    bool run_3Dseg = conf.gB( "SSContextTree", "run_3dseg", false);
+    bool run_3Dseg = semseg->isMode3D();
     string output_type = conf.gS ( "debug", "output_type", "ppm" );
 
     vector< int > zsizeVec;
-    semseg->getDepthVector ( testFiles, zsizeVec, run_3Dseg );
+    SemSegTools::getDepthVector ( testFiles, zsizeVec, run_3Dseg );
     int depthCount = 0, idx = 0;
     vector< string > filelist;
     NICE::MultiChannelImageT<int> segresult;
@@ -87,6 +87,7 @@ void startClassification (SemanticSegmentation *semseg,
                 depthBoundary = zsizeVec[idx];
             }
 
+//            std::cout << depthCount << " " << depthBoundary << std::endl;
             if ( depthCount < depthBoundary ) continue;
 
             NICE::MultiChannelImage3DT<double> probabilities;

+ 5 - 0
semseg/SemSegContextTree.h

@@ -168,6 +168,11 @@ class SemSegContextTree : public SemanticSegmentation
      */
     void semanticseg ( CachedExample *ce,   NICE::ImageT<int> & segresult,  NICE::MultiChannelImageT<double> & probabilities );
 
+    void semanticseg ( CachedExample *ce,
+                       NICE::MultiChannelImageT<int> & segresult,
+                       NICE::MultiChannelImage3DT<double> & probabilities )
+    {}
+
     /**
      * the main training method
      * @param md training data

+ 3 - 3
semseg/SemSegContextTree3D.cpp

@@ -1,4 +1,5 @@
 #include "SemSegContextTree3D.h"
+#include "SemSegTools.h"
 
 #include <core/basics/FileName.h>
 #include <core/basics/numerictools.h>
@@ -88,7 +89,6 @@ SemSegContextTree3D::SemSegContextTree3D (
 
     this->lfcw                = NULL;
     this->firstiteration      = true;
-    this->run3Dseg            = conf->gB ( section, "run_3dseg", false );
     this->maxSamples          = conf->gI ( section, "max_samples", 2000 );
     this->minFeats            = conf->gI ( section, "min_feats", 50 );
     this->maxDepth            = conf->gI ( section, "max_depth", 10 );
@@ -516,7 +516,7 @@ void SemSegContextTree3D::train ( const LabeledSet * trainp )
     timer.start();
 
     vector<int> zsizeVec;
-    getDepthVector ( trainp, zsizeVec, run3Dseg );
+    SemSegTools::getDepthVector ( trainp, zsizeVec, run3Dseg );
 
     //FIXME: memory usage
     vector<MultiChannelImage3DT<double> > allfeats;   // Feature Werte
@@ -1597,7 +1597,7 @@ void SemSegContextTree3D::classify (
                 }
 
 #ifdef VISUALIZE
-        getProbabilityMap( probabilities );
+        saveProbabilityMapAsImage( probabilities );
 #endif
     }
     else

+ 8 - 6
semseg/SemSegContextTree3D.h

@@ -41,9 +41,6 @@ private:
   /** local features */
   LocalFeatureColorWeijer *lfcw;
 
-  /** whether to run in 3D mode or not */
-  bool run3Dseg;
-
   /** whether to use a particular feature type or not */
   bool useFeat0, useFeat1, useFeat2, useFeat3, useFeat4;
 
@@ -233,9 +230,14 @@ public:
   void train ( const MultiDataset *md );
 
   // deprecated stuff
-  virtual void semanticseg ( OBJREC::CachedExample *ce,
-                             NICE::ImageT<int> & segresult,
-                             NICE::MultiChannelImageT<double> & probabilities )
+  void semanticseg ( CachedExample *ce,
+                     NICE::ImageT<int> & segresult,
+                     NICE::MultiChannelImageT<double> & probabilities )
+  {}
+
+  void semanticseg ( CachedExample *ce,
+                     NICE::MultiChannelImageT<int> & segresult,
+                     NICE::MultiChannelImage3DT<double> & probabilities )
   {}
 
   bool active3DMode ()

+ 5 - 0
semseg/SemSegCsurka.h

@@ -235,6 +235,11 @@ class SemSegCsurka : public SemanticSegmentation
                        NICE::ImageT<int> & segresult,
                        NICE::MultiChannelImageT<double> & probabilities );
 
+    void semanticseg ( CachedExample *ce,
+                       NICE::MultiChannelImageT<int> & segresult,
+                       NICE::MultiChannelImage3DT<double> & probabilities )
+    {}
+
     /** this procedure is equal semanticseg, if there is no post process
     * @param ce image data
     * @param segresult result of the semantic segmentation with a label for each pixel

+ 5 - 0
semseg/SemSegLocal.h

@@ -40,6 +40,11 @@ class SemSegLocal : public SemanticSegmentation
                        NICE::ImageT<int> & segresult,
                        NICE::MultiChannelImageT<double> & probabilities );
 
+    void semanticseg ( CachedExample *ce,
+                       NICE::MultiChannelImageT<int> & segresult,
+                       NICE::MultiChannelImage3DT<double> & probabilities )
+    {}
+
 };
 
 

+ 5 - 0
semseg/SemSegNovelty.h

@@ -245,6 +245,11 @@ class SemSegNovelty : public SemanticSegmentation
                        NICE::ImageT<int> & segresult,
                        NICE::MultiChannelImageT<double> & probabilities );
 
+    void semanticseg ( CachedExample *ce,
+                       NICE::MultiChannelImageT<int> & segresult,
+                       NICE::MultiChannelImage3DT<double> & probabilities )
+    {}
+
     /**
      * @brief visualize a specific region in the original image
      *

+ 5 - 0
semseg/SemSegNoveltyBinary.h

@@ -197,6 +197,11 @@ class SemSegNoveltyBinary : public SemanticSegmentation
                        NICE::ImageT<int> & segresult,
                        NICE::MultiChannelImageT<double> & probabilities );
     
+    void semanticseg ( CachedExample *ce,
+                       NICE::MultiChannelImageT<int> & segresult,
+                       NICE::MultiChannelImage3DT<double> & probabilities )
+    {}
+
     /**
      * @brief visualize a specific region in the original image
      *

+ 94 - 57
semseg/SemSegObliqueTree.cpp

@@ -55,52 +55,53 @@ void SemSegObliqueTree::preprocessChannels (
         CachedExample *ce,
         bool isColor ) const
 {
-    NICE::MultiChannelImageT<int> * img = NULL;
-    NICE::MultiChannelImageT<double> * imgD = NULL;
+    NICE::MultiChannelImage3DT<int> * img = NULL;
+    NICE::MultiChannelImage3DT<double> * imgD = NULL;
 
-    imgD    = & ce->getDChannel( CachedExample::D_EOH );
+    imgD = & ce->getDChannel( CachedExample::D_EOH );
     assert( imgD->channels() == 0 );
 
     if ( isColor )
     {
         img = & ce->getIChannel( CachedExample::I_COLOR );
 
-        imgD->reInit ( img->width(), img->height(), 3 );
+        imgD->reInit ( img->width(), img->height(), img->depth(), 3 );
 
-        for ( int y = 0; y < img->height(); y++ )
-            for ( int x = 0; x < img->width(); x++ )
-            {
-                double r = (double)img->get( x, y, 0);
-                double g = (double)img->get( x, y, 1);
-                double b = (double)img->get( x, y, 2);
-
-                if ( colorMode == 1 )
-                {
-                    double h,s,v;
-                    ColorConversion::ccRGBtoHSV(r, g, b, &h, &s, &v);
-                    imgD->set( x, y, h, 0);
-                    imgD->set( x, y, s, 1);
-                    imgD->set( x, y, v, 2);
-                }
-                else if ( colorMode == 2 )
+        for ( int z = 0; z < img->depth(); z++ )
+            for ( int y = 0; y < img->height(); y++ )
+                for ( int x = 0; x < img->width(); x++ )
                 {
-                    double cX, cY, cZ, cL, ca, cb;
-                    r /= 255.0;
-                    g /= 255.0;
-                    b /= 255.0;
-                    ColorConversion::ccRGBtoXYZ( r, g, b, &cX, &cY, &cZ, 0 );
-                    ColorConversion::ccXYZtoCIE_Lab( cX, cY, cZ, &cL, &ca, &cb, 0 );
-                    imgD->set( x, y, cL, 0);
-                    imgD->set( x, y, ca, 1);
-                    imgD->set( x, y, cb, 2);
+                    double r = (double)img->get( x, y, z, 0);
+                    double g = (double)img->get( x, y, z, 1);
+                    double b = (double)img->get( x, y, z, 2);
+
+                    if ( colorMode == 1 )
+                    {
+                        double h,s,v;
+                        ColorConversion::ccRGBtoHSV(r, g, b, &h, &s, &v);
+                        imgD->set( x, y, z, h, 0);
+                        imgD->set( x, y, z, s, 1);
+                        imgD->set( x, y, z, v, 2);
+                    }
+                    else if ( colorMode == 2 )
+                    {
+                        double cX, cY, cZ, cL, ca, cb;
+                        r /= 255.0;
+                        g /= 255.0;
+                        b /= 255.0;
+                        ColorConversion::ccRGBtoXYZ( r, g, b, &cX, &cY, &cZ, 0 );
+                        ColorConversion::ccXYZtoCIE_Lab( cX, cY, cZ, &cL, &ca, &cb, 0 );
+                        imgD->set( x, y, z, cL, 0);
+                        imgD->set( x, y, z, ca, 1);
+                        imgD->set( x, y, z, cb, 2);
+                    }
+                    else
+                    {
+                        imgD->set( x, y, z, r/255.0, 0 );
+                        imgD->set( x, y, z, g/255.0, 1 );
+                        imgD->set( x, y, z, b/255.0, 2 );
+                    }
                 }
-                else
-                {
-                    imgD->set( x, y, r/255.0, 0 );
-                    imgD->set( x, y, g/255.0, 1 );
-                    imgD->set( x, y, b/255.0, 2 );
-                }
-            }
 
         // remove integer channels
         img->freeData();
@@ -110,18 +111,18 @@ void SemSegObliqueTree::preprocessChannels (
         img = & ce->getIChannel( CachedExample::I_GRAYVALUES );
 
         // gray values to range [0,1]
-        imgD->reInit ( img->width(), img->height(), 1 );
+        imgD->reInit ( img->width(), img->height(), img->depth(), 1 );
 
-        for ( int y = 0; y < img->height(); y++ )
-            for ( int x = 0; x < img->width(); x++ )
-            {
-                double g = (double)img->get( x, y, 0) / 255.0;
-                imgD->set( x, y, g, 0);
-            }
+        for ( int z = 0; z < img->depth(); z++ )
+            for ( int y = 0; y < img->height(); y++ )
+                for ( int x = 0; x < img->width(); x++ )
+                {
+                    double g = (double)img->get( x, y, z, 0) / 255.0;
+                    imgD->set( x, y, z, g, 0);
+                }
 
         // remove integer channel
         img->freeData();
-
     }
 
     img = NULL;
@@ -130,7 +131,7 @@ void SemSegObliqueTree::preprocessChannels (
 
 
 void SemSegObliqueTree::initFromConfig( const Config *_conf,
-                                         const string &s_confSection )
+                                        const string &s_confSection )
 {
     conf = _conf;
     saveLoadData = conf->gB ( s_confSection, "save_load_data", false );
@@ -146,7 +147,7 @@ void SemSegObliqueTree::train ( const MultiDataset *md )
 {
     if ( saveLoadData && FileMgt::fileExists( fileLocation ) )
     {
-        read( fileLocation );
+        read( fileLocation, 1 );
     }
     else
     {
@@ -162,7 +163,8 @@ void SemSegObliqueTree::train ( const MultiDataset *md )
           * ( ( *md ) ["train"] ),
           *classNames,
           examples,
-          imgexamples );
+          imgexamples,
+          run3Dseg );
 
         assert ( examples.size() > 0 );
 
@@ -178,7 +180,7 @@ void SemSegObliqueTree::train ( const MultiDataset *md )
         fpc->train( fp, examples);
 
         // save trained classifier to file
-        if (saveLoadData) save( fileLocation );
+        if (saveLoadData) save( fileLocation, 1 );
 
         // Cleaning up
         for ( vector<CachedExample *>::iterator i = imgexamples.begin();
@@ -212,15 +214,50 @@ void SemSegObliqueTree::semanticseg(
 
     Example pce ( ce, 0, 0 );
     for ( int y = 0 ; y < ysize ; y++ )
-      for ( int x = 0 ; x < xsize ; x++ )
-      {
-        pce.x = x ;
-        pce.y = y;
-        ClassificationResult r = fpcrf->classify ( pce );
-        segresult.setPixel ( x, y, r.classno );
-        for ( int i = 0 ; i < ( int ) probabilities.channels(); i++ )
-          probabilities[i](x,y) = r.scores[i];
-      }
+        for ( int x = 0 ; x < xsize ; x++ )
+        {
+            pce.x = x;
+            pce.y = y;
+            ClassificationResult r = fpcrf->classify ( pce );
+            segresult.setPixel ( x, y, r.classno );
+            for ( int i = 0 ; i < ( int ) probabilities.channels(); i++ )
+                probabilities[i](x,y) = r.scores[i];
+        }
+}
+
+/** classification function 3d */
+void SemSegObliqueTree::semanticseg(
+        OBJREC::CachedExample *ce,
+        NICE::MultiChannelImageT<int> &segresult,
+        NICE::MultiChannelImage3DT<double> &probabilities )
+{
+    // for speed optimization
+    FPCRandomForests *fpcrf = dynamic_cast<FPCRandomForests *> ( fpc );
+
+    int xsize, ysize, zsize;
+    ce->getImageSize3 ( xsize, ysize, zsize );
+    probabilities.reInit ( xsize, ysize, zsize, classNames->getMaxClassno() + 1 );
+    segresult.reInit ( xsize, ysize, (unsigned int)zsize );
+
+    vector<DecisionTree *> forest = fpcrf->getForest ();
+    DecisionNode *root = forest[0]->getRoot ();
+    ConvolutionFeature* cf = dynamic_cast<ConvolutionFeature*> (root->f);
+
+    preprocessChannels( ce, cf->isColorMode() ); //FIXME!!!
+
+    Example pce ( ce, 0, 0, 0 );
+    for ( int z = 0 ; z < zsize; z++ )
+        for ( int y = 0 ; y < ysize ; y++ )
+            for ( int x = 0 ; x < xsize ; x++ )
+            {
+                pce.x = x;
+                pce.y = y;
+                pce.z = z;
+                ClassificationResult r = fpcrf->classify ( pce );
+                segresult.set ( x, y, r.classno, (unsigned int)z );
+                for ( int i = 0 ; i < ( int ) probabilities.channels(); i++ )
+                    probabilities.set ( x, y, z, r.scores[i], i );
+            }
 }
 
 ///////////////////// INTERFACE PERSISTENT /////////////////////

+ 13 - 2
semseg/SemSegObliqueTree.h

@@ -52,8 +52,9 @@ class SemSegObliqueTree : public SemanticSegmentation
         SemSegObliqueTree ();
 
         /** config constructor */
-        SemSegObliqueTree ( const NICE::Config *conf,
-                                  const ClassNames *classNames );
+        SemSegObliqueTree (
+                const NICE::Config *conf,
+                const ClassNames *classNames );
 
         /** simple destructor */
         virtual ~SemSegObliqueTree();
@@ -85,6 +86,16 @@ class SemSegObliqueTree : public SemanticSegmentation
                            NICE::ImageT<int> &segresult,
                            NICE::MultiChannelImageT<double> &probabilities );
 
+        /**
+         * Classify each voxel of a 3D image (image stack)
+         * @author Sven Sickert
+         * @param ce 3d image data
+         * @param segresult segmentation results (output)
+         * @param probabilities probabilities for each pixel (output)
+         */
+        void semanticseg ( OBJREC::CachedExample *ce,
+                           NICE::MultiChannelImageT<int> & segresult,
+                           NICE::MultiChannelImage3DT<double> & probabilities );
 
         ///////////////////// INTERFACE PERSISTENT /////////////////////
         // interface specific methods for store and restore

+ 174 - 75
semseg/SemSegTools.cpp

@@ -8,6 +8,7 @@
 #include <iostream>
 #include <iomanip>
 
+#include "core/basics/StringTools.h"
 #include "SemSegTools.h"
 
 using namespace OBJREC;
@@ -99,7 +100,7 @@ void SemSegTools::computeClassificationStatistics(
     std::cout << "\nPERFORMANCE" << std::endl;
     std::cout << "###########\n" << std::endl;
 
-    double overallTrue = confMat.trace();
+    double accuracy = confMat.trace();
     double sumAll  = 0.0;
 
     // overall recognition rate
@@ -107,31 +108,48 @@ void SemSegTools::computeClassificationStatistics(
         for ( int c = 0; c < (int) confMat.cols(); c++ )
             sumAll += confMat( r, c );
 
-    overallTrue /= sumAll;
+    accuracy /= sumAll;
 
-    double precision = 0.0, recall = 0.0, f1score = 0.0, iuScore = 0.0;
+    double prec = 0.0, rec = 0.0, f1score = 0.0, iuScore = 0.0;
 
-    // binary classification
+    // classification
+    int normConst = classMappingInv.size();
     for ( int c = 0; c < classMappingInv.size(); c++ )
     {
+        std::cout << "Class " << classNames.text( classMappingInv[c] ) << ":" << std::endl;
+
         double precBase = 0.0, recBase = 0.0;
+        // row-wise sum
         for ( int r = 0; r < classMappingInv.size(); r++ )
             precBase += confMat(r,c);
 
+        // column-wise sum
         for ( int cc = 0; cc < classMappingInv.size(); cc++ )
             recBase += confMat(c,cc);
 
-        precision += confMat(c,c) / precBase;
-        recall += confMat(c,c) / recBase;
-        iuScore += confMat(c,c) / (precBase+recBase-confMat(c,c));
+        double precClass = 0, recClass = 0;
+
+        if (precBase > 0) precClass = confMat(c,c) / precBase;
+
+        if (recBase > 0) recClass = confMat(c,c) / recBase;
+
+        std::cout << "  Precision: " << precClass << std::endl;
+        std::cout << "  Recall:    " << recClass << std::endl;
+        prec += precClass;
+        rec += recClass;
+
+        if (precBase > 0 && recBase > 0)
+            iuScore += confMat(c,c) / (precBase+recBase-confMat(c,c));
+        else
+            normConst--;
     }
 
-    precision /= classMappingInv.size();
-    recall /= classMappingInv.size();
-    iuScore /= classMappingInv.size();
-    f1score = 2.0*(precision*recall)/(precision+recall);
+    prec /= (double)normConst;
+    rec /= (double)normConst;
+    iuScore /= (double)normConst;
+    f1score = 2.0*(prec*rec)/(prec+rec);
 
-    // normalizing confMat using rows
+    // row-wise normalization of confMat
     for ( int r = 0 ; r < (int) confMat.rows() ; r++ )
     {
         double sum = 0.0;
@@ -176,12 +194,12 @@ void SemSegTools::computeClassificationStatistics(
     }
 
     // print classification statistics
-    std::cout << "\nAccuracy: " << overallTrue;
-    std::cout << "\nPrecision: " << precision;
-    std::cout << "\nRecall: " << recall;
+    std::cout << "\nAccuracy: " << accuracy;
+    std::cout << "\nPrecision: " << prec;
+    std::cout << "\nRecall: " << rec;
     std::cout << "\nF1Score: " << f1score;
     std::cout << "\nIU: " << iuScore;
-    std::cout << "\n\nAverage Recognition Rate: " << confMat.trace() / (double)classMappingInv.size();
+    //std::cout << "\n\nAverage Recognition Rate: " << confMat.trace() / (double)classMappingInv.size();
     //std::cout << "\nLower Bound: " << 1.0 /(double)classMappingInv.size();
     std::cout << std::endl;
 }
@@ -235,98 +253,179 @@ void SemSegTools::saveResultsToImageFile(
     outStr = out.str();
 }
 
-void SemSegTools::collectTrainingExamples ( 
+void SemSegTools::getDepthVector (
+        const LabeledSet *Files,
+        std::vector<int> & depthVec,
+        const bool run3Dseg )
+{
+    std::string oldName;
+    int zsize = 0;
+    bool isInit = false;
+
+    for (LabeledSet::const_iterator it = Files->begin(); it != Files->end(); it++)
+    {
+        for (std::vector<ImageInfo *>::const_iterator jt = it->second.begin();
+             jt != it->second.end(); jt++)
+        {
+            ImageInfo & info = *(*jt);
+            std::string file = info.img();
+
+            std::vector< std::string > list;
+            StringTools::split ( file, '/', list );
+            std::string filename = list.back();
+            uint found = filename.find_last_of ( "_" );
+            if (run3Dseg && found < filename.size() && found-3 > 0 )
+            {
+                std::string curName = filename.substr ( found-3,3 );
+                if ( !isInit )
+                {
+                    oldName = curName;
+                    isInit = true;
+                }
+                if ( curName.compare ( oldName ) == 0 ) // if strings match up
+                {
+                    zsize++;
+                }
+                else
+                {
+                    depthVec.push_back ( zsize );
+                    zsize = 1;
+                    oldName = curName;
+                }
+            }
+            else
+            {
+                zsize = 1;
+                depthVec.push_back ( zsize );
+            }
+
+        }
+    }
+    depthVec.push_back ( zsize );
+}
+
+void SemSegTools::collectTrainingExamples (
         const Config * conf,
         const std::string & section,
         const LabeledSet & train,
         const ClassNames & cn,
         Examples & examples,
-        vector<CachedExample *> & imgexamples )
+        vector<CachedExample *> & imgexamples,
+        const bool run3Dseg )
 {
     assert ( train.count() > 0 );
     examples.clear();
     imgexamples.clear();
 
+    vector<int> zsizeVec;
+    SemSegTools::getDepthVector ( &train, zsizeVec, run3Dseg );
+
     int grid_size_x = conf->gI(section, "grid_size_x", 5 );
     int grid_size_y = conf->gI(section, "grid_size_y", 5 );
+    int grid_size_z = conf->gI(section, "grid_size_z", 5 );
     int grid_border_x = conf->gI(section, "grid_border_x", 20 );
     int grid_border_y = conf->gI(section, "grid_border_y", 20 );
+    int grid_border_z = conf->gI(section, "grid_border_z", 20 );
+
+    if (!run3Dseg)
+    {
+        grid_size_z = 1;
+        grid_border_z = 0;
+    }
 
     std::string selection = conf->gS(section, "train_selection" );
 
     set<int> classnoSelection;
     cn.getSelection ( selection, classnoSelection );
-    
+
     bool useExcludedAsBG = conf->gB(section, "use_excluded_as_background", false );
 
     int backgroundClassNo = 0;
-    
+
     if ( useExcludedAsBG )
     {
         backgroundClassNo = cn.classno("various");
         assert ( backgroundClassNo >= 0 );
     }
 
-    LOOP_ALL_S (train)
-    {
-        EACH_INFO(image_classno,imgInfo);
-        std::string imgfn = imgInfo.img();
-
-        if ( ! imgInfo.hasLocalizationInfo() ) {
-            std::cerr << "WARNING: NO localization info found for "
-                      << imgfn << " !" << std::endl;
-            continue;
-        }
-
-        int xsize, ysize;
-        CachedExample *ce = new CachedExample ( imgfn );
-        ce->getImageSize ( xsize, ysize );
-        imgexamples.push_back ( ce );
+    int depthCount = 0;
+    int imgCounter = 0;
+    vector<std::string> filelist;
+    NICE::MultiChannelImageT<int> pixelLabels;
 
-        const LocalizationResult *locResult = imgInfo.localization();
-        if ( locResult->size() <= 0 ) {
-            std::cerr << "WARNING: NO ground truth polygons found for "
-                      << imgfn << " !" << std::endl;
-            continue;
-        }
-
-        std::cerr << "SemSegTools: Collecting pixel examples from localization info: "
-                  << imgfn << std::endl;
+    for (LabeledSet::const_iterator it = train.begin(); it != train.end(); it++)
+    {
+        for (std::vector<ImageInfo *>::const_iterator jt = it->second.begin();
+             jt != it->second.end(); jt++)
+        {
+            ImageInfo & info = *(*jt);
+            std::string file = info.img();
+            filelist.push_back ( file );
+            depthCount++;
+
+            const LocalizationResult *locResult = info.localization();
+
+            // getting groundtruth
+            NICE::ImageT<int> pL;
+            pL.resize ( locResult->xsize, locResult->ysize );
+            pL.set ( 0 );
+            locResult->calcLabeledImage ( pL, cn.getBackgroundClass() );
+            pixelLabels.addChannel ( pL );
+
+            if ( locResult->size() <= 0 ) {
+                std::cerr << "WARNING: NO ground truth polygons found for "
+                          << file << " !" << std::endl;
+                continue;
+            }
 
-        NICE::ImageT<int> pixelLabels (xsize, ysize);
-        pixelLabels.set(0);
-        locResult->calcLabeledImage ( pixelLabels, cn.getBackgroundClass() );
+            std::cerr << "SemSegTools: Collecting pixel examples from localization info: "
+                      << file << std::endl;
 
-#ifdef DEBUG_LOCALIZATION
-        NICE::Image img (imgfn);
-        showImage(img);
-        showImage(pixelLabels);
-#endif
-
-        Example pce ( ce, 0, 0 );
-        for ( int x = 0 ; x < xsize ; x += grid_size_x )
-            for ( int y = 0 ; y < ysize ; y += grid_size_y )
+            int depthBoundary = 0;
+            if ( run3Dseg )
             {
-                if ( (x >= grid_border_x) &&
-                     ( y >= grid_border_y ) && ( x < xsize - grid_border_x ) &&
-                     ( y < ysize - grid_border_x ) )
-                {
-                    pce.x = x; pce.y = y;
-                    int classno = pixelLabels.getPixel(x,y);
-
-                    if ( classnoSelection.find(classno) != classnoSelection.end() ) {
-                        examples.push_back ( pair<int, Example> (
-                                                 classno,
-                                                 pce // FIXME: offset handling
-                                                 ) );
-                    } else if ( useExcludedAsBG ) {
-                        examples.push_back ( pair<int, Example> (
-                                                 backgroundClassNo,
-                                                 pce // FIXME: offset handling
-                                                 ) );
-                    }
-                }
+                depthBoundary = zsizeVec[imgCounter];
             }
+
+            if ( depthCount < depthBoundary ) continue;
+
+            int xsize, ysize, zsize;
+            CachedExample *ce = new CachedExample ( filelist );
+            ce->getImageSize3 ( xsize, ysize, zsize );
+            imgexamples.push_back ( ce );
+
+            // drawing actual examples
+            Example pce ( ce, 0, 0, 0 );
+            for ( int z = 0; z < zsize; z += grid_size_z )
+                for ( int x = 0 ; x < xsize ; x += grid_size_x )
+                    for ( int y = 0 ; y < ysize ; y += grid_size_y )
+                        if ( ( x >= grid_border_x ) &&
+                             ( y >= grid_border_y ) &&
+                             ( z >= grid_border_z ) &&
+                             ( x < xsize - grid_border_x ) &&
+                             ( y < ysize - grid_border_y ) &&
+                             ( z < zsize - grid_border_z ) )
+                        {
+                            pce.x = x; pce.y = y; pce.z = z;
+                            int classno = pixelLabels.get(x,y,(unsigned int)z);
+
+                            if ( classnoSelection.find(classno) != classnoSelection.end() )
+                            {
+                                examples.push_back (
+                                            pair<int, Example> ( classno, pce ) );
+                            } else if ( useExcludedAsBG )
+                            {
+                                examples.push_back (
+                                            pair<int, Example> ( backgroundClassNo, pce ) );
+                            }
+                        }
+
+            // prepare for new 3D image
+            filelist.clear();
+            pixelLabels.reInit ( 0,0,0 );
+            depthCount = 0;
+            imgCounter++;
+        }
     }
 
     std::cerr << "total number of examples: " << (int)examples.size() << std::endl;

+ 15 - 2
semseg/SemSegTools.h

@@ -89,6 +89,18 @@ class SemSegTools
             const std::string & file,
             std::string & outStr );
 
+    /**
+     * @brief Collect information about the depth of 3d images
+     * @author Sven Sickert
+     * @param Files a labeled set of data
+     * @param depthVec output of depth values
+     * @param run3dseg whether slice counting is necessary or not
+     */
+    static void getDepthVector (
+            const LabeledSet *Files,
+            std::vector<int> & depthVec,
+            const bool run3dseg );
+
     /** collect pixel-wise training examples
         from a set of images
         @param conf includes settings about grid size etc.
@@ -97,6 +109,7 @@ class SemSegTools
         @param cn classNames object
         @param examples resulting pixel-wise examples
         @param imgexamples image based caching structure referenced by pixel-wise examples
+        @param run3Dseg whether to run in 3D segmentation mode or not
     */
     static void collectTrainingExamples (
             const NICE::Config * conf,
@@ -104,8 +117,8 @@ class SemSegTools
             const LabeledSet & train,
             const ClassNames & cn,
             Examples & examples,
-            std::vector<CachedExample *> & imgexamples );
-
+            std::vector<CachedExample *> & imgexamples,
+            const bool run3Dseg = false );
 };
 
 

+ 268 - 383
semseg/SemanticSegmentation.cpp

@@ -7,10 +7,8 @@
 */
 #include "SemanticSegmentation.h"
 
-#include <core/basics/StringTools.h>
-
-#include <vislearning/baselib/Preprocess.h>
-#include <vislearning/baselib/Globals.h>
+#include "vislearning/baselib/Preprocess.h"
+#include "vislearning/baselib/Globals.h"
 
 #include <iostream>
 
@@ -25,27 +23,27 @@ using namespace NICE;
 SemanticSegmentation::SemanticSegmentation ( )
     : iterationCountSuffix(1)
 {
-  this->imagetype = IMAGETYPE_RGB;
-  
-  this->classNames = new ClassNames();
-
+    this->imagetype = IMAGETYPE_RGB;
+    this->classNames = new ClassNames();
+    this->run3Dseg = false;
+    this->coarseMode = false;
 }
 
 SemanticSegmentation::SemanticSegmentation ( const Config *conf,
                                              const ClassNames *classNames )
     : iterationCountSuffix(1)
 {
-  ///////////
-  // same code as in empty constructor - duplication can be avoided with C++11 allowing for constructor delegation
-  /////////// 
-  
-  ///////////
-  // here comes the new code part different from the empty constructor
-  /////////// 
-
-  this->classNames = classNames; 
-  
-  this->initFromConfig( conf ); 
+    ///////////
+    // same code as in empty constructor - duplication can be avoided with C++11 allowing for constructor delegation
+    ///////////
+
+    ///////////
+    // here comes the new code part different from the empty constructor
+    ///////////
+
+    this->classNames = classNames;
+
+    this->initFromConfig( conf );
 }
 
 SemanticSegmentation::~SemanticSegmentation()
@@ -54,60 +52,73 @@ SemanticSegmentation::~SemanticSegmentation()
 
 void SemanticSegmentation::initFromConfig(const Config* conf, const string& s_confSection)
 {
-  std::string imagetype_s = conf->gS ( "main", "imagetype", "rgb" );
-  coarseMode = conf->gB( "main", "coarse_mode", false );
-
-  if ( imagetype_s == "rgb" )
-    imagetype = IMAGETYPE_RGB;
-  else if ( imagetype_s == "gray" )
-    imagetype = IMAGETYPE_GRAY;
-  else {
-    fprintf ( stderr, "SemanticSegmentation:: unknown image type option\n" );
-    exit ( -1 );
-  }
-
-  // dangerous!!!
-  Preprocess::Init ( conf );
+    std::string imagetype_s = conf->gS ( "main", "imagetype", "rgb" );
+    coarseMode = conf->gB( "main", "coarse_mode", false );
+    run3Dseg = conf->gB( "main", "run_3dseg", false );
+
+    if ( imagetype_s == "rgb" )
+        imagetype = IMAGETYPE_RGB;
+    else if ( imagetype_s == "gray" )
+        imagetype = IMAGETYPE_GRAY;
+    else {
+        fprintf ( stderr, "SemanticSegmentation:: unknown image type option\n" );
+        exit ( -1 );
+    }
+
+    // dangerous!!!
+    Preprocess::Init ( conf );
 }
 
 ///////////////////// ///////////////////// /////////////////////
 //                      SEGMENTATION STUFF
 ///////////////////// ///////////////////// /////////////////////
 
-void SemanticSegmentation::semanticseg ( const std::string & filename,
-    NICE::ImageT<int> & segresult,
-    NICE::MultiChannelImageT<double> & probabilities )
+void SemanticSegmentation::semanticseg (
+        const std::string & filename,
+        NICE::ImageT<int> & segresult,
+        NICE::MultiChannelImageT<double> & probabilities )
 {
-  Globals::setCurrentImgFN ( filename );
-  CachedExample *ce;
-  if ( imagetype == IMAGETYPE_RGB )
-  {
-    NICE::ColorImage img = Preprocess::ReadImgAdvRGB ( filename );
-    ce = new CachedExample ( img );
-  } else {
-
-    NICE::Image img = Preprocess::ReadImgAdv ( filename );
-    ce = new CachedExample ( img );
-  }
-#ifdef DEBUG_PRINTS
-  fprintf ( stderr, "Starting Semantic Segmentation !\n" );
-#endif
-  this->semanticseg ( ce, segresult, probabilities );
-  delete ce;
+    Globals::setCurrentImgFN ( filename );
+    CachedExample *ce;
+    if ( imagetype == IMAGETYPE_RGB )
+    {
+        NICE::ColorImage img = Preprocess::ReadImgAdvRGB ( filename );
+        ce = new CachedExample ( img );
+    } else {
+
+        NICE::Image img = Preprocess::ReadImgAdv ( filename );
+        ce = new CachedExample ( img );
+    }
+
+    this->semanticseg ( ce, segresult, probabilities );
+    delete ce;
+}
+
+void SemanticSegmentation::semanticseg (
+        const std::vector<std::string> & filelist,
+        NICE::MultiChannelImageT<int> & segresult,
+        NICE::MultiChannelImage3DT<double> & probabilities )
+{
+    //NICE::MultiChannelImage3DT<int> img;
+    //make3DImage( filelist, img );
+    CachedExample *ce = new CachedExample (filelist);
+
+    this->semanticseg ( ce, segresult, probabilities );
+    delete ce;
 }
 
 void SemanticSegmentation::classify ( const std::vector<std::string> & filelist,
                                       NICE::MultiChannelImageT<int> & segresult,
                                       NICE::MultiChannelImage3DT<double> & probabilities )
 {
-  for ( int it = 0; it < ( int ) filelist.size(); it++ )
-  {
-    NICE::MultiChannelImageT<double> probs;
-    NICE::ImageT<int> res ( segresult.width(), segresult.height() );
-    this->semanticseg( filelist[it], res, probs );
-    probabilities.addChannel( probs );
-    segresult.addChannel( res );
-  }
+    for ( int it = 0; it < ( int ) filelist.size(); it++ )
+    {
+        NICE::MultiChannelImageT<double> probs;
+        NICE::ImageT<int> res ( segresult.width(), segresult.height() );
+        this->semanticseg( filelist[it], res, probs );
+        probabilities.addChannel( probs );
+        segresult.addChannel( res );
+    }
 }
 
 ///////////////////// ///////////////////// /////////////////////
@@ -116,298 +127,172 @@ void SemanticSegmentation::classify ( const std::vector<std::string> & filelist,
 void SemanticSegmentation::convertLSetToSparseExamples ( Examples &examples, LabeledSetVector &lvec )
 {
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertLSetToExamples starts" << endl;
+    cout << "SemSegRegionBased::convertLSetToExamples starts" << endl;
 #endif
-  for ( map< int, vector<NICE::Vector *> >::iterator iter = lvec.begin(); iter != lvec.end(); ++iter )
-  {
-    for ( int j = 0; j < ( int ) iter->second.size(); j++ )
+    for ( map< int, vector<NICE::Vector *> >::iterator iter = lvec.begin(); iter != lvec.end(); ++iter )
     {
-      Vector &tmp = * ( iter->second[j] );
-      int dim = tmp.size();
-      SparseVector *vec = new SparseVector ( dim );
-      for ( int j = 0; j < dim; j++ )
-      {
-        if ( tmp[j] != 0.0 )
+        for ( int j = 0; j < ( int ) iter->second.size(); j++ )
         {
-          ( *vec ) [j] = tmp[j];
+            Vector &tmp = * ( iter->second[j] );
+            int dim = tmp.size();
+            SparseVector *vec = new SparseVector ( dim );
+            for ( int j = 0; j < dim; j++ )
+            {
+                if ( tmp[j] != 0.0 )
+                {
+                    ( *vec ) [j] = tmp[j];
+                }
+            }
+            Example ex;
+            ex.svec = vec;
+            examples.push_back ( pair<int, Example> ( iter->first, ex ) );
         }
-      }
-      Example ex;
-      ex.svec = vec;
-      examples.push_back ( pair<int, Example> ( iter->first, ex ) );
     }
-  }
-  lvec.clear();
+    lvec.clear();
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertLSetToExamples finished" << endl;
+    cout << "SemSegRegionBased::convertLSetToExamples finished" << endl;
 #endif
 }
 
 void SemanticSegmentation::convertLSetToExamples ( Examples &examples, LabeledSetVector &lvec, const bool & removeOldDataPointer )
 {
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertLSetToExamples starts" << endl;
+    cout << "SemSegRegionBased::convertLSetToExamples starts" << endl;
 #endif
-  for ( map< int, vector<NICE::Vector *> >::iterator iter = lvec.begin(); iter != lvec.end(); ++iter )
-  {
-    for ( int j = 0; j < (int)iter->second.size(); j++ )
+    for ( map< int, vector<NICE::Vector *> >::iterator iter = lvec.begin(); iter != lvec.end(); ++iter )
     {
-      NICE::Vector *vec = new NICE::Vector ( * ( iter->second[j] ) );
-      Example ex ( vec );
-      examples.push_back ( pair<int, Example> ( iter->first, ex ) );
+        for ( int j = 0; j < (int)iter->second.size(); j++ )
+        {
+            NICE::Vector *vec = new NICE::Vector ( * ( iter->second[j] ) );
+            Example ex ( vec );
+            examples.push_back ( pair<int, Example> ( iter->first, ex ) );
+        }
     }
-  }
 
-  if (!removeOldDataPointer)
-  {
-    //NOTE this is only useful, if our classifier does NOT need the data explicitely
-    lvec.clear();
-  }
-  else
-  {
-    lvec.removePointersToDataWithoutDeletion();
-    //after setting all the pointers to NULL, we can savely clear the LSet without deleting the previously
-    //stored features, which might be needed somewhere else, e.g., in the VCNearestNeighbour
-    lvec.clear();
-  }
+    if (!removeOldDataPointer)
+    {
+        //NOTE this is only useful, if our classifier does NOT need the data explicitely
+        lvec.clear();
+    }
+    else
+    {
+        lvec.removePointersToDataWithoutDeletion();
+        //after setting all the pointers to NULL, we can savely clear the LSet without deleting the previously
+        //stored features, which might be needed somewhere else, e.g., in the VCNearestNeighbour
+        lvec.clear();
+    }
 
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertLSetToExamples finished" << endl;
+    cout << "SemSegRegionBased::convertLSetToExamples finished" << endl;
 #endif
 }
 
 void SemanticSegmentation::convertExamplesToLSet ( Examples &examples, LabeledSetVector &lvec )
 {
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertExamplesToLSet starts" << endl;
+    cout << "SemSegRegionBased::convertExamplesToLSet starts" << endl;
 #endif
-  lvec.clear();
-  for ( int i = 0; i < ( int ) examples.size(); i++ )
-  {
-    if ( examples[i].second.vec != NULL )
-    {
-      lvec.add ( examples[i].first, *examples[i].second.vec );
-      delete examples[i].second.vec;
-      examples[i].second.vec = NULL;
-    }
-    else
+    lvec.clear();
+    for ( int i = 0; i < ( int ) examples.size(); i++ )
     {
-      if ( examples[i].second.svec != NULL )
-      {
-        NICE::Vector v;
-        examples[i].second.svec->convertToVectorT(v);
-        lvec.add ( examples[i].first, v );
-        delete examples[i].second.svec;
-        examples[i].second.svec = NULL;        
-      }
-      else
-      {
-        throw ( "no features for LabeledSet" );
-      }
-    }
+        if ( examples[i].second.vec != NULL )
+        {
+            lvec.add ( examples[i].first, *examples[i].second.vec );
+            delete examples[i].second.vec;
+            examples[i].second.vec = NULL;
+        }
+        else
+        {
+            if ( examples[i].second.svec != NULL )
+            {
+                NICE::Vector v;
+                examples[i].second.svec->convertToVectorT(v);
+                lvec.add ( examples[i].first, v );
+                delete examples[i].second.svec;
+                examples[i].second.svec = NULL;
+            }
+            else
+            {
+                throw ( "no features for LabeledSet" );
+            }
+        }
 
-  }
-  examples.clear();  
+    }
+    examples.clear();
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertExamplesToLSet finished" << endl;
+    cout << "SemSegRegionBased::convertExamplesToLSet finished" << endl;
 #endif
 }
 
 void SemanticSegmentation::convertExamplesToVVector ( VVector &feats, Examples &examples, vector<int> &label )
 {
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertExamplesToVVector starts" << endl;
+    cout << "SemSegRegionBased::convertExamplesToVVector starts" << endl;
 #endif
-  feats.clear();
-  label.clear();
-  for ( int i = 0; i < ( int ) examples.size(); i++ )
-  {
-    label.push_back ( examples[i].first );
-    feats.push_back ( *examples[i].second.vec );
-    delete examples[i].second.vec;
-    examples[i].second.vec = NULL;
-  }
-  examples.clear();
+    feats.clear();
+    label.clear();
+    for ( int i = 0; i < ( int ) examples.size(); i++ )
+    {
+        label.push_back ( examples[i].first );
+        feats.push_back ( *examples[i].second.vec );
+        delete examples[i].second.vec;
+        examples[i].second.vec = NULL;
+    }
+    examples.clear();
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertExamplesToVVector finished" << endl;
+    cout << "SemSegRegionBased::convertExamplesToVVector finished" << endl;
 #endif
 }
 
 void SemanticSegmentation::convertVVectorToExamples ( VVector &feats, Examples &examples, vector<int> &label )
 {
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertVVectorToExamples starts" << endl;
+    cout << "SemSegRegionBased::convertVVectorToExamples starts" << endl;
 #endif
-  for ( int i = 0; i < ( int ) feats.size(); i++ )
-  {
-    NICE::Vector *v = new NICE::Vector ( feats[i] );
-    Example ex ( v );
-    ex.position = 0; //TODO: hier mal was besseres überlegen, damit Klassifikator wieder Bildspezifisch lernt
-    examples.push_back ( pair<int, Example> ( label[i], ex ) );
-    feats[i].clear();
-  }
-  feats.clear();
-  label.clear();
+    for ( int i = 0; i < ( int ) feats.size(); i++ )
+    {
+        NICE::Vector *v = new NICE::Vector ( feats[i] );
+        Example ex ( v );
+        ex.position = 0; //TODO: hier mal was besseres überlegen, damit Klassifikator wieder Bildspezifisch lernt
+        examples.push_back ( pair<int, Example> ( label[i], ex ) );
+        feats[i].clear();
+    }
+    feats.clear();
+    label.clear();
 #ifdef DEBUG_PRINTS
-  cout << "SemSegRegionBased::convertVVectorToExamples finished" << endl;
+    cout << "SemSegRegionBased::convertVVectorToExamples finished" << endl;
 #endif
 }
 
 void SemanticSegmentation::setIterationCountSuffix( const int & _iterationCountSuffix)
 {
-  this->iterationCountSuffix = _iterationCountSuffix;
+    this->iterationCountSuffix = _iterationCountSuffix;
 }
 
 void SemanticSegmentation::setClassNames ( const OBJREC::ClassNames * _classNames )
 {
-  this->classNames = _classNames;
+    this->classNames = _classNames;
 }
 
-void SemanticSegmentation::getDepthVector ( const LabeledSet *Files,
-                                            vector<int> & depthVec,
-                                            const bool run3Dseg )
+void SemanticSegmentation::saveProbabilityMapAsImage ( const NICE::MultiChannelImage3DT<double> & prob )
 {
-  std::string oldName;
-  int zsize = 0;
-  bool isInit = false;
-
-  for (LabeledSet::const_iterator it = Files->begin(); it != Files->end(); it++)
-  {
-    for (std::vector<ImageInfo *>::const_iterator jt = it->second.begin();
-         jt != it->second.end(); jt++)
-    {
-      ImageInfo & info = *(*jt);
-      std::string file = info.img();
-
-      std::vector< std::string > list;
-      StringTools::split ( file, '/', list );
-      std::string filename = list.back();
-      uint found = filename.find_last_of ( "_" );
-      if (run3Dseg && found < filename.size() && found-3 > 0 )
-      {
-        std::string curName = filename.substr ( found-3,3 );
-        if ( !isInit )
-        {
-          oldName = curName;
-          isInit = true;
-        }
-        if ( curName.compare ( oldName ) == 0 ) // if strings match up
-        {
-          zsize++;
-        }
-        else
-        {
-          depthVec.push_back ( zsize );
-          zsize = 1;
-          oldName = curName;
-        }
-      }
-      else
-      {
-        zsize = 1;
-        depthVec.push_back ( zsize );
-      }
+    std::string s;
 
-    }
-  }
-  depthVec.push_back ( zsize );
-}
-
-void SemanticSegmentation::make3DImage ( const std::vector<std::string> & filelist,
-    NICE::MultiChannelImage3DT<double> & imgData )
-{
-  bool isInit = false;
-  for ( int it = 0; it < ( int ) filelist.size(); it++ )
-  {
-    if ( imagetype == IMAGETYPE_RGB )
-    {
-      NICE::ColorImage img;
-      try
-      {
-        img.read ( filelist[it] );
-      }
-      catch ( ImageException iE )
-      {
-        fprintf ( stderr, "Failed to open color image file: %s\n", filelist[it].c_str() );
-        fprintf ( stderr, "%s\n", iE.what() );
-        exit ( -1 );
-      }
-      if ( !isInit )
-      {
-        imgData.reInit ( img.width(),img.height(),filelist.size(),3 );
-        isInit = true;
-      }
-      for ( int y = 0; y < img.height(); y++ )
-      {
-        for ( int x = 0; x < img.width(); x++ )
-        {
-          for ( int r = 0; r < 3; r++ )
-          {
-            imgData.set ( x, y, it, img.getPixel ( x,y,r ), r );
-          }
-        }
-      }
-    }
-    else
-    {
-      NICE::Image img;
-      try
-      {
-        img.read ( filelist[it] );
-      }
-      catch ( ImageException iE )
-      {
-        fprintf ( stderr, "Failed to open image file: %s\n", filelist[it].c_str() );
-        fprintf ( stderr, "%s\n", iE.what() );
-        exit ( -1 );
-      }
-      if ( !isInit )
-      {
-        imgData.reInit ( img.width(),img.height(),filelist.size(),1 );
-        isInit = true;
-      }
-      for ( int y = 0; y < img.height(); y++ )
-      {
-        for ( int x = 0; x < img.width(); x++ )
+    for ( int cl = 0; cl < prob.channels(); cl++ )
+        for ( int z = 0; z < prob.depth(); z++ )
         {
-          imgData.set ( x, y, it, img.getPixel ( x,y ), 0 );
-        }
-      }
-    }
-  }
+            NICE::ColorImage img( prob.width(),prob.height() );
+            NICE::ImageT<double> m = prob.getChannelT(z, cl);
+            imageToPseudoColor(m, img);
 
-  if ( imagetype == IMAGETYPE_GRAY )
-  {
-    imgData.equalizeHistogram( 0 );
-#ifdef DEBUG_PRINTS
-    for (int z = 0; z < imgData.depth(); z++)
-    {
-      NICE::Image im = imgData.getChannel( z, 0);
-      im.write( filelist[z]+"_eq.pgm");
-    }
-#endif
-  }
-}
-
-void SemanticSegmentation::getProbabilityMap ( const NICE::MultiChannelImage3DT<double> & prob )
-{
-  std::string s;
-
-  for ( int cl = 0; cl < prob.channels(); cl++ )
-    for ( int z = 0; z < prob.depth(); z++ )
-    {
-      NICE::ColorImage img( prob.width(),prob.height() );
-      NICE::ImageT<double> m = prob.getChannelT(z, cl);
-      imageToPseudoColor(m, img);
+            std::stringstream out;
+            out << "probmap_s" << z << "_c" << cl << ".ppm";
+            s = out.str();
+            img.write( s );
 
-      std::stringstream out;
-      out << "probmap_s" << z << "_c" << cl << ".ppm";
-      s = out.str();
-      img.write( s );
-
-      //showImage(img, "Probability map");
-      //getchar();
-    }
+            //showImage(img, "Probability map");
+            //getchar();
+        }
 }
 
 ///////////////////// INTERFACE PERSISTENT /////////////////////
@@ -416,123 +301,123 @@ void SemanticSegmentation::getProbabilityMap ( const NICE::MultiChannelImage3DT<
 
 void SemanticSegmentation::restore ( std::istream & is, int format )
 {
-  //delete everything we knew so far...
-  this->clear();
+    //delete everything we knew so far...
+    this->clear();
 
-  bool b_restoreVerbose ( false );
+    bool b_restoreVerbose ( false );
 #ifdef B_RESTOREVERBOSE
-  b_restoreVerbose = true;
+    b_restoreVerbose = true;
 #endif
 
-  if ( is.good() )
-  {
-    if ( b_restoreVerbose )
-      std::cerr << " restore SemanticSegmentation" << std::endl;
+    if ( is.good() )
+    {
+        if ( b_restoreVerbose )
+            std::cerr << " restore SemanticSegmentation" << std::endl;
 
-    std::string tmp;
-    is >> tmp; //class name
+        std::string tmp;
+        is >> tmp; //class name
 
-    if ( ! this->isStartTag( tmp, "SemanticSegmentation" ) )
-    {
-      std::cerr << " WARNING - attempt to restore SemanticSegmentation, but start flag " << tmp << " does not match! Aborting... " << std::endl;
-      throw;
-    }
+        if ( ! this->isStartTag( tmp, "SemanticSegmentation" ) )
+        {
+            std::cerr << " WARNING - attempt to restore SemanticSegmentation, but start flag " << tmp << " does not match! Aborting... " << std::endl;
+            throw;
+        }
 
-    is.precision (numeric_limits<double>::digits10 + 1);
+        is.precision (numeric_limits<double>::digits10 + 1);
 
-    bool b_endOfBlock ( false ) ;
+        bool b_endOfBlock ( false ) ;
 
-    while ( !b_endOfBlock )
+        while ( !b_endOfBlock )
+        {
+            is >> tmp; // start of block
+
+            if ( this->isEndTag( tmp, "SemanticSegmentation" ) )
+            {
+                b_endOfBlock = true;
+                continue;
+            }
+
+            tmp = this->removeStartTag ( tmp );
+
+            if ( b_restoreVerbose )
+                std::cerr << " currently restore section " << tmp << " in SemanticSegmentation" << std::endl;
+
+            if ( tmp.compare("classNames") == 0 )
+            {
+                //dirty solution to circumvent the const-flag
+                const_cast<ClassNames*>(this->classNames)->restore ( is, format );
+
+                is >> tmp; // end of block
+                tmp = this->removeEndTag ( tmp );
+            }
+            else if ( tmp.compare("imagetype") == 0 )
+            {
+                unsigned int ui_imagetyp;
+                is >> ui_imagetyp;
+                this->imagetype = static_cast<IMAGETYP> ( ui_imagetyp );
+
+                is >> tmp; // end of block
+                tmp = this->removeEndTag ( tmp );
+            }
+            else if ( tmp.compare("iterationCountSuffix") == 0 )
+            {
+                is >> this->iterationCountSuffix;
+
+                is >> tmp; // end of block
+                tmp = this->removeEndTag ( tmp );
+            }
+            else
+            {
+                std::cerr << "WARNING -- unexpected SemanticSegmentation object -- " << tmp << " -- for restoration... aborting" << std::endl;
+                throw;
+            }
+        }
+    }
+    else
     {
-      is >> tmp; // start of block
-
-      if ( this->isEndTag( tmp, "SemanticSegmentation" ) )
-      {
-        b_endOfBlock = true;
-        continue;
-      }
-
-      tmp = this->removeStartTag ( tmp );
-
-      if ( b_restoreVerbose )
-        std::cerr << " currently restore section " << tmp << " in SemanticSegmentation" << std::endl;
-
-      if ( tmp.compare("classNames") == 0 )
-      {
-  //dirty solution to circumvent the const-flag
-        const_cast<ClassNames*>(this->classNames)->restore ( is, format );
-
-        is >> tmp; // end of block
-        tmp = this->removeEndTag ( tmp );
-      }
-      else if ( tmp.compare("imagetype") == 0 )
-      {
-        unsigned int ui_imagetyp;
-        is >> ui_imagetyp;
-        this->imagetype = static_cast<IMAGETYP> ( ui_imagetyp );
-
-        is >> tmp; // end of block
-        tmp = this->removeEndTag ( tmp );
-      }
-      else if ( tmp.compare("iterationCountSuffix") == 0 )
-      {
-        is >> this->iterationCountSuffix;
-
-        is >> tmp; // end of block
-        tmp = this->removeEndTag ( tmp );
-      }
-      else
-      {
-      std::cerr << "WARNING -- unexpected SemanticSegmentation object -- " << tmp << " -- for restoration... aborting" << std::endl;
-      throw;
-      }
+        std::cerr << "SemanticSegmentation::restore -- InStream not initialized - restoring not possible!" << std::endl;
+        throw;
     }
-  }
-  else
-  {
-    std::cerr << "SemanticSegmentation::restore -- InStream not initialized - restoring not possible!" << std::endl;
-    throw;
-  }
 
 
- //TODO check whether we also have to do something linke Preprocess::Init ( conf );
+    //TODO check whether we also have to do something linke Preprocess::Init ( conf );
 }
 
 void SemanticSegmentation::store ( std::ostream & os, int format ) const
 {
-  if (os.good())
-  {
-    // show starting point
-    os << this->createStartTag( "SemanticSegmentation" ) << std::endl;
+    if (os.good())
+    {
+        // show starting point
+        os << this->createStartTag( "SemanticSegmentation" ) << std::endl;
 
-    os.precision (numeric_limits<double>::digits10 + 1);
+        os.precision (numeric_limits<double>::digits10 + 1);
 
-    os << this->createStartTag( "classNames" ) << std::endl;
-    this->classNames->store ( os, format );
-    os << this->createEndTag( "classNames" ) << std::endl;
+        os << this->createStartTag( "classNames" ) << std::endl;
+        this->classNames->store ( os, format );
+        os << this->createEndTag( "classNames" ) << std::endl;
 
-    //
+        //
 
-    os << this->createStartTag( "imagetype" ) << std::endl;
-    os << imagetype << std::endl;
-    os << this->createEndTag( "imagetype" ) << std::endl;
+        os << this->createStartTag( "imagetype" ) << std::endl;
+        os << imagetype << std::endl;
+        os << this->createEndTag( "imagetype" ) << std::endl;
 
-    //
+        //
 
-    os << this->createStartTag( "iterationCountSuffix" ) << std::endl;
-    os << iterationCountSuffix << std::endl;
-    os << this->createEndTag( "iterationCountSuffix" ) << std::endl;
+        os << this->createStartTag( "iterationCountSuffix" ) << std::endl;
+        os << iterationCountSuffix << std::endl;
+        os << this->createEndTag( "iterationCountSuffix" ) << std::endl;
 
-    // done
-    os << this->createEndTag( "SemanticSegmentation" ) << std::endl;
-  }
-  else
-  {
-    std::cerr << "OutStream not initialized - storing not possible!" << std::endl;
-  }
+        // done
+        os << this->createEndTag( "SemanticSegmentation" ) << std::endl;
+    }
+    else
+    {
+        std::cerr << "OutStream not initialized - storing not possible!" << std::endl;
+    }
 }
 
 void SemanticSegmentation::clear ()
 {
- //TODO
+    //TODO
 }

+ 41 - 14
semseg/SemanticSegmentation.h

@@ -65,6 +65,9 @@ class SemanticSegmentation : public NICE::Persistent
     /** whether to do a coarse segmentation or not */
     bool coarseMode;
 
+    /** whether to run in 3D mode or not */
+    bool run3Dseg;
+
     /////////////////////////
     /////////////////////////
     //  PROTECTED METHODS  //
@@ -105,11 +108,30 @@ class SemanticSegmentation : public NICE::Persistent
     //                      SEGMENTATION STUFF
     ///////////////////// ///////////////////// /////////////////////
 
+    /**
+     * @brief return whether 3D mode is activated or not
+     * @return bool 3d mode status
+     */
+    bool isMode3D ()
+    {
+        return run3Dseg;
+    }
+
     /** load img from file call localize(CachedExample *ce) etc. */
     void semanticseg ( const std::string & filename,
                        NICE::ImageT<int> & segresult,
                        NICE::MultiChannelImageT<double> & probabilities );
 
+    /**
+     * @brief Pre-processing and classification of a 3D image
+     * @param filelist filename list of images that represent slices of a stack
+     * @param segresult segmentation results (output)
+     * @param probabilities probabilities for each pixel (output)
+     */
+    void semanticseg ( const std::vector<std::string> & filelist,
+                       NICE::MultiChannelImageT<int> & segresult,
+                       NICE::MultiChannelImage3DT<double> & probabilities );
+
     /**
      * Classify each voxel of a 3D image (image stack)
      * @author Sven Sickert
@@ -132,6 +154,17 @@ class SemanticSegmentation : public NICE::Persistent
                                NICE::ImageT<int> & segresult,
                                NICE::MultiChannelImageT<double> & probabilities ) = 0;
 
+    /**
+     * Classify each voxel of a 3D image (image stack)
+     * @author Sven Sickert
+     * @param ce 3d image data
+     * @param segresult segmentation results (output)
+     * @param probabilities probabilities for each pixel (output)
+     */
+    virtual void semanticseg ( OBJREC::CachedExample *ce,
+                               NICE::MultiChannelImageT<int> & segresult,
+                               NICE::MultiChannelImage3DT<double> & probabilities ) = 0;
+
 
     /** training function (has to be overloaded by all subclasses)
      * @param md the data set
@@ -150,8 +183,9 @@ class SemanticSegmentation : public NICE::Persistent
      * @param filelist filename list of images that represent slices of a stack
      * @param imgData output
      */
+    template<class SrcP>
     void make3DImage ( const std::vector<std::string> & filelist,
-                       NICE::MultiChannelImage3DT<double> & imgData );
+                       NICE::MultiChannelImage3DT<SrcP> & imgData );
 
 
     ///////////////////// ///////////////////// /////////////////////
@@ -202,29 +236,20 @@ class SemanticSegmentation : public NICE::Persistent
     }
 
     /**
-     * @brief Collect information about the depth of 3d images
-     * @author Sven Sickert
-     * @param Files a labeled set of data
-     * @param depthVec output of depth values
-     * @param run3dseg whether slice counting is necessary or not
-     */
-    void getDepthVector ( const LabeledSet *Files, std::vector<int> & depthVec, const bool run3dseg );
-
-    /**
-     * @brief Save probability maps of all classes to iamge files
+     * @brief Save probability maps of all classes to image files
      * @author Sven Sickert
      * @param prob class probability maps
      */
-    void getProbabilityMap( const NICE::MultiChannelImage3DT<double> & prob );
+    void saveProbabilityMapAsImage( const NICE::MultiChannelImage3DT<double> & prob );
 
     /**
      * @author Alexander Freytag
      * @date 06-02-2014 ( dd-mm-yyyy )
      */
     void setClassNames ( const OBJREC::ClassNames * _classNames  ) ;
-    
+
     void setIterationCountSuffix( const int & _iterationCountSuffix);
-    
+
     ///////////////////// INTERFACE PERSISTENT /////////////////////
     // interface specific methods for store and restore
     ///////////////////// INTERFACE PERSISTENT /////////////////////
@@ -252,4 +277,6 @@ class SemanticSegmentation : public NICE::Persistent
 
 } // namespace
 
+#include "SemanticSegmentation.tcc"
+
 #endif

+ 77 - 0
semseg/SemanticSegmentation.tcc

@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <vector>
+
+namespace OBJREC {
+
+template<class SrcP>
+void SemanticSegmentation::make3DImage ( const std::vector<std::string> & filelist,
+                                         NICE::MultiChannelImage3DT<SrcP> & imgData )
+{
+    bool isInit = false;
+    for ( int it = 0; it < ( int ) filelist.size(); it++ )
+    {
+        if ( imagetype == IMAGETYPE_RGB )
+        {
+            NICE::ColorImage img;
+            try
+            {
+                img.read ( filelist[it] );
+            }
+            catch ( NICE::ImageException iE )
+            {
+                fprintf ( stderr, "Failed to open color image file: %s\n", filelist[it].c_str() );
+                fprintf ( stderr, "%s\n", iE.what() );
+                exit ( -1 );
+            }
+            if ( !isInit )
+            {
+                imgData.reInit ( img.width(),img.height(),filelist.size(),3 );
+                isInit = true;
+            }
+            for ( int y = 0; y < img.height(); y++ )
+            {
+                for ( int x = 0; x < img.width(); x++ )
+                {
+                    for ( int r = 0; r < 3; r++ )
+                    {
+                        imgData.set ( x, y, it, (SrcP)img.getPixel ( x,y,r ), r );
+                    }
+                }
+            }
+        }
+        else
+        {
+            NICE::Image img;
+            try
+            {
+                img.read ( filelist[it] );
+            }
+            catch ( NICE::ImageException iE )
+            {
+                fprintf ( stderr, "Failed to open image file: %s\n", filelist[it].c_str() );
+                fprintf ( stderr, "%s\n", iE.what() );
+                exit ( -1 );
+            }
+            if ( !isInit )
+            {
+                imgData.reInit ( img.width(),img.height(),filelist.size(),1 );
+                isInit = true;
+            }
+            for ( int y = 0; y < img.height(); y++ )
+            {
+                for ( int x = 0; x < img.width(); x++ )
+                {
+                    imgData.set ( x, y, it, (SrcP)img.getPixel ( x,y ), 0 );
+                }
+            }
+        }
+    }
+
+    if ( imagetype == IMAGETYPE_GRAY )
+    {
+        imgData.equalizeHistogram( 0 );
+    }
+
+}
+
+}

+ 14 - 14
semseg/postsegmentation/RelativeLocationPrior.cpp

@@ -1,6 +1,6 @@
 #include "RelativeLocationPrior.h"
 
-#include "core/image/Filter.h"
+#include "core/image/FilterT.h"
 
 using namespace std;
 using namespace NICE;
@@ -104,9 +104,9 @@ void RelativeLocationPrior::finishPriorsMaps ( ClassNames &cn )
     }
   }
 
-  double sigma = 0.1 * ( double ) mapsize; // 10% der Breite/Höhe der Maps
+  double sigma = 0.1 * ( double ) mapsize; // 10 percent of the maps height/width
 
-  // alle Priormaps weichzeichnen
+  // Smoothing the maps
   for ( int j = 0; j < classno; j++ )
   {
     for ( int i = 0; i < classno; i++ )
@@ -122,8 +122,8 @@ void RelativeLocationPrior::finishPriorsMaps ( ClassNames &cn )
       }
 
       NICE::FloatImage out;
-      //FourierLibrary::gaussFilterD(tmp, out, sigma);
-      NICE::filterGaussSigmaApproximate<float, float, float> ( tmp, sigma, &out );
+      NICE::FilterT<float,float,float> filter;
+      filter.filterGaussSigmaApproximate( tmp, sigma, &out );
 
       for ( int x = 0; x < mapsize; x++ )
       {
@@ -135,7 +135,7 @@ void RelativeLocationPrior::finishPriorsMaps ( ClassNames &cn )
     }
   }
 
-  // Summe aller Pixel an einer Position über jede Klasse = 1
+  // Sum of all pixels over all classes at a certain position equals 1
   for ( int i = 0; i < classno; i++ )
   {
     for ( int x = 0; x < mapsize; x++ )
@@ -239,7 +239,7 @@ void RelativeLocationPrior::finishPriorsMaps ( ClassNames &cn )
 
 void RelativeLocationPrior::trainClassifier ( Examples &regions, NICE::MultiChannelImageT<double> & probabilities )
 {
-  // für alle Regionen einen Merkmalsvektor erzeugen und diesen der Trainingsmenge hinzufügen
+  // Creating a feature vector for all regions and adding it to the training set
   getFeature ( regions, probabilities );
 
   for ( int i = 0; i < ( int ) regions.size(); i++ )
@@ -251,9 +251,9 @@ void RelativeLocationPrior::trainClassifier ( Examples &regions, NICE::MultiChan
 
 void RelativeLocationPrior::finishClassifier()
 {
-  //////////////////////////////
-  // Klassifikatoren anlernen //
-  //////////////////////////////
+  //////////////////////
+  // Train Classifier //
+  //////////////////////
   FeaturePool fp;
   Feature *f = new SparseVectorFeature ( featdim );
   f->explode ( fp );
@@ -404,7 +404,7 @@ void RelativeLocationPrior::getFeature ( Examples &regions, NICE::MultiChannelIm
     alpha.push_back ( tmpalpha );
   }
 
-  //erzeuge f_relloc
+  // create f_relloc
   vector<vector<double> > vother;
   vector<vector<double> > vself;
   for ( int i = 0; i < ( int ) regions.size(); i++ )
@@ -430,7 +430,7 @@ void RelativeLocationPrior::getFeature ( Examples &regions, NICE::MultiChannelIm
 
         double val = priormaps[c]->get ( x, y, bestclasses[j] ) * alpha[j]; ;
 
-        if ( bestclasses[j] == bestclasses[i] ) //Objektbestandteile
+        if ( bestclasses[j] == bestclasses[i] ) //parts of the object
         {
           tmp_self += val;
         }
@@ -469,7 +469,7 @@ void RelativeLocationPrior::getFeature ( Examples &regions, NICE::MultiChannelIm
 
     for ( int i = 0; i < classno; i++ )
     {
-      //appearence feature (old probability for each class
+      //appearence feature (old probability for each class)
       double fapp = log ( probabilities.get ( regions[r].second.x, regions[r].second.y, i ) );
 
       if ( fabs ( fapp ) > 10e-7 )
@@ -497,7 +497,7 @@ void RelativeLocationPrior::restore ( istream & is, int format )
   is >> mapsize;
   is >> featdim;
 
-  //Priorsmaps erzeugen
+  // Create prior maps
   for ( int i = 0; i < classno; i++ )
   {
     NICE::MultiChannelImageT<double> *tmp  = new NICE::MultiChannelImageT<double> ( mapsize, mapsize, classno);