Forráskód Böngészése

new version of SSContextTree

Bjoern Froehlich 13 éve
szülő
commit
7b14c16b29
2 módosított fájl, 228 hozzáadás és 80 törlés
  1. 172 35
      semseg/SemSegContextTree.cpp
  2. 56 45
      semseg/SemSegContextTree.h

+ 172 - 35
semseg/SemSegContextTree.cpp

@@ -11,6 +11,7 @@
 #include <iostream>
 
 #define BOUND(x,min,max) (((x)<(min))?(min):((x)>(max)?(max):(x)))
+#define LOCALFEATS
 
 using namespace OBJREC;
 using namespace std;
@@ -19,7 +20,7 @@ using namespace NICE;
 class Minus:public Operation
 {
 public:
-	virtual double getVal(const MultiChannelImageT<double> &feats, const int &x, const int &y)
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
 	{
 		int xsize = feats.width();
 		int ysize = feats.height();
@@ -32,12 +33,17 @@ public:
 	{
 		return new Minus();
 	};
+	
+	virtual void writeInfos()
+	{
+		cout << "Minus: " << endl;
+	}
 };
 
 class MinusAbs:public Operation
 {
 public:
-	virtual double getVal(const MultiChannelImageT<double> &feats, const int &x, const int &y)
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
 	{
 		int xsize = feats.width();
 		int ysize = feats.height();
@@ -50,12 +56,17 @@ public:
 	{
 		return new MinusAbs();
 	};
+	
+	virtual void writeInfos()
+	{
+		cout << "MinusAbs: " << endl;
+	}
 };
 
 class Addition:public Operation
 {
 public:
-	virtual double getVal(const MultiChannelImageT<double> &feats, const int &x, const int &y)
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
 	{
 		int xsize = feats.width();
 		int ysize = feats.height();
@@ -68,12 +79,17 @@ public:
 	{
 		return new Addition();
 	};
+	
+	virtual void writeInfos()
+	{
+		cout << "Addition: " << endl;
+	}
 };
 
 class Only1:public Operation
 {
 public:
-	virtual double getVal(const MultiChannelImageT<double> &feats, const int &x, const int &y)
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
 	{
 		int xsize = feats.width();
 		int ysize = feats.height();
@@ -85,6 +101,102 @@ public:
 	{
 		return new Only1();
 	};
+	
+	virtual void writeInfos()
+	{
+		cout << "Only1: " << endl;
+	}
+};
+
+class ContextMinus:public Operation
+{
+public:
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
+	{
+		int xsize = feats.width();
+		int ysize = feats.height();
+		double v1 = tree[cfeats[BOUND(x+x1,0,xsize-1)][BOUND(y+y1,0,ysize-1)]].dist[channel1];
+		double v2 = tree[cfeats[BOUND(x+x2,0,xsize-1)][BOUND(y+y2,0,ysize-1)]].dist[channel2];
+		return v1-v2;
+	}
+	
+	virtual Operation* clone()
+	{
+		return new ContextMinus();
+	};
+	
+	virtual void writeInfos()
+	{
+		cout << "ContextMinus: " << endl;
+	}
+};
+
+class ContextMinusAbs:public Operation
+{
+public:
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
+	{
+		int xsize = feats.width();
+		int ysize = feats.height();
+		double v1 = tree[cfeats[BOUND(x+x1,0,xsize-1)][BOUND(y+y1,0,ysize-1)]].dist[channel1];
+		double v2 = tree[cfeats[BOUND(x+x2,0,xsize-1)][BOUND(y+y2,0,ysize-1)]].dist[channel2];
+		return abs(v1-v2);
+	}
+	
+	virtual Operation* clone()
+	{
+		return new ContextMinusAbs();
+	};
+	
+	virtual void writeInfos()
+	{
+		cout << "ContextMinusAbs: " << endl;
+	}
+};
+
+class ContextAddition:public Operation
+{
+public:
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
+	{
+		int xsize = feats.width();
+		int ysize = feats.height();
+		double v1 = tree[cfeats[BOUND(x+x1,0,xsize-1)][BOUND(y+y1,0,ysize-1)]].dist[channel1];
+		double v2 = tree[cfeats[BOUND(x+x2,0,xsize-1)][BOUND(y+y2,0,ysize-1)]].dist[channel2];
+		return v1+v2;
+	}
+	
+	virtual Operation* clone()
+	{
+		return new ContextAddition();
+	};
+	
+	virtual void writeInfos()
+	{
+		cout << "ContextAddition: " << endl;
+	}
+};
+
+class ContextOnly1:public Operation
+{
+public:
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y)
+	{
+		int xsize = feats.width();
+		int ysize = feats.height();
+		double v1 = tree[cfeats[BOUND(x+x1,0,xsize-1)][BOUND(y+y1,0,ysize-1)]].dist[channel1];
+		return v1;
+	}
+	
+	virtual Operation* clone()
+	{
+		return new ContextOnly1();
+	};
+	
+	virtual void writeInfos()
+	{
+		cout << "ContextOnly1: " << endl;
+	}
 };
       
 
@@ -108,17 +220,25 @@ SemSegContextTree::SemSegContextTree( const Config *conf, const MultiDataset *md
 	featsPerSplit = conf->gI(section, "feats_per_split", 200);
 	
 	useShannonEntropy = conf->gB(section, "use_shannon_entropy", true);
+
+	
+	ftypes = conf->gI(section, "features", 2);;
 	
 	ops.push_back(new Minus());
 	ops.push_back(new MinusAbs());
 	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());
+	
 	classnames = md->getClassNames ( "train" );
 	
 	///////////////////////////////////
 	// Train Segmentation Context Trees
-	//////////////////////////////////
+	///////////////////////////////////
 
 	train ( md );
 }
@@ -129,6 +249,7 @@ SemSegContextTree::~SemSegContextTree()
 
 void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &feats, vector<vector<vector<int> > > &currentfeats,const vector<vector<vector<int> > > &labels, int node, Operation *&splitop, double &splitval)
 {
+
 	int imgCount, featdim;
 	try
 	{
@@ -139,7 +260,7 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 	{
 		cerr << "no features computed?" << endl;
 	}
-	
+
 	double bestig = -numeric_limits< double >::max();
 	splitop = NULL;
 	splitval = -1.0;
@@ -147,7 +268,7 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 	set<vector<int> >selFeats;
 	map<int,int> e;
 	int featcounter = 0;
-	
+
 	for(int iCounter = 0; iCounter < imgCount; iCounter++)
 	{
 		int xsize = (int)currentfeats[iCounter].size();
@@ -163,7 +284,7 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 			}
 		}
 	}
-	
+
 	if(featcounter < minFeats)
 	{
 		cout << "only " << featcounter << " feats in current node -> it's a leaf" << endl;
@@ -182,9 +303,7 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 	//cout << "a.size(): " << a.size() << endl;
 	//getchar();
 	featcounter = 0;
-	
-	
-	
+
 	for(int iCounter = 0; iCounter < imgCount; iCounter++)
 	{
 		int xsize = (int)currentfeats[iCounter].size();
@@ -208,12 +327,11 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 						e[cn]++;
 					}
 				}
-
 			}
 		}
 	}
