Browse Source

Initial revision

froehlich 15 years ago
commit
7d3cfc6a79
6 changed files with 558 additions and 0 deletions
  1. 8 0
      Makefile
  2. 103 0
      Makefile.inc
  3. 88 0
      progs/Makefile.inc
  4. 1 0
      progs/libdepend.inc
  5. 73 0
      progs/test.cpp
  6. 285 0
      progs/testSemanticSegmentation.cpp

+ 8 - 0
Makefile

@@ -0,0 +1,8 @@
+#TARGETS_FROM:=$(notdir $(patsubst %/,%,$(shell pwd)))/$(TARGETS_FROM)
+#$(info recursivly going up: $(TARGETS_FROM) ($(shell pwd)))
+
+all:
+
+%:
+	$(MAKE) TARGETS_FROM=$(notdir $(patsubst %/,%,$(shell pwd)))/$(TARGETS_FROM) -C .. $@
+

+ 103 - 0
Makefile.inc

@@ -0,0 +1,103 @@
+# LIBRARY-DIRECTORY-MAKEFILE
+# conventions:
+# - all subdirectories containing a "Makefile.inc" are considered sublibraries
+#   exception: "progs/" and "tests/" subdirectories!
+# - all ".C", ".cpp" and ".c" files in the current directory are linked to a
+#   library
+# - the library depends on all sublibraries 
+# - the library name is created with $(LIBNAME), i.e. it will be somehow
+#   related to the directory name and with the extension .a
+#   (e.g. lib1/sublib -> lib1_sublib.a)
+# - the library will be added to the default build list ALL_LIBRARIES
+
+# --------------------------------
+# - remember the last subdirectory
+#
+# set the variable $(SUBDIR) correctly to the current subdirectory. this
+# variable can be used throughout the current makefile.inc. The many 
+# SUBDIR_before, _add, and everything are only required so that we can recover
+# the previous content of SUBDIR before exitting the makefile.inc
+
+SUBDIR_add:=$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+SUBDIR_before:=$(SUBDIR)
+SUBDIR:=$(strip $(SUBDIR_add))
+SUBDIR_before_$(SUBDIR):=$(SUBDIR_before)
+ifeq "$(SUBDIR)" "./"
+SUBDIR:=
+endif
+
+# ------------------------
+# - include subdirectories
+#
+# note the variables $(SUBDIRS_OF_$(SUBDIR)) are required later on to recover
+# the dependencies automatically. if you handle dependencies on your own, you
+# can also dump the $(SUBDIRS_OF_$(SUBDIR)) variable, and include the
+# makefile.inc of the subdirectories on your own...
+
+SUBDIRS_OF_$(SUBDIR):=$(patsubst %/Makefile.inc,%,$(wildcard $(SUBDIR)*/Makefile.inc))
+include $(SUBDIRS_OF_$(SUBDIR):%=%/Makefile.inc)
+
+# ----------------------------
+# - include local dependencies
+#
+# you can specify libraries needed by the individual objects or by the whole
+# directory. the object specific additional libraries are only considered
+# when compiling the specific object files
+# TODO: update documentation...
+
+-include $(SUBDIR)libdepend.inc
+
+$(foreach d,$(filter-out %progs %tests,$(SUBDIRS_OF_$(SUBDIR))),$(eval $(call PKG_DEPEND_INT,$(d))))
+
+# ---------------------------
+# - objects in this directory
+#
+# the use of the variable $(OBJS) is not mandatory. it is mandatory however
+# to update $(ALL_OBJS) in a way that it contains the path and name of
+# all objects. otherwise we can not include the appropriate .d files.
+
+OBJS:=$(patsubst %.cpp,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.cpp))) \
+      $(patsubst %.C,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.C))) \
+	  $(shell grep -ls Q_OBJECT $(SUBDIR)*.h | sed -e's@^@/@;s@.*/@$(OBJDIR)moc_@;s@\.h$$@.o@') \
+      $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.c)))
+ALL_OBJS += $(OBJS)
+
+# ----------------------------
+# - binaries in this directory
+#
+# output of binaries in this directory. none of the variables has to be used.
+# but everything you add to $(ALL_LIBRARIES) and $(ALL_BINARIES) will be
+# compiled with `make all`. be sure again to add the files with full path.
+
+LIBRARY_BASENAME:=$(call LIBNAME,$(SUBDIR))
+ifneq "$(SUBDIR)" ""
+ALL_LIBRARIES+=$(LIBDIR)$(LIBRARY_BASENAME).$(LINK_FILE_EXTENSION)
+endif
+
+# ---------------------
+# - binary dependencies
+#
+# there is no way of determining the binary dependencies automatically, so we
+# follow conventions. the current library depends on all sublibraries.
+# all other dependencies have to be added manually by specifying, that the
+# current .pc file depends on some other .pc file. binaries depending on
+# libraries should exclusivelly use the .pc files as well.
+
+ifeq "$(SKIP_BUILD_$(OBJDIR))" "1"
+$(LIBDIR)$(LIBRARY_BASENAME).a:
+else
+$(LIBDIR)$(LIBRARY_BASENAME).a:$(OBJS) \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).a,.$(LINK_FILE_EXTENSION))
+endif
+
+$(PKGDIR)$(LIBRARY_BASENAME).pc: \
+	$(call PRINT_INTLIB_DEPS,$(PKGDIR)$(LIBRARY_BASENAME).pc,.pc)
+
+# -------------------
+# - subdir management
+#
+# as the last step, always add this line to correctly recover the subdirectory
+# of the makefile including this one!
+
+SUBDIR:=$(SUBDIR_before_$(SUBDIR))
+

