|
@@ -42,6 +42,7 @@ SemSegContextTree::SemSegContextTree () : SemanticSegmentation ()
|
|
{
|
|
{
|
|
this->lfcw = NULL;
|
|
this->lfcw = NULL;
|
|
this->firstiteration = true;
|
|
this->firstiteration = true;
|
|
|
|
+ this->run3Dseg = false;
|
|
this->maxSamples = 2000;
|
|
this->maxSamples = 2000;
|
|
this->minFeats = 50;
|
|
this->minFeats = 50;
|
|
this->maxDepth = 10;
|
|
this->maxDepth = 10;
|
|
@@ -83,6 +84,7 @@ SemSegContextTree::SemSegContextTree (
|
|
|
|
|
|
this->lfcw = new LFColorWeijer ( conf );
|
|
this->lfcw = new LFColorWeijer ( conf );
|
|
this->firstiteration = true;
|
|
this->firstiteration = true;
|
|
|
|
+ this->run3Dseg = conf->gB ( section, "run_3dseg", false );
|
|
this->maxSamples = conf->gI ( section, "max_samples", 2000 );
|
|
this->maxSamples = conf->gI ( section, "max_samples", 2000 );
|
|
this->minFeats = conf->gI ( section, "min_feats", 50 );
|
|
this->minFeats = conf->gI ( section, "min_feats", 50 );
|
|
this->maxDepth = conf->gI ( section, "max_depth", 10 );
|
|
this->maxDepth = conf->gI ( section, "max_depth", 10 );
|
|
@@ -316,8 +318,8 @@ void SemSegContextTree::initOperations()
|
|
tops5.push_back ( new RayDiff() );
|
|
tops5.push_back ( new RayDiff() );
|
|
if ( conf->gB ( featsec, "ray_dist", false ) )
|
|
if ( conf->gB ( featsec, "ray_dist", false ) )
|
|
tops5.push_back ( new RayDist() );
|
|
tops5.push_back ( new RayDist() );
|
|
- if ( conf->gB ( featsec, "ray_theta", false ) )
|
|
|
|
- tops5.push_back ( new RayTheta() );
|
|
|
|
|
|
+ if ( conf->gB ( featsec, "ray_orient", false ) )
|
|
|
|
+ tops5.push_back ( new RayOrient() );
|
|
if ( conf->gB ( featsec, "ray_norm", false ) )
|
|
if ( conf->gB ( featsec, "ray_norm", false ) )
|
|
tops5.push_back ( new RayNorm() );
|
|
tops5.push_back ( new RayNorm() );
|
|
|
|
|
|
@@ -433,9 +435,6 @@ double SemSegContextTree::getBestSplit (
|
|
}
|
|
}
|
|
while ( channelsPerType[ft].size() == 0 );
|
|
while ( channelsPerType[ft].size() == 0 );
|
|
|
|
|
|
- if ( firstiteration )
|
|
|
|
- ft = 0;
|
|
|
|
-
|
|
|
|
int tmpws = windowSize;
|
|
int tmpws = windowSize;
|
|
|
|
|
|
if ( ft == 2 || ft == 4 )
|
|
if ( ft == 2 || ft == 4 )
|
|
@@ -644,41 +643,6 @@ inline double SemSegContextTree::getMeanProb (
|
|
return val / ( double ) nbTrees;
|
|
return val / ( double ) nbTrees;
|
|
}
|
|
}
|
|
|
|
|
|
-void SemSegContextTree::closestContourPoint( const NICE::Image &B,
|
|
|
|
- const NICE::Image &G,
|
|
|
|
- NICE::Matrix &D,
|
|
|
|
- NICE::Matrix &N,
|
|
|
|
- int x,
|
|
|
|
- int y,
|
|
|
|
- const int &dir)
|
|
|
|
-{
|
|
|
|
- int xo = 0, yo = 0; // offsets
|
|
|
|
-
|
|
|
|
- switch (dir)
|
|
|
|
- {
|
|
|
|
- case 0: yo = -1; break;
|
|
|
|
- case 1: xo = 1; yo = -1; break;
|
|
|
|
- case 2: xo = 1; x = (B.width()-1)-x; break;
|
|
|
|
- case 3: xo = 1; yo = -1; break;
|
|
|
|
- case 4: yo = 1; y = (B.height()-1)-y; break;
|
|
|
|
- case 5: xo = -1 ; yo = 1; y = (B.height()-1)-y; break;
|
|
|
|
- case 6: xo = -1; break;
|
|
|
|
- case 7: xo = -1; yo = -1; break;
|
|
|
|
- default: return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (B.getPixelQuick(x,y) != 0 || x+xo < 0 || x+xo >= B.width() || y+yo < 0 || y+yo >= B.height() )
|
|
|
|
- {
|
|
|
|
- D(x, y) = 0;
|
|
|
|
- N(x, y) = G.getPixelQuick(x,y);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- D(x, y) = D(x+xo,y+yo) + 1;
|
|
|
|
- N(x, y) = N(x+xo,y+yo);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void SemSegContextTree::computeRayFeatImage (
|
|
void SemSegContextTree::computeRayFeatImage (
|
|
NICE::MultiChannelImage3DT<double> &feats,
|
|
NICE::MultiChannelImage3DT<double> &feats,
|
|
int firstChannel )
|
|
int firstChannel )
|
|
@@ -693,7 +657,6 @@ void SemSegContextTree::computeRayFeatImage (
|
|
for ( int z = 0; z < zsize; z++)
|
|
for ( int z = 0; z < zsize; z++)
|
|
{
|
|
{
|
|
// canny image from raw channel
|
|
// canny image from raw channel
|
|
- NICE::Image gra = feats.getChannel( z, 1 );
|
|
|
|
NICE::Image med (xsize,ysize);
|
|
NICE::Image med (xsize,ysize);
|
|
NICE::median ( feats.getChannel( z, 0 ), &med, 2);
|
|
NICE::median ( feats.getChannel( z, 0 ), &med, 2);
|
|
NICE::Image* can = NICE::canny( med, 5, 25);
|
|
NICE::Image* can = NICE::canny( med, 5, 25);
|
|
@@ -702,10 +665,49 @@ void SemSegContextTree::computeRayFeatImage (
|
|
{
|
|
{
|
|
NICE::Matrix dist(xsize,ysize,0);
|
|
NICE::Matrix dist(xsize,ysize,0);
|
|
NICE::Matrix norm(xsize,ysize,0);
|
|
NICE::Matrix norm(xsize,ysize,0);
|
|
|
|
+ NICE::Matrix orient(xsize,ysize,0);
|
|
|
|
|
|
for (int y = 0; y < ysize; y++)
|
|
for (int y = 0; y < ysize; y++)
|
|
for ( int x = 0; x < xsize; x++)
|
|
for ( int x = 0; x < xsize; x++)
|
|
- this->closestContourPoint(*(can), gra, dist, norm, x, y, dir);
|
|
|
|
|
|
+ {
|
|
|
|
+ int xo = 0, yo = 0; // offsets
|
|
|
|
+ int theta = 0;
|
|
|
|
+
|
|
|
|
+ switch (dir)
|
|
|
|
+ {
|
|
|
|
+ case 0: theta = 0; yo = -1; break;
|
|
|
|
+ case 1: theta = 45; xo = 1; yo = -1; break;
|
|
|
|
+ case 2: theta = 90; xo = 1; x = (xsize-1)-x; break;
|
|
|
|
+ case 3: theta = 135; xo = 1; yo = -1; break;
|
|
|
|
+ case 4: theta = 180; yo = 1; y = (ysize-1)-y; break;
|
|
|
|
+ case 5: theta = 225; xo = -1; yo = 1; y = (ysize-1)-y; break;
|
|
|
|
+ case 6: theta = 270; xo = -1; break;
|
|
|
|
+ case 7: theta = 315; xo = -1; yo = -1; break;
|
|
|
|
+ default: return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (can->getPixelQuick(x,y) != 0
|
|
|
|
+ || x+xo < 0
|
|
|
|
+ || x+xo >= xsize
|
|
|
|
+ || y+yo < 0
|
|
|
|
+ || y+yo >= ysize )
|
|
|
|
+ {
|
|
|
|
+ double gx = feats.get(x, y, z, 1);
|
|
|
|
+ double gy = feats.get(x, y, z, 2);
|
|
|
|
+
|
|
|
|
+ //double go = atan2 (gy, gx);
|
|
|
|
+
|
|
|
|
+ norm(x, y) = sqrt(gx*gx+gy*gy);
|
|
|
|
+ orient(x, y) = ( gx*cos(theta)+gy*sin(theta) ) / norm(x,y);
|
|
|
|
+ dist(x, y) = 0;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ orient(x, y) = orient(x+xo,y+yo);
|
|
|
|
+ norm(x, y) = norm(x+xo,y+yo);
|
|
|
|
+ dist(x, y) = dist(x+xo,y+yo) + 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
for (int y = 0; y < ysize; y++)
|
|
for (int y = 0; y < ysize; y++)
|
|
for (int x = 0; x < xsize; x++)
|
|
for (int x = 0; x < xsize; x++)
|
|
@@ -714,6 +716,8 @@ void SemSegContextTree::computeRayFeatImage (
|
|
feats.set( x, y, z, dist(x,y), firstChannel + dir );
|
|
feats.set( x, y, z, dist(x,y), firstChannel + dir );
|
|
// norm feature maps
|
|
// norm feature maps
|
|
feats.set( x, y, z, norm(x,y), firstChannel + amountDirs + dir );
|
|
feats.set( x, y, z, norm(x,y), firstChannel + amountDirs + dir );
|
|
|
|
+ // orientation feature maps
|
|
|
|
+ feats.set( x, y, z, norm(x,y), firstChannel + (amountDirs*2) + dir );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -828,9 +832,8 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
Timer timer;
|
|
Timer timer;
|
|
timer.start();
|
|
timer.start();
|
|
|
|
|
|
- bool run_3dseg = conf->gB ( "debug", "run_3dseg", true );
|
|
|
|
vector<int> zsizeVec;
|
|
vector<int> zsizeVec;
|
|
- getDepthVector ( trainp, zsizeVec, run_3dseg );
|
|
|
|
|
|
+ getDepthVector ( trainp, zsizeVec, run3Dseg );
|
|
|
|
|
|
//FIXME: memory usage
|
|
//FIXME: memory usage
|
|
vector<MultiChannelImage3DT<double> > allfeats;
|
|
vector<MultiChannelImage3DT<double> > allfeats;
|
|
@@ -857,7 +860,7 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
rawChannels = 1;
|
|
rawChannels = 1;
|
|
|
|
|
|
if ( useGradient )
|
|
if ( useGradient )
|
|
- rawChannels *= 2;
|
|
|
|
|
|
+ rawChannels *= 3;
|
|
|
|
|
|
if ( useWeijer )
|
|
if ( useWeijer )
|
|
rawChannels += 11;
|
|
rawChannels += 11;
|
|
@@ -905,7 +908,7 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
fprintf ( stderr, "SSContext: Collecting pixel examples from localization info: %s\n", file.c_str() );
|
|
fprintf ( stderr, "SSContext: Collecting pixel examples from localization info: %s\n", file.c_str() );
|
|
|
|
|
|
int depthBoundary = 0;
|
|
int depthBoundary = 0;
|
|
- if ( run_3dseg )
|
|
|
|
|
|
+ if ( run3Dseg )
|
|
{
|
|
{
|
|
depthBoundary = zsizeVec[imgCounter];
|
|
depthBoundary = zsizeVec[imgCounter];
|
|
}
|
|
}
|
|
@@ -956,7 +959,7 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
if ( useFeat1 )
|
|
if ( useFeat1 )
|
|
rSize[imgCounter][allfeats[imgCounter] ( x, y, z, rawChannels ) ]++;
|
|
rSize[imgCounter][allfeats[imgCounter] ( x, y, z, rawChannels ) ]++;
|
|
|
|
|
|
- if ( run_3dseg )
|
|
|
|
|
|
+ if ( run3Dseg )
|
|
classno = pixelLabels ( x, y, ( uint ) z );
|
|
classno = pixelLabels ( x, y, ( uint ) z );
|
|
else
|
|
else
|
|
classno = pL.getPixelQuick ( x,y );
|
|
classno = pL.getPixelQuick ( x,y );
|
|
@@ -994,7 +997,6 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Type 0: single pixel & pixel-comparison features on gray value channels
|
|
// Type 0: single pixel & pixel-comparison features on gray value channels
|
|
- if ( useFeat0 )
|
|
|
|
for ( int i = 0; i < rawChannels; i++ )
|
|
for ( int i = 0; i < rawChannels; i++ )
|
|
channelType.push_back ( 0 );
|
|
channelType.push_back ( 0 );
|
|
|
|
|
|
@@ -1029,7 +1031,7 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
|
|
|
|
// Type 5: ray features for shape modeling on canny-map
|
|
// Type 5: ray features for shape modeling on canny-map
|
|
if ( useFeat5 )
|
|
if ( useFeat5 )
|
|
- for ( int i = 0; i < 16; i++ )
|
|
|
|
|
|
+ for ( int i = 0; i < 24; i++ )
|
|
channelType.push_back ( 5 );
|
|
channelType.push_back ( 5 );
|
|
|
|
|
|
// 'amountTypes' sets upper bound for usable feature types
|
|
// 'amountTypes' sets upper bound for usable feature types
|
|
@@ -1140,6 +1142,29 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ //compute integral & ray images
|
|
|
|
+ int multi = 0, multi2 = 0;
|
|
|
|
+ if (useFeat3) multi=1;
|
|
|
|
+ if (useFeat4) multi=2;
|
|
|
|
+ if (useFeat5) multi2 = 1;
|
|
|
|
+
|
|
|
|
+ if ( firstiteration && ( useFeat2 || useFeat3 || useFeat4) )
|
|
|
|
+ for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
+ allfeats[i].addChannel ( (multi*classes) + rawChannels );
|
|
|
|
+
|
|
|
|
+ if ( firstiteration && useFeat5 )
|
|
|
|
+ for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
+ allfeats[i].addChannel ( 24 );
|
|
|
|
+
|
|
|
|
+ int firstChannel = channelType.size() - (multi*classes) - (multi2*24);
|
|
|
|
+ if ( useFeat2 || useFeat3 || useFeat4 )
|
|
|
|
+ for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
+ computeIntegralImage ( nodeIndices[i], allfeats[i], firstChannel );
|
|
|
|
+
|
|
|
|
+ if ( firstiteration && useFeat5 )
|
|
|
|
+ for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
+ computeRayFeatImage( allfeats[i], channelType.size()-24);
|
|
|
|
+
|
|
#ifdef VERBOSE
|
|
#ifdef VERBOSE
|
|
Timer timerDepth;
|
|
Timer timerDepth;
|
|
timerDepth.start();
|
|
timerDepth.start();
|
|
@@ -1367,29 +1392,6 @@ void SemSegContextTree::train ( const LabeledSet * trainp )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- //compute integral & ray images
|
|
|
|
- int multi = 0, multi2 = 0;
|
|
|
|
- if (useFeat3) multi=1;
|
|
|
|
- if (useFeat4) multi=2;
|
|
|
|
- if (useFeat5) multi2 = 1;
|
|
|
|
-
|
|
|
|
- if ( firstiteration && (useFeat3 || useFeat4) )
|
|
|
|
- for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
- allfeats[i].addChannel ( (multi*classes) + rawChannels );
|
|
|
|
-
|
|
|
|
- if ( firstiteration && useFeat5 )
|
|
|
|
- for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
- allfeats[i].addChannel ( 16 );
|
|
|
|
-
|
|
|
|
- int firstChannel = channelType.size() - (multi*classes) - (multi2*16);
|
|
|
|
- if ( useFeat3 || useFeat4 )
|
|
|
|
- for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
- computeIntegralImage ( nodeIndices[i], allfeats[i], firstChannel );
|
|
|
|
-
|
|
|
|
- if ( firstiteration && useFeat5 )
|
|
|
|
- for ( int i = 0; i < imgCounter; i++ )
|
|
|
|
- computeRayFeatImage( allfeats[i], channelType.size()-16);
|
|
|
|
-
|
|
|
|
if ( firstiteration ) firstiteration = false;
|
|
if ( firstiteration ) firstiteration = false;
|
|
|
|
|
|
#ifdef VERBOSE
|
|
#ifdef VERBOSE
|
|
@@ -1555,17 +1557,22 @@ void SemSegContextTree::addFeatureMaps (
|
|
if ( useGradient )
|
|
if ( useGradient )
|
|
{
|
|
{
|
|
int currentsize = imgData.channels();
|
|
int currentsize = imgData.channels();
|
|
- imgData.addChannel ( currentsize );
|
|
|
|
|
|
+ imgData.addChannel ( 2*currentsize );
|
|
|
|
|
|
for ( int z = 0; z < zsize; z++ )
|
|
for ( int z = 0; z < zsize; z++ )
|
|
for ( int c = 0; c < currentsize; c++ )
|
|
for ( int c = 0; c < currentsize; c++ )
|
|
{
|
|
{
|
|
ImageT<double> tmp = imgData.getChannelT(z, c);
|
|
ImageT<double> tmp = imgData.getChannelT(z, c);
|
|
- ImageT<double> tmp2( xsize, ysize );
|
|
|
|
- NICE::FilterT<double, double, double>::gradientStrength ( tmp, tmp2 );
|
|
|
|
|
|
+ ImageT<double> sobX( xsize, ysize );
|
|
|
|
+ ImageT<double> sobY( xsize, ysize );
|
|
|
|
+ NICE::FilterT<double, double, double>::sobelX ( tmp, sobX );
|
|
|
|
+ NICE::FilterT<double, double, double>::sobelY ( tmp, sobY );
|
|
for ( int y = 0; y < ysize; y++ )
|
|
for ( int y = 0; y < ysize; y++ )
|
|
for ( int x = 0; x < xsize; x++ )
|
|
for ( int x = 0; x < xsize; x++ )
|
|
- imgData.set(x, y, z, tmp2.getPixelQuick(x,y), c+currentsize);
|
|
|
|
|
|
+ {
|
|
|
|
+ imgData.set( x, y, z, sobX.getPixelQuick(x,y), c+currentsize );
|
|
|
|
+ imgData.set( x, y, z, sobY.getPixelQuick(x,y), c+(currentsize*2) );
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1745,6 +1752,29 @@ void SemSegContextTree::classify (
|
|
depth++;
|
|
depth++;
|
|
vector<vector<double> > lastRegionProbs = regionProbs;
|
|
vector<vector<double> > lastRegionProbs = regionProbs;
|
|
|
|
|
|
|
|
+ int multi = 0, multi2 = 0;
|
|
|
|
+ if (useFeat3) multi=1;
|
|
|
|
+ if (useFeat4) multi=2;
|
|
|
|
+ if (useFeat5) multi2=1;
|
|
|
|
+
|
|
|
|
+ if ( depth < maxDepth )
|
|
|
|
+ {
|
|
|
|
+ //compute integral images
|
|
|
|
+ if ( firstiteration && ( useFeat2 || useFeat3 || useFeat4 ) )
|
|
|
|
+ imgData.addChannel ( (multi*classes) + rawChannels );
|
|
|
|
+
|
|
|
|
+ //compute canny image
|
|
|
|
+ if ( firstiteration && useFeat5 )
|
|
|
|
+ imgData.addChannel ( 24 );
|
|
|
|
+
|
|
|
|
+ int firstChannel = channelType.size() - (multi*classes) - (multi2*24);
|
|
|
|
+ if ( useFeat2 || useFeat3 || useFeat4 )
|
|
|
|
+ computeIntegralImage ( nodeIndices, imgData, firstChannel );
|
|
|
|
+
|
|
|
|
+ if ( firstiteration && useFeat5 )
|
|
|
|
+ computeRayFeatImage( imgData, channelType.size()-24 );
|
|
|
|
+ }
|
|
|
|
+
|
|
if ( useFeat1 )
|
|
if ( useFeat1 )
|
|
{
|
|
{
|
|
int numRegions = ( int ) regionProbs.size();
|
|
int numRegions = ( int ) regionProbs.size();
|
|
@@ -1854,30 +1884,7 @@ void SemSegContextTree::classify (
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- int multi = 0, multi2 = 0;
|
|
|
|
- if (useFeat3) multi=1;
|
|
|
|
- if (useFeat4) multi=2;
|
|
|
|
- if (useFeat5) multi2=1;
|
|
|
|
-
|
|
|
|
- if ( depth < maxDepth )
|
|
|
|
- {
|
|
|
|
- //compute integral images
|
|
|
|
- if ( firstiteration && ( useFeat3 || useFeat4 ) )
|
|
|
|
- imgData.addChannel ( (multi*classes) + rawChannels );
|
|
|
|
-
|
|
|
|
- //compute canny image
|
|
|
|
- if ( firstiteration && useFeat5 )
|
|
|
|
- imgData.addChannel ( 16 );
|
|
|
|
-
|
|
|
|
- int firstChannel = channelType.size() - (multi*classes) - (multi2*16);
|
|
|
|
- if ( useFeat3 || useFeat4 )
|
|
|
|
- computeIntegralImage ( nodeIndices, imgData, firstChannel );
|
|
|
|
-
|
|
|
|
- if ( firstiteration && useFeat5 )
|
|
|
|
- computeRayFeatImage( imgData, channelType.size()-16 );
|
|
|
|
-
|
|
|
|
- if ( firstiteration ) firstiteration = false;
|
|
|
|
- }
|
|
|
|
|
|
+ if ( (depth < maxDepth) && firstiteration ) firstiteration = false;
|
|
}
|
|
}
|
|
|
|
|
|
vector<int> classesInImg;
|
|
vector<int> classesInImg;
|