-	
-	cout << "size: " << selFeats.size() << endl;
+
+	//cout << "size: " << selFeats.size() << endl;
 	//getchar();
 	
 	map<int,int>::iterator mapit;
@@ -232,6 +350,8 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 		return;
 	}
 	
+
+	int classes = (int)labelmap.size();
 	featsel.clear();
 	for(int i = 0; i < featsPerSplit; i++)
 	{
@@ -239,13 +359,28 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 		int x2 = (int)((double)rand()/(double)RAND_MAX*(double)windowSize)-windowSize/2;
 		int y1 = (int)((double)rand()/(double)RAND_MAX*(double)windowSize)-windowSize/2;
 		int y2 = (int)((double)rand()/(double)RAND_MAX*(double)windowSize)-windowSize/2;
-		int f1 = (int)((double)rand()/(double)RAND_MAX*(double)featdim);
-		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);
-		featsel.push_back(op);
+		int ft = (int)((double)rand()/(double)RAND_MAX*(double)ftypes);
+		
+		if(ft == 0)
+		{
+			int f1 = (int)((double)rand()/(double)RAND_MAX*(double)featdim);
+			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);
+			featsel.push_back(op);
+		}
+		else if(ft == 1)
+		{
+			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);
+			featsel.push_back(op);
+		}
+		
 	}
 	
 #pragma omp parallel for private(mapit)