+ 88 - 0
progs/Makefile.inc

@@ -0,0 +1,88 @@
+# BINARY-DIRECTORY-MAKEFILE
+# conventions:
+# - there are no subdirectories, they are ignored!
+# - all ".C", ".cpp" and ".c" files in the current directory are considered
+#   independent binaries, and linked as such.
+# - the binaries depend on the library of the parent directory
+# - the binary names are created with $(BINNAME), i.e. it will be more or less
+#   the name of the .o file
+# - all binaries will be added to the default build list ALL_BINARIES
+
+# --------------------------------
+# - remember the last subdirectory
+#
+# set the variable $(SUBDIR) correctly to the current subdirectory. this
+# variable can be used throughout the current makefile.inc. The many 
+# SUBDIR_before, _add, and everything are only required so that we can recover
+# the previous content of SUBDIR before exitting the makefile.inc
+
+SUBDIR_add:=$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+SUBDIR_before:=$(SUBDIR)
+SUBDIR:=$(strip $(SUBDIR_add))
+SUBDIR_before_$(SUBDIR):=$(SUBDIR_before)
+
+# ------------------------
+# - include subdirectories
+#
+# note the variables $(SUBDIRS_OF_$(SUBDIR)) are required later on to recover
+# the dependencies automatically. if you handle dependencies on your own, you
+# can also dump the $(SUBDIRS_OF_$(SUBDIR)) variable, and include the
+# makefile.inc of the subdirectories on your own...
+
+#SUBDIRS_OF_$(SUBDIR):=$(patsubst %/Makefile.inc,%,$(wildcard $(SUBDIR)*/Makefile.inc))
+#include $(SUBDIRS_OF_$(SUBDIR):%=%/Makefile.inc)
+
+# ----------------------------
+# - include local dependencies
+#
+# include the libdepend.inc file, which gives additional dependencies for the
+# libraries and binaries. additionally, an automatic dependency from the library
+# of the parent directory is added (commented out in the code below).
+
+-include $(SUBDIR)libdepend.inc
+
+PARENTDIR:=$(patsubst %/,%,$(dir $(patsubst %/,%,$(SUBDIR))))
+$(eval $(call PKG_DEPEND_INT,$(PARENTDIR)))
+
+# ---------------------------
+# - objects in this directory
+#
+# the use of the variable $(OBJS) is not mandatory. it is mandatory however
+# to update $(ALL_OBJS) in a way that it contains the path and name of
+# all objects. otherwise we can not include the appropriate .d files.
+
+OBJS:=$(patsubst %.cpp,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.cpp))) \
+      $(patsubst %.C,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.C))) \
+      $(shell grep -ls Q_OBJECT $(SUBDIR)*.h | sed -e's@^@/@;s@.*/@$(OBJDIR)moc_@;s@\.h$$@.o@') \
+      $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(wildcard $(SUBDIR)*.c)))
+ALL_OBJS += $(OBJS)
+
+# ----------------------------
+# - binaries in this directory
+#
+# output of binaries in this directory. none of the variables has to be used.
+# but everything you add to $(ALL_LIBRARIES) and $(ALL_BINARIES) will be
+# compiled with `make all`. be sure again to add the files with full path.
+
+BINARIES:=$(patsubst %.o,$(BINDIR)%,$(filter-out moc_%,$(notdir $(OBJS))))
+ALL_BINARIES+=$(BINARIES)
+
+# ---------------------
+# - binary dependencies
+#
+# there is no way of determining the binary dependencies automatically, so we
+# follow conventions. each binary depends on the corresponding .o file and
+# on the libraries specified by the INTLIBS/EXTLIBS. these dependencies can be
+# specified manually or they are automatically stored in a .bd file.
+
+$(foreach head,$(wildcard $(SUBDIR)*.h),$(eval $(shell grep -q Q_OBJECT $(head) && echo $(head) | sed -e's@^@/@;s@.*/\(.*\)\.h$$@$(BINDIR)\1:$(OBJDIR)moc_\1.o@')))
+-include $(OBJS:%.o=%.bd)
+
+# -------------------
+# - subdir management
+#
+# as the last step, always add this line to correctly recover the subdirectory
+# of the makefile including this one!
+
+SUBDIR:=$(SUBDIR_before_$(SUBDIR))
+

