Browse Source

some edits

Bjoern Froehlich 13 years ago
parent
commit
863c2c56bf
2 changed files with 295 additions and 188 deletions
  1. 266 184
      semseg/SemSegContextTree.cpp
  2. 29 4
      semseg/SemSegContextTree.h

+ 266 - 184
semseg/SemSegContextTree.cpp

@@ -16,193 +16,128 @@
 
 #define BOUND(x,min,max) (((x)<(min))?(min):((x)>(max)?(max):(x)))
 #undef LOCALFEATS
-
-
 //#define LOCALFEATS
 
 using namespace OBJREC;
 using namespace std;
 using namespace NICE;
 
-class Minus:public Operation
+class MCImageAccess:public ValueAccess
 {
 public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
-	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = feats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
-		double v2 = feats.get(BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel2);
-		return v1-v2;
-	}
-	
-	virtual Operation* clone()
+	virtual double getVal(const Features &feats, const int &x, const int &y, const int &channel)
 	{
-		return new Minus();
+		return feats.feats->get(x,y,channel);
 	}
 	
 	virtual string writeInfos()
 	{
-		return "Minus";
-	}
-};
-
-class MinusAbs:public Operation
-{
-public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
-	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = feats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
-		double v2 = feats.get(BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel2);
-		return abs(v1-v2);
-	}
-	
-	virtual Operation* clone()
-	{
-		return new MinusAbs();
-	};
-	
-	virtual string writeInfos()
-	{
-		return "MinusAbs";
+		return "raw";
 	}
 };
 
-class Addition:public Operation
+class ClassificationResultAcess:public ValueAccess
 {
 public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
-	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = feats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
-		double v2 = feats.get(BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel2);
-		return v1+v2;
-	}
-	
-	virtual Operation* clone()
+	virtual double getVal(const Features &feats, const int &x, const int &y, const int &channel)
 	{
-		return new Addition();
+		return (*feats.tree)[feats.cfeats->get(x,y,feats.cTree)].dist[channel];
 	}
 	
 	virtual string writeInfos()
 	{
-		return "Addition";
+		return "context";
 	}
 };
 
-class Only1:public Operation
-{
-public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
-	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = feats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
-		return v1;
-	}
-	
-	virtual Operation* clone()
-	{
-		return new Only1();
-	}
-	
-	virtual string writeInfos()
-	{
-		return "Only1";
-	}
-};
-
-class ContextMinus:public Operation
+class Minus:public Operation
 {
 public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
+	virtual double getVal(const Features &feats, const int &x, const int &y)
 	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = tree[cfeats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),cTree)].dist[channel1];
-		double v2 = tree[cfeats.get(BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),cTree)].dist[channel2];
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		double v1 = values->getVal(feats, BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
+		double v2 = values->getVal(feats, BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel2);
 		return v1-v2;
 	}
 	
 	virtual Operation* clone()
 	{
-		return new ContextMinus();
+		return new Minus();
 	}
 	
 	virtual string writeInfos()
 	{
-		return "ContextMinus";
+		return "Minus"+values->writeInfos();
 	}
 };
 
-class ContextMinusAbs:public Operation
+class MinusAbs:public Operation
 {
 public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
+	virtual double getVal(const Features &feats, const int &x, const int &y)
 	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = tree[cfeats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),cTree)].dist[channel1];
-		double v2 = tree[cfeats.get(BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),cTree)].dist[channel2];
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		double v1 = values->getVal(feats, BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
+		double v2 = values->getVal(feats, BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel2);
 		return abs(v1-v2);
 	}
 	
 	virtual Operation* clone()
 	{
-		return new ContextMinusAbs();
-	}
+		return new MinusAbs();
+	};
 	
 	virtual string writeInfos()
 	{
-		return "ContextMinusAbs";
+		return "MinusAbs"+values->writeInfos();
 	}
 };
 
-class ContextAddition:public Operation
+class Addition:public Operation
 {
 public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
+	virtual double getVal(const Features &feats, const int &x, const int &y)
 	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = tree[cfeats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),cTree)].dist[channel1];
-		double v2 = tree[cfeats.get(BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),cTree)].dist[channel2];
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		double v1 = values->getVal(feats, BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
+		double v2 = values->getVal(feats, BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel2);
 		return v1+v2;
 	}
 	
 	virtual Operation* clone()
 	{
-		return new ContextAddition();
+		return new Addition();
 	}
 	
 	virtual string writeInfos()
 	{
-		return "ContextAddition";
+		return "Addition"+values->writeInfos();
 	}
 };
 