@@ -255,10 +390,10 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 		double l_splitval = -1.0;
 		set<vector<int> >::iterator it;
 		vector<double> vals;
-
+		
 		for ( it=selFeats.begin() ; it != selFeats.end(); it++ )
 		{
-			vals.push_back(featsel[f]->getVal(feats[(*it)[0]],(*it)[1], (*it)[2]));
+			vals.push_back(featsel[f]->getVal(feats[(*it)[0]],currentfeats[(*it)[0]],tree,(*it)[1], (*it)[2]));
 		}
 		
 		int counter = 0;
@@ -334,6 +469,8 @@ void SemSegContextTree::getBestSplit(const vector<MultiChannelImageT<double> > &
 		}
 }
 	}
+		splitop->writeInfos();
+		cout<< "ig: " << bestig << endl;
 	
 	/*for(int i = 0; i < featsPerSplit; i++)
 	{
@@ -407,8 +544,8 @@ void SemSegContextTree::train ( const MultiDataset *md )
 		//TODO: resize image?!
 		MultiChannelImageT<double> feats;
 		allfeats.push_back(feats);
-#if 0
-		lfcw->getFeats(img, feats);
+#ifdef LOCALFEATS
+		lfcw->getFeats(img, allfeats[imgcounter]);
 #else
 		allfeats[imgcounter].reInit(xsize, ysize, 3, true);
 		for(int x = 0; x < xsize; x++)
@@ -421,9 +558,7 @@ void SemSegContextTree::train ( const MultiDataset *md )
 				}
 			}
 		}
-#endif
-cout << 5 << endl;
-		
+#endif		
 		
 		// getting groundtruth
 		NICE::Image pixelLabels (xsize, ysize);
@@ -488,12 +623,14 @@ cout << 5 << endl;
 	cout << "a.size: " << a.size() << endl;
 #endif
 	
-	tree.push_back(Node());
+	tree.push_back(TreeNode());
 	tree[0].dist = vector<double>(classes,0.0);
 	int depth = 0;
 	tree[0].depth = depth;
 	int startnode = 0;
 	bool allleaf = false;
+	//int baseFeatSize = allfeats[0].size();
+	
 	while(!allleaf && depth < maxDepth)
 	{
 		allleaf = true;
@@ -509,17 +646,17 @@ cout << 5 << endl;
 			{  
 				Operation *splitfeat = NULL;
 				double splitval;
-
 				getBestSplit(allfeats, currentfeats,labels, i, splitfeat, splitval);
 				tree[i].feat = splitfeat;
+				
 				tree[i].decision = splitval;
 				
 				if(splitfeat != NULL)
 				{
 					allleaf = false;
 					int left = tree.size();
-					tree.push_back(Node());
-					tree.push_back(Node());
+					tree.push_back(TreeNode());
+					tree.push_back(TreeNode());
 					int right = left+1;
 					tree[i].left = left;
 					tree[i].right = right;
@@ -538,7 +675,7 @@ cout << 5 << endl;
 							{
 								if(currentfeats[iCounter][x][y] == i)
 								{
-									double val = splitfeat->getVal(allfeats[iCounter],x,y);
+									double val = splitfeat->getVal(allfeats[iCounter],currentfeats[iCounter],tree,x,y);
 
 									if(val < splitval)
 									{ 
@@ -587,9 +724,9 @@ cout << 5 << endl;
 				{
 					tree[i].isleaf = true;
 				}
+				
 			}
 		}
-		
 		//TODO: features neu berechnen!
 		depth++;
 #ifdef DEBUG
@@ -639,7 +776,7 @@ void SemSegContextTree::semanticseg ( CachedExample *ce, NICE::Image & segresult
 	//TODO: resize image?!
 		
 		MultiChannelImageT<double> feats;
-#if 0
+#ifdef LOCALFEATS
 		lfcw->getFeats(img, feats);
 #else
 		feats.reInit (xsize, ysize, 3, true);
@@ -675,7 +812,7 @@ void SemSegContextTree::semanticseg ( CachedExample *ce, NICE::Image & segresult
 					if(tree[t].left > 0)
 					{
 						allleaf = false;
-						double val = tree[t].feat->getVal(feats,x,y);
+						double val = tree[t].feat->getVal(feats,currentfeats,tree,x,y);
 						
 						if(val < tree[t].decision)
 						{

+ 56 - 45
semseg/SemSegContextTree.h

@@ -13,7 +13,43 @@
 #include "vislearning/features/localfeatures/LFColorWeijer.h"
 
 namespace OBJREC {
-
+	
+class Operation;
+	
+class TreeNode
+{
+public:
+	/** probabilities for each class */
+	std::vector<double> probs;
+	
+	/** left child node */
+	int left;
+	
+	/** right child node */
+	int right;
+	
+	/** position of feat for decision */
+	Operation *feat;
+	
+	/** decision stamp */
+	double decision;
+	
+	/** is the node a leaf or not */
+	bool isleaf;
+	
+	/** distribution in current node */
+	std::vector<double> dist;
+	
+	/** depth of the node in the tree */
+	int depth;
+	
+	/** simple constructor */
+	TreeNode():left(-1),right(-1),feat(NULL), decision(-1.0), isleaf(false){}
+	
+	/** standard constructor */
+	TreeNode(int _left, int _right, Operation *_feat, double _decision):left(_left),right(_right),feat(_feat), decision(_decision),isleaf(false){}
+};
+	
 class Operation
 {
 protected:
@@ -28,61 +64,33 @@ public:
 		channel1 = _channel1;
 		channel2 = _channel2;
 	}