+ 1 - 0
progs/libdepend.inc

@@ -0,0 +1 @@
+$(call PKG_DEPEND_INT,objrec)

+ 73 - 0
progs/test.cpp

@@ -0,0 +1,73 @@
+// Beispielhafter Aufruf: BUILD_x86_64/progs/testSemanticSegmentation -config <CONFIGFILE>
+
+/**
+ * @file test.cpp
+ * @brief simple test program for everything
+ * @author Björn Fröhlich
+ * @date 03/10/2010
+ */
+
+#ifdef NICE_USELIB_OPENMP
+#include <omp.h>
+#endif
+
+#include <iostream>
+#include <fstream>
+
+#include "objrec/segmentation/RSMeanShift.h"
+#include "objrec/segmentation/RSCache.h"
+
+#include "objrec/baselib/Globals.h"
+
+using namespace std;
+
+using namespace OBJREC;
+
+int main(int argc, char **argv)
+{
+	
+	//popen test
+	string fn = "/tmp/img.ppm";
+	std::string call = "ls *";
+	const int buffersize = 65536;
+	char *buffer = new char [buffersize];
+	
+	FILE *f = popen ( call.c_str(), "r" );
+
+	cout << call << endl;
+	
+	if ( f == NULL )
+	{
+		fprintf (stderr, "FATAL ERROR, unable to run program\n");
+		return -1;
+	}
+	
+	while ( ! feof(f) ) 
+	{
+		if ( fgets ( buffer, buffersize, f ) <= 0 )
+		{
+			break;
+		} else {
+			fprintf (stderr, "%s", buffer );
+		}
+	}
+	pclose(f);
+
+	//openMP test
+#pragma omp parallel for
+	for(int i = 0; i < 3; i++)
+	{
+		cout << i << endl;
+	}
+	
+	Config * conf = new Config();
+	RegionSegmentationMethod *tmprsm = new RSMeanShift(conf);
+	RSCache rsm( conf, tmprsm );
+	Image cimg(fn);
+	Matrix mask;
+	Globals::setCurrentImgFN ( fn );
+	rsm.segRegions (cimg, mask);
+	
+	
+	return 0;
+}

+ 285 - 0
progs/testSemanticSegmentation.cpp