-class ContextOnly1:public Operation
+class Only1:public Operation
 {
 public:
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
+	virtual double getVal(const Features &feats, const int &x, const int &y)
 	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		double v1 = tree[cfeats.get(BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),cTree)].dist[channel1];
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		double v1 = values->getVal(feats, BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
 		return v1;
 	}
 	
 	virtual Operation* clone()
 	{
-		return new ContextOnly1();
+		return new Only1();
 	}
 	
 	virtual string writeInfos()
 	{
-		return "ContextOnly1";
+		return "Only1"+values->writeInfos();
 	}
 };
 
@@ -210,7 +145,7 @@ public:
 class IntegralOps:public Operation
 {
 public:
-	virtual void set(int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2)
+	virtual void set(int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2, ValueAccess *_values)
 	{
 		x1 = min(_x1,_x2);
 		y1 = min(_y1,_y2);
@@ -218,13 +153,14 @@ public:
 		y2 = max(_y1,_y2);
 		channel1 = _channel1;
 		channel2 = _channel2;
+		values = _values;
 	}
 	
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
+	virtual double getVal(const Features &feats, const int &x, const int &y)
 	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		return computeMean(integralImg,BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel1);
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		return computeMean(*feats.integralImg,BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel1);
 	}
 	
 	inline double computeMean(const NICE::MultiChannelImageT<double> &intImg, const int &uLx, const int &uLy, const int &lRx, const int &lRy, const int &chan)
@@ -254,14 +190,21 @@ class IntegralCenteredOps:public IntegralOps
 public:
 	virtual void set(int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2)
 	{
-		x1 = min(_x1,-_x1);
-		y1 = min(_y1,-_y1);
-		x2 = -x1;
-		y2 = -y1;
+		x1 = abs(_x1);
+		y1 = abs(_y1);
+		x2 = abs(_x2);
+		y2 = abs(_y2);
 		channel1 = _channel1;
 		channel2 = _channel2;
 	}
 	
+	virtual double getVal(const Features &feats, const int &x, const int &y)
+	{
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		return computeMean(*feats.integralImg,BOUND(x-x1,0,xsize-1),BOUND(y-y1,0,ysize-1),BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1);
+	}
+	
 	virtual Operation* clone()
 	{
 		return new IntegralCenteredOps();
@@ -274,7 +217,7 @@ public:
 };
 
 //uses different of mean of Integral image given by two windows, where (x1,y1) is the width and height of window1 and (x2,y2) of window 2
-class BiIntegralCenteredOps:public IntegralOps
+class BiIntegralCenteredOps:public IntegralCenteredOps
 {
 public:
 	virtual void set(int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2)
@@ -287,11 +230,11 @@ public:
 		channel2 = _channel2;
 	}
 	
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y)
+	virtual double getVal(const Features &feats, const int &x, const int &y)
 	{
-		int xsize = feats.width();
-		int ysize = feats.height();
-		return computeMean(integralImg,BOUND(x-x1,0,xsize-1),BOUND(y-y1,0,ysize-1),BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1) - computeMean(integralImg,BOUND(x-x2,0,xsize-1),BOUND(y-y2,0,ysize-1),BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel1);
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		return computeMean(*feats.integralImg,BOUND(x-x1,0,xsize-1),BOUND(y-y1,0,ysize-1),BOUND(x+x1,0,xsize-1),BOUND(y+y1,0,ysize-1),channel1) - computeMean(*feats.integralImg,BOUND(x-x2,0,xsize-1),BOUND(y-y2,0,ysize-1),BOUND(x+x2,0,xsize-1),BOUND(y+y2,0,ysize-1),channel1);
 	}
 	
 	virtual Operation* clone()
@@ -305,6 +248,137 @@ public:
 	}
 };
 