-	virtual double getVal(const MultiChannelImageT<double> &feats, const int &x, const int &y) = 0;
+	/**
+	 * @brief abstract interface for feature computation
+	 * @param feats features
+	 * @param cfeats number of tree node for each pixel
+	 * @param tree current tree
+	 * @param x current x position
+	 * @param y current y position
+	 * @return double distance
+	 **/
+	virtual double getVal(const NICE::MultiChannelImageT<double> &feats, const std::vector<std::vector<int> > &cfeats, const std::vector<TreeNode> &tree, const int &x, const int &y) = 0;
 	virtual Operation* clone() = 0;
+	virtual void writeInfos() = 0;
 };
   
 /** Localization system */
 class SemSegContextTree : public SemanticSegmentation
 {
-    protected:
- 
-	class Node
-	{
-	public:
-		/** probabilities for each class */
-		std::vector<double> probs;
-		
-		/** left child node */
-		int left;
-		
-		/** right child node */
-		int right;
-		
-		/** position of feat for decision */
-		Operation *feat;
-		
-		/** decision stamp */
-		double decision;
-		
-		/** is the node a leaf or not */
-		bool isleaf;
-		
-		/** distribution in current node */
-		std::vector<double> dist;
-		
-		/** depth of the node in the tree */
-		int depth;
-		
-		/** simple constructor */
-		Node():left(-1),right(-1),feat(NULL), decision(-1.0), isleaf(false){}
-		
-		/** standard constructor */
-		Node(int _left, int _right, Operation *_feat, double _decision):left(_left),right(_right),feat(_feat), decision(_decision),isleaf(false){}
-	};
-	
-	/** store features */
-	NICE::VVector currentfeats;
-	
-	/** store the positions of the features */
-	NICE::VVector positions;
-	
+    protected:	
 	/** tree -> saved as vector of nodes */
-	std::vector<Node> tree;
+	std::vector<TreeNode> tree;
 	
 	/** local features */
 	LFColorWeijer *lfcw;
 	
+	/** number of featuretype -> currently: local and context features = 2 */
+	int ftypes;
+	
 	/** distance between features */
 	int grid;
 	
@@ -116,6 +124,9 @@ class SemSegContextTree : public SemanticSegmentation
 	/** operations for pairwise features */
 	std::vector<Operation*> ops;
 	
+	/** operations for pairwise context features */
+	std::vector<Operation*> cops;
+	
 	/** vector of all possible features */
 	std::vector<Operation*> featsel;