@@ -0,0 +1,285 @@
+// Beispielhafter Aufruf: BUILD_x86_64/progs/testSemanticSegmentation -config <CONFIGFILE>
+
+/**
+* @file testSemanticSegmentation.cpp
+* @brief test semantic segmentation routines
+* @author Erik Rodner
+* @date 03/20/2008
+*/
+
+#ifdef NICE_USELIB_OPENMP
+#include <omp.h>
+#endif
+
+#include <objrec/baselib/Config.h>
+#include <objrec/baselib/StringTools.h>
+#include <objrec/baselib/ICETools.h>
+
+#include <objrec/semanticsegmentation/SemanticSegmentation.h>
+#include <objrec/semanticsegmentation/SemSegLocal.h>
+#include <objrec/semanticsegmentation/SemSegSTF.h>
+#include <objrec/semanticsegmentation/SemSegCsurka.h>
+#include <objrec/semanticsegmentation/SemSegRegionBased.h>
+
+#include <fstream>
+
+using namespace OBJREC;
+
+using namespace NICE;
+
+using namespace std;
+
+void updateMatrix(const NICE::Image & img, const NICE::Image & gt,
+																		NICE::Matrix & M, const set<int> & forbidden_classes)
+{
+	double subsamplex = gt.width() / (double)img.width();
+	double subsampley = gt.height() / (double)img.height();
+
+	for (int y = 0 ; y < gt.height() ; y++)
+		for (int x = 0 ; x < gt.width() ; x++)
+		{
+			int xx = (int)(x / subsamplex);
+			int yy = (int)(y / subsampley);
+
+			if (xx < 0) xx = 0;
+
+			if (yy < 0) yy = 0;
+
+			if (xx > img.width() - 1) xx = img.width() - 1;
+
+			if (yy > img.height() - 1) yy = img.height() - 1;
+
+			int cimg = img.getPixel(xx, yy);
+
+			int gimg = gt.getPixel(x, y);
+
+			if (forbidden_classes.find(gimg) == forbidden_classes.end())
+			{
+				M(gimg, cimg)++;
+			}
+		}
+}
+
+/**
+ test semantic segmentation routines
+*/
+int main(int argc, char **argv)
+{
+	std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
+
+	Config conf(argc, argv);
+
+	bool show_result = conf.gB("debug", "show_results", false);
+
+	bool write_results = conf.gB("debug", "write_results", false);
+
+	bool write_results_pascal = conf.gB("debug", "write_results_pascal", false);
+
+	std::string resultdir = conf.gS("debug", "resultdir", ".");
+
+	if (write_results)
+	{
+		cerr << "Writing Results to " << resultdir << endl;
+	}
+
+	MultiDataset md(&conf);
+
+	const ClassNames & classNames = md.getClassNames("train");
+
+	//SemanticSegmentation *semseg = new SemSegLocal ( &conf, &md );
+	//SemanticSegmentation *semseg = new SemSegSTF ( &conf, &md );
+	//SemanticSegmentation *semseg = new SemSegCsurka ( &conf, &md);
+
+	SemanticSegmentation *semseg = new SemSegRegionBased(&conf, &md);
+
+	const LabeledSet *testFiles = md["test"];
+	NICE::Matrix M(classNames.getMaxClassno() + 1, classNames.getMaxClassno() + 1);
+	M.set(0);
+
+	set<int> forbidden_classes;
+
+	std::string forbidden_classes_s = conf.gS("analysis", "forbidden_classes", "");
+
+	classNames.getSelection(forbidden_classes_s, forbidden_classes);
+
+	ProgressBar pb("Semantic Segmentation Analysis");
+	pb.show();
+
+	int fileno = 0;
+
+	LOOP_ALL_S(*testFiles)
+	{
+		EACH_INFO(classno, info);
+		pb.update(testFiles->count());
+
+		std::string file = info.img();
+
+		NICE::Image lm;
+		GenericImage<double> probabilities;
+		
+		if (info.hasLocalizationInfo())
+		{
+			const LocalizationResult *l_gt = info.localization();
+
+			lm.resize(l_gt->xsize, l_gt->ysize);
+			lm.set(0);
+			l_gt->calcLabeledImage(lm, classNames.getBackgroundClass());
+		}
+
+		semseg->semanticseg(file, lm, probabilities);
+		fprintf(stderr, "testSemanticSegmentation: Segmentation finished !\n");
+
+		NICE::Image lm_gt;
+
+		if (info.hasLocalizationInfo())
+		{
+			const LocalizationResult *l_gt = info.localization();
+
+			lm_gt.resize(l_gt->xsize, l_gt->ysize);
+			lm_gt.set(0);
+
+			fprintf(stderr, "testSemanticSegmentation: Generating Labeled NICE::Image (Ground-Truth)\n");
+			l_gt->calcLabeledImage(lm_gt, classNames.getBackgroundClass());
+		}
+
+		std::string fname = StringTools::baseName(file, false);
+
+		if (write_results_pascal)
+		{
+			NICE::Image pascal_lm(lm.width(), lm.height());
+			int backgroundClass = classNames.getBackgroundClass();
+
+			for (int y = 0 ; y < lm.height(); y++)
+				for (int x = 0 ; x < lm.width(); x++)
+				{
+					int v = lm.getPixel(x, y);
+
+					if (v == backgroundClass)
+						pascal_lm.setPixel(x, y, 255);
+					else
+						pascal_lm.setPixel(x, y, 255 - v - 1);
+				}
+
+			char filename[1024];
+
+			char *format = (char *)"pgm";
+			sprintf(filename, "%s/%s.%s", resultdir.c_str(), fname.c_str(), format);
+
+			pascal_lm.write(filename);
+		}
+
+		if (show_result || write_results)
+		{
+			NICE::ColorImage orig(file);
+			NICE::ColorImage rgb;
+			NICE::ColorImage rgb_gt;
+			classNames.labelToRGB(lm, rgb);
+			classNames.labelToRGB(lm_gt, rgb_gt);
+
+			if (write_results)
+			{
+				char filename[1024];
+				char *format = "ppm";
+				sprintf(filename, "%06d.%s", fileno, format);
+				std::string origfilename = resultdir + "/orig_" + string(filename);
+				cerr << "Writing to file " << origfilename << endl;
+				orig.write(origfilename);
+				rgb.write(resultdir + "/result_" + string(filename));
+				rgb_gt.write(resultdir + "/groundtruth_" + string(filename));
+			}
+
+			if (show_result)
+			{
+#ifndef NOVISUAL
+				showImage(rgb, "Result");
+				showImage(rgb_gt, "Groundtruth");
+				showImage(orig, "Input");
+#endif
+			}
+		}
+
+//#pragma omp critical
+		updateMatrix(lm, lm_gt, M, forbidden_classes);
+
+		cerr << M << endl;
+		fileno++;
+	}
+
+	pb.hide();
+
+	double overall = 0.0;
+	double sumall = 0.0;
+	for(int r = 0; r < (int)M.rows(); r++)
+	{
+		for(int c = 0; c < (int)M.cols(); c++)
+		{
+			if(r == c)
+				overall += M(r,c);
+			sumall += M(r,c);
+		}
+	}
+	
+	overall /= sumall;
+	
+	// normalizing M using rows
+	for (int r = 0 ; r < (int)M.rows() ; r++)
+	{
+		double sum = 0.0;
+
+		for (int c = 0 ; c < (int)M.cols() ; c++)
+			sum += M(r, c);
+
+		if (fabs(sum) > 1e-4)
+			for (int c = 0 ; c < (int)M.cols() ; c++)
+				M(r, c) /= sum;
+	}
+
+	cerr << M << endl;
+	
+	double avg_perf = 0.0;
+	int classes_trained = 0;
+
+	for (int r = 0 ; r < (int)M.rows() ; r++)
+	{
+		if ((classNames.existsClassno(r)) && (forbidden_classes.find(r) == forbidden_classes.end()))
+		{
+			avg_perf += M(r, r);
+			classes_trained++;
+		}
+	}
+
+	if (write_results)
+	{
+		ofstream fout((resultdir + "/res.txt").c_str(), ios::out);
+		fout <<  "overall: " << overall << endl;
+		fout << "Average Performance " << avg_perf / (classes_trained) << endl;
+		fout << "Lower Bound " << 1.0  / classes_trained << endl;
+
+		for (int r = 0 ; r < (int)M.rows() ; r++)
+		{
+			if ((classNames.existsClassno(r)) && (forbidden_classes.find(r) == forbidden_classes.end()))
+			{
+				std::string classname = classNames.text(r);
+				fout << classname.c_str() << ": " << M(r, r) << endl;
+			}
+		}
+
+		fout.close();
+	}
+
+	cerr <<  "overall: " << overall << endl;
+	fprintf(stderr, "Average Performance %f\n", avg_perf / (classes_trained));
+	//fprintf(stderr, "Lower Bound %f\n", 1.0 / classes_trained);
+	for (int r = 0 ; r < (int)M.rows() ; r++)
+	{
+		if ((classNames.existsClassno(r)) && (forbidden_classes.find(r) == forbidden_classes.end()))
+		{
+			std::string classname = classNames.text(r);
+			fprintf(stderr, "%s: %f\n", classname.c_str(), M(r, r));
+		}
+	}
+
+	delete semseg;
+
+	return 0;
+}