+/** horizontal Haar features
+ * ++
+ * --
+ */
+class HaarHorizontal:public IntegralCenteredOps
+{
+	virtual double getVal(const Features &feats, const int &x, const int &y)
+	{
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		
+		int tlx = BOUND(x-x1,0,xsize-1);
+		int tly = BOUND(y-y1,0,ysize-1);
+		int lrx = BOUND(x+x1,0,xsize-1);
+		int lry = BOUND(y+y1,0,ysize-1);
+		
+		return computeMean(*feats.integralImg,tlx,tly,lrx, y,channel1)-computeMean(*feats.integralImg,tlx,y,lrx, lry,channel1);
+	}
+	
+	virtual string writeInfos()
+	{
+		return "HaarHorizontal";
+	}
+};
+
+/** vertical Haar features
+ * +-
+ * +-
+ */
+class HaarVertical:public IntegralCenteredOps
+{
+	virtual double getVal(const Features &feats, const int &x, const int &y)
+	{
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		
+		int tlx = BOUND(x-x1,0,xsize-1);
+		int tly = BOUND(y-y1,0,ysize-1);
+		int lrx = BOUND(x+x1,0,xsize-1);
+		int lry = BOUND(y+y1,0,ysize-1);
+		
+		return computeMean(*feats.integralImg,tlx,tly,x, lry,channel1)-computeMean(*feats.integralImg,x,tly,lrx, lry,channel1);
+	}
+	
+	virtual string writeInfos()
+	{
+		return "HaarVertical";
+	}
+};
+
+/** vertical Haar features
+ * +-
+ * -+
+ */
+class HaarDiag:public IntegralCenteredOps
+{
+	virtual double getVal(const Features &feats, const int &x, const int &y)
+	{
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		
+		int tlx = BOUND(x-x1,0,xsize-1);
+		int tly = BOUND(y-y1,0,ysize-1);
+		int lrx = BOUND(x+x1,0,xsize-1);
+		int lry = BOUND(y+y1,0,ysize-1);
+		
+		return computeMean(*feats.integralImg,tlx,tly,x, y,channel1)+computeMean(*feats.integralImg,x,y,lrx, lry,channel1) - computeMean(*feats.integralImg,tlx,y,x, lry,channel1)-computeMean(*feats.integralImg,x,tly,lrx, y,channel1);
+	}
+	
+	virtual string writeInfos()
+	{
+		return "HaarDiag";
+	}
+};
+
+/** horizontal Haar features
+ * +++
+ * ---
+ * +++
+ */
+class Haar3Horiz:public BiIntegralCenteredOps
+{
+	virtual double getVal(const Features &feats, const int &x, const int &y)
+	{
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		
+		int tlx = BOUND(x-x2,0,xsize-1);
+		int tly = BOUND(y-y2,0,ysize-1);
+		int mtly = BOUND(y-y1,0,ysize-1);
+		int mlry = BOUND(y-y1,0,ysize-1);
+		int lrx = BOUND(x+x2,0,xsize-1);
+		int lry = BOUND(y+y2,0,ysize-1);
+		
+		return computeMean(*feats.integralImg,tlx,tly,lrx, mtly,channel1) -computeMean(*feats.integralImg,tlx,mtly,lrx, mlry,channel1) + computeMean(*feats.integralImg,tlx,mlry,lrx, lry,channel1);
+	}
+	
+	virtual string writeInfos()
+	{
+		return "Haar3Horiz";
+	}
+};
+
+/** vertical Haar features
+ * +-+
+ * +-+
+ * +-+
+ */
+class Haar3Vert:public BiIntegralCenteredOps
+{
+	virtual double getVal(const Features &feats, const int &x, const int &y)
+	{
+		int xsize, ysize;
+		getXY(feats, xsize, ysize);
+		
+		int tlx = BOUND(x-x2,0,xsize-1);
+		int tly = BOUND(y-y2,0,ysize-1);
+		int mtlx = BOUND(x-x1,0,xsize-1);
+		int mlrx = BOUND(x-x1,0,xsize-1);
+		int lrx = BOUND(x+x2,0,xsize-1);
+		int lry = BOUND(y+y2,0,ysize-1);
+		
+		return computeMean(*feats.integralImg,tlx,tly,mtlx, lry,channel1) -computeMean(*feats.integralImg,mtlx,tly,mlrx, lry,channel1) + computeMean(*feats.integralImg,mlrx,tly,lrx, lry,channel1);
+	}
+	
+	virtual string writeInfos()
+	{
+		return "Haar3Vert";
+	}
+};
+
 SemSegContextTree::SemSegContextTree( const Config *conf, const MultiDataset *md )
     : SemanticSegmentation ( conf, &(md->getClassNames("train")) )
 {
@@ -357,13 +431,17 @@ SemSegContextTree::SemSegContextTree( const Config *conf, const MultiDataset *md
 	ops.push_back(new Addition());
 	ops.push_back(new Only1());
 	
-	cops.push_back(new ContextMinus());
-	cops.push_back(new ContextMinusAbs());
-	cops.push_back(new ContextAddition());
-	cops.push_back(new ContextOnly1());
 	cops.push_back(new BiIntegralCenteredOps());
 	cops.push_back(new IntegralCenteredOps());
 	cops.push_back(new IntegralOps());
+	cops.push_back(new HaarHorizontal());
+	cops.push_back(new HaarVertical());
+	cops.push_back(new HaarDiag());
+	cops.push_back(new Haar3Horiz());
+	cops.push_back(new Haar3Vert());
+	
+	calcVal.push_back(new MCImageAccess());
+	calcVal.push_back(new ClassificationResultAcess());
 	
 	classnames = md->getClassNames ( "train" );
 	
@@ -378,9 +456,8 @@ SemSegContextTree::~SemSegContextTree()
 {
 }
 
-double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImageT<double> > &feats, std::vector<NICE::MultiChannelImageT<int> > &currentfeats, std::vector<NICE::MultiChannelImageT<double> > &integralImgs, const std::vector<NICE::MatrixT<int> > &labels, int node, Operation *&splitop, double &splitval, const int &tree)
+double SemSegContextTree::getBestSplit(std::vector<NICE::MultiChannelImageT<double> > &feats, std::vector<NICE::MultiChannelImageT<int> > &currentfeats, std::vector<NICE::MultiChannelImageT<double> > &integralImgs, const std::vector<NICE::MatrixT<int> > &labels, int node, Operation *&splitop, double &splitval, const int &tree)
 {
-
 	int imgCount = 0, featdim = 0;
 	try
 	{
@@ -391,7 +468,7 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 	{
 		cerr << "no features computed?" << endl;
 	}
-
+	
 	double bestig = -numeric_limits< double >::max();
 	splitop = NULL;
 	splitval = -1.0;
@@ -399,7 +476,7 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 	set<vector<int> >selFeats;
 	map<int,int> e;
 	int featcounter = 0;
-
+	
 	for(int iCounter = 0; iCounter < imgCount; iCounter++)
 	{
 		int xsize = (int)currentfeats[iCounter].width();
@@ -415,7 +492,7 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 			}
 		}
 	}
-
+	
 	if(featcounter < minFeats)
 	{
 		cout << "only " << featcounter << " feats in current node -> it's a leaf" << endl;
@@ -434,7 +511,7 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 	//cout << "a.size(): " << a.size() << endl;
 	//getchar();
 	featcounter = 0;
-
+	
 	for(int iCounter = 0; iCounter < imgCount; iCounter++)
 	{
 		int xsize = (int)currentfeats[iCounter].width();
@@ -479,7 +556,7 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 		cout << "globent to small: " << globent << endl;
 		return 0.0;
 	}
-
+	
 	int classes = (int)forest[tree][0].dist.size();
 	featsel.clear();
 	for(int i = 0; i < featsPerSplit; i++)
@@ -519,16 +596,27 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 			int f2 = (int)((double)rand()/(double)RAND_MAX*(double)featdim);
 			int o = (int)((double)rand()/(double)RAND_MAX*(double)ops.size());
 			Operation *op = ops[o]->clone();
-			op->set(x1,y1,x2,y2,f1,f2);
+			op->set(x1,y1,x2,y2,f1,f2, calcVal[ft]);
 			featsel.push_back(op);
 		}
 		else if(ft == 1)
 		{
+			int opssize = (int)ops.size();
 			int f1 = (int)((double)rand()/(double)RAND_MAX*(double)classes);
 			int f2 = (int)((double)rand()/(double)RAND_MAX*(double)classes);
-			int o = (int)((double)rand()/(double)RAND_MAX*(double)cops.size());
-			Operation *op = cops[o]->clone();
-			op->set(x1,y1,x2,y2,f1,f2);
+			int o = (int)((double)rand()/(double)RAND_MAX*((double)cops.size())+(double)opssize);
+			Operation *op;
+			if(o < opssize)
+			{
+				op = ops[o]->clone();
+				op->set(x1,y1,x2,y2,f1,f2, calcVal[ft]);
+			}
+			else
+			{
+				o -= opssize;
+				op = cops[o]->clone();
+				op->set(x1,y1,x2,y2,f1,f2, calcVal[ft]);
+			}
 			featsel.push_back(op);
 		}
 	}
@@ -543,7 +631,13 @@ double SemSegContextTree::getBestSplit(const std::vector<NICE::MultiChannelImage
 		
 		for ( it=selFeats.begin() ; it != selFeats.end(); it++ )
 		{
-			vals.push_back(featsel[f]->getVal(feats[(*it)[0]],currentfeats[(*it)[0]], tree, forest[tree], integralImgs[(*it)[0]], (*it)[1], (*it)[2]));
+			Features feat;
+			feat.feats = &feats[(*it)[0]];
+			feat.cfeats = &currentfeats[(*it)[0]];
+			feat.cTree = tree;
+			feat.tree = &forest[tree];
+			feat.integralImg = &integralImgs[(*it)[0]];
+			vals.push_back(featsel[f]->getVal(feat, (*it)[1], (*it)[2]));
 		}
 		
 		int counter = 0;
@@ -757,7 +851,7 @@ void SemSegContextTree::train ( const MultiDataset *md )
 				}
 			}
 		}
-#endif		
+#endif
 		
 		// getting groundtruth
 		NICE::Image pixelLabels (xsize, ysize);
@@ -775,6 +869,7 @@ void SemSegContextTree::train ( const MultiDataset *md )
 				
 			}
 		}
+		
 		imgcounter++;
 		pb.update ( trainp->count());
 		delete ce;
@@ -891,7 +986,13 @@ void SemSegContextTree::train ( const MultiDataset *md )
 								{
 									if(currentfeats[iCounter].get(x, y, tree) == i)
 									{
-										double val = splitfeat->getVal(allfeats[iCounter],lastfeats[iCounter], tree, forest[tree], integralImgs[iCounter],x,y);
+										Features feat;
+										feat.feats = &allfeats[iCounter];
+										feat.cfeats = &lastfeats[iCounter];
+										feat.cTree = tree;
+										feat.tree = &forest[tree];
+										feat.integralImg = &integralImgs[iCounter];
+										double val = splitfeat->getVal(feat,x,y);
 										if(val < splitval)
 										{ 
 											currentfeats[iCounter].set(x,y,left,tree);
@@ -924,32 +1025,8 @@ void SemSegContextTree::train ( const MultiDataset *md )
 							}
 						}
 						
-						if(lcounter <= 0 || rcounter <= 0)
-						{
-							cout << "lcounter : " << lcounter << " rcounter: " << rcounter << endl;
-							cout << "splitval: " << splitval << " splittype: " << splitfeat->writeInfos() << endl;
-							cout << "bestig: " << bestig << endl;
-							for(int iCounter = 0; iCounter < imgcounter; iCounter++)
-							{
-								int xsize = currentfeats[iCounter].width();
-								int ysize = currentfeats[iCounter].height();
-								int counter = 0;
-								for(int x = 0; x < xsize; x++)
-								{
-									for(int y = 0; y < ysize; y++)
-									{
-										if(lastfeats[iCounter].get(x,y,tree) == i)
-										{
-											if(++counter > 30)
-												break;
-											double val = splitfeat->getVal(allfeats[iCounter],lastfeats[iCounter], tree, forest[tree], integralImgs[iCounter],x,y);
-											cout << "splitval: " << splitval << " val: " << val << endl;
-										}
-									}
-								}
-							}
-							assert(lcounter > 0 && rcounter > 0);
-						}
+						assert(lcounter > 0 && rcounter > 0);
+
 						for(uint d = 0; d < forest[tree][left].dist.size(); d++)
 						{
 							forest[tree][left].dist[d]/=lcounter;
@@ -962,32 +1039,30 @@ void SemSegContextTree::train ( const MultiDataset *md )
 					}
 				}
 			}
+		}
+		//TODO: features neu berechnen!
 			
-#if 1
-		timer.stop();
-		cout << "time for depth " << depth << ": " << timer.getLast() << endl;
-#endif
-			
-			//TODO: features neu berechnen!
-			
-			//compute integral image
-			int channels = classes;
-			
-			if(integralImgs[0].width() == 0)
-			{
-				for(int i = 0; i < imgcounter; i++)
-				{
-					int xsize = allfeats[i].width();
-					int ysize = allfeats[i].height();
-					integralImgs[i].reInit(xsize, ysize, channels);
-				}
-			}
+		//compute integral image
+		int channels = classes;
 			
+		if(integralImgs[0].width() == 0)
+		{
 			for(int i = 0; i < imgcounter; i++)
 			{
-				computeIntegralImage(currentfeats[i],integralImgs[i]);
+				int xsize = allfeats[i].width();
+				int ysize = allfeats[i].height();
+				integralImgs[i].reInit(xsize, ysize, channels);
 			}
 		}
+			
+		for(int i = 0; i < imgcounter; i++)
+		{
+			computeIntegralImage(currentfeats[i],integralImgs[i]);
+		}
+#if 1
+		timer.stop();
+		cout << "time for depth " << depth << ": " << timer.getLast() << endl;
+#endif
 		depth++;
 	#ifdef DEBUG
 			cout << "depth: " << depth << endl;
@@ -1080,7 +1155,14 @@ void SemSegContextTree::semanticseg ( CachedExample *ce, NICE::Image & segresult
 					if(forest[tree][t].left > 0)
 					{
 						allleaf = false;
-						double val = forest[tree][t].feat->getVal(feats,lastfeats,tree, forest[tree], integralImg,x,y);
+						Features feat;
+						feat.feats = &feats;
+						feat.cfeats = &lastfeats;
+						feat.cTree = tree;
+						feat.tree = &forest[tree];
+						feat.integralImg = &integralImg;
+						
+						double val = forest[tree][t].feat->getVal(feat,x,y);
 						
 						if(val < forest[tree][t].decision)
 						{

+ 29 - 4
semseg/SemSegContextTree.h

@@ -16,7 +16,7 @@
 namespace OBJREC {
 	
 class Operation;
-	
+
 class TreeNode
 {
 public:
@@ -51,12 +51,28 @@ public:
 	TreeNode(int _left, int _right, Operation *_feat, double _decision):left(_left),right(_right),feat(_feat), decision(_decision),isleaf(false){}
 };
 	
+struct Features{
+	NICE::MultiChannelImageT<double> *feats;
+	MultiChannelImageT<int> *cfeats;
+	int cTree;
+	std::vector<TreeNode> *tree;
+	NICE::MultiChannelImageT<double> *integralImg;
+};
+
+class ValueAccess
+{
+public:
+	virtual double getVal(const Features &feats, const int &x, const int &y, const int &channel) = 0;
+	virtual std::string writeInfos() = 0;
+};
+
 class Operation
 {
 protected:
 	int x1, y1, x2, y2, channel1, channel2;
+	ValueAccess *values;
 public:
-	virtual void set(int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2)
+	virtual void set(int _x1, int _y1, int _x2, int _y2, int _channel1, int _channel2, ValueAccess *_values)
 	{
 		x1 = _x1;
 		y1 = _y1;
@@ -64,6 +80,7 @@ public:
 		y2 = _y2;
 		channel1 = _channel1;
 		channel2 = _channel2;
+		values = _values;
 	}
 	/**
 	 * @brief abstract interface for feature computation
@@ -74,9 +91,15 @@ public:
 	 * @param y current y position
 	 * @return double distance
 	 **/
-	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const MultiChannelImageT<int> &cfeats, const int &cTree, const std::vector<TreeNode> &tree, NICE::MultiChannelImageT<double> &integralImg, const int &x, const int &y) = 0;
+	virtual double getVal(const Features &feats, const int &x, const int &y) = 0;
 	virtual Operation* clone() = 0;
 	virtual std::string writeInfos() = 0;
+	
+	inline void getXY(const Features &feats, int &xsize, int &ysize)
+	{
+		xsize = feats.feats->width();
+		ysize = feats.feats->height();
+	}
 };
   
 /** Localization system */
@@ -130,6 +153,8 @@ class SemSegContextTree : public SemanticSegmentation
 	/** operations for pairwise context features */
 	std::vector<Operation*> cops;
 	
+	std::vector<ValueAccess*> calcVal;
+	
 	/** vector of all possible features */
 	std::vector<Operation*> featsel;
 	
@@ -195,7 +220,7 @@ class SemSegContextTree : public SemanticSegmentation
 	 * @param splitval 
 	 * @return best information gain
 	 */
-	double getBestSplit(const std::vector<NICE::MultiChannelImageT<double> > &feats, std::vector<NICE::MultiChannelImageT<int> > &currentfeats, std::vector<NICE::MultiChannelImageT<double> > &integralImgs, const std::vector<NICE::MatrixT<int> > &labels, int node, Operation *&splitop, double &splitval, const int &tree);
+	double getBestSplit(std::vector<NICE::MultiChannelImageT<double> > &feats, std::vector<NICE::MultiChannelImageT<int> > &currentfeats, std::vector<NICE::MultiChannelImageT<double> > &integralImgs, const std::vector<NICE::MatrixT<int> > &labels, int node, Operation *&splitop, double &splitval, const int &tree);
 	
 	/**
 	 * @brief computes the mean probability for a given class over all trees